      1 ﻿
      2 /**
      3  * @name	CeL function for web
      4  * @fileoverview
      5  * 本檔案包含了 web 的 functions。
      6  * @since
      7  */
      8
      9 /*
     10 http://www.comsharp.com/GetKnowledge/zh-CN/It_News_K902.aspx
     11 http://www.nczonline.net/blog/2010/01/12/history-of-the-user-agent-string/
     12 當 IE 初次推出它們的 User Agent 標誌的時候，是這個樣子：
     13 MSIE/3.0 (Win95; U)
     14
     15 TODO:
     16 don't use .innerHTML
     17 通盤確認所有 HTMLElement 變數已經設成 null
     18
     19
     20 功能探測 vs 瀏覽器探測
     21 http://www.comsharp.com/GetKnowledge/zh-CN/It_News_K987.aspx
     22 Mark Pilgrim 有一個清單，它可以讓你探測任何功能。
     23 http://diveintohtml5.org/everything.html
     24
     25 */
     26
     27 if (typeof CeL === 'function'){
     28
     29 /**
     30  * 本 module 之 name(id)，<span style="text-decoration:line-through;">不設定時會從呼叫時之 path (directory + file name) 取得</span>。
     31  * @type	String
     32  * @constant
     33  * @inner
     34  * @ignore
     35  */
     36 var module_name = 'net.web';
     37
     38 //===================================================
     39 /**
     40  * 若欲 include 整個 module 時，需囊括之 code。
     41  * @type	Function
     42  * @param	{Function} library_namespace	namespace of library
     43  * @param	load_arguments	呼叫時之 argument(s)
     44  * @return
     45  * @name	CeL.net.web
     46  * @constant
     47  * @inner
     48  * @ignore
     49  */
     50 var code_for_including = function(library_namespace, load_arguments) {
     51
     52 //	requires
     53 if (eval(library_namespace.use_function(
     54 		'code.compatibility.is_DOM,data.split_String_to_Object')))
     55 	return;
     56
     57
     58 /**
     59  * null module constructor
     60  * @class	web 的 functions
     61  */
     62 CeL.net.web
     63 = function() {
     64 	//	null module constructor
     65 };
     66
     67 /**
     68  * for JSDT: 有 prototype 才會將之當作 Class
     69  */
     70 CeL.net.web
     71 .prototype = {
     72 };
     73
     74
     75
     76
     77
     78
     79 /*
     80 	HTML only	-------------------------------------------------------
     81 */
     82
     83 /**
     84  * NodeType: const unsigned short.
     85  * @see
     86  * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-1950641247
     87  * http://www.w3.org/TR/DOM-Level-2-Core/core.html
     88  * ELEMENT_NODE,ATTRIBUTE_NODE,TEXT_NODE,CDATA_SECTION_NODE,ENTITY_REFERENCE_NODE,ENTITY_NODE,PROCESSING_INSTRUCTION_NODE,COMMENT_NODE,DOCUMENT_NODE,DOCUMENT_TYPE_NODE,DOCUMENT_FRAGMENT_NODE,NOTATION_NODE
     89  * @inner
     90  */
     91 var ELEMENT_NODE = 1,
     92 	TEXT_NODE = 3,
     93 	DOCUMENT_NODE = 9;
     94
     95 if(is_DOM('document') &&
     96 		//	IE8: undefined
     97 		!isNaN(document.ELEMENT_NODE))
     98 	ELEMENT_NODE = document.ELEMENT_NODE,
     99 	TEXT_NODE = document.TEXT_NODE,
    100 	DOCUMENT_NODE = document.DOCUMENT_NODE;
    101
    102 //	IE 中 Object.prototype.toString.call(HTML Element)==='[object Object]', 得用 ''+node
    103 var get_object_type = Object.prototype.toString,
    104 element_pattern = /^\[object HTML([A-U][A-Za-z]{1,15})?Element\]$/;
    105
    106
    107
    108 CeL.net.web
    109 .
    110 /**
    111  * 判斷是否為 HTML Element。
    112  * @param	value	value to test
    113  * @return	{Boolean}	value is HTML Element
    114  * @since	2010/6/23 02:32:41
    115  * @memberOf	CeL.net.web
    116  * @see
    117  * http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-58190037,
    118  * http://www.w3.org/DOM/
    119  */
    120 is_HTML_element = function(value) {
    121 	// return get_object_type.call(value).indexOf('[object HTML')===0;
    122 	return element_pattern.test(get_object_type.call(value))
    123 		|| '[object Text]' === get_object_type.call(value)
    124 		&& value.nodeType === TEXT_NODE;
    125 	// return get_object_type.call(value).match(element_pattern);
    126 };
    127
    128 CeL.net.web
    129 .
    130 /**
    131  * 判斷為指定 nodeType 之 HTML Element。
    132  * @param	value	value to test
    133  * @param	type	type
    134  * @return	{Boolean}	value is the type of HTML Element
    135  * @since	2010/6/23 02:32:41
    136  * @memberOf	CeL.net.web
    137  * @see
    138  * http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-58190037,
    139  * http://www.w3.org/DOM/
    140  */
    141 is_HTML_element_type = function(value, type) {
    142 	return type === TEXT_NODE ?
    143 			'[object Text]' === get_object_type.call(value) && value.nodeType === TEXT_NODE
    144 			: element_pattern.test(get_object_type.call(value)) && value.nodeType === type;
    145 };
    146
    147 CeL.net.web
    148 .
    149 /**
    150  * 判斷為 HTML Element。
    151  * @param	value	value to test
    152  * @return	{Boolean}	value is HTML Element
    153  * @since	2010/6/23 02:32:41
    154  * @memberOf	CeL.net.web
    155  * @see
    156  * http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-58190037,
    157  * http://www.w3.org/DOM/
    158  */
    159 is_element_node = function(value) {
    160 	//library_namespace.debug('Test '+get_object_type.call(value)+' '+((typeof value==='object'||typeof value==='function')&&value.nodeType||'')+': '+element_pattern.test(get_object_type.call(value))+','+(value.nodeType === 1));
    161 	return element_pattern.test(get_object_type.call(value)) && value.nodeType === ELEMENT_NODE;
    162 };
    163
    164
    165 /*
    166
    167 IE5DOM @ IE9 test:
    168 IE7DOM @ IE9 test:
    169 node <DIV>: type object, toString.call: [object Object], ""+node: [object], nodeType: 1:
    170
    171 IE8:
    172 IE8DOM @ IE9 test:
    173 IE9DOM @ IE9 test:
    174 node <DIV>: type object, toString.call: [object Object], ""+node: [object HTMLDivElement], nodeType: 1:
    175
    176 IE8:
    177 node <A>: type object, toString.call: [object Object], ""+node: , nodeType: 1:
    178 node <OBJECT>: type object, toString.call: [object Object], ""+node: [object], nodeType: 1:
    179
    180 */
    181 function show_node(node) {
    182 	if(_.is_element_node(node))
    183 		library_namespace.debug('node'
    184 			+ (node.tagName ? ' <' + node.tagName
    185 					+ (node.id ? '#' + node.id : '') + '>' : '') + ': type '
    186 			+ typeof node + ', toString.call: ' + get_object_type.call(node)
    187 			+ ', ""+node: ' + ('' + node) + ', nodeType: ' + node.nodeType
    188 			+ ('innerHTML' in node ? ': ' + node.innerHTML : ''));
    189 }
    190
    191 try {
    192 	// workaround for IE, 因用 General type, 效能較差
    193 	var d = document.createElement('div'), s;
    194 	// alert('toString test: ' + element_pattern.test(get_object_type.call(d)));
    195
    196 	if(d.nodeType !== ELEMENT_NODE)
    197 		//	doesn't support W3C DOM?
    198 		throw 0;
    199
    200 	if (!(s = element_pattern.test(get_object_type.call(d)))) {
    201 		if (element_pattern.test('' + d))
    202 			// IE8-9
    203 			_.is_HTML_element = function(value) {
    204 				return element_pattern.test('' + value)
    205 						// for IE8. value 可能是 null!
    206 						|| typeof value === 'object' && value !== null && value.nodeType === ELEMENT_NODE// && value.tagName === "OBJECT"
    207 							&& "[object NamedNodeMap]" === '' + value.attributes;
    208 			};
    209 		else if (get_object_type.call(d) === '[object Object]')
    210 			// IE5-7, 這種判別方法有漏洞!
    211 			_.is_HTML_element = function(value) {
    212 				return '[object Object]' === get_object_type.call(value) && value !== null && typeof value.nodeType === 'number';
    213 			};
    214 		else
    215 			throw 1;
    216
    217 		//	General type
    218 		_.is_HTML_element_type = function(value, type) {
    219 			return _.is_HTML_element(value) && value.nodeType === type;
    220 		};
    221 		_.is_element_node = function(value) {
    222 			return _.is_HTML_element(value) && value.nodeType === ELEMENT_NODE;
    223 		};
    224 	}
    225
    226 } catch (e) {
    227 	// TODO: handle exception
    228 } finally {
    229 	d = null;
    230 }
    231
    232
    233
    234 /*	test if can use flash
    235
    236 	better use SWFObject:
    237 	http://code.google.com/p/swfobject/
    238
    239 	Browser detect:	http://www.quirksmode.org/js/detect.html
    240 var plugin=(window.navigator.mimeTypes && window.navigator.mimeTypes["application/x-shockwave-flash"]) ? window.navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin : 0;
    241 if ( plugin ) {
    242         plugin=parseInt(plugin.description.substring(plugin.description.indexOf(".")-1)) >= 3;
    243 }
    244 else if (window.navigator.userAgent && window.navigator.userAgent.indexOf("MSIE")>=0 && window.navigator.userAgent.indexOf("Windows")>=0) {
    245         document.write('<SCRIPT LANGUAGE=VBScript\> \n');
    246         document.write('on error resume next \n');
    247         document.write('plugin=( IsObject(CreateObject("ShockwaveFlash.ShockwaveFlash.6")))\n');
    248         document.write('<\/SCRIPT\> \n');
    249 }
    250 if ( plugin ) {
    251         document.write('<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"');
    252         document.write('  codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" ');
    253         document.write(' ID=flash5clickTAG WIDTH='+n_width+' HEIGHT='+n_height+'>');
    254         document.write(' <PARAM NAME=movie VALUE="'+ n_flashfile +'"><param name=wmode value=opaque><PARAM NAME=loop VALUE=true><PARAM NAME=quality VALUE=high>  ');
    255         document.write(' <EMBED src="'+ n_flashfile +'" loop=true wmode=opaque quality=high  ');
    256         document.write(' swLiveConnect=FALSE WIDTH='+n_width+' HEIGHT='+n_height+'');
    257         document.write(' TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash">');
    258         document.write(' <\/EMBED>');
    259         document.write(' <\/OBJECT>');
    260 } else if (!(window.navigator.appName && window.navigator.appName.indexOf("Netscape")>=0 && window.navigator.appVersion.indexOf("2.")>=0)){
    261         document.write('<A HREF="'+ n_altURL +'" target="'+n_target+'"><IMG SRC="'+ n_altimg +'" WIDTH='+n_width+' HEIGHT='+n_height+' BORDER=0><\/A>');
    262 }
    263 */
    264
    265 //	copy from base.js
    266 //window.onerror=HandleError;
    267 function HandleError(message, url, line) {
    268 	// if(window.confirm())_DO_CONTINUE_
    269 	if (window.navigator.appName == "Microsoft Internet Explorer")
    270 		return !window.confirm(url + '\n\nJavaScript Error: ' + line
    271 				+ '\n' + message + '\n\nSee more details?');
    272 	else if (window.navigator.appName == "Netscape")
    273 		// document.location.href="javascript:";
    274 		window.navigate('javascript:');
    275
    276 	//return message;	'Warning: function HandleError does not always return a value' in some Firebird with	user_pref("javascript.options.strict", true);	@ prefs.js
    277 }
    278
    279 //window.onresize=OnResize;	//	預防(舊版)NS resize時版面亂掉
    280 function OnResize() {
    281 	//	回上一頁	history.go(-1),history.back()/history.forward()	this.location.replace(document.referrer)
    282 	//	Opera's document.referrer returns only null if referrer logging is disabled
    283 	//location.replace(),location.reload()
    284 	history.go(0);
    285 }
    286
    287 /*
    288 IE only!!
    289 	http://blog.livedoor.jp/dankogai/archives/50952477.html	DOM時代のdocument.write()
    290
    291 if (typeof document == 'object')
    292 	write = document.write;
    293 */
    294
    295 /*
    296 http://blog.taragana.com/index.php/archive/how-to-enable-windowstatus-in-firefox/
    297 window.status在firefox下默認是不能修改的。
    298 可以通過工具->選項->網頁特性->啟用javascript->高級->把修改狀態欄文本打上勾就好了。
    299
    300 Open about:config in browser and search for dom.disable_window_status_change. Change it to false.
    301 Additionally in Firefox v1.0, this can be changed via "Tools → Options → Web Features → Enable JavaScript / Advanced → Allow scripts to change status bar text"
    302 In Firefox v1.5, this can be changed via "Tools → Options → Content → Enable JavaScript / Advanced → Allow scripts to change status bar text"
    303 via MozillaZine; learnt the hard way.
    304 */
    305 function RollStatus(m,v,from,RollStatusL){//message,速度velocity,from where,unit length(基本上後兩者勿設定)
    306  var s='    ';//間隔以s
    307  if(!RollStatusL)RollStatusL=m.length,m+=s+m;if(!from||from>=RollStatusL+s.length)from=0;
    308  if(!m)if(window.status)RollStatus(window.status,v);else return;else if(m.slice(from)!=window.status&&m.length>L)return;
    309  var L=99,V=v||999;//L:least length
    310  while(m.length<L)m+=s+m;
    311  window.status=m.slice(++from);
    312  RollStatusS=window.setTimeout('RollStatus("'+m+'",'+V+','+from+','+RollStatusL+');',V);
    313  //RollStatusS=window.setInterval('RollStatus("'+m+'",'+V+','+from+')',V)
    314 }
    315
    316 //	↑copy from base.js
    317
    318
    319 /*	預防hack：禁止鍵盤keyboard&滑鼠mouse輸入,可以再加上一層div於最上方以防止copy
    320 	下面一行調到檔案頭
    321 var disabledKM=0;
    322 */
    323 //disableKM[generateCode.dLK]='disabledKM';
    324 function disableKM(s,m){	//	s=1:回復,s=2:使螢幕亦無法捲動(對NS無效),m:message,輸入時發出警告
    325  /*
    326  window.onerror=function(){return ture;};
    327  //	定義亦可用 function document.onmousedown(){..}
    328  document.onmousedown=document.oncontextmenu=document.onselectstart=document.ondragstart=function(e){return false;};
    329  //	印刷を禁止して
    330  window.onbeforeprint=function(){for(i=0;i<document.all.length;i++){if(document.all[i].style.visibility!="hidden"){document.all[i].style.visibility="hidden";document.all[i].id="elmid";}}};
    331  window.onafterprint=function(){for(i=0;i<document.all.length;i++){if(document.all[i].id=="elmid"){document.all[i].style.visibility="";}}};
    332  */
    333  if(!document.body)return;
    334  if(typeof s=='undefined')s=1;
    335  if(typeof disabledKM=='undefined')disabledKM=0;
    336
    337  if(!s){
    338   if(disabledKM){
    339    ondragstart=document.body.Oondragstart||null,
    340    oncontextmenu=document.body.Ooncontextmenu||null,
    341    onselectstart=document.body.Oonselectstart||null;
    342    with(window.document.body)
    343     if(disabledKM==2)style.overflow=typeof document.body.Ooverflow=='string'?Ooverflow:'auto';
    344    onmousedown=window.Oonmousedown||null,
    345    onkeydown=window.Oonkeydown||null;
    346    onmousedown=document.Oonmousedown||null,
    347    onkeydown=document.Oonkeydown||null;
    348   }
    349   disabledKM=0;
    350   return;
    351  }
    352
    353 if(disabledKM){with(document.body)	//	已lock時不執行多餘的動作與覆蓋舊資訊
    354  if(s==2)style.overflow='hidden';
    355  else if(typeof document.body.Ooverflow=='string')style.overflow=Ooverflow;
    356 }else{
    357 //	<body oncontextmenu="return false" ondragstart="return false" onselectstart="return false">
    358  with(document.body){	//	預防hack
    359   //leftMargin=topMargin=rightMargin=bottomMargin=0;	//	使body填滿視窗
    360   document.body.Ooverflow=style.overflow;
    361   if(s==2)style.overflow='hidden';	//	使螢幕亦無法捲動
    362   if(typeof onselectstart!='undefined')document.body.Oonselectstart=onselectstart;
    363   if(typeof oncontextmenu!='undefined')document.body.Ooncontextmenu=oncontextmenu;
    364   if(typeof ondragstart!='undefined')document.body.Oondragstart=ondragstart;
    365   ondragstart=oncontextmenu=onselectstart=
    366 	//new Function("return false;");
    367 	function(){return false;};
    368  }
    369  //	不要在 document 对象中设置 expando 属性，在 window 对象上设置 expando 属性。
    370  with(window){
    371   if(typeof onmousedown!='undefined')document.Oonmousedown=onmousedown;
    372   if(typeof onkeydown!='undefined')document.Oonkeydown=onkeydown;
    373  }
    374  with(window.document){
    375   //ndblclick=
    376   if(typeof onmousedown!='undefined')document.Oonmousedown=onmousedown;
    377   if(typeof onkeydown!='undefined')document.Oonkeydown=onkeydown;
    378  }
    379 }
    380  window.onmousedown=window.onkeydown=document.onmousedown=document.onkeydown=document.onContextMenu
    381 	=new Function('e',
    382 			'if(window.navigator.appName=="Microsoft Internet Explorer"&&event.button!=1||window.navigator.appName=="Netscape"&&e.which!=1){'
    383 			+(m?'alert('+dQuote(m)+');':'')+'return false;}');
    384 /*
    385 			'if(window.navigator.appName=="Microsoft Internet Explorer"\
    386 			&&event.button!=1||window.navigator.appName=="Netscape"&&e.which!=1){'+(m?'alert('+dQuote(m)+');':'')+'return false;}');
    387 */
    388
    389  //	window.captureEvents(Event.MOUSEUP|Event.MOUSEDOWN);
    390  //	window.onmousedown=function(e){if(e.which==1){window.captureEvents(Event.MOUSEMOVE);window.onmousemove=rf;}};
    391  //	window.onmouseup=function(e){if(e.which==1){window.releaseEvents(Event.MOUSEMOVE);window.onmousemove=null;}};
    392  //	Navigator 4.0x
    393  //	http://topic.csdn.net/t/20020125/13/498661.html
    394  if(!disabledKM && window.Event && window.captureEvents)
    395 	window.captureEvents(Event.MOUSEDOWN),
    396 	window.captureEvents(Event.KEYDOWN);
    397
    398  disabledKM=s;
    399 };
    400
    401
    402 CeL.net.web
    403 .
    404 /**
    405  * toggle/swap display and visibility.
    406  * display:none or visibility:hidden.
    407  * TODO: computed style
    408  * @param element	HTML element
    409  * @param	{String|Number} type	show or hidden or set the status type:
    410  * 			{Number} type: 0: hidden(→none), 1: show(→block), 2||undefined: switch, others: get status only with no change
    411  * 			{String} type: set CSS: display type: none, '', block, inline, list-item. 其他恐造成 error?
    412  * @return	display status
    413  * @since	2010/4/1 10:24:43 rewrite
    414  * @see
    415  * http://www.w3schools.com/CSS/pr_class_visibility.asp
    416  * http://www.w3schools.com/css/pr_class_display.asp
    417  * http://www.javaeye.com/topic/140784
    418  * 	通過element.style對象只能取得內聯的樣式，也就是說只能取得html標籤裡寫的屬性。
    419  * @requires	[_.get_element],[_.get_style]
    420  * @memberOf	CeL.net.web
    421  */
    422 toggle_display = function(element, type){
    423 	// showObj(div);
    424 	if (typeof element === 'string')
    425 		element = typeof _.get_element === 'function' ? _.get_element(element)
    426 			: document.getElementById(element);
    427
    428 	if (!element)
    429 		return;
    430
    431 	// Opera 7.5 意外的沒有 tagName (-_-) 而 Firefox 也可能沒有此 property
    432 	var tagName = ('' + element.tagName).toLowerCase(), style = element.style,
    433 		v_value = {'visible':1, 'hidden': 2, 'collapse': 3};
    434
    435 	if (typeof type === 'undefined' || type == 2)
    436 		type = style ?
    437 				(_.get_style ? _.get_style(element, 'display') :
    438 					//	style.display === '' 時預設為顯示
    439 					style.display) === 'none'
    440 			: element.visibility !== 'visible';
    441
    442 	if (typeof type === 'boolean')
    443 		type = type ? 1 : 0;
    444
    445 	if (!isNaN(type))
    446 		type = type == 0 ? style ? 'none' : tagName === 'tr' ? 'collapse' : 'hidden'
    447 			: type == 1 ? style ? (tagName in {'div':1, 'iframe':1}) ? 'block' : 'inline' : 'visible'
    448 			: null;
    449
    450 	//	test .innerHTML
    451
    452 	//library_namespace.debug('set display style to [' + type + ']');
    453 	if (style)
    454 		style[type in v_value? 'visibility' : 'display'] = type;
    455 	else if(type in v_value)// &&!(tagName in {'iframe':1,'input':1})
    456 		element.visibility = type;
    457 	else return;
    458
    459 	return type;
    460 };
    461 //simpleWrite('a.txt',reduceCode([f,toggle,setObjValue]));
    462 //for(var i in style)tt+=i+'='+document.getElementById("others").style[i]+"<br/>";document.write(tt);
    463
    464
    465
    466 CeL.net.web
    467 .
    468 /*	http://blog.stevenlevithan.com/archives/faster-than-innerhtml
    469 You can use the above as el = replace_HTML(el, newHtml) instead of el.innerHTML = newHtml.
    470
    471 .innerHTML=,document.createElement(→XML_node()
    472 .innerHTML='' → remove_all_child
    473
    474
    475 http://forum.moztw.org/viewtopic.php?t=17984&postdays=0&postorder=asc&start=15
    476 adoptNode() 會把現有的節點拿去用，ownerDocument 會被變更，被 adopt 的節點會從原來的 document 消失。
    477 importNode() 比較像是 cloneNode() 加上變更 ownerDocument。
    478 以前因為 Gecko 沒有太嚴格，所以可以用 Ajax 取回一個 XML 文件並直接透過 responseXML 把裡面的節點當 HTML 節點一樣的插入現有的網頁。
    479 */
    480 /**
    481  * replace HTML
    482  * @param o
    483  * @param html
    484  * @return
    485  * @memberOf	CeL.net.web
    486  */
    487 replace_HTML = function(o, html){
    488 	if (typeof o === 'string')
    489 		o = document.getElementById(o);
    490 	if (!o || typeof o !== 'object')
    491 		return;
    492 	try{
    493 		/*@cc_on	// Pure innerHTML is slightly faster in IE
    494 		 o.innerHTML=html||'';
    495 		 return o;
    496 		@*/
    497 		var n = o.cloneNode(false);
    498 		n.innerHTML = html || '';
    499 		o.parentNode.replaceChild(n, o);
    500 	}catch (e) {
    501 		library_namespace.err(e);
    502 	}
    503 	// Since we just removed the old element from the DOM, return a reference to the new element, which can be used to restore variable references.
    504 	return n;
    505 };
    506
    507 /*
    508 使用.firstChild或.lastChild須注意此node可能是text node，不能appendChild。須以.nodeType判別。
    509
    510 http://msdn2.microsoft.com/zh-tw/library/system.xml.xmlnode.removechild(VS.80).aspx
    511 繼承者注意事項 在衍生類別中覆寫 RemoveChild 時，為了要正確引發事件，您必須呼叫基底類別的 RemoveChild 方法。
    512
    513 removeAllChild[generateCode.dLK]='replace_HTML';
    514 function removeAllChild(o){
    515  //return removeNode(o,1);
    516
    517  //	http://blog.stevenlevithan.com/archives/faster-than-innerhtml
    518  if(typeof o=='string')o=document.getElementById(o);
    519  if(!o||typeof o!='object')return;
    520  o.parentNode.replaceChild(o.cloneNode(false),o);
    521  return o;
    522 }
    523
    524 http://www.webreference.com/js/column43/replace.html
    525 The replaceNode method is much more intuitive than the removeNode method. While the removeNode method just removes the specified element and makes its descendents children of their grandfather, the replaceNode method deletes the whole subtree that is rooted at the specified element, and substitutes it with a new element.
    526 node_want_to_replace.removeNode(new_node)
    527 */
    528 CeL.net.web
    529 .
    530 /**
    531  * 移除 node.
    532  * TODO:
    533  * also remove event handlers
    534  * @param o
    535  * @param tag	tag===1: only child, undefined: remove only self, others: only <tag> child
    536  * @return
    537  * @memberOf	CeL.net.web
    538  */
    539 remove_node = function remove_node(o, tag) {
    540 	var _f = remove_node, i;
    541 	if (typeof o === 'string')
    542 		o = document.getElementById(o);
    543 	if (!o || typeof o !== 'object')
    544 		return;
    545
    546 	// remove child
    547 	if (tag) {
    548 		if (typeof tag === 'string')
    549 			tag = tag.toLowerCase();
    550
    551 		//	safer: if you have any asynchronous events going. But node.hasChildNodes() will always do an evaluation.
    552 		//while(o.hasChildNodes()&&(i=o.firstChild))o.removeChild(i);
    553
    554 		// don't use for()
    555 		// http://weblogs.macromedia.com/mesh/archives/2006/01/removing_html_e.html
    556 		//	TODO: 直接用 replaceNode 就不用 recursion
    557 		i = o.childNodes.length;
    558 		while (i--)
    559 			if (tag === 1 || tag == o.childNodes[i].tagName.toLowerCase())
    560 				// _f(o.childNodes[i],tag), // TODO: 會有問題
    561 				o.removeChild(o.childNodes[i]);
    562 	}
    563
    564 	// remove self
    565 	//	測試 o.parentNode: 預防輸入的o為create出來的
    566 	return tag || !(i = o.parentNode) ? o : i.removeChild(o);
    567 };
    568
    569 CeL.net.web
    570 .
    571 remove_all_child = _.replace_HTML;
    572
    573
    574
    575
    576
    577 CeL.net.web
    578 .
    579 /**
    580  * set/get/remove attribute of a element<br/>
    581  * in IE: setAttribute does not work when used with the style attribute (or with event handlers, for that matter).
    582  * @param _e	element
    583  * @param propertyO	attributes object (array if you just want to get)
    584  * @return
    585  * @requires	split_String_to_Object
    586  * @see
    587  * setAttribute,getAttribute,removeAttribute
    588  * http://www.quirksmode.org/blog/archives/2006/04/ie_7_and_javasc.html
    589  * @since	2006/12/10 21:25 分離 separate from XML_node()
    590  * @memberOf	CeL.net.web
    591  */
    592 set_attribute = function(_e, propertyO, ns) {
    593 	if (typeof _e === 'string')
    594 		_e = typeof _.get_element === 'function' ? _.get_element(_e)
    595 				: document.getElementById(_e);
    596 		if (!_e || !propertyO/* ||_e.nodeType==3/* TEXT_NODE */)
    597 			return;
    598
    599  var _l,_m,_g,
    600 	//	Namespaces:SVG,MathML,XHTML,XLink
    601  _N=_.new_node.ns;
    602  if (typeof propertyO == 'string')
    603 	 propertyO = /[=:]/.test(propertyO) ? split_String_to_Object(propertyO)
    604 			 : propertyO.split(',');
    605 	 if (propertyO instanceof Array)
    606 		 _g = propertyO.length == 1 ? propertyO[0] : 1,
    607 				 propertyO = split_String_to_Object(propertyO.join(','));
    608
    609 		 for (_l in propertyO) {
    610 			 if (_l == 'class' && !propertyO['className'])
    611 				 propertyO[_l = 'className'] = propertyO['class'];
    612 			 if (_g || (_l in propertyO) && propertyO[_l] != null)
    613    if(_l=='className'||typeof propertyO[_l]=='function')if(_g)propertyO[_l]=_e[_l];else _e[_l]=propertyO[_l];//_l=='id'||
    614 	/*
    615 		XML 中id不能以setAttribute設定。
    616 		class不能以setAttribute設定@IE。
    617 		http://www.quirksmode.org/bugreports/archives/2005/03/setAttribute_does_not_work_in_IE_when_used_with_th.html
    618 		IE ignores the "class" setting, and Mozilla will have both a "class" and "className" attribute defined
    619 	*/
    620    else if (_e.setAttributeNS
    621 		   && (_m = _l.match(/^(.+):([^:]+)$/))) {
    622 	   _m = _m[1];
    623 	   if (_m.indexOf('://') == -1 && _N[_m.toLowerCase()])
    624 		   _m = 'http://www.w3.org/' + _N[_m.toLowerCase()];
    625 	   if (_g)
    626 		   propertyO[_l] = _e.getAttributeNS(_m, _l);
    627 	   else
    628 		   _e.setAttributeNS(_m, _l, propertyO[_l]);// try{_e.setAttributeNS(_m,_l,propertyO[_l]);}catch(e){alert('set_attribute:
    629 	   // Error!');}
    630    } else if (_g)
    631 	   propertyO[_l] = _e.getAttribute(_l);
    632    else
    633 	   _e.setAttribute(_l, propertyO[_l]);// _e.setAttributeNS?_e.setAttributeNS(null,_l,propertyO[_l]):_e.setAttribute(_l,propertyO[_l]);
    634  }
    635
    636  return typeof _g == 'string' ? propertyO[_g] : propertyO;
    637 };
    638
    639
    640 CeL.net.web
    641 .
    642 /**
    643  * append children node to specified element
    644  * @param node	node / node id
    645  * @param child_list	children node array
    646  * @return
    647  * @since	2007/1/20 14:12
    648  * @memberOf	CeL.net.web
    649  */
    650 add_node = function add_node(node, child_list) {
    651 	var _s = add_node;
    652 	if (typeof node === 'string')
    653 		node = typeof _.get_element === 'function' ? _.get_element(node)
    654 				: document.getElementById(node);
    655
    656 	if (node && arguments.length > 2) {
    657 		for ( var _j = 1, l = arguments.length; _j < l; _j++)
    658 			_s(node, arguments[_j]);
    659 		return;
    660 	}
    661
    662 	if (!node || !child_list
    663 			// || node.nodeType == 3/* TEXT_NODE */
    664 	)
    665 		return;
    666
    667 	//	預防 RegExp 等，需要 toString()
    668 	if (child_list instanceof RegExp)
    669 		child_list = '';
    670
    671 	if (typeof child_list === 'object') {
    672 		if (child_list)
    673 			if (child_list instanceof Array
    674 					// && child_list.length
    675 			)
    676 				for ( var _j = 0, l = child_list.length; _j < l; _j++)
    677 					_s(node, child_list[_j]);
    678 			else
    679 				node.appendChild(child_list);
    680 		return;
    681 	}
    682 	if (typeof child_list === 'number' && !isNaN(child_list))
    683 		// child_list=child_list.toString();
    684 		child_list += '';
    685 	if (typeof child_list === 'string') {
    686 		var tag_name = node.tagName.toLowerCase();
    687 		if (tag_name === 'textarea' || tag_name === 'select' || tag_name === 'option'
    688 			|| (tag_name === 'input' && node.type === 'text'))
    689 			node.value = child_list;
    690 		else if (tag_name === 'option') {
    691 			if (!node.value)
    692 				node.value = child_list;
    693 			node.innerHTML = child_list;
    694 		} else if (child_list.indexOf('<') != -1)
    695 			//	may cause error: -2146827687 未知的執行階段錯誤 e.g., XML_node('a',0,0,[XML_node('a'),'<br/>']);
    696 			//try{
    697 				node.innerHTML += child_list;
    698 			//}catch(e){node.appendChild(XML_node('span',0,0,child_list));}
    699
    700 		else
    701 			//try{
    702 				node.appendChild(document.createTextNode(child_list));
    703 			//}catch(e){alert(e.description);}
    704
    705 		// else alert('add_node: Error insert contents:\n['+child_list+']');
    706 	}
    707 };
    708
    709
    710 /*
    711
    712 var alias={
    713 	//	'child' || 'c' || '$' || '0' || ..
    714 	$:'childNode',
    715 	//	class: 'className' || 'c' ..
    716 	c:'className'
    717 	s:'style'
    718 };
    719
    720 輸入 ( [{tag1:{attb:attb_val,child:[inner objects]}}, {tag2:{}}, 'br'], insertBeforeO)
    721 e.g.,
    722 ([
    723 	{
    724 		p:[span:'>>test<<'],
    725 		id:'a',
    726 		c:'cls',
    727 		s:{color:'#123'}
    728 	},
    729 	//	width:12 === width:'12px'
    730 	{
    731 		span:['<<test2>>','text'],
    732 		s:{color:'',width:12}
    733 	},
    734 	'<<test3>>',
    735 	{'hr':0},
    736 	{'br':0},
    737 	{
    738 		$:tag_name,
    739 		tag_name:[]
    740 	},
    741 	{
    742 		tag_ns:0,
    743 		ns:'http://~'
    744 	}
    745 ], insertSetting)
    746
    747 insertSetting:
    748 	(null)		just create & return the node
    749 	以下：===0 則設成 document.body
    750 	parent/id		appendChild
    751 	[refO,0-4]	0:appendChild (add as lastChild), 1: add as firstChild, 2: add as nextSibling, 3: add as priviusSibling, 4: add as parent
    752
    753
    754 */
    755 //[{tag1:{attb:attb_val,child:[inner objects]}}, {tag2:{}}, 'br'];
    756
    757
    758
    759 CeL.net.web
    760 .
    761 /**
    762  * 創建新的 DOM 節點(node)。
    763  * createNode() 的功能補充加強版。
    764  * TODO: 分割功能(set_attrib, add_child, ..), 簡化
    765  * @param	{Object|Array} nodes	node structure
    766  * @param	{String|Array|HTMLElement} [layer]	where to layer this node. e.g., parent node
    767  * @return	{HTMLElement}	new node created
    768  * @since	2010/6/21 13:45:02
    769  */
    770 new_node = function(nodes, layer) {
    771 	var _s = _.new_node, node, for_each,
    772 	// parent: parent node of layer or layer.firstChild
    773 	parent,
    774 	children,
    775 	handle = _s.handle;
    776
    777 	if (!is_DOM('document')
    778 		|| !document.createElement
    779 		//&& !document.createElementNS
    780 		) {
    781 		library_namespace.warn('new_node: DOM error? Cannot create node [' + nodes + '].');
    782 		return;
    783 	}
    784
    785 	if (typeof nodes === 'number')
    786 		//.toString();
    787 		nodes += '';
    788
    789 	if (library_namespace.is_Object(nodes)) {
    790 		var tag = nodes.$, n = 'className', ns, s, ignore = {
    791 			// tag
    792 			$ : null,
    793 			// attrib
    794 			A : null
    795 /*
    796 			// namespace
    797 			NS : null,
    798 			// class
    799 			C : null,
    800 			// style
    801 			S : null
    802 */
    803 		};
    804
    805 		if (typeof tag === 'undefined')
    806 			for (node in nodes)
    807 				if(!(node in ignore)){
    808 					tag = node;
    809 					break;
    810 				}
    811 		else if (tag === 0) {
    812 			//	0: just set attributes
    813 			if (!_.is_element_node(layer)) {
    814 				library_namespace.warn('new_node: There is no tag and the layer is NOT a HTML Element!');
    815 				return;
    816 			}
    817 			tag = layer;
    818 		}else if (typeof tag !== 'undefined')
    819 			node = tag;
    820
    821 		//	set/create node
    822 		if (_.is_HTML_element(tag))
    823 			node = tag;
    824
    825 		else if (typeof tag !== 'string'){
    826 			library_namespace.err('new_node: Error create tag: ['+(typeof tag)+'][' + tag + ']');
    827 			return;
    828
    829 		} else {
    830 			if ('NS' in nodes)
    831 				ignore.NS = null,
    832 				ns = nodes.NS;
    833 			else if (s = tag.match(/^(.+):([^:]+)$/))
    834 				tag = s[2], ns = s[1];
    835
    836 			try {
    837 				if (ns && document.createElementNS) {
    838 					if (ns in (s = _s.ns))
    839 						ns = 'http://www.w3.org/' + s[ns];
    840 					node = document.createElementNS(ns, tag);
    841 				} else
    842 					node = tag ? document.createElement(ns ? ns + ':' + tag : tag)
    843 							//: document.createTextNode();
    844 							//	由後面判定。
    845 							: nodes[tag];
    846 			} catch (_e) {
    847 				library_namespace.err('new_node: Error create tag: [' + tag + ']');
    848 				node = null;
    849 				return;
    850 			}
    851 		}
    852
    853 		if (_.is_element_node(node)) {
    854 			s = node.setAttributeNS ? function(n, v) {
    855 				if (library_namespace.is_Function(v)) {
    856 					node[n] = v;
    857 					//	TODO: _.add_listener();
    858 					return;
    859 				}
    860 				var _n = n.match(/^(.+):([^:]+)$/);
    861 				if (_n)
    862 					n = _n[2], _n = _n[1];
    863 				if (_n)
    864 					node.setAttributeNS(
    865 							_n in _s.ns ? 'http://www.w3.org/'
    866 									+ _s.ns[_n] : ns, n, v);
    867 				else
    868 					node.setAttribute(n, v);
    869 			} : function(n, v) {
    870 				if (library_namespace.is_Function(v))
    871 					node[n] = v;
    872 				else
    873 					node.setAttribute(n, v);
    874 			};
    875
    876 			//	對常用的特別處理
    877 			// class name
    878 			/*
    879 				XML 中id不能以setAttribute設定。
    880 				class不能以setAttribute設定@IE。
    881 				http://www.quirksmode.org/bugreports/archives/2005/03/setAttribute_does_not_work_in_IE_when_used_with_th.html
    882 				IE ignores the "class" setting, and Mozilla will have both a "class" and "className" attribute defined
    883 			 */
    884 			if ((n in nodes) || ((n = 'class') in nodes) || ((n = 'C') in nodes))
    885 				ignore[n] = null,
    886 				node.className = nodes[n];
    887
    888 			// IE 需要先 appendChild 才能操作 style，moz不用..??
    889 			//	http://www.peterbe.com/plog/setAttribute-style-IE
    890 			//	或需要將 font-size -> fontSize 之類?
    891 			// IE6 (no firefox or IE7~) 可設定:
    892 			//	oNewDiv.style.setAttribute('border', '1px solid #000');
    893 			//	oNewDiv.style.setAttribute('backgroundColor', '#fff');
    894 			if (((n = 'style') in nodes) || ((n = 'S') in nodes)) {
    895 				ignore[n] = null;
    896 				n = nodes[n];
    897 				var i, style = node.style;
    898 				if (typeof n === 'string')
    899 					style.cssText = n;
    900 				else if (library_namespace.is_Object(n))
    901 					for (i in n)
    902 						// is_IE?"styleFloat":"cssFloat"
    903 						style[i === 'float' ? 'cssFloat' in style ? 'cssFloat' : 'styleFloat' : i] = n[i];
    904 				else
    905 					library_namespace.warn('new_node: Error set style: [' + styleO + ']');
    906 			}
    907
    908 			// children nodes
    909 			ignore[tag] = null;
    910 			children = nodes[tag];
    911
    912 			//	自動作 list 的轉換
    913 			if (tag in {
    914 						ol : 1,
    915 						ul : 1
    916 					} && library_namespace.is_Array(children))
    917 			{
    918 				var i = 0, o = [], l = children.length, t, c, change = false;
    919 				for (; i < l; i++)
    920 					if (c = children[i]) {
    921 						t = typeof c === 'string'
    922 							|| typeof c === 'number';
    923 						if (!t && library_namespace.is_Object(t)) {
    924 							t = c.$;
    925 							if (!t)
    926 								for (t in c)
    927 									break;
    928 							t = t.toLowerCase() !== 'li';
    929 						}
    930
    931 						if(t)
    932 							change = true;
    933 						o.push(t ? {
    934 							li : c
    935 						} : c);
    936 					}
    937
    938 				// 盡量別動到原來的
    939 				if (change)
    940 					children = o;
    941
    942 			}else if(tag === 'select' && library_namespace.is_Object(children)){
    943 				var i;
    944 				for (i in children)
    945 					break;
    946
    947 				if (i !== 'option') {
    948 					var o = [];
    949 					for (i in children)
    950 						o.push( {
    951 							option : children[i],
    952 							value : i
    953 						});
    954
    955 					// 盡量別動到原來的
    956 					children = o;
    957 				}
    958 			}
    959
    960
    961 			// attributes
    962 			if('A' in nodes){
    963 				var a = nodes.A;
    964 				if (typeof a === 'string')
    965 					a = split_String_to_Object(a);
    966
    967 				for (n in a)
    968 					s(n, a[n]);
    969 			}
    970
    971 			for (n in nodes)
    972 				if (!(n in ignore)){
    973 					//library_namespace.debug('new_node: set attribute ['+n+'] = ['+nodes[n]+']'),
    974 					s(n, nodes[n]);
    975 					//library_namespace.debug('new_node: get attribute ['+n+'] = ['+node.getAttribute(n)+']');
    976 				}
    977 		} else if(tag && !_.is_HTML_element(node))
    978 			show_node(node),
    979 			library_namespace.warn('new_node: node is not a HTML Element!');
    980
    981 	} else if (typeof nodes !== 'string' && !library_namespace.is_Array(nodes)
    982 			&& isNaN(nodes.nodeType)) {
    983 		//	for Safari: library_namespace.is_Array(nodes)
    984 		if(nodes)
    985 			library_namespace.warn('new_node: Unknown nodes [' + nodes + ']');
    986
    987 		node = null;
    988 		return;
    989 	} else
    990 		node = nodes;
    991
    992
    993 	// layer 處理: 插入document中。
    994 	if (typeof layer !== 'undefined' && layer !== null) {
    995 		// 正規化 layer
    996 		// for_each: type→deal function
    997 		if (library_namespace.is_Function(layer))
    998 			for_each = layer;
    999 		else {
    1000 			if (library_namespace.is_Array(layer))
    1001 				for_each = layer[1], layer = layer[0];
    1002
    1003 			if (layer === 0)
    1004 				layer = document.body;
    1005 			else if (typeof layer === 'string')
    1006 				layer = _.get_element(layer);
    1007 			//	[object HTMLLIElement]
    1008 			if (!_.is_element_node(layer))
    1009 				//library_namespace.warn('is_element_node: ' + _.is_element_node),
    1010 				show_node(layer),
    1011 				library_namespace.warn('new_node: layer is not a HTML Element!');
    1012
    1013 			if (for_each == 1 && (parent = layer.firstChild))
    1014 				// add as firstChild of layer
    1015 				for_each = handle[1];
    1016
    1017 			else if (for_each > 1 && for_each < 5) {
    1018 				if (parent = layer.parentNode) {
    1019 					if (for_each == 2)
    1020 						// add as nextSibling of layer
    1021 						for_each = handle[2];
    1022 					else if (for_each == 3)
    1023 						// add as priviusSibling of layer
    1024 						for_each = handle[3];
    1025 					else
    1026 						// if (f == 4)
    1027 						// add as parent of layer
    1028 						for_each = handle[4];
    1029 				} else
    1030 					// 輸入的 layer 為create出來的?
    1031 					library_namespace.warn('new_node: No parent node found!');
    1032
    1033 			} else if (_.is_element_node(layer)){
    1034 				//	若輸入 [id, null] 則先清空，相當於 replace
    1035 				if (for_each === null)
    1036 					layer = _.remove_all_child(layer);
    1037 				// appendChild (add as lastChild)
    1038 				for_each = handle[0];
    1039 			}
    1040 		}
    1041
    1042 	}
    1043
    1044 	if (!library_namespace.is_Function(for_each))
    1045 		for_each = false;
    1046
    1047 	if (library_namespace.is_Array(node)) {
    1048 		node = [];
    1049 		//	不宜個個重新呼叫是為了效能
    1050 		for ( var i = 0, l = nodes.length, n, _l = layer, _p = parent; i < l; i++) {
    1051 			node.push(n = _s(nodes[i], for_each && function(n) {
    1052 					for_each(n, _l, _p);
    1053 				} || null));
    1054 			/*
    1055 			node.push(n = _s(nodes[i], for_each));
    1056 			if (for_each)
    1057 				try {
    1058 					for_each(n, layer, parent);
    1059 				} catch (e) {
    1060 					library_namespace.err(e);
    1061 					library_namespace.err('new_node: handle function execution error for node Array['+i+'/'+l+']!<br/>' + for_each);
    1062 				}
    1063 			*/
    1064 		}
    1065
    1066 	} else{
    1067 		if (typeof node === 'string' && for_each !== handle[0])
    1068 			node = document.createTextNode(nodes);
    1069
    1070 		if (for_each)
    1071 			try {
    1072 				for_each(node, layer, parent);
    1073 			} catch (e) {
    1074 				library_namespace.err(e);
    1075 				library_namespace.err('new_node: handle function execution error!<br/>' + for_each);
    1076 			}
    1077
    1078 		//	設定 childNodes
    1079 		//	先插入document而後設定childNodes是因為IE有Cross-Page Leaks.
    1080 		//	http://www.blogjava.net/tim-wu/archive/2006/05/29/48729.html
    1081 		//	http://www-128.ibm.com/developerworks/tw/library/x-matters41.html
    1082 		//	Try to use createDocumentFragment()
    1083 		//	http://wiki.forum.nokia.com/index.php/JavaScript_Performance_Best_Practices
    1084 		if (children !== null && typeof children !== 'undefined')
    1085 			_s(children, node);
    1086 	}
    1087
    1088
    1089 	//	This helps to fix the memory leak issue.
    1090 	//	http://www.hedgerwow.com/360/dhtml/ie6_memory_leak_fix/
    1091 	//	http://jacky.seezone.net/2008/09/05/2114/
    1092 	try {
    1093 		return typeof node === 'string' ? document.createTextNode(node) : node;
    1094 	} finally {
    1095 		node = null;
    1096 	}
    1097 };
    1098
    1099 _.new_node.handle = [
    1100 	function(n, l) {
    1101 		var is_e = _.is_element_node(l), t = is_e ? l.tagName.toLowerCase() : null;
    1102 		if (typeof n === 'number')
    1103 			n += '';
    1104
    1105 		if (t in {
    1106 				//	no <select>!
    1107 				textarea : 1,
    1108 				input : 1,
    1109 				text : 1
    1110 			})
    1111 			l.value = (l.value || '') + (is_e ? n.innerHTML : n);
    1112
    1113 		else {
    1114 			if (typeof n === 'string' && n.indexOf('<') === -1){
    1115 				if (t === 'option' && !l.value)
    1116 					l.value = n;
    1117 				n = document.createTextNode(n);
    1118 			}
    1119
    1120 			if (typeof n === 'string')
    1121 				// this may throw error: -2146827687 未知的執行階段錯誤
    1122 				l.innerHTML += n;
    1123 			else{
    1124 				t = l.innerHTML;
    1125 				l.appendChild(n);
    1126 				if (t === l.innerHTML)
    1127 					;//library_namespace.warn('new_node.handle[0]: The addition does not change the layer!');
    1128 			}
    1129 		}
    1130 		n = null;
    1131 	}, function(n, l, p) {
    1132 		l.insertBefore(n, p);
    1133 	}, function(n, l, p) {
    1134 		//	將 node 插入作為 layer 之 nextSibling.
    1135 		//	p: parent node of layer
    1136 		//	TODO: 輸入多 node 時 cache next
    1137 		var next = l.nextSibling;
    1138 		if (next)
    1139 			p.insertBefore(n, next);
    1140 		else
    1141 			p.appendChild(n);
    1142 	}, function(n, l, p) {
    1143 		p.insertBefore(n, l);
    1144 	}, function(n, l, p) {
    1145 		n.appendChild(p.replaceChild(n, l));
    1146 	}
    1147 ];
    1148
    1149 // Namespaces: SVG,MathML,XHTML,XLink,..
    1150 _.new_node.ns = {
    1151 	svg : '2000/svg',
    1152 	mathml : '1998/Math/MathML',
    1153 	xhtml : '1999/xhtml',
    1154 	xlink : '1999/xlink',
    1155 	// 亦可用'1999/xhtml'
    1156 	html : 'TR/REC-html40',
    1157 	html4:'TR/REC-html40',
    1158 	html5:'TR/html5'
    1159 };
    1160
    1161
    1162
    1163 /*
    1164 XML_node('div','id:idName');	doesn't insert, just return the object
    1165 XML_node('div',{'id':null});	won't set id
    1166 XML_node('div',{'id':undefined});	won't set id
    1167
    1168 XML_node('div','id:idName',1);	insert at last of document
    1169 XML_node('div',{id:'idName'},refO);	insert before(prepend) obj refO: refO.parentNode.insertBefore(_newNode_,refO)
    1170 XML_node('div','id:idName',document.body);	insert at top of document
    1171 XML_node('div','id:idName',[parent]);	append as a child of obj parent: parent.appendChild(_newNode_)
    1172 XML_node('div','id:idName',[parent,0]);	append as a child of obj parent: parent.appendChild(_newNode_)
    1173 XML_node('div','id:idName',[parent,refNode]);	insert before refNode: parent.insertBefore(_newNode_,refNode)
    1174 XML_node('div','id:idName',[parent,refNode,1]);	insert after refNode: UNDO
    1175 XML_node('div','id:idName',[parent,1]);	insert as the first child of parent: parent.insertBefore(_newNode_,parent.firstChild)
    1176 XML_node('div','id:idName',[0,refNode]);	insert before refNode: document.body.insertBefore(_newNode_,refNode)
    1177 XML_node('div','id:idName',[0]);	append after all: document.body.appendChild(_newNode_,refNode)
    1178
    1179 XML_node('div','id:idName',0,'asas');	insert 'asas' as innerText
    1180 	new_node({div:'asas',id:'idName'},0);
    1181 XML_node('div','id:idName',0,'<a>sas</a>');	insert 'asas' as innerHTML
    1182 	new_node({div:{a:'sas'},id:'idName'},0);
    1183 XML_node('div','id:idName',0,obj);	insert obj as childNode
    1184 	new_node({div:obj,id:'idName'},0);
    1185 XML_node('div','id:idName',0,[o1,o2]);	insert o1,o2 as childNodes
    1186 	new_node({div:[o1,o2],id:'idName'},0);
    1187
    1188
    1189 有用到新建 HTML element 的函數執行完畢應該將所有變數，尤其是 object 重設；
    1190 這是因為 HTML element 的存在會使函數裡的 object 變數不能被釋放。
    1191 設成 null 是因為 null 不能設定 method，而 string, number 可以。
    1192
    1193 http://www.blogjava.net/tim-wu/archive/2006/05/29/48729.html
    1194 為預防IE Cross-Page Leaks，
    1195 use:
    1196 XML_node(++, ++, [XML_node(.., .., [meta])]);
    1197 instead of:
    1198 XML_node(.., .., [meta], XML_node(++, ++));
    1199 P.S. 2007/11/11 似乎已修正？
    1200
    1201
    1202 buggy 瑕疵:
    1203 XML_node(0,0,[parent],'innerText');	return a textNode append as a child of obj parent
    1204
    1205 TODO:
    1206 XML 中 insertBefore(),appendChild()似乎無反應？	http://developer.mozilla.org/en/docs/SVG:Namespaces_Crash_Course
    1207 insertAfter
    1208
    1209 */
    1210 CeL.net.web
    1211 .
    1212 /**
    1213  * create new HTML/XML <a href="https://developer.mozilla.org/en/DOM/node">node</a>(<a href="https://developer.mozilla.org/en/DOM/element">element</a>)
    1214  * @param tag	tag name
    1215  * @param propertyO	attributes object
    1216  * @param insertBeforeO	object that we wnat to insert before it
    1217  * @param innerObj	inner object(s)
    1218  * @param styleO	style object
    1219  * @return	node object created
    1220  * @requires	set_attribute,add_node
    1221  * @since	2006/9/6 20:29,11/12 22:13
    1222  * @memberOf	CeL.net.web
    1223  */
    1224 XML_node = function(tag, propertyO, insertBeforeO, innerObj, styleO) {
    1225 	//	XML 中沒有document.body！
    1226 	//if(typeof document.body=='undefined')document.body=document.getElementsByTagName('body')[0];
    1227
    1228 	if (typeof document !== 'object'
    1229 			|| (!document.createElement && !document.createElementNS)
    1230 			|| !document.body) {
    1231 		library_namespace.warn('XML_node: Cannot create tag [' + tag + '].');
    1232 		return;
    1233 	}
    1234
    1235 	var _NS,
    1236 	//	Namespaces: SVG,MathML,XHTML,XLink
    1237 	_i = _.new_node.ns,
    1238 	//	use Namespaces or not
    1239 	//	buggy now.
    1240 	_DOM2 = document.createElementNS ? 1 : 0,
    1241 	//	Namespaces base
    1242 	_e = 'http://www.w3.org/';
    1243
    1244 	/*
    1245 	//	依styleO指定 Namespace
    1246 	if (typeof styleO === 'string') {
    1247 		if (styleO.indexOf('://') != -1)
    1248 			_NS = styleO, styleO = 0;
    1249 		else if (_i[styleO])
    1250 			_NS = _e + _i[styleO], styleO = 0;
    1251 	} else
    1252 		// buggy now.
    1253 		_DOM2 = 0;//_NS = styleO === null ? null : _e + _i['XHTML'];//undefined==null
    1254 	*/
    1255
    1256 	//	指定 Namespace
    1257 	if (tag)
    1258 		if (_NS = tag.match(/^(.+):([^:]+)$/)) {
    1259 			tag = _NS[2];
    1260 			_NS = _NS[1];
    1261 			if (_NS.indexOf('://') === -1 && (_i = _i[_NS.toLowerCase()]))
    1262 				_NS = _e + _i;
    1263 			// library_namespace.warn('XML_node: Add ['+tag+'] of\n'+_NS);
    1264 		}
    1265
    1266 	/*
    1267 		for MathML:
    1268 			IE: document.createElement('m:'+tag)
    1269 				(surely 'mml:', but 'm:' is default of MathPlayer, so now <html> works without the xmlns attribute)
    1270 			NS: document.createElementNS('http://www.w3.org/1998/Math/MathML', tag)
    1271 	*/
    1272 	try {
    1273 		_e = tag ? _DOM2 && _NS ? document.createElementNS(_NS, tag)
    1274 				: document.createElement(tag/* .replace(/[<>\/]/g,'') */)
    1275 				: document.createTextNode(innerObj || '');
    1276 	} catch (_e) {
    1277 		library_namespace.warn('XML_node: Error create tag:\n' + tag/* + '\n' + _e.description */);
    1278 		return;
    1279 	}
    1280 	if (tag)
    1281 		_.set_attribute(_e, propertyO);
    1282
    1283 	//	IE需要先appendChild才能操作style，moz不用..??
    1284 	if (tag && styleO && _e.style)
    1285 		if (typeof styleO === 'string')
    1286 			_e.style.cssText = styleO;
    1287 		else if (typeof styleO === 'object')
    1288 			for (_i in styleO)
    1289 				//	is_IE?"styleFloat":"cssFloat"
    1290 				_e.style[_i === 'float' ? 'cssFloat' in _e.style ? 'cssFloat' : 'styleFloat' : _i] = styleO[_i];
    1291 	//else library_namespace.warn('XML_node: Error set style:\n[' + styleO + ']');
    1292
    1293
    1294 	//	插入document中。先插入document而後設定childNodes是因為IE有Cross-Page Leaks
    1295 	//	http://www.blogjava.net/tim-wu/archive/2006/05/29/48729.html
    1296 	//	http://www-128.ibm.com/developerworks/tw/library/x-matters41.html
    1297 	if (insertBeforeO) {
    1298 		var rO = undefined/* [][1] */, tO = function(_o) {
    1299 			return typeof _o == 'string' && (_i = document.getElementById(_o)) ? _i
    1300 					: _o;
    1301 		}, iO = tO(insertBeforeO);
    1302 		// Opera9 need .constructor===Array
    1303 		if (library_namespace.is_Array(iO) && iO.length)
    1304 			// 在disable CSS時可能會 Warning: reference to undefined property iO[1]
    1305 			// rO: referrer object,
    1306 			// 以此決定以appendChild()或insertBefore()的形式插入
    1307 			rO = iO.length > 1 && tO(iO[1]) || 0, iO = tO(iO[0]);
    1308
    1309 		//if(typeof iO !== 'object' && (iO = document.body, typeof rO === 'undefined')) rO = 0;
    1310 		if (typeof iO !== 'object') {
    1311 			iO = document.body;
    1312 			if (typeof rO === 'undefined')
    1313 				rO = 0;
    1314 		}
    1315
    1316 		if (typeof rO === 'undefined')
    1317 			iO = (rO = iO).parentNode;
    1318 		if (iO)
    1319 			// 預防輸入的rO為create出來的
    1320 			if (rO)
    1321 				try {
    1322 					//	.firstChild == .childNodes[0]
    1323 					iO.insertBefore(_e, rO === 1 ? iO.firstChild : rO);
    1324 				} catch (e) {
    1325 					library_namespace.warn('XML_node: ' + e.message + '\niO:'
    1326 							+ iO + '\nrO:' + rO);
    1327 				}
    1328 				else
    1329 					//document.body.insertBefore(_e, iO);
    1330 					iO.appendChild(_e);
    1331 	}
    1332
    1333
    1334 	//	設定 childNodes
    1335 	if (tag)
    1336 		_.add_node(_e, innerObj);
    1337 	/*
    1338 	 if (tag && innerObj)
    1339 		(_i = function(_o) {
    1340 			if (typeof _o == 'object') {
    1341 				if (_o)
    1342 					if (_o instanceof Array)// &&_o.length
    1343 						for ( var _j = 0; _j < _o.length; _j++)
    1344 							_i(_o[_j]);
    1345 					else
    1346 						_e.appendChild(_o);
    1347 				return;
    1348 			}
    1349 			if (typeof _o == 'number' && !isNaN(_o))
    1350 				// _o+='';
    1351 				_o = _o.toString();
    1352 			if (typeof _o == 'string')
    1353 				if (_o.indexOf('<') != -1)
    1354 					_e.innerHTML += _o;
    1355 				else
    1356 					_e.appendChild(document.createTextNode(_o));
    1357 			//else library_namespace.warn('XML_node: Error insert contents:\n[' + _o + ']');
    1358 		})(innerObj);
    1359 	*/
    1360
    1361 	//	this helps to fix the memory leak issue
    1362 	//	http://www.hedgerwow.com/360/dhtml/ie6_memory_leak_fix/
    1363 	//	http://jacky.seezone.net/2008/09/05/2114/
    1364 	try {
    1365 		return _e;
    1366 	} finally {
    1367 		_e = null;
    1368 	}
    1369 };
    1370
    1371
    1372
    1373
    1374
    1375 CeL.net.web
    1376 .
    1377 /**
    1378  * 設定 HTML element 的 text。
    1379  * 對付IE與Moz不同的text取得方法。現階段不應用innerText，應該用此函數來取得或設定內部text。
    1380  * TODO: DOM: 用.nodeValue
    1381  * @param element	HTML element
    1382  * @param {String} text	the text to be set
    1383  * @return
    1384  * @see
    1385  * http://www.klstudio.com/post/94.html
    1386  * @memberOf	CeL.net.web
    1387  */
    1388 set_text=function (element, text) {
    1389 	if (!element || typeof window !== 'object' || typeof window.document !== 'object'
    1390 			|| typeof o === 'string' && !(element = _.get_element(element)))
    1391 		return;
    1392
    1393 	var text_p=_.set_text.p;
    1394 	if (typeof text_p !== 'string' || !text_p)
    1395 		_.set_text.p = text_p =
    1396 				typeof document.body.textContent === 'string' ? 'textContent'
    1397 				: typeof document.body.innerText === 'string' ? 'innerText'
    1398 				: 'innerHTML';
    1399
    1400 	var p = typeof element.value === 'string' ? 'value' : text_p;
    1401 	if (typeof text !== 'undefined')
    1402 		element[p] = text;
    1403
    1404 	//	http://www-128.ibm.com/developerworks/tw/library/x-matters41.html
    1405 	if (element.nodeType === 3 || element.nodeType === 4)
    1406 		return element.data;
    1407
    1408 	/*
    1409 	var i = 0, t = [];
    1410 	for (; i < element.childNodes.length; i++)
    1411 		t.push(set_text(element.childNodes[i]));
    1412 	return t.join('');
    1413 	*/
    1414
    1415 	return element[p];
    1416 };
    1417
    1418
    1419 /*	用在top的index.htm中，當setTopP()後指定特殊頁面	2005/1/26 21:46
    1420 set:	window.onload=setFrame;
    1421 	var setFrameTarget='MAIN',setFrameTargetSet={'menu.htm':'MENU','all.htm':'MENU','midi.htm':'MIDI'};
    1422
    1423 ** xhtml1-frameset.dtd中<script>只能放在<head>
    1424 */
    1425 var setFrameTarget,setFrameTargetSet;	//	預設target, 轉頁的target lists
    1426 //setFrame[generateCode.dLK]='setFrameTarget,setFrameTargetSet';
    1427 function setFrame(){
    1428  //alert(window.name);
    1429  //for(var i=0;i<window.frames.length;i++)alert(window.frames[i].name);
    1430  //alert(top.location.href+'\n'+location.href+'\n'+(top.location.href!=location.href)+'\n'+(window.top!=window.window));
    1431  if(window.top!=window.window){//top.location.href!=location.href
    1432   window.top.location.replace(location.href);
    1433   return;
    1434  }
    1435  var l,f;
    1436  try{l=location.hash.slice(1);}catch(e){return;}	//	IE在about:blank的情況下呼叫網頁，網頁完全載入前location無法呼叫。例如從FireFox拉進IE時使用location.*有可能'沒有使用權限'，reload即可。
    1437  if(typeof setFrameTargetSet!='object')setFrameTargetSet={};
    1438  if(l)try{l=decodeURIComponent(l);}catch(e){l=unescape(l);}
    1439  //location.hash='';	//	這一項會reload
    1440  if( l && (f=(f=l.match(/([^\/]+)$/)?RegExp.$1:l)&&(f=f.match(/^([^?#]+)/)?RegExp.$1:f)&&(l in setFrameTargetSet)?setFrameTargetSet[f]:setFrameTarget) && f!=window.name && window.frames[f] && window.frames[f].location.href!=l )
    1441   //alert(l+'\n==>\n'+f),
    1442   window.open(l,f);//if((l=window.open(l,f).top).focus(),alert(l!=self.top),l!=self.top)self.top.close();//alert(l+'\n'+f),	//	moz需要等到frame load之後才能得到window.frames[f].location.href==l的結果，所以可以考慮作setTimeout的延遲。但是假如真的不是預設的page，這樣會造成多load一遍。
    1443  //setTimeout('alert(window.frames["'+f+'"].location.href);',900);
    1444 }
    1445 /*
    1446 	set window.top page to certain location
    1447 	setTopP(location,search)
    1448 	search===setTopP_doTest: do a test, return window.top不為指定頁?1:0
    1449 */
    1450 var setTopPDTopP,setTopP_doTest=.234372464;	//	default top page(file) path
    1451 //setTopP[generateCode.dLK]='dBasePath,getFN,setTopPDTopP,setTopP_doTest';
    1452 function setTopP(l, s) {
    1453 	if (!setTopPDTopP)
    1454 		return 2;
    1455 	if (!l)
    1456 		l = dBasePath(setTopPDTopP) + getFN(setTopPDTopP);
    1457 	// alert(l);
    1458 	if (typeof s == 'undefined')
    1459 		try {
    1460 			//	IE在about:blank的情況下呼叫網頁，網頁完全載入前location無法呼叫。
    1461 			//	例如從FireFox拉進IE時使用location.*有可能'沒有使用權限'，reload即可。
    1462 			s = window/* self */.location.search;
    1463 		} catch (e) {
    1464 			return;
    1465 		}
    1466 	var t, r = /[\/\\]$/i, ri = /[\/\\](index.s?html?)?$/i;
    1467 	try {
    1468 		//	top.location.pathname在遇到local file時可能出問題。
    1469 		//	若不同domain時top.location也不能取用，應改成window.top!=window.window
    1470 		t = window.top.location.href.replace(/[?#](.*)$/, '');
    1471 	} catch (e) {
    1472 		t = '';
    1473 	}
    1474 	// alert(t+'\n'+l+'\n'+(t!=l));
    1475 	if (t != l && !(r.test(l) && ri.test(t)) && !(ri.test(l) && r.test(t)))
    1476 		if (s === setTopP_doTest)
    1477 			return 1;
    1478 		// replace() 方法可以開啟檔案，但是卻不會更動瀏覽器的瀏覽歷程（history）內容.
    1479 		// IE6若location.href長度超過2KB，光是'location.search'這項敘述就會導致異常.
    1480 		else
    1481 			// 預設page：xx/和xx/index.htm相同
    1482 			window.top.location.replace(l + s + '#'
    1483 					+ encodeURIComponent(location.href));
    1484 };
    1485
    1486
    1487 //	設在body.onload，改變IE中所有<a>在滑鼠移入移出時的 window.status
    1488 var setAstatusOS;	//	old status,也可設定event.srcElement.ostatus等等，但考慮到將造成記憶體浪費…
    1489 //setAstatus[generateCode.dLK]='setAstatusOver,setAstatusOut';
    1490 function setAstatus() {
    1491 	if (typeof window !== 'object' || typeof window.event === 'undefined' || typeof window.status === 'undefined'
    1492 			//||typeof event.srcElement=='undefined'
    1493 		)
    1494 		// 預防版本過低(4以下)的瀏覽器出現錯誤：event至IE4才出現
    1495 		return;
    1496 	var i, o, l;
    1497 	if (o = document.getElementsByTagName('a'))
    1498 		for (i = 0, l = o.length; i < l; i++)
    1499 			if (o[i].title && !o[i].onmouseover && !o[i].onmouseout)
    1500 				o[i].onmouseover = setAstatusOver,
    1501 				o[i].onmouseout = setAstatusOut;
    1502 };
    1503 //setAstatusOver[generateCode.dLK]=setAstatusOut[generateCode.dLK]='setAstatusOS';
    1504 function setAstatusOver() {
    1505 	var o = window.event.srcElement;
    1506 	if (o.title) {
    1507 		setAstatusOS = window.status, window.status = o.title;
    1508 		return true;
    1509 	}
    1510 };
    1511 function setAstatusOut() {
    1512 	//var o=event.srcElement;if(typeof o.ostatus!='undefined'){window.status=o.ostatus;return true;}
    1513 	window.status = setAstatusOS;
    1514 	return true;
    1515 };
    1516
    1517
    1518
    1519
    1520
    1521 CeL.net.web
    1522 .
    1523 /**
    1524  * fill data to table.
    1525  * 增加 table 的列(row)
    1526  * @param {Array|Object} data	data list
    1527  * @param table	table element
    1528  * @param {Array} header	header list
    1529  * @return
    1530  * @example
    1531  * table_list([list1],[list2],..)
    1532  * e.g.,	table_list([1,2,3,4],[4,5,3,4]);
    1533  * table_list([[list1],[list2],..])
    1534  * e.g.,	table_list( [ [1,2,3,4],[4,5,3,4] ] );
    1535  * @since	2010/05/03 14:13:18
    1536  * @memberOf	CeL.net.web
    1537  * @see
    1538  * http://www.datatables.net/
    1539  */
    1540 table_list = function(data, table, header, do_clean) {
    1541 	var i = 0, l, add_list = function(array, d) {
    1542 		if (!library_namespace.is_Array(array))
    1543 			return;
    1544
    1545 		var j = 0, tr = document.createElement('tr'), td, array, L = array.length;
    1546 		for (; j < L; j++) {
    1547 			td = document.createElement(d || 'td');
    1548 			td.appendChild(document.createTextNode(array[j]));
    1549 			tr.appendChild(td);
    1550 		}
    1551 		table.appendChild(tr);
    1552 	};
    1553
    1554 	if (typeof table === 'string')
    1555 		table = document.getElementById(table);
    1556
    1557 	/*
    1558 	//	in  Chrome/5.0.342.9 @ Ubuntu, 加了會出問題。
    1559 	try{
    1560 		if(l=table.getElementsByTagName('tbody'))
    1561 			table=l[0];
    1562 	}catch(e){}
    1563 	*/
    1564
    1565 	if (do_clean)
    1566 		table.innerHTML = '';
    1567 		/*
    1568 		try {
    1569 			// moz
    1570 			table.innerHTML = '';
    1571 		} catch (e) {
    1572 			try {
    1573 				// alert(table.rows.length);
    1574 				// IE
    1575 				for ( var i = table.rows.length; i > 0;)
    1576 					table.deleteRow(--i);
    1577 			} catch (e) {
    1578 			}
    1579 		}
    1580 		*/
    1581
    1582 	if (header)
    1583 		add_list(header, 'th');
    1584
    1585 	if (data.length === 1 && typeof (l=data[0]) === 'object'
    1586 			&& library_namespace.is_Array(l[0]))
    1587 		data = l;
    1588
    1589 	if (library_namespace.is_Array(data))
    1590 		for (l = data.length; i < l; i++) {
    1591 			add_list(data[i]);
    1592 		}
    1593 	else if (library_namespace.is_Object(data)) {
    1594 		for (i in data) {
    1595 			add_list( [ i, data[i] ]);
    1596 		}
    1597 	} else
    1598 		library_namespace.debug('Error input: not legal data!');
    1599 };
    1600
    1601
    1602
    1603 /*
    1604
    1605 test:
    1606 /fsghj.sdf
    1607 a.htm
    1608 http://www.whatwg.org/specs/web-apps/current-work/#attr-input-pattern
    1609 file:///D:/USB/cgi-bin/lib/JS/_test_suit/test.htm
    1610 //www.whatwg.org/specs/web-apps/current-work/#attr-input-pattern
    1611
    1612 TODO:
    1613 .fileName:
    1614 file:///D:/USB/cgi-bin/lib/JS/_test_suit/test.htm
    1615 ->
    1616 D:\USB\cgi-bin\lib\JS\_test_suit\test.htm
    1617
    1618 eURI : /^((file|telnet|ftp|https?)\:\/\/|~?\/)?(\w+(:\w+)?@)?(([-\w]+\.)+([a-z]{2}|com|org|net))?(:\d{1,5})?(\/([-\w~!$+|.,=]|%[a-f\d]{2})*)?(\?(([-\w~!$+|.,*:]|%[a-f\d{2}])+(=([-\w~!$+|.,*:=]|%[a-f\d]{2})*)?&?)*)?(#([-\w~!$+|.,*:=]|%[a-f\d]{2})*)?$/i,
    1619
    1620 */
    1621 CeL.net.web
    1622 .
    1623 /**
    1624  * Parses URI
    1625  * @param {String} URI	URI to parse
    1626  * @return	parsed object
    1627  * @example
    1628  * alert(parse_URI('ftp://user:cgh@dr.fxgv.sfdg:4231/3452/dgh.rar?fg=23#hhh').hostname);
    1629  * @since	2010/4/13 23:53:14 from parseURI+parseURL
    1630  * @memberOf	CeL.net.web
    1631  * @see
    1632  * RFC 1738, RFC 2396, RFC 3986,
    1633  * Uniform Resource Identifier (URI): Generic Syntax,
    1634  * http://tools.ietf.org/html/rfc3987,
    1635  * http://flanders.co.nz/2009/11/08/a-good-url-regular-expression-repost/,
    1636  * http://www.mattfarina.com/2009/01/08/rfc-3986-url-validation,
    1637  * also see batURL.htm
    1638  */
    1639 parse_URI = function(URI) {
    1640 	var m, n, h = URI, p;
    1641 	if (!h
    1642 			||
    1643 			// 不能用 instanceof String!
    1644 			typeof h !== 'string'
    1645 				|| !(m = h.match(/^([\w\d\-]{2,}:)?(\/\/)?(\/[A-Za-z]:|[^\/#?&\s:]+)([^\s:]*)$/)))
    1646 		return;
    1647 	//library_namespace.debug('parse [' + URI + ']: '+m);
    1648
    1649 	URI = is_DOM('location') ? {
    1650 		// protocol包含最後的':',search包含'?',hash包含'#'
    1651 		// file|telnet|ftp|https
    1652 		protocol : location.protocol,
    1653 		hostname : location.hostname,
    1654 		port : location.port,
    1655 		host : location.host,
    1656 		//	local file @ IE: C:\xx\xx\ff, others: /C:/xx/xx/ff
    1657 		pathname : location.pathname
    1658 	} : {};
    1659 	URI.URI = h;
    1660
    1661 	if (n = m[1])
    1662 		URI.protocol = n;
    1663 	URI._protocol = URI.protocol.slice(0,-1);
    1664 	//library_namespace.debug('protocol [' + URI._protocol + ']');
    1665
    1666 	/*	** filename 可能歸至m[4]!
    1667 	 * 判斷準則:
    1668 	 * gsh.sdf.df#dhfjk		filename|hostname
    1669 	 * gsh.sdf.df/dhfjk		hostname
    1670 	 * gsh.sdf.df?dhfjk		filename
    1671 	 * gsh.sdf.df			filename
    1672 	 */
    1673 	h = m[3], p = m[4];
    1674 	if (h && !/^\/[A-Za-z]:$/.test(h) && (p.charAt(0) === '/' || /[@:]/.test(h))) {
    1675 		// 處理 username:password
    1676 		if (m = h.match(/^([^@]*)@(.+)$/)) {
    1677 			n = m[1].match(/^([^:]+)(:(.*))?$/);
    1678 			if (!n)
    1679 				return;
    1680 			URI.username = n[1];
    1681 			if (n[3])
    1682 				URI.password = n[3];
    1683 			h = m[2];
    1684 		}
    1685
    1686 		// 處理 host
    1687 		if (m = h.match(/^([^\/#?&\s:]+)(:(\d{1,5}))?$/)) {
    1688 			// host=hostname:port
    1689 			URI.host = URI.hostname = m[1];
    1690 			if (m[3])
    1691 				URI.port = parseInt(m[3], 10);
    1692 			else if (n = {
    1693 						http : 80,
    1694 						ftp : 21
    1695 					}[URI._protocol])
    1696 				URI.host += ':' + (URI.port = n);
    1697 		} else
    1698 			return;
    1699
    1700 	} else//	test URI.protocol === 'file:'
    1701 		p = h + p, h = '';
    1702 	//if (!h) library_namespace.warn('將[' + p + ']當作 pathname!');
    1703 	//library_namespace.debug('local file: [' + location.pathname + ']'),
    1704
    1705 	if(!/^([^%]+|%[a-f\d]{2})+$/.test(p))
    1706 		library_namespace.warn('encoding error: [' + p + ']');
    1707
    1708 	if (p && (m = p.match(/^(((\/.*)\/)?([^\/#?]*))?(\?([^#]*))?(#(.*))?$/)))
    1709 		// pathname={path}filename
    1710 		//library_namespace.warn('pathname: [' + m + ']'),
    1711 		//	.path 會隨不同 OS 之 local file 表示法作變動!
    1712 		URI.path = /^\/[A-Za-z]:/.test(URI.pathname = m[1]) ? m[2].slice(1).replace(/\//g,'\\') : m[2],
    1713 		URI.filename = m[4],
    1714 		URI.search = m[5], URI._search = m[6],
    1715 		URI.hash = m[7], URI._hash = m[8];
    1716 	else {
    1717 		if (!h)
    1718 			return;
    1719 		URI.path = URI.pathname.replace(/[^\/]+$/, '');
    1720 	}
    1721 	//library_namespace.debug('path: [' + URI.path + ']'),
    1722
    1723
    1724 	// href=protocol:(//)?username:password@hostname:port/path/filename?search#hash
    1725 	URI.href = (URI.protocol ? URI.protocol + '//' : '')
    1726 	+ (URI.username ? URI.username
    1727 			+ (URI.password ? ':' + URI.password : '') + '@' : '')
    1728 			+ URI.host + URI.pathname + (URI.search || '') + (URI.hash || '');
    1729
    1730 	//library_namespace.debug('href: [' + URI.href + ']');
    1731 	return URI;
    1732 };
    1733
    1734
    1735
    1736
    1737
    1738
    1739 /*	Copy id(or object) to user's clipboard or Paste clipboard to id(or object).
    1740
    1741 	return the value set to clipboard
    1742 	http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/obj_textrange.asp
    1743 	http://msdn.microsoft.com/workshop/author/dhtml/reference/collections/textrange.asp
    1744 	http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/execcommand.asp
    1745 	way 2:use window.clipboardData	http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/clipboarddata.asp
    1746
    1747 	clipboardFunction()	paste/get clipboard
    1748 	clipboardFunction(0,divObj)	paste/get clipboard to divObj
    1749 	clipboardFunction(1,'divObj name')	Copy divObj to clipboard/set clipboard
    1750 	clipboardFunction(2,'dcfvdf')	set clipboard by string
    1751 	clipboardFunction(3,divObj)	Copies divObj to the clipboard/set clipboard and then deletes it. *return the value set to clipboard
    1752 */
    1753 var clipboardFunctionObj = 'clipboardFunctionDiv';
    1754 //clipboardFunction[generateCode.dLK]='clipboardFunctionObj';
    1755 function clipboardFunction(m,o){	//	method,object/(string)set value
    1756 if(window.navigator.appName=="Microsoft Internet Explorer"){
    1757  var t,O,tN;
    1758  if(m==2)t=o,o='';else if(typeof o=='string')o=document.getElementById(o);
    1759  //	try .nodeName instead of .tagName	http://twpug.net/modules/smartsection/item.php?itemid=35
    1760  if((typeof o!='object'||!o||(tN=(o.tagName||'').toLowerCase())!='textarea'&&tN!='select'&&tN!='option'&&(tN!='input'||o.type!='text')&&(O=o))&&!(o=document.getElementById(clipboardFunctionObj)))	//	textarea,select,option,input需使用.value!	o.type!='INPUT'||o.type!='text'：這樣大概也沒copy的價值了吧，應該會出現錯誤。
    1761   try{document.body.appendChild(o=document.createElement('textarea')),o.id=clipboardFunctionObj;}catch(e){return;}	//	只對IE5.5之後有用
    1762  //var t=document.body.createTextRange();t.moveToElementText(o);
    1763  if(m==2)o.value=t;else{if(O)o.value=O.innerText;if(m==3)t=o.value;}
    1764  if(o.id==clipboardFunctionObj)o.style.display='block';	//	得出現才能execCommand()
    1765  o.createTextRange()//TextRange Object
    1766 	.execCommand(m?m==3?"Cut":"Copy":"Paste");
    1767  if(o.id==clipboardFunctionObj)o.style.display='none';
    1768  //t.execCommand("ForeColor","false","plum"),t.execCommand("BackColor","false","glay");
    1769  //alert(o.tagName+'\n'+o.id+'\n['+o.innerText+']\n'+(m?m==3?"Cut":"Copy":"Paste"));
    1770  if(m!=3)t=o.value;
    1771  if(O)O.innerText=o.value;
    1772  return t;
    1773 }
    1774
    1775 //	http://www.mozilla.org/xpfe/xptoolkit/clipboard.html
    1776 //	http://mozilla.org/editor/midasdemo/securityprefs.html
    1777 //	http://blog.darkthread.net/blogs/darkthreadtw/archive/2009/06/21/4850.aspx
    1778 //	http://www.webdeveloper.com/forum/archive/index.php/t-170520.html
    1779 //	http://forum.moztw.org/viewtopic.php?p=131407
    1780 /*
    1781 if(window.navigator.appName=="Netscape"){	//	…不能用！
    1782  if(typeof o=='string')o=document.getElementById(o);
    1783  if(m==2||!o||o.tagName!='TEXTAREA'&&o.tagName!='SELECT'&&o.tagName!='OPTION'&&(o.tagName!='INPUT'||o.type!='text'))return;	//	無法設定
    1784
    1785  if(!Zwischenablage){	//	初始設定
    1786   netscape.security.PrivilegeManager.enablePrivilege("UniversalSystemClipboardAccess");
    1787   //var fr=new java.awt.Frame();
    1788   Zwischenablage=new java.awt.Frame().getToolkit().getSystemClipboard();
    1789  }
    1790
    1791  if(m==0){
    1792   var Inhalt=Zwischenablage.getContents(null);
    1793   if(Inhalt!=null)o.value=Inhalt.getTransferData(java.awt.datatransfer.DataFlavor.stringFlavor);
    1794  }
    1795  else{	//	m=1,3
    1796   o.select();
    1797   Zwischenablage.setContents(new java.awt.datatransfer.StringSelection(o.value),null);
    1798  }
    1799
    1800  return o.value;
    1801 }
    1802 */
    1803 }	//	clipboardFunction()
    1804
    1805
    1806
    1807
    1808 Clipboard = function() {
    1809 };
    1810
    1811
    1812 CeL.net.web
    1813 .
    1814 //	2010/1/15 00:17:38
    1815 //	IE, FF only
    1816 //	http://www.jeffothy.com/weblog/clipboard-copy/
    1817 //	http://bravo9.com/journal/copying-into-the-clipboard-with-javascript-in-firefox-safari-ie-opera-292559a2-cc6c-4ebf-9724-d23e8bc5ad8a/
    1818 //	http://code.google.com/p/zeroclipboard/
    1819 copy_to_clipboard = function(text) {
    1820 	var clip;
    1821 	if (clip = window.clipboardData) {
    1822 		clip.clearData();
    1823 		clip.setData('Text', text);
    1824 	} else if (is_DOM('Components')){
    1825 		library_namespace.require_netscape_privilege(
    1826 			//	在您的機器上執行或安裝軟體
    1827 			'UniversalXPConnect', function() {
    1828 			//	https://developer.mozilla.org/en/Using_the_Clipboard
    1829 			//	[xpconnect wrapped nsIClipboardHelper]
    1830 			return Components.classes["@mozilla.org/widget/clipboardhelper;1"]
    1831 					.getService(Components.interfaces.nsIClipboardHelper)
    1832 					//	跳出函數即無效，因此不能 cache。
    1833 					.copyString(text);
    1834 		});
    1835 	}
    1836 	//else if (navigator.userAgent.indexOf("Opera") != -1)
    1837 	//	window.location = text;
    1838 };
    1839
    1840
    1841
    1842 /*	2009/5/13 21:21:49
    1843 	unfinished
    1844 */
    1845 function clipB() {
    1846 }
    1847 clipB.start_op = function() {
    1848 	var o = this.temp_obj;
    1849 	if (!o) {
    1850 		document.body.appendChild(o = document.createElement('div'));
    1851 		// for modify
    1852 		o.contentEditable = true;
    1853 		// o.style.height=0;o.style.width=0;
    1854 		this.temp_obj = o;
    1855 	}
    1856
    1857 	document.selection.empty();
    1858 	// initial
    1859 	o.innerHTML = '';
    1860 	// 得出現才能 focus(), execCommand()
    1861 	o.style.display = 'block';
    1862 	o.focus();
    1863 	return o;
    1864 };
    1865 clipB.end_op = function() {
    1866 	var o = this.temp_obj;
    1867 	document.selection.empty();
    1868 	if (o)
    1869 		o.style.display = 'none';
    1870 };
    1871 //	return [text, obj]
    1872 clipB.get_obj = function(t) {
    1873 	var o;
    1874 	if (typeof t == 'object' && 'innerHTML' in t
    1875 			|| (o = document.getElementById('' + t)) && (t = o))
    1876 		return [ t.innerHTML, t ];
    1877 	return [ t ];
    1878 };
    1879 clipB.paste_to = function(o) {
    1880 	o = this.get_obj(o);
    1881 	if (o = o[1])
    1882 		o.innerHTML = this.get(1);
    1883 };
    1884 clipB.set = function(o) {
    1885 	o = this.get_obj(o);
    1886 };
    1887 //	get HTML
    1888 clipB.get = function(h) {
    1889 	var o = this.start_op(), r = document.selection.createRange(), t;
    1890 	r.select();
    1891 	r.execCommand('Paste');
    1892 	t = h ? r.htmlText : r.text;
    1893 	this.end_op();
    1894 	return h ? o.innerHTML : o.innerText;
    1895 };
    1896 clipB.cut_from = function(o) {
    1897 	o = this.get_obj(o);
    1898 };
    1899
    1900
    1901 //從後面調過來的
    1902 var disabledKM=0,scrollToXY,scrollToInterval,scrollToOK,doAlertDivName,doAlertOldScrollLocation;
    1903
    1904
    1905 CeL.net.web
    1906 .
    1907 /**
    1908  * 設定document.cookie.
    1909  * You can store up to 20 name=value pairs in a cookie, and the cookie is always returned as a string of all the cookies that apply to the page.
    1910  * TODO:
    1911  * HTML5 localStorage (name/value item pairs).
    1912  * test various values.
    1913  * document.cookie.setPath("/");
    1914
    1915  * @example
    1916 	範例：
    1917 //	delete domain
    1918 set_cookie('domain',0);
    1919 //	一個月(30 days)
    1920 set_cookie('expires',30);
    1921 //	設定name之值為jj
    1922 set_cookie(name,'jj');
    1923 //	設定name之值為56
    1924 set_cookie(name,56);
    1925 //	除去name
    1926 set_cookie(name);
    1927 //	設給本host全部使用
    1928 set_cookie(_.set_cookie.f.set_root);
    1929 //	設給本domain使用
    1930 set_cookie(_.set_cookie.f.set_domain);
    1931 //	依現有設定除去所有值
    1932 set_cookie(_.set_cookie.f.delete_all);
    1933 //	除去所有值
    1934 set_cookie(_.set_cookie.f.delete_all_root);
    1935 //	永久儲存（千年）
    1936 set_cookie(_.set_cookie.f.forever);
    1937 //	準確設定這之後只在這次瀏覽使用這些cookie，也可用set_cookie('expires',-1);
    1938 set_cookie(_.set_cookie.f.moment);
    1939 //	將expires設定成forever或moment後再改回來（不加expires設定）
    1940 set_cookie('expires',0);
    1941
    1942  * @param {String|Object|_module_.set_cookie.f} name	set_cookie.f flag | varoius name
    1943  * @param value	varoius value
    1944  * @param {Boolean|Object} config	若對於特殊設定僅暫時設定時，設定此項。
    1945  * @returns
    1946  * @see
    1947  * Chrome doesn't support cookies for local files unless you start it with the --enable-file-cookies flag.
    1948  * chrome.exe --allow-file-access-from-files --enable-extension-timeline-api --enable-file-cookies
    1949  * http://stackoverflow.com/questions/335244/why-does-chrome-ignore-local-jquery-cookies
    1950  * http://code.google.com/p/chromium/issues/detail?id=535
    1951  * @memberOf	CeL.net.web
    1952  */
    1953 set_cookie = function (name, value, config) {
    1954 	if (!is_DOM('document') || typeof document.cookie !== 'string'
    1955 				|| typeof name === 'undefined')
    1956 		return;
    1957
    1958 	var _s = _.set_cookie, flag = _s.f, m;
    1959 	if (!config)
    1960 		//	預設傳到 default
    1961 		config = _s.c;
    1962 	else if (!library_namespace.is_Object(config))
    1963 		//	document.cookie 不須每次詳細設定，但這樣可以選擇 {} / {..} / true
    1964 		config = library_namespace.extend(_s.c, {});
    1965
    1966 	if (library_namespace.is_Object(name)) {
    1967 		for ( var i in name)
    1968 			_s(i, name[i], config);
    1969 		return config;
    1970 	}
    1971
    1972 	try {
    1973 		//	This will cause error in Phoenix 0.1:
    1974 		// Error: uncaught exception: [Exception... "Component returned failure code: 0x8000ffff (NS_ERROR_UNEXPECTED) [nsIDOMNavigator.cookieEnabled]"  nsresult: "0x8000ffff (NS_ERROR_UNEXPECTED)"  location: "JS frame :: http://lyrics.meicho.com.tw/game/game.js :: set_cookie :: line 737"  data: no]
    1975 		if (window.navigator && !window.navigator.cookieEnabled)
    1976 			throw 1;
    1977 	} catch (e) {
    1978 		CeL.warn('set_cookie: We cannot use cookie!');
    1979 		return;
    1980 	}
    1981
    1982 	//library_namespace.debug('set_cookie: ' + name + ' = [' + value + ']', 1);
    1983 	if (name === flag.set_root)
    1984 		// 設給本 host 全部使用
    1985 		name = 'path', value = '/';
    1986 	else if (name === flag.set_domain)
    1987 		// 設給本 domain 使用，尚不是很好的判別法。
    1988 		name = 'domain', value = location.hostname.replace(/^[^.]+\./, '.');
    1989 	else if (name === flag.forever)
    1990 		// 永久儲存，date之time值不能>1e16
    1991 		name = 'expires', value = 1e14;
    1992 	else if (name === flag.moment)
    1993 		// 準確設定這之後只在這次瀏覽使用這些cookie
    1994 		name = 'expires', value = -1;
    1995
    1996 	// detect special config / 特殊設定
    1997 	if (typeof name === 'string'
    1998 			&& (m = name.match(/^(expires|path|domain|secure)$/i))) {
    1999 		name = m[1];
    2000 		if (name === 'expires' && typeof value === 'number' && value) {
    2001 			//if(value<8000)value*=86400000;//幾日，86400000=1000*60*60*24
    2002 			//value=(new Date(value<3e13?(new Date).getTime()+value:1e14)).toUTCString();	//	3e13~千年
    2003 			value = (new Date(value < 1e14 ? value < 0 ? 0 : (new Date).getTime()
    2004 					+ (value < 8e3 ? value * 86400000 : value) : 1e14)).toUTCString();
    2005 		}
    2006 		config[name] = value;
    2007 		//library_namespace.debug('set_cookie: ' + name + ' = [' + value + ']', 1);
    2008 		return name + '=' + value + ';';
    2009
    2010 	} else {
    2011 		var set = name === flag.delete_all_root ? 'expires=' + (new Date(0)).toUTCString() + ';path=/;'
    2012 			: (typeof value === 'undefined' ? 'expires=' + (new Date(0)).toUTCString() + ';'
    2013 			: config.expires ? 'expires=' + config.expires + ';' : '')
    2014 				+ (config.path ? 'path=' + config.path + ';' : '')
    2015 				+ (config.domain ? 'domain=' + config.domain + ';' : '')
    2016 				+ (config.secure ? 'secure;' : '');
    2017
    2018 		if (name === flag.delete_all || name === flag.delete_all_root) {
    2019 			/*
    2020 			   var c=document.cookie;
    2021 			   while(c.match(/([^=;]+)(=[^;]{0,})?/)){
    2022 			    c=c.substr(RegExp.lastIndex);
    2023 			    if(!/expires/i.test(RegExp.$1))document.cookie=RegExp.$1+'=;'+set;
    2024 			   }
    2025 			*/
    2026 			for ( var p = document.cookie.split(';'), n, l = p.length, i = 0; i < l; i++)
    2027 				if (!/^\s*expires\s*$/i.test(n = c[i].split('=')[0]))
    2028 					document.cookie = n + '=;' + set;
    2029 			return document.cookie;
    2030
    2031 		} else {
    2032 			//	可用escape(value)/unescape()來設定，速度會比較快，但佔空間。
    2033 			//value=name+'='+(typeof value=='undefined'?'':dQuote(''+value).replace(/([\01-\11\13-\14\16-\40=;])/g,function($0,$1){var c=$1.charCodeAt(0),d=c.toString(16);return'\\x'+(c<16?'0':'')+d;}))+';'+set;
    2034 			//	2004/11/23 21:11	因為cookie儲存成中文時會fault,所以只好還是使用escape()
    2035 			value = escape(name) + '='
    2036 					+ (typeof value == 'undefined' ? '' : escape(value)) + ';'
    2037 					+ set;
    2038 			//library_namespace.debug('set_cookie: [' + value + ']', 1);
    2039 			//library_namespace.debug('set_cookie: [' + document.cookie + ']', 1);
    2040 			// 長度過長時（約4KB）會清空，連原先的值都不復存在！
    2041 			return value.length < 4096 && (document.cookie = value) ? value
    2042 					: -1;
    2043 		}
    2044
    2045 	}
    2046 };
    2047
    2048 CeL.net.web
    2049 .
    2050 set_cookie.f = {
    2051 		moment : -1,
    2052 		delete_all : 2,
    2053 		delete_all_root : 3,
    2054 		set_root : 4,
    2055 		set_domain : 5,
    2056 		forever : 6
    2057 };
    2058
    2059 CeL.net.web
    2060 .
    2061 //	特殊設定
    2062 set_cookie.c = {
    2063 		expires : 0,
    2064 		path : 0,
    2065 		domain : 0,
    2066 		secure : 0
    2067 };
    2068
    2069 /*	取得document.cookie中所需之值	看起來只能取得相同domain，有設定的path之cookie
    2070
    2071 	flag=0: only get the lastest matched value;
    2072 	flag=1: only get all matched in a array;
    2073 	other flag: auto detect by name
    2074
    2075 get_cookie(name);	//	取得name之值，亦可用RegExp：if(c=get_cookie())c['name1']==value1;
    2076 get_cookie('nn[^=]*');	//	取得所有nn開頭之組合
    2077 get_cookie();	//	取得所有name=value組
    2078
    2079 因為 cookie 較容易遭到竄改或是出問題，建議設定 verify。
    2080 */
    2081 CeL.net.web
    2082 .
    2083 //get_cookie[generateCode.dLK]='renew_RegExp_flag';
    2084 get_cookie=function (name,flag,verify){
    2085  if(!is_DOM('document')||!document.cookie)return;
    2086  if(!name)name='[^;=\\s]+';//\w+
    2087  var c,R=name instanceof RegExp?name:new RegExp('('+escape(name)+')\\s*=\\s*([^;=\\s]*)','g')
    2088 	,m=document.cookie.match(R);
    2089  //library_namespace.debug('get_cookie: [' + R + '] = ['+m+']', 1);
    2090  //library_namespace.debug('get_cookie: [' + document.cookie + ']', 1);
    2091  if(!m)return;
    2092  if(R.global)R=library_namespace.renew_RegExp_flag(R,'-g');
    2093  if(m.length>1)
    2094 	 //	取最後一個
    2095 	 if(flag==0 || typeof flag=='undefined'&&typeof name=='string')
    2096 		 m=m.slice(-1);
    2097  //	表示不是因name為RegExp而得出之值.
    2098  //	TODO: bug: 找 "count" 可能找到 "data_count"!!
    2099  if(m.length===1&&typeof m[0]==='string'&&(c=m[0].match(R))[1]===escape(name)){
    2100 /*
    2101   if((m=c[2])&&((c=m.charAt(0))=='"'||c=="'")&&c==m.slice(-1))	//	將值為".."或'..'轉為引號中表示之值
    2102    try{
    2103     //alert('get 1:\n'+m+'\n'+unescape(m));
    2104     window.eval('c='+m);return c;
    2105    }catch(e){}
    2106   return m;
    2107 */
    2108   return unescape(c[2]);
    2109  }
    2110
    2111  var r={},v,M,i=0;
    2112  //alert(document.cookie+'\n'+R+'\n'+m.length+'\n'+m);
    2113
    2114  for(;i<m.length;i++)
    2115   if(typeof m[i]==='string'&&(M=m[i].match(R)))
    2116    r[unescape(M[1])]=unescape(M[2]);
    2117 /*
    2118  for(;i<m.length;i++){
    2119   M=m[i].match(R),v=unescape(M[2]);
    2120   if(v&&((c=v.charAt(0))=='"'||c=="'")&&c==v.slice(-1))
    2121    try{
    2122     //alert('get 2:\n'+v+'\n'+unescape(v));
    2123     window.eval('c='+v);v=c;
    2124    }catch(e){}
    2125   r[M[1]]=v;	//	有必要可用unescape()，畢竟那是模範做法。
    2126  }
    2127 */
    2128
    2129  return r;
    2130 };
    2131
    2132
    2133 /*	取得註解部份資料：這個值會連 NewLine 都保存下來
    2134 	其實IE用document.getElementsByTagName('!')就可以了，不管幾層都能到。
    2135 	註解中[!-]需要escape！IE6之div內不能沒東西，所以得加個 （並且得在前面）之後加<!-- -->才有用。
    2136
    2137 div	從哪裡開始找
    2138 level	最多往下找幾層
    2139 retType	回傳0:node本身,1:註解值
    2140 */
    2141 function get_comments(div, level, retType) {
    2142 	if (!div) div = window.document;
    2143 	var i = 0, d, _f = get_comments;
    2144 	if (isNaN(_f.endLevel)) _f.endLevel = 2;
    2145 	if (isNaN(level) || level === -1) _f.a = [], level = _f.endLevel;
    2146 	else if (typeof _f.a != 'object') _f.a = [];
    2147 	div = div.childNodes;
    2148 	for (; i < div.length; i++) {
    2149 		d = div[i]; //if(d.nodeType==8)alert(d.tagName+'\n'+d.nodeName+'\n'+d.nodeType+(d.nodeValue?'\n'+d.nodeValue.slice(0,30):''));
    2150 		if (d.tagName && d.tagName == '!') _f.a.push(retType ? d : d.text.replace(/^<!(--)?/, '').replace(/(--)?>$/, '')); //,alert(d.tagName+'\n'+d.text.slice(0,30));
    2151 		else if (d.nodeType == 8) _f.a.push(retType ? d : d.nodeValue); //alert('*	'+_f.a.length+'\n'+d.nodeValue.slice(0,30));	//	NS	http://allabout.co.jp/career/javascript/closeup/CU20040307/index.htm?FM=cukj&GS=javascript
    2152 		//	http://www.w3.org/TR/DOM-Level-2-Core/core.html
    2153 		//	ELEMENT_NODE,ATTRIBUTE_NODE,TEXT_NODE,CDATA_SECTION_NODE,ENTITY_REFERENCE_NODE,ENTITY_NODE,PROCESSING_INSTRUCTION_NODE,COMMENT_NODE,DOCUMENT_NODE,DOCUMENT_TYPE_NODE,DOCUMENT_FRAGMENT_NODE,NOTATION_NODE
    2154 		if (level && d.childNodes) _f(d, level - 1, retType);
    2155 	}
    2156 	return _f.a;
    2157 }
    2158 //window.onload=function(){get_comments();alert(get_comments.a.length);for(var i=0;i<get_comments.a.length;i++)alert('['+get_comments.a[i]+']');};
    2159
    2160
    2161
    2162
    2163
    2164
    2165 /*	background image load
    2166 	**	本函數會倒著load！請將優先度高的排後面！
    2167
    2168 new Image看起來不是個好方法…
    2169 http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/img.asp
    2170
    2171 var img=new Image(width,heighr);img.onload=function(){docImageElement.src=this.src;}img.src=__SRC__;	//	onload應在前面，預防設定onload前就已被load?
    2172
    2173 var bgLoadImgA,bgLoadImgLA;
    2174 function bgLoadImg(){
    2175  if(location.protocol=='file:')return;
    2176  if(typeof bgLoadImgA=='string'){
    2177   var s=[1];
    2178   try{s.pop();bgLoadImgA=bgLoadImgA.split(',');setTimeout('bgLoadImg();',5000);}catch(e){}	//	測試舊版可能沒有pop()功能，會出現error
    2179   return;
    2180  }
    2181  if(bgLoadImgA.length){var i=new Image(1,1);i.function(){setTimeout('bgLoadImg();',0);},i.src=typeof getObjURL=='function'?getObjURL(bgLoadImgA.pop()):bgLoadImgA.pop();bgLoadImgLA.push(i);}
    2182 }
    2183
    2184
    2185 TODO:
    2186 Javascript uses automatic garbage collection. Set to [null] as well.	http://www.thescripts.com/forum/thread95206.html
    2187 須注意 JavaScript closure and IE 4-6 memory leak! IE 7 seems to have solved the memory leaks.	http://anotherblog.spaces.live.com/blog/cns!E9C5235EBD2C699D!458.entry?ppud=0&wa=wsignin1.0
    2188 http://laurens.vd.oever.nl/weblog/items2005/closures/	http://www.blogjava.net/tim-wu/archive/2006/05/29/48729.html
    2189 IE 6對於純粹的Script Objects間的Circular References是可以正確處理的，可惜它處理不了的是JScript與Native Object(例如Dom、ActiveX Object)之間的Circular References。
    2190 P.S. 2007/11/11 似乎已修正？
    2191 */
    2192
    2193 /*	bgLoadImg() Cookie版	2006/3/3 20:08
    2194 	**	本函數正著load！請將優先度高的排前面！
    2195
    2196 	To use:
    2197 	,set_cookie,get_cookie,bgLoadImgId,bgLoadImgI,bgLoadImg
    2198 	bgLoadImgId='id_of_this_session',bgLoadImgA='img_url1,img_url2,..';	//	** MUST string!
    2199 	function getObjURL(bgLoadImgA_element){return the real URL of bgLoadImgA_element;}
    2200 	window.onload="bgLoadImg();"
    2201
    2202 var bgLoadImgId='bg',bgLoadImgI;	//	loaded index
    2203 */
    2204 //bgLoadImg[generateCode.dLK]='bgLoadImgId,bgLoadImgI';
    2205 function bgLoadImg(i) {
    2206 	var bgLoadImgM = 'bgLoadImgOK_' + bgLoadImgId;
    2207 	// alert('_'+bgLoadImgM+','+bgLoadImgI)
    2208 	if (typeof bgLoadImgA != 'object') {
    2209 		// needless
    2210 		if (!bgLoadImgA || location.protocol === 'file:')
    2211 			return;
    2212 		// http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/readystate_1.asp
    2213 		var r = document.readyState;
    2214 		if (typeof r === 'string' && r !== 'complete') {
    2215 			setTimeout(bgLoadImg, 500);
    2216 			return;
    2217 		}
    2218 		// initialization
    2219 		bgLoadImgA = bgLoadImgA.replace(/,\s*,/g, ',').split(',');
    2220 		if (typeof get_cookie != 'function'
    2221 			|| get_cookie(bgLoadImgM) != bgLoadImgA.length) { // 全部OK後就別再來了。
    2222 			if (isNaN(bgLoadImgI))
    2223 				bgLoadImgI = 0;
    2224 			if (typeof r != 'string') {
    2225 				setTimeout(bgLoadImg, 5e3);
    2226 				return;
    2227 			}
    2228 		} else
    2229 			return;
    2230 	}
    2231
    2232  //if(!isNaN(i)&&!bgLoadImgA[i].complete);	//	timeout
    2233  if(!isNaN(i)&&i<bgLoadImgI-1)return;	//	防止timeout的備援
    2234
    2235  //	標記已load counter
    2236  //	假如一個圖一個圖標記，set_cookie在超過二十個之後好像就沒效了…被限制？
    2237  _.set_cookie(bgLoadImgM,bgLoadImgI);
    2238
    2239  if(bgLoadImgI==bgLoadImgA.length)bgLoadImgI++,setTimeout('bgLoadImg();',500);	//	馬上進入判別，最後一個尚未complete
    2240  else if(bgLoadImgI<bgLoadImgA.length){
    2241   var bgLoadImgURL=typeof getObjURL=='function'?getObjURL(bgLoadImgA[bgLoadImgI]):bgLoadImgA[bgLoadImgI];
    2242   //setTimeout('bgLoadImg('+bgLoadImgI+')',5e3);	//	set timeout
    2243   with(bgLoadImgA[bgLoadImgI++]=new Image(1,1))
    2244 	//	這是個多執行緒技巧：假如使用onload=bgLoadImg，有可能在下一指令碼前就已onload，這樣會造成Stack overflow
    2245 	onload=function(){setTimeout('bgLoadImg();',0);},
    2246 	src=bgLoadImgURL;
    2247   window.status='bgLoadImg ['+bgLoadImgURL+']: '+bgLoadImgI+' / '+bgLoadImgA.length+'..';
    2248  }else{
    2249 /*
    2250   var f=[];
    2251   for(i=0;i<bgLoadImgA.length;i++)if(!bgLoadImgA[i].complete)f.push(bgLoadImgA[i].src);
    2252   if(f.length)_.set_cookie(bgLoadImgM,0);
    2253   window.status='bgLoadImg '+(f.length?'end: failed '+f.length+' / '+bgLoadImgA.length+' ('+f+')':'complete!'),bgLoadImgA=0;
    2254 */
    2255 	 var f = 0;
    2256 	 for (i = 0; i < bgLoadImgA.length; i++)
    2257 		 if (!bgLoadImgA[i].complete)
    2258 			 f++;
    2259 	 if (f)
    2260 		 _.set_cookie(bgLoadImgM, 0);
    2261 	 window.status = 'bgLoadImg '
    2262 		 + (f ? 'end: failed ' + f + ' / ' + bgLoadImgA.length
    2263 				 : 'complete!'), bgLoadImgA = 0;
    2264 	}
    2265 };
    2266
    2267
    2268
    2269 /*	儲存/回存使用者輸入之form資料用。	2004/11/23 21:38
    2270 		*已測試過text(select-one,textarea,password,hidden)/radio/checkbox/select-multiple
    2271 	formIdA:	form id or id array.不輸入或輸入'',0等表示所有的form
    2272 	expires:	不輸入或輸入''表示回存，輸入0會以預設days代替，輸入<0會刪除掉cookie中這項設定。
    2273 	targetItemA:	要處理的name。例如'name,tel,email'。假如包括unselect，會處理除了targetItemA之外所有的。
    2274
    2275 	input type="checkbox"	value不能包含';'!
    2276 	password也會被儲存，得自己排除!
    2277 e.g.,
    2278 cookieForm()	recall all items of all forms
    2279 cookieForm(0,1,'email');	save all items named 'email' of all forms
    2280 cookieForm(0,'','email');	recall all items named 'email' of all forms
    2281 cookieForm(0,-1);	消除所有*版面上現有form*之紀錄
    2282
    2283 TODO:
    2284 排除名單
    2285 對於較多的entries,也許需要使用到Object[key]來代替String.indexOf(key)
    2286 */
    2287 //cookieForm[generateCode.dLK]='get_cookie,set_cookie';
    2288 function cookieForm(formIdA,expires,targetItemA){
    2289 	if (typeof document != 'object')
    2290 		return;
    2291  if(!formIdA)formIdA=document.getElementsByTagName('FORM');else if(typeof formIdA=='string')formIdA=[formIdA];
    2292  var i,n,o,dealO=function(o){	//	メソッドをプロトタイプではなく、オブジェクト自身にセットしていることです。これでは継承できませんし、ECMAScript のプロトタイプベースのセマンティクスから外れてしまいます。
    2293   for(var j=0,c=o.childNodes,sp=';',e,cn,cv,tp;j<c.length;j++){
    2294    if((e=c[j]).hasChildNodes)dealO(e);
    2295    if(e.name&&typeof e.value!='undefined'){//cv=e.tagName=='TEXTAREA'?e.innerHTML:e.value	//	TEXTAREA,SELECT,OPTION,INPUT需使用.value!
    2296     //if(!e.value&&e.text)e.value=e.text;	//	假如沒有.value,利用.text代替
    2297     if(targetItemA)if(targetItemA.unselect&&targetItemA[e.name]||!targetItemA.unselect&&!targetItemA[e.name])continue;
    2298     //alert((isNaN(expires)?'load':'save')+'\n'+n+'::'+e.name+'['+e.type+']='+e.value);
    2299     cn='cookieForm_'+n+'_'+e.name;cv=e.value;
    2300     tp=e.type.toLowerCase();//e.tagName=='INPUT'?e.type.toLowerCase():'';
    2301     if(isNaN(expires)){if(typeof(cn=get_cookie(cn))!='undefined'){
    2302      if(tp=='radio'){
    2303       if(cv==cn)e.checked=true;
    2304      }else if(tp=='checkbox'){
    2305       if(cn.indexOf(sp+cv+sp+sp)!=-1)e.checked=true;
    2306      }else if(tp=='select-multiple')
    2307       for(var i=0;i<e.options.length;i++)
    2308        e.options[i].selected=cn.indexOf(sp+e.options[i].value+sp)!=-1;
    2309      else e.value=cn;
    2310     }}else{
    2311      if(tp=='radio'){if(!e.checked)continue;}
    2312      else if(tp=='checkbox')
    2313       if(cv.indexOf(sp)!=-1)continue;	//	value不能包含sp	checkbox之cookie形式:[;value1;;value2;value3;;value4;]:value1,3:checked
    2314       else cv=((tp=get_cookie(cn))&&tp.indexOf(sp+cv+sp)==-1?tp:sp)+cv+sp+(e.checked?sp:'');
    2315      //else if(tp=='select-one')cv=e.options[e.selectedIndex].value;	//	可省略!	用.selectedIndex會比較快，但更改原文件可能會造成index錯誤
    2316      else if(tp=='select-multiple'){
    2317       cv=sp+cv+sp;
    2318       for(var i=e.selectedIndex+1;i<e.options.length;i++)
    2319        if(e.options[i].selected)cv+=e.options[i].value+sp;
    2320      }
    2321      if(expires)_.set_cookie(cn,cv);
    2322      else _.set_cookie(cn);
    2323     }
    2324    }
    2325   }
    2326  };
    2327
    2328  if(targetItemA){
    2329   o=targetItemA;targetItemA={};if(typeof o=='string')o=o.split(',');
    2330   for(i in o)targetItemA[o[i]]=1;
    2331  }
    2332  if(expires==='')expires=NaN;
    2333  if(!isNaN(expires)){
    2334   if(expires)expires=7;	//	預設days
    2335   _.set_cookie(_.set_cookie.f.set_root);	//	Gecko need this
    2336   _.set_cookie('expires',expires);
    2337  }
    2338  for(i=0;i<formIdA.length;i++)if(o=formIdA[i]){
    2339   if(typeof o=='string')o=document.getElementById(n=o);else if(!(n=o.id))n=o.name;
    2340   if(o&&(o.tagName||'').toLowerCase()=='form'&&n&&typeof n=='string')dealO(o);
    2341  }
    2342  if(!isNaN(expires))_.set_cookie('expires',0);
    2343
    2344 }
    2345
    2346
    2347 //	登入FTP	IE使用者若要上傳，請開啟FTP 站台的資料夾檢視功能。
    2348 //	<input type="text" autocomplete="off"/>
    2349 function loginFTP(n,p,path,hostname){	//	name,password
    2350  if(!hostname&&!(hostname=location.hostname))return;
    2351  if(n=='ftp'||n=='anonymous')n='';
    2352  if(!p&&n)p=window.prompt('請輸入['+n+']之密碼：');
    2353  if(p==null)return;	//	取消輸入
    2354  p='ftp://'+(n?n+(p?':'+p:'')+'@':'')+(hostname+'/'+(path||'')).replace(/\/{2,}/g,'/');
    2355  window.open(p,'ftpW');//location.href=p;	//	用location.href不能進入資料夾檢視功能
    2356 }
    2357
    2358
    2359 //	reference page set	==================
    2360
    2361 CeL.net.web
    2362 .
    2363 /**
    2364  * 簡化 document.getElementById 並配合 loadReference()
    2365  * @since 2004/6/25 19:33
    2366  * @param id	所欲找尋之 element id
    2367  * @param flag
    2368  *            {HTML Object} object: 參考此 document object
    2369  *            {Number} flag: 參見 code
    2370  * @return	{HTML Object} Object
    2371  * @requires	referenceDoc,loadReferenceDone,`get_element();`
    2372  * @memberOf	CeL.net.web
    2373  */
    2374 get_element = function get_element(id, flag) {
    2375 	var _s = get_element, _f = _s.f;
    2376 	if (!_f)
    2377 		// 在 Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040510 中會出問題，所以改到函數中執行。但得先執行過一次。
    2378 		//alert('get_element: set flags get_element.f'),
    2379 		_s.f = _f = {
    2380 			//	僅參考自身頁面，default
    2381 			'self' : 0,
    2382 			//	可參考 reference page
    2383 			'ref' : 1,
    2384 			//	僅參考 reference page
    2385 			'refOnly' : 2
    2386 		};
    2387
    2388 	if (!id || typeof window !== 'object' || typeof document !== 'object'
    2389 			|| document !== window.document)
    2390 		return null;
    2391 	// if(flag)alert('get_element: '+id+','+flag);
    2392
    2393 	// 後面暫時沒用到
    2394 	// if(!flag)flag=_f.self;
    2395
    2396 	if (
    2397 			//typeof document !== 'object' ||
    2398 			!document.body)
    2399 		// document 尚未 load
    2400 		return;
    2401
    2402 	if(_.is_HTML_element(id))
    2403 		return id;
    2404
    2405 	var o;
    2406 	if (flag !== _f.refOnly)
    2407 		// 僅參考 reference page 時不設定
    2408 		o = document.getElementById ? document.getElementById(id)
    2409 			: document.all ? document.all[id]
    2410 			: document.layers ? document.layers[id]
    2411 			: window[id];
    2412 	//if(flag)alert('get_element: '+id+','+flag+'\nloadReferenceDone='+loadReferenceDone+'\nreferenceDoc: '+referenceDoc+'\no: '+o+'\nreferenceDoc.get: '+referenceDoc.getElementById(id)+'\n'+referenceDoc.body.innerHTML.slice(0,200));
    2413 	try {
    2414 		// 偶爾還是有可能'沒有使用權限'
    2415 		typeof flag === 'object' && typeof flag.getElementById === 'function' && (o = flag.getElementById(id))
    2416 		|| o
    2417 		|| flag && loadReferenceDone === 1 && (o = referenceDoc.getElementById(id));
    2418 	} catch (e) {
    2419 	}
    2420 	return o || null;
    2421 };
    2422
    2423
    2424
    2425 /*	以外掛的reference page配置data object	2004/6/25 21:01
    2426
    2427 	toUse:
    2428 	準備好reference.htm
    2429 	在需要的文件加入	window.onload="loadReference()";
    2430 	在需要的文件body加入	<iframe id="reference"></iframe>
    2431 	function setupPageR()	initial after load of reference page
    2432
    2433 	如上，再使用 get_element() 即可得到 reference.htm 中的 obj
    2434 */
    2435 var referenceDoc,loadReferenceDone;//,loadReferenceCount;
    2436 //loadReference[generateCode.dLK]='get_element,referenceDoc,loadReferenceDone,parseFunction';
    2437 function loadReference(referenceURL,iframeId){
    2438  if(loadReferenceDone||typeof location!='object'||!location.protocol||location.protocol=='https:')return;	//	https會拒絕存取，所以直接放棄。
    2439  //if(loadReferenceDone)return;	//	https會拒絕存取，所以直接放棄。
    2440  var o=_.get_element(iframeId||'reference'),thisFuncName=parseFunction().funcName;
    2441  if(typeof referenceDoc=='object' && typeof referenceDoc.document=='object' && referenceDoc.document){	//	referenceDoc is still contentWindow here.	typeof referenceDoc.document:預防使用https時產生不能讀取的權限問題。
    2442   referenceDoc=o.contentWindow.document;//referenceDoc.document;	//	遺憾：在舊版IE不能用後者。也許是因為舊版IE連contentWindow都會重造。
    2443   o=referenceDoc.body;//alert(o.innerHTML.length+'\n'+o.innerHTML);
    2444   if(o/*&&referenceDoc.body.innerHTML=='string'*/&&o.innerHTML.length){
    2445    //alert(typeof o+','+(o?typeof o.innerHTML+'('+o.innerHTML.length+')\n'+o.innerHTML.slice(0,200):'(null)'));
    2446    //	before IE5, the first argument must be a string.
    2447    //	setTimeout(function_handle,..) 不一定代表setTimeout('function_handle();',..)，可能會傳入奇異的引數！
    2448    if(typeof setupPageR=='function')setTimeout(setupPageR,9);
    2449    loadReferenceDone=1;//window.status='reference page load OK!';alert(window.status);
    2450   }else{
    2451    //try{window.status='Wait while reference page loading..3',alert(window.status+'\nURL:'+o.contentWindow.document.src+'\ncontent('+o.contentWindow.document.body.innerHTML.length+'):\n'+o.contentWindow.document.body.innerHTML);}catch(e){}
    2452    //if(!--loadReferenceCount)history.go(0);
    2453    setTimeout(thisFuncName+'();',200);
    2454   }
    2455   return;
    2456  }
    2457  if(typeof document!='object'||!document.body){	//	document尚未load
    2458   setTimeout(thisFuncName+'();',90);
    2459   return 1;
    2460  }
    2461  //o=_.get_element(iframeId||'reference');	//	原來把設定放在這，不過反正都要在前面用到…
    2462  if(!o||(o.tagName||'').toLowerCase()!='iframe'){loadReferenceDone=2;return;}	//	iframe不存在
    2463  if(!o.src)o.style.display='none',//'block',//
    2464   o.src=referenceURL;	//	for game.js: typeof relatePath=='function'?relatePath(0,'cgi-bin/game/data/reference.htm'):'data/reference.htm'
    2465
    2466  if(typeof o.contentWindow=='object'&&typeof o.contentWindow.document=='object'){	//	typeof o.contentWindow=='object'&&: for JS5	應該不能用o.contentWindow吧？怕o.contentWindow就算沒能載入文件，也會被定義
    2467   //	Martin Honnen wrote: If you load a new document then certainly the browser has to create a new document object.
    2468   referenceDoc=o.contentWindow;//.document;	o.contentWindow.document still index to a blank window here, when new document load, this point to document won't work.
    2469
    2470   //window.status='Wait while reference page loading..2';alert(window.status+'\nURL:'+o.src);
    2471   setTimeout(thisFuncName+'();',20);//loadReferenceCount=9;
    2472  }else{
    2473   //if(location.protocol=='https:')return;	//	https會拒絕存取，所以直接放棄。最晚在這就得判別
    2474   if(!referenceDoc)referenceDoc=40;	//	尚未load完成時作倒數計時..假如加上if(o.contentWindow)，這方法正確嗎?
    2475   //else if(isNaN(referenceDoc))return 3;	//	異常(for https):不能用else if(isNaN(referenceDoc))
    2476   try{
    2477    if(referenceDoc--){
    2478     //window.status='Wait while reference page loading..';alert(window.status);
    2479     setTimeout(thisFuncName+'();',300);return 2;
    2480    }else{
    2481     //window.status='reference page load FAILED!';alert(window.status);
    2482     return 4;
    2483    }
    2484   }catch(e){
    2485    return 5;	//	Error: uncaught exception: Permission denied to get property HTMLDocument.document
    2486   }
    2487  }
    2488 }
    2489 //	translate object(innerHTML) from reference page to document
    2490 //transRefObj[generateCode.dLK]='get_element';
    2491 function transRefObj(id,id2,force){
    2492  if(typeof id2!='string'&&typeof id2!='object')force=id2,id2=typeof id=='object'?id.id:id;
    2493  var o=typeof id=='object'?id:_.get_element(id,_.get_element.f.self),p;
    2494  //alert('transRefObj: '+id2+' -> '+id+'('+(force?'':'not ')+'force)\n'+o+'\ntarget:'+(o.innerHTML?'\n'+o.innerHTML.slice(0,200):' (null)'));
    2495  if( o && (force||!o.innerHTML)
    2496 	&& (p=typeof id2=='object'?id2:_.get_element(id2,_.get_element.f.refOnly)) && (force||p.innerHTML) )
    2497   try{
    2498 	//alert('transRefObj: DO '+id2+' -> '+id+'('+(force?'':'not ')+'force)\n');
    2499 	o.appendChild(p.cloneNode(true));
    2500   }catch(e){
    2501 /*
    2502    try{
    2503 	//alert('transRefObj: try2');
    2504 	var i=0;while(i<p.childNodes.length)o.appendChild(p.childNodes[i++].cloneNode(true));
    2505    }catch(e){
    2506 */
    2507 	//alert('transRefObj: try3');
    2508 	o.innerHTML=p.innerHTML;//p.cloneNode(true);	//serialize(p)	serialize方法把一个node串行化成字符串。在ie环境的具体实现上，对于XmlDocument，使用node.xml，对于HtmlDocument，使用node.outerHTML。	http://my.opera.com/gisor/blog/index.dml/tag/SVG
    2509 /*
    2510    }
    2511 */
    2512   }
    2513  return o;
    2514 }
    2515
    2516 //	↑reference page set	==================
    2517
    2518
    2519
    2520
    2521
    2522 //	設定自動捲動
    2523 var setAutoScrollTimer,setAutoScrollInterval;
    2524 //setAutoScroll[generateCode.dLK]='setAutoScrollTimer,setAutoScrollInterval';
    2525 function setAutoScroll(interval,force){
    2526  if(!force)if(typeof document!='object'||setAutoScrollTimer||document.onmousedown||document.ondblclick)return;
    2527  if(interval)setAutoScrollInterval=interval;else if(!setAutoScrollInterval&&!(setAutoScrollInterval=get_cookie('setAutoScrollInterval')))setAutoScrollInterval=200;//5,50,100,200,500
    2528  clearInterval(setAutoScrollTimer),setAutoScrollTimer=0;	//	無論如何，先把執行中的幹掉。
    2529  if(setAutoScrollInterval<0){document.onmousedown=document.ondblclick=null;return;}
    2530  document.onmousedown=function(){if(setAutoScrollTimer)window.clearInterval(setAutoScrollTimer),setAutoScrollTimer=0;};
    2531  document.ondblclick=function(){if(setAutoScrollTimer)return;setAutoScrollTimer=window.setInterval('window.scrollBy(0,1);',setAutoScrollInterval);};//window.scrollTo(0,document.body.scrollTop+1);
    2532 }
    2533
    2534
    2535 /*	捲到設定的定點，因為某些多工慢速環境中只設定一次沒有用，所以…
    2536 	下面一行調到檔案頭
    2537 var scrollToXY,scrollToInterval,scrollToOK;
    2538 */
    2539 //scrollTo[generateCode.dLK]='scrollToXY,scrollToInterval,scrollToOK,get_window_status';
    2540 function scrollTo(y,x){
    2541  //	initial
    2542  if(typeof scrollToXY!='object')scrollToXY={};
    2543
    2544  if(typeof y=='object'&&(!isNaN(y.x)||!isNaN(y.y))){if(!isNaN(y.x))scrollToXY.x=y.x;if(!isNaN(y.y))scrollToXY.y=y.y;}
    2545  else if(y instanceof Array)scrollToXY.x=y[0],scrollToXY.y=y[1];
    2546  else{if(typeof x!='undefined')scrollToXY.x=x;if(typeof y!='undefined')scrollToXY.y=y;}
    2547  if(isNaN(scrollToXY.x))scrollToXY.x=0;if(isNaN(scrollToXY.y))scrollToXY.y=0;
    2548
    2549  setTimeout('window.scrollTo(scrollToXY.x,scrollToXY.y);',9);	//	main function
    2550  var _w=get_window_status();
    2551  //status=scrollToInterval+','+scrollToOK+';'+_w.scrollX+','+scrollToXY.x+';'+_w.scrollY+','+scrollToXY.y;
    2552  if(_w.scrollX==scrollToXY.x&&_w.scrollY==scrollToXY.y){
    2553   if(!--scrollToOK&&scrollToInterval)window.clearInterval(scrollToInterval),scrollToInterval=0;
    2554  }else if(!scrollToInterval)scrollToInterval=window.setInterval(scrollTo,90),scrollToOK=3;	//	預防萬一：總會跳回原處
    2555 }
    2556
    2557 /*	doAlert() & doAlertAccess：彈出使用注意事項視窗
    2558 	下面一行調到檔案頭
    2559 var doAlertDivName,doAlertOldScrollLocation;
    2560
    2561 TODO
    2562 設定其不可作用之 background object
    2563
    2564 	使用方法：
    2565 <head>
    2566 <script type="text/javascript" src="function.js"></script>
    2567 <script type="text/javascript">
    2568 window.onload=init;window.onscroll=window.onresize=doAlertScroll;
    2569 function init(){doAlertInit('kousi');}
    2570 </script>
    2571
    2572 <style type="text/css"><!--
    2573
    2574 /*	kousi用	加上filter:alpha(opacity=10);：因為IE5.5不吃DXImageTransform.Microsoft.Alpha，這樣用不能以.filters.alpha.opacity控制。	* /
    2575 #kousi{color:blue;background:#e2e0f8;border:double 3px red;padding:.5em;filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80,Style=0);filter:Alpha(Opacity=80,Style=0);z-index:2;overflow:auto;}
    2576 #kousiBg{background:blue;filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=30,Style=0);filter:Alpha(Opacity=30,Style=0);z-index:1;}
    2577 #kousiI{color:brown;background-color:#e6e6ff;cursor:pointer;border:1 solid red;white-space:nowrap;padding:2px;margin:2px;filter:Alpha(Opacity=80,Style=0);}
    2578
    2579 #kousi h2{color:brown;margin-left:2em;}
    2580 #kousi input{color:#114f12;background-color:#fddbfb;border:1 brown solid;}
    2581
    2582 --></style>
    2583 </head>
    2584
    2585 <body>
    2586 <!--div id="kousiBg"></div--><div id="kousi">
    2587 <h2>使用注意事項</h2>
    2588
    2589 注意事項
    2590
    2591 <hr style="color:#928cd9"/>
    2592 <table style="width:90%;text-align:center;"><tr><td><input type="button" onclick="top.location.href='http://www.hinet.net';" value="誰管你！"/></td>
    2593 <td><input type="button" onclick="doAlertAccess();//this.parentNode.parentNode.parentNode.parentNode.parentNode.id" value="我願意遵守上述規定"/></td>
    2594 <td><input type="button" onclick="set_cookie(set_cookie.f.forever),set_cookie('doAlert',doAlertDivName),doAlertAccess();" value="我往後皆會遵守上述規定"/></td></tr></table>
    2595 </div>
    2596
    2597 <a href="#" onclick="doAlert();">注意事項</a>
    2598
    2599 正文
    2600
    2601 </body>
    2602 */
    2603 function doAlertResize(){	//	確保置中
    2604  if(typeof doAlertDivName!='string'||!doAlertDivName||!(o=document.getElementById(doAlertDivName)))return;
    2605  with(o.style){
    2606   position='absolute',display='block',width='70%';
    2607 /*	因為'%'是以整體長寬為主，故不適用。
    2608   var t=Math.round(50*(1-o.offsetHeight/document.body.clientHeight));
    2609   if(t<0)width='99%',top='0';else top=t+'%';
    2610   t=Math.round(50*(1-o.offsetWidth/document.body.clientWidth));
    2611   left=t<0?'0':t+'%';
    2612 */
    2613   //alert(offsetHeight+','+window.offsetHeight+','+window.innerHeight+','+window.outerHeight);
    2614   if(typeof window.innerHeight=='undefined')window.innerHeight=document.body.clientHeight;
    2615   if(typeof window.innerWidth=='undefined')window.innerWidth=document.body.clientWidth;
    2616   var t=(window.innerHeight-o.offsetHeight)/2;
    2617   if(t<0)width=height='99%',top=0;else top=t+'px';
    2618   t=(window.innerWidth-o.offsetWidth)/2;
    2619   left=t<0?0:t+'px';	//	不用marginTop與marginLeft，因為這裡要放置div
    2620  }
    2621 }
    2622 //	初始化
    2623 //doAlertInit[generateCode.dLK]='set_cookie,doAlert';
    2624 function doAlertInit(n){	//	n:div name
    2625  //if(typeof doAlertDone!='undefined'&&doAlertDone)return;	//	防止重複執行
    2626  if(!n){	//	doAlertInit()重設
    2627 	 _.set_cookie(_.set_cookie.f.set_root);	//	Gecko need this
    2628 	 _.set_cookie('doAlert');
    2629   return;
    2630  }
    2631  var d=document.getElementById(n);
    2632  if(d){
    2633   if(typeof doAlertDivName=='undefined')doAlertDivName=n;
    2634   doAlert();
    2635  }
    2636 }
    2637 //	出現警告
    2638 //doAlert[generateCode.dLK]='doAlertInit,doAlertResize,doAlertAccess,doAlertScroll,doAlertDivName,doAlertOldScrollLocation,get_cookie,get_window_status';
    2639 function doAlert(n,m,iconContent){	//	n:name,m:mode=1:use alert(),icon div的文字內容
    2640  if(!n&&typeof doAlertDivName=='string'&&doAlertDivName)n=doAlertDivName;
    2641  var o=document.getElementById(n),oBg=document.getElementById(n+'Bg'),oI=document.getElementById(n+'I');
    2642  if(!document.body||!o||m&&!alert(o.innerHTML))return;	//	alert()會return undefined
    2643  if(!oI)try{
    2644   o.parentNode.insertBefore(oI=document.createElement('div'),o);//document.body.insertBefore();
    2645   oI.id=n+'I';oI.onclick=function(){doAlertInit();doAlert();};oI.title="注意事項";
    2646   oI.innerHTML=iconContent||'別忘了';oI.doAlertScrollT=oI.doAlertScrollL=0;
    2647  }catch(e){return;}	//	只對IE5.5之後有用
    2648  if(!oBg)try{o.parentNode.insertBefore(oBg=document.createElement('div'),o);oBg.id=n+'Bg';}catch(e){return;}	//	只對IE5.5之後有用
    2649  //if(!oI||!oBg)alert('No index or bg div!');
    2650  disableKM(2);doAlertResize();window.Oonresize=window.onresize,window.onresize=doAlertResize;
    2651  with(oI.style)display='none',position='absolute',right='.1em',top='.1em';
    2652  with(oBg.style)position='absolute',left=-parseInt(document.body.leftMargin),top=-parseInt(document.body.topMargin),width=height='110%',display='inline';	//	offset*:唯讀
    2653  if(o.filters)o.filters.alpha.opacity=85;//try{o.filters.alpha.opacity=85;}catch(e){}
    2654  if(oBg.filters)try{oBg.filters.alpha.opacity=30;}catch(e){}
    2655  else{	//	for Moz
    2656   o.style.position='fixed';
    2657   with(oBg.style)position='fixed',opacity=oBg.style['-moz-opacity']=.3,left=top=0,width=height='100%';
    2658  }
    2659  if(get_cookie('doAlert')==n)doAlertAccess(n);
    2660  else o=get_window_status(),doAlertOldScrollLocation=[o.scrollX,o.scrollY],setTimeout('scrollTo(0,0);',0);	//	奇怪的是，直接執行scrollTo(0,0)沒啥用。
    2661 }
    2662 //	pass
    2663 function doAlertAccess(n){
    2664  if(!n&&typeof doAlertDivName=='string'&&doAlertDivName)n=doAlertDivName;
    2665  var o=document.getElementById(n),oBg=document.getElementById(n+'Bg');
    2666  if(oBg)oBg.style.display='none';o.style.display='none';
    2667  disableKM(0);
    2668  window.onresize=window.Oonresize||null;
    2669  if(doAlertOldScrollLocation)scrollTo(doAlertOldScrollLocation,0,1);
    2670  doAlertScroll(1);
    2671 }
    2672 //	icon div的捲動：置於右上角
    2673 //doAlertScroll[generateCode.dLK]='get_window_status';
    2674 function doAlertScroll(m){var oI;
    2675  if(typeof doAlertDivName!='string'||!doAlertDivName||!(oI=document.getElementById(doAlertDivName+'I')))return;
    2676  if(typeof m!='undefined'){
    2677   oI.style.display=m?'block':'none';
    2678   oI.doAlertScrollL=oI.offsetWidth+(m||0);
    2679   if(oI.currentStyle){	//	IE
    2680    if(m=parseInt(oI.currentStyle.paddingTop))oI.doAlertScrollT=m;
    2681    m=parseInt(oI.currentStyle.paddingLeft);
    2682    if(m=parseInt(oI.currentStyle.paddingRight))oI.doAlertScrollL+=m;
    2683   }else{
    2684    oI.style.position='fixed';
    2685 /*	//	Moz..but no use
    2686    if(m=oI.offsetTop)oI.doAlertScrollT=m;
    2687    m=oI.offsetLeft;
    2688    if(m=oI.offsetRight)oI.doAlertScrollL+=m;
    2689 */
    2690   }
    2691  }
    2692  //window.status=m=window.scrollX+','+window.scrollY+','+window.innerWidth+','+window.innerHeight+';'+document.body.scrollLeft+','+document.body.scrollTop+','+document.body.offsetWidth+','+document.body.clientWidth+','+oI.offsetWidth+','+document.body.scrollWidth;alert(m);
    2693  m=get_window_status();
    2694  oI.style.left=m.scrollX+m.windowW-oI.doAlertScrollL+'px';//-document.body.leftMargin-document.body.rightMargin
    2695  oI.style.top=m.scrollY-oI.doAlertScrollT+'px';	//	只有在padding用px時有效！
    2696 }
    2697
    2698
    2699 CeL.net.web
    2700 .
    2701 /**
    2702  * Sets / adds class of specified element.<br/>
    2703  * TODO:<br/>
    2704  * 1. 一次處理多個 className。<br/>
    2705  * 2. 以字串處理可能較快。<br/>
    2706  * 3. 用 +/- 設定。<br/>
    2707  * 4. https://developer.mozilla.org/en/DOM/element.classList
    2708  * @param element	HTML elements
    2709  * @param class_name	class name || {class name 1:, class name 2:, ..}
    2710  * @param flag
    2711  * default: just add the specified className
    2712  * (flag&1)==1:	reset className (else just add)
    2713  * (flag&2)==1:	return {className1:, className2:, ..}
    2714  * (flag&4)==1:	remove className
    2715  * @return
    2716  * @see
    2717  * <a href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-95362176" accessdate="2009/12/14 22:26">className of type DOMString</a>,
    2718  * <a href="https://developer.mozilla.org/En/DOM/Element.className" accessdate="2009/12/14 22:27">element.className - MDC</a>
    2719  * @memberOf	CeL.net.web
    2720  */
    2721 set_class = function(element, class_name, flag) {
    2722 	if (typeof element === 'string')
    2723 		element = document.getElementById(element);
    2724
    2725 	if (typeof element !== 'object' || !element || typeof element.className !== 'string')
    2726 		return;
    2727 	// if(!flag)flag=0;
    2728 	var c, remove = (flag & 4) == 4;
    2729
    2730 	if (class_name && !remove) {
    2731 		c = class_name instanceof Array ? class_name.join(' ') : class_name;
    2732 		if (flag & 1)
    2733 			element.className = c;
    2734 		else
    2735 			// add 時不 detect 是為了速度
    2736 			element.className += ' ' + c;
    2737
    2738 		if ((flag & 2) != 2)
    2739 			return;
    2740 	}
    2741
    2742 	//sl('set_class: remove [' + class_name + '] from [' + o.className + ']');
    2743 	c = element.className.split(/\s+/);
    2744 	var r = {}, i;
    2745
    2746 	for (i in c)
    2747 		r[c[i]] = 1;
    2748
    2749 	if (remove && class_name) {
    2750 		if (!(class_name instanceof Array))
    2751 			class_name = [ class_name ];
    2752 		for (i in class_name) {
    2753 			c = class_name[i];
    2754 			if (c in r) {
    2755 				// has removed
    2756 				remove = 0;
    2757 				delete r[c];
    2758 			}
    2759 		}
    2760 		if (!remove) {
    2761 			c = [];
    2762 			for (i in r)
    2763 				c.push(i);
    2764 			element.className = c.join(' ');
    2765 		}
    2766 	}
    2767
    2768 	//sl('set_class: → ['+o.className+']');
    2769 	return r;
    2770 };
    2771
    2772 //	if cN instanceof RegExp, cN should has NO global flag.
    2773 CeL.net.web
    2774 .
    2775 /**
    2776  * If HTML element has specified class
    2777  * @param {HTMLElement} element	HTML elements
    2778  * @param {String} class_name	class_name_1[ class_name_2 ..]
    2779  * @return	{Boolean}
    2780  */
    2781 has_class = function(element, class_name) {
    2782 	var _s = _.has_class, n = element.className, i;
    2783 	//class_name = class_name.replace(/\s+$|^\s+/g, '');
    2784 	if (!n || !class_name)
    2785 		return;
    2786
    2787 	if (class_name instanceof Array) {
    2788 		for (i = n = 0; i < class_name.length; i++)
    2789 			if (_s(element, class_name[i]))
    2790 				n++;
    2791 		return n;
    2792 	}
    2793
    2794 	if (class_name instanceof RegExp)
    2795 		return class_name.test(n);
    2796
    2797 	if (n === class_name)
    2798 		return true;
    2799
    2800 	//return (new RegExp('(^|\\s)' + class_name + '(\\s|$)'/* ,i */)).test(n);
    2801 	return (' '+n+' ').indexOf(' ' + class_name + ' ')!==-1;
    2802 };
    2803
    2804
    2805 CeL.net.web
    2806 .
    2807 /**
    2808  * @param {String} class_name	class_name_1[ class_name_2 ..]
    2809  * @param {HTMLElement} element	HTML elements
    2810  * @param {HTMLElement} parent_node	parent node
    2811  * @param {String} tag_name	tag name
    2812  * @return	{[HTMLElement]}	nodes
    2813  * @see
    2814  * document.getElementsByClassName in prototype.js,
    2815  * jquery('.class')
    2816  *
    2817  * document.querySelector()
    2818  * http://www.w3.org/TR/selectors-api/
    2819  * http://blog.darkthread.net/blogs/darkthreadtw/archive/2008/04/17/document-queryselector-in-ie8.aspx
    2820  */
    2821 find_class = function(class_name, parent_node, tag_name, call_function,
    2822 		flag) {
    2823 	var elements = class_name
    2824 			&& (parent_node || document).getElementsByTagName(tag_name || '*'), l = elements
    2825 			&& elements.length;
    2826
    2827 	if (l) {
    2828 		var i = 0, c = [], r = new RegExp('(^|\\s)' + class_name + '(\\s|$)'/* ,i */);
    2829 		for (; i < l; i++)
    2830 			if (r.test(elements[i].className)/* has_class(elements, r) */
    2831 					&& (!call_function || call_function.call(elements[i])))
    2832 				c.push(elements[i]);
    2833 		return c;
    2834 	}
    2835
    2836 	return null;
    2837 };
    2838
    2839
    2840
    2841
    2842
    2843 /*	處理 popup 用
    2844 	對className的tag作popup處理
    2845 	window.onload="dealPopup()";
    2846 	<b title="注釋">正文</b>
    2847 */
    2848 //dealPopup[generateCode.dLK]='sPop,has_class';
    2849 function dealPopup(tag,classN,func){
    2850 	if (!tag)
    2851 		tag = 'b';
    2852
    2853 /*
    2854 	http://enable.nat.gov.tw/document/4_2.jsp
    2855 	http://ccca.nctu.edu.tw/~hlb/tavi/ABBRorACRONYM
    2856 	應該用abbr(abbreviation/abbrevitated form/簡稱)
    2857 	abbr包含acronym(頭文字/首字母縮寫,通常這個字的發音像一個字)
    2858 	根據W3C的規範說，中日文的縮寫格式要套用的是abbr標籤。
    2859 	XHTML2.0把acronym移掉了，只剩下abbr標籤。
    2860 	http://www.sovavsiti.cz/css/abbr.html
    2861 	if(!!document.all)document.body.innerHTML=document.body.innerHTML.replace(/<\s*(\/?)\s*abbr([>\s])/gi,'<$1span$2');
    2862 */
    2863
    2864 	var i, j, o = document.getElementsByTagName(tag), tp;
    2865 	dealPopup.list=[];
    2866 	if(o.length)for(i=0;i<o.length;i++){
    2867 		if (classN && !has_class(o[i], classN) || func
    2868 				&& func(o[i]))
    2869 			continue;
    2870 		//	測試是否有特定標籤
    2871 		for (j = 0, tp = ''; j < sPopP.allTypes.length; j++)
    2872 			if (o[i][sPopP.allTypes[j]]) {
    2873 				tp = sPopP.allTypes[j];
    2874 				break;
    2875 			}
    2876 		//	有的話設定event
    2877 		if( tp && (tp=sPop(o[i],sPopF[tp]|sPopF.nopop)) ){
    2878 			//o[i].innerHTML+='<b style="color:peru">['+sPopP.types[tp]+']<\/b>';
    2879
    2880 			dealPopup.list.push(o[i]);
    2881 			if(tp==sPopF.window){
    2882 				if(!o[i].onclick)o[i].onclick=new Function('sPop(this,'+tp+');'),o[i].style.cursor='pointer';
    2883 			}else if(tp==sPopF.popup){
    2884 				if(!o[i].onmouseover){//o[i].ruby=o[i].popup='',
    2885 					o[i].onmouseover=new Function('sPop(this,'+tp+');');
    2886 					if(!o[i].onmouseout)o[i].onmouseout=new Function('sPop(this,sPopF.clearPop);');
    2887 					if(!o[i].onclick)o[i].onclick=new Function('this.onmouseout=null;sPop(this,'+tp+');'),o[i].style.cursor='pointer';
    2888 				}
    2889 				//else alert(tp+'\n'+sPopF[tp]+'\n'+typeof o[i].onmouseover+'\n'+o[i].onmouseover);
    2890 			}
    2891 		}
    2892 	}
    2893 }
    2894 /*	注釋(reference) / show popup-window or ruby	2004/4/3 17:20
    2895 	http://www.comsharp.com/GetKnowledge/zh-CN/TeamBlogTimothyPage_K742.aspx
    2896
    2897 example:
    2898 	<b onmouseover="sPop(this,sPopF._type_,'注釋')">txt</b>
    2899 	<b onmouseover="sPop(this,sPopF._type_)" title="注釋">txt</b>
    2900 	window.onload="dealPopup()"; + <b title="注釋">txt</b>,<b sPop="注釋">txt</b>
    2901 	<b onmouseover="sPop('．',this)">txt</b>	在每個字旁邊加上[．]或[。]
    2902 	sPop('txt')	popup txt(自動設成sPopF.popup)
    2903 	sPop('txt',sPopF.window)	popup txt by window
    2904
    2905 flag & type:
    2906 	sPopF.title/sPopF.auto	（依字數）自動選取
    2907 	sPopF.ruby	採用<ruby>
    2908 	sPopF.popup	採用popup window
    2909 	sPopF.window	將資料開在新視窗
    2910
    2911 	sPopF.nopop	just test, don't popup(for ruby)
    2912 	sPopF.repeat	repeat ruby
    2913 	sPopF.clearPop	clear popup window
    2914 	sPopF.force	若是不能使用此種表示方法，則放棄顯示。(for popup @ Mozilla)
    2915
    2916 style class application(應用):
    2917 	sPopP.DclassName中所定之className為觸發事件時會設定的class
    2918
    2919 執行環境environment:
    2920 	JScript @ HTML
    2921
    2922 include function:
    2923 	String.x()
    2924 	parseFunction()
    2925 	setObjValue()
    2926
    2927 TODO:
    2928 submenu
    2929 	http://dynamicdrive.com/dynamicindex1/popupmenu.htm
    2930 Tipped - The Javascript Tooltip Framework
    2931 	http://projects.nickstakenburg.com/tipped
    2932
    2933 How to Create a Valid Non-Javascript Lightbox | Carsonified
    2934 http://carsonified.com/blog/design/css/how-to-create-a-valid-non-javascript-lightbox/
    2935
    2936 move/resize/最小化: popup dialog
    2937 	http://deluxepopupwindow.com/html-popup-dialog-vista-graphite.html
    2938
    2939 獨佔 window, 訊息列, 多功能(HTML+Script)內容
    2940 	http://vision-media.ca/resources/jquery/jquery-popup-plugin-review
    2941
    2942 key (Esc)
    2943 time limit
    2944
    2945 */
    2946 var sPopP={}	//	sPop properties object
    2947 	,sPopF	//	flag
    2948 	,sPopError//	for error
    2949 	;
    2950
    2951 //	初始值設定 & 設定flag
    2952 //if(sPopP)alert('sPopP 已被佔用！');else
    2953 function sPopInit(){
    2954
    2955 	//	預設style class name:(null:used last time),ruby,popup,window
    2956 	sPopP.DclassName=',popupedTxt_ruby,popupedTxt,popupedTxt'.split(',');
    2957 	//	已登記的背景style,請在CSS中加入[sPopC]_[body class name]
    2958 	sPopP.bgS='bgb,bgn';
    2959 {
    2960  var i=0,t=sPopP.bgS.split(',');sPopP.bgS={};
    2961  for(;i<t.length;i++)sPopP.bgS[t[i]]=i+1;
    2962 }
    2963 	//	popup window style
    2964 	sPopP.popupS="color:blue;padding:.5em;overflow:auto;position:absolute;top:0;left:0;width:100%;height:100%;scrollbar-face-color:khaki;scrollbar-arrow-color:teal;border:1px solid green;font:normal 10pt tahoma;filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#ffd700, EndColorStr=#ffffff);";
    2965 	//	chars to repeat(for ruby)
    2966 	sPopP.RepeatC='‧．。ヽ○●◎☆★※＊＃▽▼△▲◆◇□■↓↑';//.turnU();
    2967 	//	types:auto,這些attribute可被處理，且將被視為自動選取type。
    2968 	sPopP.autoTypes='title,_sPop';//+',_'+sPopP.functionName
    2969 	//	types,最多七種
    2970 	sPopP.types='ruby,popup,window';	//	+div(參考dealLinkPopup())
    2971 	//	所有可用的types，可用來detect是否能為sPop()所接受。但Mozilla中無法使用title之外的attribute。
    2972 	sPopP.allTypes=(sPopP.autoTypes+','+sPopP.types).split(',');
    2973 	//	function name
    2974 	sPopP.functionName='';//;parseFunction().funcName;
    2975 	//	popup window(for popup)
    2976 	if(typeof window.createPopup!='undefined')sPopP.window=window.createPopup();
    2977 {
    2978  var i=0,t=sPopP.types.split(','),T='';
    2979  for(;i<t.length;)T+=t[i]+'='+ ++i+',';//alert(T);
    2980  setObjValue('sPopF','title=0,auto=0,'
    2981 	//+'_'+sPopP.functionName+'=0,'
    2982 	+T+'nopop=8,repeat=16,clearPop=32,force=64','int');
    2983 }
    2984 //	sPopP.types[index]=type name
    2985 sPopP.types=(
    2986 	//'_'+sPopP.functionName+
    2987 	','+sPopP.types).split(',');
    2988 sPopP.commentTitle='Comment';	//	註解
    2989 sPopP.commentTitlePattern=sPopP.commentTitle+' of %s';
    2990 sPopP.closeM='Close';	//	close message: 關閉視窗或popup
    2991 sPopP.biggerM='Bigger';	//	bigger message: 放大
    2992 sPopP.resetM='Reset size';	//	reset size message: 回復原大小
    2993 }
    2994
    2995 //	主object(正文或主object，會從之取得正文與注釋)[, flag, text string or object(注釋,會蓋過從主object取得之text), 使用的class name]
    2996 //sPop[generateCode.dLK]='sPopP,sPopF,sPopInit,*sPopInit();';
    2997 function sPop(oPos,flag,oTxt,classN){
    2998  //if(flag&sPopF.clearPop){if(sPopP.window)sPopP.window.hide();return;}
    2999
    3000  //	input value test & 修正
    3001  if(!oPos&&!oTxt)return;
    3002
    3003  var limitW=screen.width-50,limitH=screen.height>>1;
    3004  if(!sPopP.width)sPopP.width=250;if(sPopP.width>limitW)sPopP.width=limitW;
    3005  if(!sPopP.height)sPopP.height=100;if(sPopP.height>limitH)sPopP.height=limitH;
    3006
    3007  //	初始值設定
    3008  if(!sPopP.functionName)
    3009   sPopF[ sPopP.types[0]='_'+(sPopP.functionName=parseFunction().funcName) ]=0;
    3010
    3011  var repopMark='repop',repop=oPos===repopMark,nopop=flag&sPopF.nopop,tp=flag&7
    3012 	,useAttbTxt=false,brReg=/\r*\n/g,brT='<br/>\n';	//	轉成br用
    3013
    3014 if(repop){
    3015   if( !sPopP.popObj || typeof sPopP.popObj!='object' || typeof sPopP.popObj.innerHTML!='string' || !sPopP.popObj.innerHTML )return;
    3016   oPos=sPopP.popObj,tp=sPopF.popup;	//	重pop時不作其他判別處置
    3017 }else{
    3018
    3019  //	處理object
    3020  if( typeof oPos=='string' && oPos )
    3021   if( oPos.length<32 && document.getElementById(oPos) )
    3022    oPos=document.getElementById(oPos);	//	輸入object name時轉成object
    3023   else if(!oTxt)oTxt=oPos	//	若只輸入oPos，將之當作注釋(oTxt)。
    3024 	//,oPos=typeof null=='object'?0:null;
    3025 	,oPos=0;	//	若是typeof null=='object',請設成false
    3026
    3027  //	設定oTxt 1/4
    3028  if( typeof oTxt=='object' && oTxt.innerHTML )oTxt=oTxt.innerHTML;
    3029  else if(oTxt)oTxt+='';	//	轉成string
    3030
    3031  //	(自動)判別使用的type
    3032  var useAutoTxt;
    3033  if(tp==sPopF.auto){
    3034   //	設定oTxt 2/4 : 知道是自動判別後先設定
    3035   if( typeof oPos=='object' && (!oTxt||oTxt==0) )
    3036    if(oPos[sPopP.types[0]])oTxt=oPos[sPopP.types[0]],useAutoTxt=true;
    3037    else if(oPos.title)oTxt=oPos.title,useAutoTxt=true;	//	以<b title="~">的用法來說，這是最常經過的path
    3038
    3039   //	假如沒有oTxt.gText()，改成oTxt.replace(/<[^>]*>/g,'')之即可。這是為了預防HTML的情形。
    3040   var len=typeof oTxt=='string'?oTxt.length:0;//typeof oTxt=='string'?oTxt.length:typeof oTxt=='object'&&oTxt.innerHTML?oTxt.innerHTML.length:0;
    3041   //alert(len+','+(len*.7)+','+oPos.innerHTML.length);
    3042   if( typeof oPos=='object' && ( oPos.doneRuby || !oPos.innerHTML.match(/<\s*ruby/i) && (len<60&&len*.7-9<(typeof oPos.innerText=='string'?oPos.innerText:oPos.innerHTML).length) ) )
    3043    tp='ruby';	//	ruby的條件
    3044   else if(sPopP.window&&len<300){
    3045    tp='popup';
    3046    if(typeof oPos=='object'&&oPos.title===oTxt)oPos[sPopP.types[0]]=oTxt,oPos.title='';
    3047   }else tp='window';
    3048
    3049   //	設定oTxt 3/4 & type
    3050   if( typeof oPos=='object' && (!oTxt||oTxt==0) )
    3051    if(oPos[tp])oTxt=oPos[tp],useAutoTxt=true;
    3052
    3053   tp=sPopF[tp];
    3054  }
    3055
    3056  //	設定oTxt 4/4
    3057  if( !oTxt||oTxt==0 && typeof oPos!='object')
    3058   if( (oTxt=oPos[sPopP.types[tp]]) || (oTxt=oPos[sPopP.types[0]]) || (oTxt=oPos.title) )useAutoTxt=true;else return;
    3059
    3060  //	設定className與position
    3061  sPopP.left=0,sPopP.top=20;	//	popup left,popup top初始值
    3062  if( !oPos || typeof oPos!='object')
    3063   //	popup 在滑鼠指標處
    3064   //	see: add_listener()
    3065   try{sPopP.left+=event.offsetX,sPopP.top+=event.offsetY;}catch(e){}
    3066  else if( !oPos.className && sPopP.DclassName[tp] ){
    3067   if(!classN&&(classN=document.body.className)&&!sPopP.bgS[classN])classN=0;
    3068   oPos.className=sPopP.DclassName[tp]+(classN?'_'+classN:'');
    3069   var w,s=oPos.style;if(!s.fontWeight&&(w=oPos.parentNode.style.fontWeight))s.fontWeight=w;	//	除非有明確設定font-weight，否則通常不會有效
    3070  }
    3071 }
    3072
    3073  //	修正
    3074  if( tp==sPopF.popup && !sPopP.window && !(flag&sPopF.force) )
    3075   tp=sPopF.window;	//	Mozilla中無法顯示popup
    3076
    3077
    3078  //alert(sPopP.types[tp]+','+( sPopP.window || flag&sPopF.force )+','+oTxt);
    3079  //	處理pop
    3080  if(tp==sPopF.ruby){
    3081   if(typeof oPos!='object'||!oPos.innerHTML)return;	//	oPop非HTML element就return
    3082   if(oPos.doneRuby)return tp;	//	已經處理過<ruby>就pass
    3083   //	處理repeat
    3084   if( flag&sPopF.repeat || sPopP.RepeatC.indexOf(oTxt)!=-1 )
    3085    oPos.title='',oTxt=window.navigator.userAgent.indexOf("MSIE")<0?'':oTxt.x(oPos.innerHTML.length/oTxt.length);	//	只有IE提供ruby，所以這時候不宜加入旁點功能。
    3086
    3087   try{
    3088    oPos.innerHTML='<ruby><rb>'+oPos.innerHTML+'<\/rb><rp>'
    3089 	//	半形與全形的括弧
    3090 	+(oTxt?window.navigator.userAgent.indexOf("Opera")>=0||/^[a-z\d\s_,.;"'\[\]{}+\-*\/]*$/i.test(oTxt)?'(<\/rp><rt>'+oTxt+'<\/rt><rp>)':'（<\/rp><rt>'+oTxt+'<\/rt><rp>）':'<\/rp><rt><\/rt><rp>')
    3091 	+'<\/rp><\/ruby>';
    3092   }catch(e){
    3093    var n=e.number&0xFFFF;
    3094    if(n==601&&(typeof sPopError=='undefined'||sPopError!=n))alert('Error: '+e.description+' at\n'+oPos.outerHTML+'\n\n★也許是在這之前的tag出錯，例如有<b>卻沒有<\/b>。');
    3095    sPopError=n;
    3096   }
    3097   oPos.doneRuby=true;
    3098
    3099  }else if(tp==sPopF.popup){
    3100   if(nopop||!sPopP.window)return tp;
    3101   if(!repop){
    3102    if(useAutoTxt)oTxt=oTxt.replace(brReg,brT);
    3103    //	這是一種註解功能，在mouseout後，假定讀者繼續讀下去，所以就讓popup object消失。想要多看一點的，會去按他，這時才讓popup object繼續存在。
    3104    sPopP.window.document.body.innerHTML=//oTxt=
    3105 	'<div style="'+sPopP.popupS+'" onblur="parent.sPopP.window.hide();" title="reference">[<b style="color:peru;cursor:pointer;" onclick="parent.sPopP.window.hide();">'+sPopP.closeMessage+'<\/b>] [<b style="color:green;cursor:pointer;" onclick="with(parent)sPopP.width+=100,sPopP.height+=50,'
    3106 	+sPopP.functionName+'(\''+repopMark+'\');">'+sPopP.biggerM+'<\/b>] [<b style="color:orange;cursor:pointer;" onclick="with(parent)sPopP.width=sPopP.height=0,'+sPopP.functionName+'(\''+repopMark+'\');">'+sPopP.resetM+'<\/b>]<hr style="color:purple;height:1px"/>'+oTxt.replace(/'/g,''')+'<\/div>';
    3107    sPopP.popObj=oPos||document.body;	//	object deal now(for popup:repop)
    3108    //if(typeof oPos.onmouseout!='undefined')oPos.onmouseout=function(){sPopP.window.hide();};
    3109   }
    3110   //alert(sPopP.width+','+sPopP.height);
    3111   if(flag&sPopF.clearPop)sPopP.window.hide();
    3112   else sPopP.window.show(sPopP.left,sPopP.top,sPopP.width,sPopP.height,oPos||document.body);
    3113
    3114  }else if(tp==sPopF.window){
    3115   if(nopop)return tp;
    3116   //if(typeof netscape=='object')netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserWrite");	//	創造無邊框視窗:titlebar=no	dependent:ns only	全螢幕：channelmode	带有收藏链接工具栏的窗口：directories	网页对话框：'dialogWidth:400px;dialogHeight:300px;dialogLeft:200px;dialogTop:150px;center:yes;help:yes;resizable:yes;status:yes'
    3117 /*
    3118 dialogHeight: iHeight 设置对话框窗口的高度。
    3119 dialogWidth: iWidth 设置对话框窗口的宽度。
    3120 dialogLeft: iXPos 设置对话框窗口相对于桌面左上角的left位置。
    3121 dialogTop: iYPos 设置对话框窗口相对于桌面左上角的top位置。
    3122 center: {yes | no | 1 | 0 } 指定是否将对话框在桌面上居中，默认值是“yes”。
    3123 help: {yes | no | 1 | 0 } 指定对话框窗口中是否显示上下文敏感的帮助图标。默认值是“yes”。
    3124 resizable: {yes | no | 1 | 0 } 指定是否对话框窗口大小可变。默认值是“no”。
    3125 status: {yes | no | 1 | 0 } 指定对话框窗口是否显示状态栏。对于非模式对话框窗口，默认值是“yes”；对于模式对话框窗口，默认值是 “no”。
    3126
    3127 window.showModalDialog(), window.showModelessDialog(): IE only. 不如用Ajax
    3128 */
    3129   var w=window.open('','comment','titlebar=no,dependent,resizable=1,menubar=0,toolbar=0,location=0,scrollbars=1,width=550,height=400'/*,fullscreen*/,false)
    3130 	,t=sPopP.commentTitle,_t=oPos.innerHTML&&oPos.innerHTML.length<9?sPopP.commentTitlePattern.replace(/%s/,oPos.innerHTML):t;	//	head, document.title
    3131   //if(typeof netscape=='object')netscape.security.PrivilegeManager.disablePrivilege("UniversalBrowserWrite");
    3132   if(document.title)t+=' @ ['+document.title+']',_t+=' @ '+document.title;
    3133   //else t+=' @ [<a href="'+location.href+'">'+location.pathname+'<\/a>]';
    3134   with(w.document)open(),
    3135    write(
    3136 	//'<?xml version="1.1" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="content-type" content="text/html;charset=utf-8"/><title>'
    3137 	//+_t+'<\/title><script type="text/javascript">window.onblur=function(){window.close();};<\/script><\/head><body><b style="color:#11f;">'+t+':<\/b>'
    3138 	'<script type="text/javascript">window.onblur=function(){window.close();};<\/script><b style="color:#11f;">'+t+':<\/b>'
    3139 	+(oPos.innerHTML?'<div id="s" style="color:#488;background-color:#FF8;">\n'+oPos.innerHTML.replace(/\n/g,'<br/>').replace(/ /g,' ')+'\n<\/div><hr/>':'')	//;white-space:normal;width:500px:useless	** 這邊會對<b title="..等造成影響！
    3140 	+'<div id="c" style="color:#404;background-color:#8FF;">\n'+oTxt.replace(/\n/g,'<br/>').replace(/ /g,' ')	//	以不換行(pre)的方式顯示.patch
    3141 	+'\n<\/div><hr/>[ <b style="cursor:pointer;color:#40f;" onclick="javascript:opener.focus();self.close();">'+sPopP.closeMessage+'<\/b> ]')//+'</body></html>'
    3142    ,close(),title=_t;
    3143   w.focus();
    3144   w=0;	//	open出來的窗口即使close了，它的window對象還是存在的，要記得刪除引用	http://www.blogjava.net/tim-wu/archive/2006/05/29/48729.html
    3145  }//else alert('type error: '+tp+'!');
    3146
    3147  return tp;	//	回傳決定的type
    3148 }
    3149
    3150
    3151 /*	開啟連結於 target
    3152 	**	最好將openAtInit();設在onload
    3153 	JScript solution for attribute 'target' @ XHTML1.1	<a target="tag">之取代策略
    3154 	way 1:	,captureE,openAtInit,"openAtInit();",openAt
    3155 	onload: + openAtInit()		,captureE,openAtInit,"openAtInit();",openAt
    3156 	target="tag"	→	onclick="return openAt('tag')"
    3157 	target="_blank"	→	onclick="return openAt()"
    3158 	target="_self"	→	onclick="return openAt(1)"
    3159 	way 2:	,openAt
    3160 	target="_blank"	→	onclick="return openAt(0,this.href)"
    3161 	target="_self"	→	onclick="return openAt(1,this.href)"
    3162 	http://tohoho.wakusei.ne.jp/js/event.htm
    3163
    3164 TODO:
    3165 http://hi.baidu.com/monyer/blog/item/56f1c88095fc96d79023d931.html
    3166 a{text:expr/*XSS* /ession(target="_blank");}
    3167
    3168 http://blog.fanstown.net/blogs/jerry/archive/2007/04/04/HTML_8476_rel_5E5C2760E68BE3890230_.aspx
    3169 原來這樣寫的代碼：
    3170 <a href="document.html" target="_blank"> 打開一個新窗口</a>
    3171 現在要寫成這樣：
    3172 <a href="document.html" rel="external">打開一個新窗口</a>
    3173 這是符合strict標準的方法。當然還必須配合一個javascript才有效。
    3174 **	應該 binding a.onclick 或 a.keypress
    3175 rel是relationship的英文縮寫.rel與rev具有互補的作用,rel指定了向前鏈接的關係,rev指定了反向鏈接的關係.
    3176
    3177 */
    3178 var captureE;
    3179 //	初始化設定
    3180 //openAtInit[generateCode.dLK]='captureE';
    3181 function openAtInit(){
    3182  if(typeof captureE!='object'&&(typeof Event=='object'||typeof Event=='function')){	//	for moz
    3183   //	http://developer.mozilla.org/en/docs/DOM:element.addEventListener	http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event
    3184   if(Event.mousedown)window.captureEvents(Event.mousedown);
    3185   if(Event.keydown)window.captureEvents(Event.keydown);
    3186   window.onmousedown=window.onkeydown=function(e){
    3187 	 captureE=e;//alert('openAtInit: '+e.target.tagName);
    3188 	};
    3189  }
    3190  for(var i,a=document.getElementsByTagName('a');i<a.length;i++)
    3191   if(a[i].onclick&&!a[i].onkeypress&&(''+a[i].onclick).indexOf('openAt')!=-1)a[i].onkeypress=a[i].onclick;
    3192 }
    3193 //	open h(ref) in tag(et)
    3194 //openAt[generateCode.dLK]='captureE,openAtInit';
    3195 function openAt(tag,h){
    3196  if(!tag)tag='_blank';//typeof tag=='undefined'||
    3197  else if(tag===1)tag='_self';
    3198  var t;
    3199  if(!h&&typeof event=='object')h=event.srcElement.href;
    3200
    3201  //	對Gecko等使用標準(?)Document Object Model的
    3202  //	http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
    3203  if(!h&&typeof captureE=='object'&&typeof captureE.target=='object'){
    3204   t=captureE.target;
    3205   while(!(h=t.href)&&(t=t.parentNode));
    3206  }
    3207
    3208  //alert(h+','+tag+'\n'+captureE.target.parentNode.tagName+":");//+captureE.target.parentElement().tagName
    3209  if(h)window.open(h,tag).focus();
    3210  return false;
    3211 }
    3212
    3213 /*	display mark to valid document
    3214 	<div id="valid"> </div>
    3215 	window.onload="addValid()";
    3216 	搞定之後把自己網站提交到W3C Sites收錄。	http://www.w3csites.com/
    3217
    3218 	for RSS:
    3219 	http://rss.scripting.com/?url=http%3A%2F%2Flyrics.meicho.com.tw%2Fgame%2Frss.xml
    3220 	http://feedvalidator.org/check.cgi?url=http%3A%2F%2Flyrics.meicho.com.tw%2Fgame%2Frss.xml
    3221 */
    3222 function addValid(v,tf){	//	object to insert valid, target window/frame
    3223  if(location.protocol=='file:')return;
    3224  if(!v)v='valid';if(typeof v!='object')v=document.getElementById(v);
    3225  if(!v)return 1;if(v.innerHTML.replace(/ /g,'').replace(/\s+/g,''))return 2;
    3226
    3227  if(typeof tf==='undefined')tf='valid_window';//tf=dQuote(tf);//tf?' target="'+tf+'"':'';
    3228  var i=0,t='',d,addValidData=[
    3229 	'Valid XHTML 1.1! by W3C	http://validator.w3.org/check?uri=referer	http://www.w3.org/Icons/valid-xhtml11'
    3230 	//,'Valid XML 1.0! by W3C	'
    3231 	,'Valid CSS! by W3C	http://jigsaw.w3.org/css-validator/check/referer	http://jigsaw.w3.org/css-validator/images/vcss'	//	http://jigsaw.w3.org/css-validator/validator?uri=~
    3232 	,'Validome Validation Services	http://www.validome.org/referer	http://www.validome.org/images/valid/set2/valid_xhtml_1_1.png'
    3233 	,'Another HTML-lint check	http://openlab.ring.gr.jp/k16/htmllint/htmllint.cgi?ViewSource=o	http://openlab.ring.gr.jp/k16/images/ahl-blue.gif'
    3234 	,'Bobby WAI-AAA Approved by bobby@watchfire.com	http://bobby.watchfire.com/bobby/bobbyServlet?URL=~&output=Submit&gl=wcag1-aaa	http://bobby.watchfire.com/bobby/html/en/images/approved_aaa.gif'
    3235 	,'Bobby 508 Approved by bobby@watchfire.com	http://bobby.watchfire.com/bobby/bobbyServlet?URL=~&output=Submit&gl=sec508	http://bobby.watchfire.com/bobby/html/en/images/approved_508.gif'
    3236 	//	http://webxact.watchfire.com/
    3237 	];
    3238  for(;i<addValidData.length;i++)
    3239   if(d=addValidData[i].split('	'),d[1])t+=' <a title="'+d[0]+'" href="'+d[1].replace(/~/g,encodeURI(location.href))
    3240 	+'" target="'+tf+'">'
    3241 	+(d[2]?'<img style="display:inline;width:88px;" alt="'//'" onclick="return openAt(\''+tf+'\');"><img style="display:inline;" alt="'	IE不通
    3242 		+d[0]+'" src="'+d[2]+'"/>':d[0])
    3243 	+'<\/a>';	//	tf.focus()
    3244   else alert('Validate data defined error!');
    3245  v.innerHTML='Validate this document:<br/>'+t;
    3246  v.style.display='block';
    3247  return t;
    3248 }
    3249
    3250
    3251 /*	延遲執行: 加強版的 setTimeout?
    3252
    3253 id=delayRun(function[,ms=0])
    3254
    3255 id=delayRun([function,[args],this] [,ms=0])
    3256
    3257 */
    3258 function delayRun(f,ms){
    3259  var _f=delayRun,i;
    3260  if(!_f.fL)_f.fL=[];
    3261  i=_f.fL.length;
    3262  _f.fL.push(f);
    3263  setTimeout('delayRun.run('+i+');',ms||0);
    3264  return i;
    3265 }
    3266 delayRun.clear=function(i){
    3267  //	clearTimeout(): 為求簡單省略
    3268  delete this.fL[i];
    3269 };
    3270 delayRun.run=function(i){
    3271  var _t=this,f=_t.fL[i];
    3272  if(f){
    3273   if(typeof f=='function')f();
    3274   else if(f instanceof Array)f[0].apply(f[2]||null,f[1]);
    3275   else eval(f);
    3276   delete _t.fL[i];
    3277  }
    3278 };
    3279
    3280
    3281
    3282
    3283
    3284
    3285
    3286 /*	MsgBox, InputBox Titlebars Prefixed with 'VBScript'	http://support.microsoft.com/default.aspx?scid=kb;en-us;234742
    3287 	http://asp.programmershelp.co.uk/vbscriptmsgbox.php
    3288 	http://17.webmasters.com/caspdoc/html/vbscript_msgbox_function.htm
    3289 請加入下面一段中介function
    3290 <script type="text/vbscript">
    3291 Function VBalert_vbf()
    3292  VBalert_f.ret=MsgBox(VBalert_f.prompt,VBalert_f.buttons,VBalert_f.title,VBalert_f.helpfile,VBalert_f.context)
    3293 End Function
    3294 </script>
    3295
    3296 or use:
    3297 window.execScript( sExpression, sLanguage );
    3298 */
    3299 //var VBalert_f;VBalert();	//	init
    3300 function VBalert(prompt,buttons,title,helpfile,context){
    3301  if(typeof VBalert_f!='object')VBalert_f={},setObjValue('VBalert_f','ret=0,'
    3302 	//	http://msdn.microsoft.com/library/en-us/script56/html/vsfctmsgbox.asp
    3303 	+'vbOK=1,vbCancel=2,vbAbort=3,vbRetry=4,vbIgnore=5,vbYes=6,vbNo=7,'
    3304 	+'vbOKOnly=0,vbOKCancel=1,vbAbortRetryIgnore=2,vbYesNoCancel=3,vbYesNo=4,vbRetryCancel=5,'
    3305 	+'vbCritical=16,'	//	Critical Message icon	(x)
    3306 	+'vbQuestion=32,'	//	Warning Query icon	(?)
    3307 	+'vbExclamation=48,'	//	Warning Message icon	(!)
    3308 	+'vbInformation=64,'	//	Information Message icon(i)
    3309 	+'vbDefaultButton1=0,vbDefaultButton2=256,vbDefaultButton3=512,vbDefaultButton4=768,vbApplicationModal=0,vbSystemModal=4096','int');
    3310  if(typeof prompt=='undefined')return;
    3311  VBalert_f.prompt=prompt||'',VBalert_f.buttons=buttons||0,VBalert_f.title=title||'';
    3312  //	Not available on 16-bit platforms.	http://msdn.microsoft.com/library/en-us/script56/html/vsfctmsgbox.asp
    3313  VBalert_f.helpfile=helpfile||'',VBalert_f.context=context||0;
    3314  try{
    3315   VBScript:VBalert_vbf();
    3316   return VBalert_f.ret;
    3317  }catch(e){
    3318   //alert('VBalert error:'+e.message);
    3319   alert(VBalert_f.prompt);
    3320  }
    3321 }
    3322 //alert(VBalert('12',VBalert_f.vbInformation+VBalert_f.vbDefaultButton3));
    3323
    3324
    3325
    3326 /*	get window status	取得視窗可利用的size。現在還得用種方法，真是羞恥。	2005/1/13 20:0
    3327 	get_window_status(event object)
    3328 	http://www.mozilla.org/docs/dom/domref/dom_window_ref.html
    3329 	http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/body.asp
    3330 	http://www.howtocreate.co.uk/tutorials/index.php?tut=0&part=16
    3331 	http://www.webdevtips.com/webdevtips/faq/javascript/index.shtml
    3332 	http://www.quirksmode.org/viewport/compatibility.html
    3333 	http://cgi.din.or.jp/~hagi3/JavaScript/JSTips/Mozilla/eventhandle.htm
    3334
    3335 ** untested !!
    3336
    3337 */
    3338
    3339 //var eventObj;
    3340 CeL.net.web
    3341 .
    3342 /**
    3343  * 取得當前 window status
    3344  * @param node	HTML element or Event object
    3345  * @returns {Object}	status
    3346  */
    3347 get_window_status = function (node) {
    3348 	var _s = get_window_status, t = _s.scroll, r = {
    3349 			scrollLeft : t[0],
    3350 			scrollTop : t[1]
    3351 	};
    3352
    3353 	//	能scroll的範圍:不準,yet test	The height of the total page (usually the body element)
    3354 	//	t:test, true:all but Explorer Mac, false:Explorer Mac, would also work in Explorer 6 Strict, Mozilla and Safari
    3355 	var t = typeof document.body.scrollHeight != 'undefined'
    3356 		&& typeof document.body.offsetHeight != 'undefined'
    3357 			&& document.body.scrollHeight > document.body.offsetHeight;
    3358
    3359 	r.scrollW = t ? document.body.scrollWidth
    3360 			: typeof document.body.offsetWidth != 'undefined' ? document.body.offsetWidth
    3361 					: null;
    3362 	r.scrollH = t ? document.body.scrollHeight
    3363 			: typeof document.body.offsetHeight != 'undefined' ? document.body.offsetHeight
    3364 					: null;
    3365
    3366 	// window大小
    3367 	// 2009/3/23 1:15:29
    3368 	var NewIE = navigator.appVersion.indexOf("MSIE") != -1
    3369 		&& parseInt(navigator.appVersion.split("MSIE")[1]) > 6;
    3370 	r.windowW = typeof window.innerWidth != 'undefined' ? window.innerWidth
    3371 			: /* typeof offsetWidth!='undefined'?offsetWidth: */!NewIE
    3372 			&& typeof document.body.clientWidth != 'undefined' ? document.body.clientWidth
    3373 					: document.documentElement
    3374 					&& !isNaN(document.documentElement.clientWidth) ? document.documentElement.clientWidth
    3375 							: null;// +offsetLeft
    3376 	r.windowH = typeof window.innerHeight != 'undefined' ? window.innerHeight
    3377 			: /* typeof offsetHeight!='undefined'?offsetHeight: */!NewIE
    3378 			&& typeof document.body.clientHeight != 'undefined' ? document.body.clientHeight
    3379 					: document.documentElement
    3380 					&& !isNaN(document.documentElement.clientHeight) ? document.documentElement.clientHeight
    3381 							: null;// +offsetTop
    3382
    3383 	var noEmu;
    3384 	if (!node)
    3385 		if (typeof window.event === 'object')
    3386 			node = window.event;
    3387 		else if (typeof e === 'object')
    3388 			node = e;
    3389 		else if (typeof eventObj === 'object')
    3390 			noEmu = true, node = eventObj;
    3391
    3392 	if (node) {
    3393 		// Safari: yet test
    3394 		var isSafari = /Safari/i.test(window.navigator.appName);
    3395
    3396 		// window相對於screen位置:不準, yet test
    3397 		r.windowX = node.clientX - ((isSafari) ? r.scrollX : 0);
    3398 		r.windowY = node.clientY - ((isSafari) ? r.scrollY : 0);
    3399 		// mouse位置
    3400 		// http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/obj_event.asp
    3401 		// http://www.mozilla.org/docs/dom/domref/dom_event_ref.html
    3402 		r.mouseX = node.clientX + ((!isSafari) ? r.scrollX : 0);
    3403 		r.mouseY = node.clientY + ((!isSafari) ? r.scrollY : 0);
    3404 		if (!noEmu)
    3405 			//	模擬event obj，因為event obj不能在event發生時之function執行完後再取得
    3406 			eventObj = {
    3407 					'clientX' : node.clientX,
    3408 					'clientY' : node.clientY
    3409 			};
    3410 			// alert(r.scrollX+','+r.scrollY+'\n'+o.clientX+','+o.clientY);
    3411 	}
    3412
    3413 	return r;
    3414 };
    3415
    3416 CeL.net.web
    3417 .
    3418 //	IE7遵照標準，不用 document.body.scrollLeft 而用 document.documentElement.scrollLeft
    3419 //	http://hkom.blog1.fc2.com/blog-entry-423.html
    3420 //	http://diaspar.jp/node/47
    3421 get_window_status.scroll = function (node) {
    3422 	var box_model, od = node && node.ownerDocument;
    3423
    3424 	try{
    3425 		//	from jQuery
    3426 		var div = document.createElement('div');
    3427 		div.style.width = div.style.paddingLeft = '1px';
    3428
    3429 		document.body.appendChild(div);
    3430 		_.get_window_status.box_model = box_model = div.offsetWidth === 2;
    3431 		if(!node)
    3432 			od = div.ownerDocument;
    3433 		document.body.removeChild(div).style.display = 'none';
    3434
    3435 		div = null;
    3436
    3437 	}catch (e) {
    3438 		// TODO: handle exception
    3439 	}
    3440
    3441 	//	到這邊，若是 od 未設定，則所有取值與 node 無關。
    3442 	//	因為大多有 ownerDocument，所以預設編入。
    3443 	//	新的 browser，od 與 dv 皆應有設定。
    3444
    3445 /*
    3446
    3447 Firefox/3.6.6: ownerDocument: [object HTMLDocument], defaultView: [object Window], box_model: true, pageXOffset: 0, body.scrollLeft: 0, documentElement.scrollLeft: 0, scrollX: 0
    3448 Chrome/6.0.453.1 Safari/534.2: ownerDocument: [object HTMLDocument], defaultView: [object DOMWindow], box_model: true, pageXOffset: 0, body.scrollLeft: 0, documentElement.scrollLeft: 0, scrollX: 0
    3449 Safari/533.16: ownerDocument: [object HTMLDocument], defaultView: [object DOMWindow], box_model: true, pageXOffset: 0, body.scrollLeft: 0, documentElement.scrollLeft: 0, scrollX: 0
    3450 Opera/9.80 Presto/2.6.30: ownerDocument: [object HTMLDocument], defaultView: [object Window], box_model: true, pageXOffset: 0, body.scrollLeft: 0, documentElement.scrollLeft: 0, scrollX: 0
    3451
    3452
    3453 MSIE 5.0 @ MSIE 9.0 test: ownerDocument: [object], defaultView: undefined, box_model: false, pageXOffset: undefined, body.scrollLeft: 0, documentElement.scrollLeft: 0, scrollX: undefined
    3454 MSIE 7.0 @ MSIE 9.0 test: ownerDocument: [object], defaultView: undefined, box_model: true, pageXOffset: undefined, body.scrollLeft: 0, documentElement.scrollLeft: 0, scrollX: undefined
    3455
    3456 MSIE 8.0: ownerDocument: [object HTMLDocument], defaultView: undefined, box_model: true, pageXOffset: undefined, body.scrollLeft: 0, documentElement.scrollLeft: 0, scrollX: undefined
    3457 MSIE 9.0 test: ownerDocument: [object HTMLDocument], defaultView: [object Window], box_model: true, pageXOffset: 0, body.scrollLeft: 0, documentElement.scrollLeft: 0, scrollX: undefined
    3458
    3459 */
    3460 	//	IE5-8: od: true, dv: false
    3461
    3462 	var doc = node && od || window.document,
    3463 	body = doc.body, dv = doc.defaultView, win = dv || doc.parentWindow;
    3464 	library_namespace.debug('ownerDocument: ' + od + ', defaultView: ' + dv + ', box_model: ' + box_model + ', pageXOffset: ' + win.pageXOffset + ', body.scrollLeft: ' + body.scrollLeft + ', documentElement.scrollLeft: ' + doc.documentElement.scrollLeft + ', scrollX: ' + win.scrollX, 2, 'get_window_status.scroll');
    3465
    3466 	//	** 順序有關係! 但在未設置 box_model 前，body.scrollLeft 排在 documentElement.scrollLeft 前面。現在已按照 jQuery 改過。
    3467 	//	TODO: do test
    3468 	//	[scrollLeft, scrollTop, clientLeft, clientTop]
    3469 	return (_.get_window_status.scroll =
    3470 		!isNaN(win.pageXOffset) ?
    3471 			//	預設 box_model === true
    3472 			function (n) {
    3473 				//	'|| window.document': for Range (see get_selection())
    3474 				var d = n && n.ownerDocument || window.document,
    3475 				w = d.defaultView;
    3476 				d = d.documentElement;
    3477 				return [ w.pageXOffset, w.pageYOffset, d.clientLeft, d.clientTop ];
    3478 			} :
    3479
    3480 		//	IE7(6?)~8
    3481 		box_model && !isNaN(doc.documentElement.scrollLeft) ?
    3482 			function (n) {
    3483 				var d = (n && n.ownerDocument || window.document).documentElement;
    3484 				return [ d.scrollLeft, d.scrollTop, d.clientLeft, d.clientTop ];
    3485 			} :
    3486
    3487 		//	IE5(6?)
    3488 		!isNaN(body.scrollLeft) ?
    3489 			function (n) {
    3490 				var b = (n && n.ownerDocument || window.document).body;
    3491 				return [ b.scrollLeft, b.scrollTop, b.clientLeft, b.clientTop ];
    3492 			} :
    3493
    3494 		!isNaN(win.scrollX) ?
    3495 			//	untested
    3496 			function() {
    3497 				var b = document.body;
    3498 				return [ window.scrollX, window.scrollY, b.clientLeft, b.clientTop ];
    3499 			} :
    3500
    3501 		function() {
    3502 			return [ 0, 0, 0, 0 ];
    3503 		}
    3504 	)(node);
    3505
    3506 };
    3507
    3508
    3509
    3510
    3511
    3512 CeL.net.web
    3513 .
    3514 /**
    3515  * get current computed style property of specified HTML element.
    3516  * TODO: 整合 get_node_offset, _.set_style
    3517  * @param element	HTML element
    3518  * @param name	W3C style property name (e.g., no '-webkit-background-clip')
    3519  * @return
    3520  * @see
    3521  * http://en.wikipedia.org/wiki/Internet_Explorer_box_model_bug, http://www.comsharp.com/GetKnowledge/zh-CN/TeamBlogTimothyPage_K983.aspx,
    3522  * curCSS @ jQuery, http://api.jquery.com/category/css/,
    3523  * <a href="http://www.quirksmode.org/dom/getstyles.html" accessdate="2010/4/1 15:44">JavaScript - Get Styles</a>,
    3524  * <a href="http://www.javaeye.com/topic/140784?page=2" accessdate="2010/4/1 15:41">style.display取值不对，难道是浏览器bug？讨论第2页:  - JavaScript - web - JavaEye论坛</a>
    3525  * 大體上，currentStyle 相當於 getComputedStyle，而 runtimeStyle 相當於 getOverrideStyle。但是它們還是有很重要的區別。那就是，IE的CSS計算步驟其實是不合標準的。
    3526  * document.defaultView在mozilla中是指向window obj的,但是很有可能在其他broswer中就不指向window obj...因為w3c中沒有強行規定document.defaultView一定是一個global obj.
    3527  *
    3528  * 返回頁內樣式表定義的類，那麼可以使用DOM樣式表對象來訪問：
    3529  * var oCssRulers = document.styleSheets[0].cssRulers || document.styleSheets[0].rulers;
    3530  * (前者是DOM方法，後者是IE私有方法)
    3531  * alert(oCssRulers[0].style.display);
    3532  * @since	2010/4/2 00:14:09	rewrite
    3533  * @memberOf	CeL.net.web
    3534  */
    3535 get_style = function(element, name, not_computed) {
    3536 	if (typeof element === 'string')
    3537 		element = document.getElementById(element);
    3538
    3539 	//	opacity
    3540
    3541 	if (!element || !name)
    3542 		return;
    3543
    3544 	var value, style_interface, e;
    3545 	name = name.toLowerCase();
    3546 	//	IE: element.style.styleFloat, firefox, chorme, safari: element.style.cssFloat
    3547 	//if (name === 'float') name = 'cssFloat' in element.style ? 'cssFloat' : 'styleFloat';
    3548
    3549 	if (style_interface = document.defaultView)	//	window.getComputedStyle
    3550 		try {
    3551 			if ((value = element.ownerDocument) && (value = value.defaultView))
    3552 				style_interface = value;
    3553 			else
    3554 				library_namespace.debug('Can not get .ownerDocument.defaultView of '
    3555 						+ library_namespace.node_description(element) + ' !');
    3556
    3557 			//if (/[A-Z]/.test(name)) name = name.replace(/([A-Z])/g, '-$1').toLowerCase();
    3558 			//	width 之類可能 === "auto"!!
    3559 			value = style_interface.getComputedStyle(element, null)
    3560 					// [name]
    3561 					.getPropertyValue(name);
    3562
    3563 			//	from curCSS @ jQuery: return a number for opacity
    3564 			if(name === 'opacity' && value === '')
    3565 				value = 1;
    3566 		} catch (e) {
    3567 			library_namespace.err(e);
    3568 		}
    3569
    3570 	//	IE 5-8
    3571 	else if (style_interface = element.currentStyle)
    3572 		//	IE: \w+\W\w+ (e.g., margin-bottom), firefox, chorme, safari: \w+-\w+
    3573 		//	IE8 中 width 之類可能 === "auto"!!
    3574 		value = style_interface[name === 'float' ? 'styleFloat' : name.replace(/-([a-z])/g, function($0, $1) { return $1.toUpperCase(); })];
    3575 		//	Dean Edwards（Base2類庫的作者）的hack	http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
    3576
    3577 	else if((style_interface = element.style) && (name in style_interface))
    3578 		value = style_interface[name];
    3579
    3580 	//	we should directly get it from element itself
    3581 	//else if (!(value = element['offset' + name.charAt(0).toUpperCase() + name.slice(1).toLowerCase()])) value = '';
    3582
    3583 	//	處理 px, pt, em, ..
    3584
    3585 	//library_namespace.debug(library_namespace.node_description(element) + '.style[' + name + '] = [' + value + ']' +(style_interface === document.defaultView ? ' (use W3C .getComputedStyle)' : style_interface === element.currentStyle ? ' (use IE .currentStyle)' : ''));
    3586
    3587 	return value;
    3588 };
    3589
    3590
    3591
    3592 CeL.net.web
    3593 .
    3594 /**
    3595  * get the actual position [left,top,width,height] of an HTML node object
    3596  * @param node	HTML node object
    3597  * @return
    3598  * @memberOf	CeL.net.web
    3599  * @deprecated	use get_style(), jQuery.offset(), jQuery.position()
    3600  * @see
    3601  * http://en.wikipedia.org/wiki/Internet_Explorer_box_model_bug, http://www.comsharp.com/GetKnowledge/zh-CN/TeamBlogTimothyPage_K983.aspx,
    3602  * http://msdn.microsoft.com/library/en-us/dndude/html/dude04032000.asp,
    3603  * http://www.mail-archive.com/mochikit@googlegroups.com/msg00584.html,
    3604  * http://hartshorne.ca/2006/01/20/javascript_positioning/,
    3605  * http://www.jb51.net/article/18340.htm,
    3606  * http://blog.csdn.net/wangjj_016/archive/2010/04/09/5467507.aspx
    3607  */
    3608 get_node_offset = function(node) {
    3609 	if (typeof node === 'string')
    3610 		//	若 node 為 id
    3611 		node = _.get_element(node);
    3612 	if(!_.is_element_node(node))
    3613 		return {};
    3614
    3615 	var _s = _.get_node_offset,
    3616 	offset = 'offsetWidth' in node ? {
    3617 		width : node.offsetWidth,
    3618 		height : node.offsetHeight
    3619 	} : {};
    3620
    3621
    3622 	if(node.getBoundingClientRect){
    3623
    3624 		//	also see: getClientRects()
    3625
    3626 		var s = _.get_window_status.scroll(node),
    3627 		box = node.getBoundingClientRect();
    3628
    3629 		offset = {
    3630 				left : box.left + s[0] - s[2],
    3631 				top : box.top + s[1] - s[3],
    3632 				width : box.right - box.left,
    3633 				height : box.bottom - box.top
    3634 		};
    3635
    3636 	} else if (_.is_HTML_element(node)) {
    3637 		//alert(node.id+':'+node.offsetLeft+','+node.offsetTop+';'+node.offsetWidth+','+node.offsetHeight);
    3638 		var l = 0, t = 0, p;
    3639 			// n,countH=window.navigator.userAgent.indexOf("MSIE")>=0,add=1,outsideBLOCK=1,
    3640 		if(0)
    3641 		if (typeof node.offsetWidth !== 'undefined') {
    3642 			var _w = node.offsetWidth, _h = node.offsetHeight
    3643 				// ,_o=window.getComputedStyle?document.defaultView.getComputedStyle(node,null):null
    3644 				;
    3645 			//	http://www.quirksmode.org/dom/getstyles.html
    3646 			/*
    3647 			   if(_o)	//	moz未包含margin+border+padding	這些值可能會有'em'等等的出現，不一定都是px！
    3648 				//alert(_o.getPropertyValue('border-left-width')+','+_o.getPropertyValue('border-right-width')),
    3649 				_w+=parseInt(_o.getPropertyValue('border-left-width'))+parseInt(_o.getPropertyValue('border-right-width')),
    3650 				_h+=parseInt(_o.getPropertyValue('border-top-width'))+parseInt(_o.getPropertyValue('border-bottom-width'));
    3651 			   else if(_o=node.currentStyle)	//	IE
    3652 				//	IE的offset已經包含margin+border+padding的部份??另，這些值可能會有'em'等等的出現，不一定都是px。
    3653 				_w+=parseInt(_o['borderLeftWidth'])+parseInt(_o['borderRightWidth']),
    3654 				_h+=parseInt(_o['borderTopWidth'])+parseInt(_o['borderBottomWidt都是px;
    3655 			*/
    3656 			r.width = _w,
    3657 			r.height = _h;
    3658 		}
    3659
    3660 		//	下面這段依瀏覽器而有不同 (-_-)!!
    3661 		//	position:absolute
    3662 		//var tt='';	//	for debug
    3663 		//	2006/2/14: 經由 offset 一個個溯源
    3664 		var _o = node;
    3665 		while(_o&&!isNaN(_o.offsetLeft)){	//	IE在用style:class時會出現誤差。
    3666 			/*
    3667 			   n=_o.tagName;
    3668 			   //if( !/^T(ABLE|BODY|R)$/.test(n=_o.tagName) && (countH||!/^H\d$/.test(n)) )l+=_o.offsetLeft,t+=_o.offsetTop;
    3669 			   if(n=='DIV')add=outsideBLOCK;
    3670 			   else if(n=='TD' || countH&&/^H\d$/.test(n))add=1;
    3671 			   outsideBLOCK= n=='TABLE'||n=='DIV';	//	_o.style.display
    3672 			   tt+=(add?'':'#')+n+(_o.style.display?'('+_o.style.display+')':'')+':'+_o.offsetLeft+','+_o.offsetTop+(outsideBLOCK?', outside BLOCK':'')+'\n';
    3673 			   if(add)add=0,l+=_o.offsetLeft,t+=_o.offsetTop;
    3674 			*/
    3675
    3676 			l += _o.offsetLeft || 0, t += _o.offsetTop || 0;
    3677 			_o = _o.offsetParent;//.parentNode
    3678 		}
    3679
    3680 		//		有些會用到overflow，影響位置。	2008/5/31 0:10:7
    3681 		_o = node;
    3682 		while ((_o = _o.parentNode) && _o.tagName.toLowerCase() != 'body')
    3683 			l -= _o.scrollLeft || 0, t -= _o.scrollTop || 0;
    3684
    3685 		//		need to enable definition of tt above
    3686 		//alert('l '+l+',t '+t+',w '+r.w+',h '+r.h+(typeof tt=='string'?'\n'+tt:''));
    3687
    3688 		offset.left = l;
    3689 		offset.top = t;
    3690 	}
    3691
    3692 	return offset;
    3693 };
    3694
    3695
    3696 /*
    3697 //	get the [left,top,width,height] of obj
    3698 function get_node_offset2(obj){
    3699  if(typeof obj=='string'){var o=document.getElementById(obj);if(o)obj=o;}	//	若loc為id
    3700  if(typeof obj=='object'&&typeof obj.offsetLeft!='undefined'){	//	若obj為Document Object
    3701   //alert(obj.id+':'+obj.offsetLeft+','+obj.offsetTop+';'+obj.offsetWidth+','+obj.offsetHeight);
    3702   var l=obj.offsetLeft,t=obj.offsetTop,n,add,outsideBLOCK,countH=window.navigator.userAgent.indexOf("MSIE")>=0,r=[];
    3703   if(typeof obj.offsetWidth!='undefined')r[2]=r.width=r.w=r.W=obj.offsetWidth,r[3]=r.height=r.h=r.H=obj.offsetHeight;
    3704
    3705   //	下面這段依瀏覽器而有不同 (-_-)!!
    3706   //	position:absolute
    3707   //var tt=obj.tagName+':'+obj.offsetLeft+','+obj.offsetTop+'\n';	//	for debug
    3708   while(isNaN((obj=obj.parentNode).offsetLeft)){	//	IE在用style:class時會出現誤差。
    3709    n=obj.tagName;
    3710    //if( !/^T(ABLE|BODY|R)$/.test(n=obj.tagName) && (countH||!/^H\d$/.test(n)) )l+=obj.offsetLeft,t+=obj.offsetTop;
    3711    if(n=='DIV')add=outsideBLOCK;
    3712    else if(n=='TD' || countH&&/^H\d$/.test(n))add=1;
    3713    outsideBLOCK= n=='TABLE'||n=='DIV';	//	obj.style.display
    3714    //tt+=(add?'':'#')+n+(obj.style.display?'('+obj.style.display+')':'')+':'+obj.offsetLeft+','+obj.offsetTop+(outsideBLOCK?', outside BLOCK':'')+'\n';
    3715    if(add)add=0,l+=obj.offsetLeft,t+=obj.offsetTop;
    3716   }
    3717   //alert('l'+l+',t'+t+',w'+w+',h'+h+'\n'+tt);	//	need to enable definition of tt above
    3718   r[0]=r.left=r.l=r.L=l,r[1]=r.top=r.t=r.T=t;
    3719   return r;
    3720  }
    3721 }
    3722 */
    3723
    3724 /*	locate a object(obj/div, dialogue box, popup dialog) on where we want followed window location	2005/1/12 19:-13 21:22
    3725 	此函數會盡量不使obj超出window範圍的大小，除非設定了noResize/noMove或發生錯誤。若moveable+resizable(default)，會嘗試先move再resize。
    3726 obj:
    3727 	object or id
    3728 loc:
    3729 	[left,top]/[left,top,width,height]/reference obj or id/0||'mouse':by mouse loc
    3730 		若left,top設定成%或是0.-，會當作相對於螢幕的比例。
    3731 margin:
    3732 	0/num=[num,num]/[offset x,offset y]
    3733 		在可能的情況下（不會造成超出window範圍）與loc之間空出的距離（所作的位移）。假如未輸入則自動設定。
    3734 flag:	locate_elementF.~	!表示未實作
    3735 	下面幾項為預設模式
    3736 	auto[Locate]	自動調整位置(default)，若設定abs/rel則不會自動調整。
    3737 	resizable	可調整obj大小(default) <-> noResize
    3738 	moveable	可移動obj(default) <-> noMove
    3739 	下面幾項為模式選擇，擇一。
    3740 	auto[Locate]	自動判定並調整位置(default)，若設定abs/rel則不會自動調整。
    3741 	abs[olute]	這裡的loc為絕對location。假如有提供margin，則會嘗試定位於loc+margin處。
    3742 	rel[ative]	這裡的loc為相對於window左上角的location。假如有提供margin，則會嘗試定位於loc+margin處。
    3743 	asDialog,dialog	預設是普通obj，但當設定為此項(dialog)時，loc會被當成reference obj。
    3744 			作為某obj(loc)之附屬obj（對話框/說明等），會避開主obj(reference obj)之顯示範圍。
    3745 			假如提供的loc並非obj，則會假設主obj是個從loc開始，長寬為margin的object。
    3746 	dialogDown,dialogUp,dialogRight,dialogLeft	預設是擺在下面，此flag可改成上面或其他不同方位。
    3747 	擇一
    3748 	resizable	可調整obj大小(default) <-> noResize
    3749 	noResize	不可調整obj大小，若可移動會將整個obj移到能看清的邊界。
    3750 	擇一
    3751 	moveable	可移動obj(default) <-> noMove
    3752 	noMove		不可移動obj，若可調整大小會將整個obj縮到能看清的大小。
    3753 	下面幾項可任喜好選購（笑）
    3754 	keepDisplay	是否維持顯示之display mode。沒有時則顯示之。
    3755 	create		假如不存在此obj就造出來。預設若無法取得此obj則會直接return
    3756
    3757 	!		!假如沒足夠空間則不顯示，或是僅顯示警告。
    3758
    3759 *	假如在事件中設定'eventObj=event'可掌握mouse event
    3760
    3761 TODO:
    3762 locate_elementClip=[l,t,w,h]:	resizable時將obj限制在這個範圍內
    3763
    3764 to top:
    3765 var locate_elementF;
    3766 setObjValue('locate_elementF','resizable=0,moveable=0,autoLocate=0,auto=0,absolute=1,abs=1,relative=2,rel=2,asDialog=3,dialog=3,modeFlag=3,dialogDown=3,dialogUp=7,dialogRight=11,dialogLeft=15,dialogFlag=15,dialogForce=16,noResize=32,noMove=64,keepDisplay=128,create=256',1);	//	revise
    3767 */
    3768 //locate_element[generateCode.dLK]='eventObj,locate_elementF,get_window_status,locate_element';
    3769 function locate_element(obj, loc, margin, flag) {
    3770 	// 前置處理
    3771
    3772 	// setup obj
    3773 	if (!flag)
    3774 		flag = locate_elementF.auto;
    3775 	if (!obj)
    3776 		return;
    3777 	if (typeof obj == 'string') {
    3778 		var id = obj;
    3779 		if (!(obj = document.getElementById(id)) && (flag & locate_elementF.create))
    3780 			document.body.appendChild(obj = document.createElement('div')),
    3781 					obj.id = id;
    3782 	}
    3783
    3784 	// 在 dialog 時之預設位移
    3785 	var dMargin = {
    3786 		'X' : 2,
    3787 		'Y' : 2
    3788 	}
    3789 	, Display = flag & locate_elementF.keepDisplay ? obj.style.display : 'block', Visibility = flag
    3790 			& locate_elementF.keepDisplay ? obj.style.visibility : 'visible', win, dialog = (flag & locate_elementF.modeFlag) == locate_elementF.dialog ? flag
    3791 			& locate_elementF.dialogFlag
    3792 			: 0, turnPercent = function(p, v) {
    3793 		if (typeof p == 'string') {
    3794 			var t = parseFloat(p.match(/([\d.]+)/));
    3795 			p = t ? t < 2 ? t * v : t < 200 ? t * v / 100 : t : 0;
    3796 		} else if (
    3797 				// typeof p1='undefined'&&
    3798 				isNaN(p))
    3799 			p = 0;
    3800 		return p;
    3801 	}, dealPercent = function(o, t) {
    3802 		// t: 0:loc, 1:margin
    3803
    3804 		// 是否重新指定
    3805 		var d = 0;
    3806 		if (typeof o == 'string')
    3807 			o = o.split(','), d = 1;
    3808 		if (!dialog && typeof o == 'object') {
    3809 			// 取百分比%
    3810 			if (typeof o[t ? 'L' : 'X'] == 'undefined'
    3811 					&& typeof o[0] != 'undefined')
    3812 				d = 1, o = t ? {
    3813 					'X' : o[0],
    3814 					'Y' : o[1]
    3815 				} : {
    3816 					'L' : o[0],
    3817 					'T' : o[1],
    3818 					// 假如o[2]未定義，W也會未定義（但有index）
    3819 					'W' : o[2],
    3820 					'H' : o[3]
    3821 				};
    3822 			if (t)
    3823 				o.X = turnPercent(o.X, win.windowW), o.Y = turnPercent(o.Y,
    3824 						win.windowH);
    3825 			else {
    3826 				o.L = turnPercent(o.L, win.windowW), o.T = turnPercent(o.T,
    3827 						win.windowH);
    3828 				if (typeof o.W == 'undefined') {
    3829 					delete o.W;
    3830 					delete o.H;
    3831 				} else
    3832 					o.W = turnPercent(o.W, win.windowW), o.H = turnPercent(o.H,
    3833 							win.windowH);
    3834 			}
    3835 		}
    3836 		if (d)
    3837 			if (t)
    3838 				margin = o;
    3839 			else
    3840 				loc = o;
    3841 	}, makeFit = function(l, t, r, b, hc) {
    3842 		//	test if out of range & 將box調整在range[left,top,right,bottom]內：先move，再resize
    3843 		if (boxL < l)
    3844 			boxL = l;
    3845 		if (boxT < t)
    3846 			boxT = t;
    3847 		var d = r - obj.offsetWidth;
    3848 		if (boxL > d)
    3849 			if (l > d)
    3850 				boxW = r - (boxL = l);
    3851 			else
    3852 				boxL = d;
    3853 		d = b - obj.offsetHeight;
    3854 		if (boxT > d)
    3855 			if (t > d)
    3856 				boxH = b - (boxT = t);
    3857 			else
    3858 				boxT = d;
    3859 		else if (hc && (boxT = hc - obj.offsetHeight / 2) < t)
    3860 			boxT = t;
    3861 	};
    3862
    3863 	with (obj.style) {
    3864 		overflow = visibility = 'hidden';
    3865 		if (width)
    3866 			width = '';
    3867 		if (height)
    3868 			//	重設obj。
    3869 			height = '';
    3870 		//	得設定obj之display，因為不這樣不能定offset。但可不顯現出來…只是好像沒啥效果。
    3871 		display = 'block';
    3872 	}
    3873
    3874 	// if(dialog!=locate_elementF.dialogDown&&dialog!=locate_elementF.dialogUp)dialog=0;
    3875 	// setup loc#1: deal dialog
    3876 	if (typeof loc == 'string') {
    3877 		// 若loc為id
    3878 		var o = document.getElementById(loc);
    3879 		if (o)
    3880 			loc = o;
    3881 	}
    3882 	if (typeof loc == 'object' && typeof loc.offsetLeft != 'undefined') {
    3883 		//	若loc為Document Object
    3884
    3885 		/*
    3886 		  //alert(loc.id+':'+loc.offsetLeft+','+loc.offsetTop+';'+loc.offsetWidth+','+loc.offsetHeight);
    3887 		  var l=loc.offsetLeft,t=loc.offsetTop,w,h,n,add,outsideBLOCK,countH=window.navigator.userAgent.indexOf("MSIE")>=0;	//	真妙..moz表示在<H\d>中的obj時不把H\d當作parent算進去
    3888 		  if(typeof loc.offsetWidth!='undefined')w=loc.offsetWidth,h=loc.offsetHeight;	//	loc.offsetWidth可能未定義？
    3889 		  //var tt=loc.tagName+':'+loc.offsetLeft+','+loc.offsetTop+'\n';	//	for debug
    3890 		  //	下面這段依瀏覽器而有不同 (-_-)!!
    3891 		  while(isNaN((loc=loc.parentNode).offsetLeft)){	//	IE在用style:class時會出現誤差。
    3892 		   n=loc.tagName;
    3893 		   //if( !/^T(ABLE|BODY|R)$/.test(n=loc.tagName) && (countH||!/^H\d$/.test(n)) )l+=loc.offsetLeft,t+=loc.offsetTop;
    3894 		   if(n=='DIV')add=outsideBLOCK;
    3895 		   else if(n=='TD' || countH&&/^H\d$/.test(n))add=1;
    3896 		   outsideBLOCK= n=='TABLE'||n=='DIV';	//	loc.style.display
    3897 		   //tt+=(add?'':'#')+n+(loc.style.display?'('+loc.style.display+')':'')+':'+loc.offsetLeft+','+loc.offsetTop+(outsideBLOCK?', outside BLOCK':'')+'\n';
    3898 		   if(add)add=0,l+=loc.offsetLeft,t+=loc.offsetTop;
    3899 		  }
    3900 		  //alert(l+','+t+'\n'+tt);	//	need to enable definition of tt above
    3901 		  loc={'L':l,'T':t,'W':w,'H':h};
    3902 		*/
    3903 		loc = get_node_offset(loc);
    3904 		if ((flag & locate_elementF.modeFlag) == locate_elementF.auto)
    3905 			flag += locate_elementF.dialog - locate_elementF.auto, dialog = locate_elementF.dialog;
    3906 	}
    3907
    3908 	// setup margin
    3909 	win = get_window_status();
    3910 	if (!margin)
    3911 		margin =
    3912 			// dialog?dMargin:{'X':0,'Y':0};
    3913 			dMargin;
    3914 	else
    3915 		dealPercent(margin, 1);
    3916
    3917 	// setup loc#2: deal abs/rel
    3918 	if (!loc || loc == 'mouse')
    3919 		loc = {
    3920 			L : win.mouseX || 0,
    3921 			T : win.mouseY || 0
    3922 		};
    3923 	else {
    3924 		if ((flag & locate_elementF.modeFlag) == locate_elementF.auto && typeof loc == 'string'
    3925 				&& /[%.]/.test(loc))
    3926 			flag += locate_elementF.rel - locate_elementF.auto;
    3927 		dealPercent(loc);
    3928 	}
    3929 	// alert(loc.L+','+loc.T+';'+margin.X+','+margin.Y);
    3930 	if ((flag & locate_elementF.modeFlag) == locate_elementF.auto)
    3931 		// 到這裡還沒決定就很奇怪了
    3932 		flag += locate_elementF[loc.W && loc.H && loc.T < win.windowH
    3933 				&& loc.L < win.windowW ? (dialog = locate_elementF.dialog) && 'dialog'
    3934 				: 'abs']
    3935 				- locate_elementF.auto;
    3936
    3937 	// 調整與判別
    3938 	// alert(loc.L+','+loc.T+';'+margin.X+','+margin.Y);
    3939 	// alert(loc.L+margin.X+','+(loc.T+margin.Y));
    3940 	// alert('dialog:'+dialog);
    3941
    3942 	if ((flag & locate_elementF.modeFlag) == locate_elementF.rel)
    3943 		// 改成絕對座標。此後僅存abs/dialog
    3944 		flag += locate_elementF.abs - locate_elementF.rel// -(flag&locate_elementF.modeFlag)
    3945 		, loc.L += win.scrollX, loc.T += win.scrollY;
    3946
    3947 	// 最後要設定的值
    3948 	var resizable = !(flag & locate_elementF.noResize), boxL = loc.L, boxT = loc.T, boxW = -1, boxH = -1;
    3949 	if (flag & locate_elementF.noMove)
    3950 		if (resizable)
    3951 			makeFit((boxL += margin.X) - margin.X, (boxT += margin.Y)
    3952 					- margin.Y, win.scrollX + win.windowW, win.scrollY
    3953 					+ win.windowH);
    3954 		else {
    3955 			if (margin.X < 0
    3956 					|| boxL + margin.X >= win.scrollX
    3957 					&& boxL + margin.X + obj.offsetWidth < win.scrollX
    3958 							+ win.windowW)
    3959 				boxL += margin.X;
    3960 			if (margin.Y < 0
    3961 					|| boxT + margin.Y >= win.scrollY
    3962 					&& boxT + margin.Y + obj.offsetHeight < win.scrollY
    3963 							+ win.windowH)
    3964 				boxT += margin.Y;
    3965 		}
    3966 	else if (!dialog)
    3967 		// abs
    3968 		boxL += margin.X, boxT += margin.Y, makeFit(win.scrollX, win.scrollY,
    3969 				win.scrollX + win.windowW, win.scrollY + win.windowH);
    3970 	else {
    3971 		// 自動調整位置
    3972 		if (dialog) {
    3973 			if (!loc.W)
    3974 				loc.W = 0;
    3975 			if (!loc.H)
    3976 				loc.H = 0;
    3977 		} else
    3978 			// abs時,相當於dialog在(0,0)大小(0,0)
    3979 			loc = {
    3980 				'L' : win.scrollX,
    3981 				'T' : win.scrollY,
    3982 				'W' : 0,
    3983 				'H' : 0
    3984 			};
    3985 		if (!obj.innerHTML)
    3986 			// 起碼先設定個大小以安排位置
    3987 			obj.innerHTML = ' ';
    3988
    3989 		var lA = win.scrollY + win.windowH - loc.T - loc.H, lB = loc.T
    3990 				- win.scrollY, lC = win.scrollX + win.windowW - loc.L - loc.W, lD = loc.L
    3991 				- win.scrollX,
    3992 				//	args for makeFit()
    3993 				m1 = win.scrollX, m2 = win.scrollY,
    3994 				m3 = win.scrollX + win.windowW, m4 = win.scrollY + win.windowH
    3995 				// move kind set use locate_elementF.dialog~ flag
    3996 				, movekind;
    3997 		// alert(lA+','+lB+','+lC+','+lD+'\n'+obj.offsetWidth+','+obj.offsetHeight);
    3998
    3999 	/*
    4000 		+---------------------+
    4001 		|        ^            |
    4002 		|        | lB         |	<--screen (active frame)
    4003 		|        |            |
    4004 		|<---->#####<-------->|	###:reference obj
    4005 		|  lD    |      lC    |
    4006 		|        |            |
    4007 		|        | lA         |
    4008 		|        |            |
    4009 		+---------------------+
    4010 	*/
    4011 		// 決定 mode
    4012 		if (dialog && (flag & locate_elementF.dialogForce))
    4013 			movekind = dialog;
    4014 		else {
    4015 			if (obj.offsetWidth < win.windowW
    4016 					&& (dialog != locate_elementF.dialogRight
    4017 							&& dialog != locate_elementF.dialogLeft || obj.offsetHeight >= win.windowH))
    4018 				if (obj.offsetHeight < lA
    4019 						&& (dialog != locate_elementF.dialogUp || obj.offsetHeight >= lB))
    4020 					movekind = locate_elementF.dialogDown;
    4021 				else if (obj.offsetHeight < lB)
    4022 					movekind = locate_elementF.dialogUp;
    4023 			if (!movekind && obj.offsetHeight < win.windowH)
    4024 				if (obj.offsetWidth < lC
    4025 						&& (dialog != locate_elementF.dialogLeft || obj.offsetWidth >= lD))
    4026 					movekind = locate_elementF.dialogRight;
    4027 				else if (obj.offsetWidth < lD)
    4028 					movekind = locate_elementF.dialogLeft;
    4029 			if (!movekind)
    4030 				movekind =
    4031 					// 以較大、可視的為準
    4032 					dialog != locate_elementF.dialogRight && dialog != locate_elementF.dialogLeft ?
    4033 						// 沒考慮假如lA<5時..
    4034 						lA < lB && resizable ? locate_elementF.dialogUp : locate_elementF.dialogDown :
    4035 						//
    4036 						lC < lD && resizable ? locate_elementF.dialogLeft : locate_elementF.dialogRight;
    4037 		}
    4038
    4039 		// alert(movekind);
    4040 		// 決定location
    4041 		if (movekind == locate_elementF.dialogDown)
    4042 			m2 = loc.T + loc.H, boxT += loc.H;
    4043 		else if (movekind == locate_elementF.dialogUp)
    4044 			m4 = loc.T, boxT -= obj.offsetHeight, margin.Y = -margin.Y;
    4045 		else if (movekind == locate_elementF.dialogRight)
    4046 			m1 = loc.L + loc.W, boxL += loc.W;
    4047 		else
    4048 			m3 = loc.L, boxL -= obj.offsetWidth, margin.X = -margin.X;
    4049 		//else if(movekind==locate_elementF.dialogLeft)
    4050
    4051 		// 加上偏移
    4052 		boxL += margin.X, boxT += margin.Y;
    4053 		if (!resizable) {
    4054 			if (boxL < m1 && margin.X < 0 || boxL + obj.offsetWidth > m3
    4055 					&& margin.X > 0)
    4056 				boxL -= margin.X;
    4057 			if (boxT < m2 && margin.Y < 0 || boxT + obj.offsetHeight > m4
    4058 					&& margin.Y > 0)
    4059 				boxT -= margin.Y;
    4060 			//	確保不會撞到
    4061 			m3 += obj.offsetWidth, m4 += obj.offsetHeight;
    4062 		}
    4063 		// 奇怪的是，alert(obj.offsetWidth)後obj.offsetWidth就變成0了。可能因為這值需要出函數之後再改。
    4064 		// alert(resizable+'\n'+m1+','+m2+','+m3+','+m4+','+movekind+'\n'+obj.offsetWidth+','+obj.offsetHeight);
    4065 		makeFit(m1, m2, m3, m4, movekind == locate_elementF.dialogRight
    4066 				|| movekind == locate_elementF.dialogLeft ? loc.T : 0);
    4067 	}
    4068
    4069 	// 設定位置
    4070 	// alert(boxL+','+boxT+','+boxW+','+boxH+','+Display);
    4071 	with (obj.style) {
    4072 		position = 'absolute';
    4073 		left = boxL + 'px';
    4074 		top = boxT + 'px';
    4075 		if (boxW >= 0 || boxH >= 0) {
    4076 			overflow = 'auto';
    4077 			//alert(width+','+height+'\n'+typeof width+'\n->w,h:'+boxW+','+boxH);
    4078 			if (boxW >= 0)
    4079 				width = boxW + 'px';
    4080 			if (boxH >= 0)
    4081 				height = boxH + 'px';
    4082 		}
    4083 		display = Display;
    4084 		visibility = Visibility;
    4085 	}
    4086
    4087 	// alert(obj.style.width+','+obj.style.height+'\n'+obj.offsetWidth+','+obj.offsetHeight);
    4088 	return obj;
    4089 };
    4090
    4091
    4092
    4093
    4094
    4095
    4096
    4097
    4098
    4099 //	2007/4/25-27 0:48:22	RFC 3492 IDNA Punycode	未最佳化
    4100 //	http://stackoverflow.com/questions/183485/can-anyone-recommend-a-good-free-javascript-for-punycode-to-unicode-conversion
    4101 //	http://xn-punycode.com/
    4102 function Punycode(){}
    4103
    4104 Punycode.map='abcdefghijklmnopqrstuvwxyz0123456789',
    4105 Punycode.Dmap=0,
    4106 Punycode.base=36,//Punycode.map.length
    4107 Punycode.tmin=1,
    4108 Punycode.tmax=26,
    4109 Punycode.skew=38,
    4110 Punycode.damp=700,
    4111 Punycode.initial_bias=72,//偏移
    4112 Punycode.initial_n=0x80,//128
    4113 Punycode.prefix="xn--",//the default ACE prefix
    4114 Punycode.delimiter='-';
    4115 Punycode._b=Punycode.base-Punycode.tmin,
    4116 //Punycode._t=(Punycode._b*Punycode.tmax)>>1,
    4117 Punycode._t=Math.floor(Punycode._b*Punycode.tmax/2);
    4118
    4119 //	IDNA ToASCII
    4120 Punycode.encodeDomain=function(UURL){
    4121  var m=UURL.match(/^([\w\d\-]+:\/\/)?([^\/]+)/),UDomain=m?m[2]:'',i=(m=UDomain)?UURL.indexOf(m):0;
    4122 	//document.write('<hr/>Punycode.encodeDomain UDomain: ['+i+']['+m+']<br/>');
    4123  if(m&&m.replace(/[\x01-\x7f]+/g,''))with(Punycode)
    4124   m=m.replace(/([^.]+)\./g,function($0,$1){
    4125 	//document.write($1+'→'+encode($1)+'<br/>');
    4126 	 return prefix+encode($1)+'.';
    4127 	}),UURL=encodeURI(UURL.slice(0,i)+m+UURL.slice(i+UDomain.length));
    4128  return UURL;
    4129 };
    4130
    4131 //	IDNA ToUnicode
    4132 Punycode.decodeDomain=function(PURL){with(Punycode){
    4133  var m=PURL.match(/^([\w\d\-]+:\/\/)?([^\/]+)/),PDomain=m?m[2]:'',i=(m=PDomain)?PURL.indexOf(m):0;
    4134 	//document.write('<hr/>Punycode.decodeDomain PDomain: ['+i+']['+m+']<br/>');
    4135  if(m){
    4136   m=m.replace(new RegExp(prefix+'([^.]+)\\.','g'),function($0,$1){
    4137 	//document.write($1+'→'+decode($1)+'<br/>');
    4138 	 return decode($1)+'.';
    4139 	});
    4140   if(m!=PDomain){
    4141    PURL=PURL.slice(0,i)+m+PURL.slice(i+PDomain.length);
    4142    try{PURL=decodeURI(PURL);}catch(e){PURL=unescape(PURL);}
    4143   }
    4144  }
    4145  return PURL;
    4146 }};
    4147
    4148
    4149 Punycode.adapt=function(delta,numpoints,firsttime){with(Punycode){
    4150 	//document.write('*adapt: '+delta+', '+numpoints+', '+firsttime+', _b='+_b+', _t='+_t+'<br/>');
    4151  delta=firsttime?Math.floor(delta/damp):delta>>1;//Math.floor(delta/(firsttime?damp:2));
    4152  delta+=Math.floor(delta/numpoints);
    4153  var k=0;
    4154  for(;delta>_t;k+=base)delta=Math.floor(delta/_b);
    4155  return k+Math.floor((_b+1)*delta/(delta+skew));
    4156 }};
    4157
    4158 Punycode.encode=function(UString){with(Punycode){
    4159  var n=initial_n,cA=[],m,mA=[],i=0,c
    4160 	,q,delta=0,bias=initial_bias,output=UString.replace(/[^\x01-\x7f]+/g,''),h=output.length,b=h;
    4161 	//document.write('<hr/>Punycode.encode begin: ['+output+']<br/>');
    4162  if(b)output+=delimiter;
    4163
    4164  for(;i<UString.length;i++){
    4165   cA.push(c=UString.charCodeAt(i));
    4166   if(c>n)mA.push(c);
    4167  }
    4168  mA.sort(function(a,b){return b-a;});
    4169
    4170  while(h<cA.length){
    4171   do{c=mA.pop();}while(m==c);	//	預防重複
    4172   m=c;
    4173   //if(m-n>(Number.MAX_VALUE-delta)/(h+1)){alert('Punycode: overflow');return;}
    4174   delta+=(m-n)*(h+1);//	should test overflow
    4175   n=m;
    4176   for(i=0;i<cA.length;i++){
    4177    if(c=cA[i],c<n)++delta;//if(c=cA[i],c<n&&!++delta){alert('Punycode: overflow');return;}//	fail on overflow
    4178 	//document.write('<b>'+UString.charAt(i)+' '+(c.toString(16)+','+n.toString(16)).toUpperCase()+'</b><br/>');
    4179    if(c==n){
    4180     for(q=delta,k=base;;k+=base){
    4181      t=k<=bias/* +tmin not needed */?tmin:k>=bias+tmax?tmax:k-bias;
    4182      if(q<t)break;
    4183      output+=map.charAt(t+(q-t)%(base-t));
    4184 	//document.write('<b>'+output+'</b><br/>');
    4185      q=Math.floor((q-t)/(base-t));
    4186     }
    4187     output+=map.charAt(q);
    4188     bias=adapt(delta,h+1,h==b);
    4189 	//document.write('h='+h+'/'+cA.length+', bias='+bias+', '+output+'<br/>');
    4190     delta=0,h++;
    4191    }
    4192   }
    4193   delta++,n++;
    4194  }
    4195 	//document.write(UString+'→'+output+'<br/>');
    4196  return output;
    4197 }};
    4198
    4199 Punycode.decode=function(PCode){with(Punycode){
    4200  var n=initial_n,i=0,p=PCode.lastIndexOf(delimiter),bias=initial_bias,output=p==-1?'':PCode.slice(0,p)
    4201 	,oldi,w,digit,l;
    4202 	//document.write('<hr/>Punycode.decode begin: ['+output+']<br/>');
    4203  if(!Dmap)for(w=0,Dmap={};w<map.length;w++)Dmap[map.charAt(w)]=w;//,document.write('Dmap['+map.charAt(w)+']='+w+'<br/>');
    4204  while(p<PCode.length-1){
    4205   for(oldi=i,w=1,k=base;;k+=base){
    4206    if(++p>=PCode.length){alert('Punycode: invalid input: out of range');return PCode;}
    4207 	//document.write('PCode.charAt('+p+')'+' = '+PCode.charAt(p)+' → '+Dmap[PCode.charAt(p)]+'<br/>');
    4208    if(isNaN(digit=Dmap[PCode.charAt(p)])){alert('Punycode: invalid input');return PCode;}
    4209    //if(digit>(Number.MAX_VALUE-i)/w){alert('Punycode: overflow');return;}
    4210    i+=digit*w;
    4211    t=k<=bias/* +tmin not needed */?tmin:k>=bias+tmax?tmax:k-bias;
    4212 	//document.write('i='+i+', t='+t+', digit='+digit+', k='+k+'<br/>');
    4213    if(digit<t)break;
    4214    //if(w>Number.MAX_VALUE/(base-t)){alert('Punycode: overflow');return;}
    4215    w*=base-t;
    4216   }
    4217   bias=adapt(i-oldi,l=output.length+1,oldi==0);
    4218 	//document.write('bias='+bias+', n='+n+', i='+i+', l='+l+'<br/>');
    4219   //if(i/l>Number.MAX_VALUE-n){alert('Punycode: overflow');return;}
    4220   n+=Math.floor(i/l);
    4221   i%=l;
    4222 	//document.write('['+output.length+']'+output+'+'+n+'(0x'+n.toString(16).toUpperCase()+')@'+i+'→');
    4223   output=output.slice(0,i)+String.fromCharCode(n)+output.slice(i);
    4224 	//document.write('['+output.length+']'+output+'<br/>');
    4225   i++;
    4226  }
    4227 	//document.write(PCode+'→'+output+'<br/>');
    4228  return output;
    4229 }};
    4230
    4231
    4232 /*
    4233 var testC='Hello-Another-Way--fc4qua05auwb3674vfr0b',rC;
    4234 document.write('<hr/>'+
    4235 //Punycode.encodeDomain('http://國際.計畫.org/國際.計畫.htm')
    4236 Punycode.decodeDomain('http://xn--9cs229l.xn--gpyr35b.org/%E5%9C%8B%E9%9A%9B.%E8%A8%88%E7%95%AB.htm')
    4237 //Punycode.encode('463578')
    4238 //Punycode.decode('ihqwcrb4cv8a8dqg056pqjye')+'<hr/>'+Punycode.encode('他们为什么不说中文')
    4239 //Punycode.decode('ihqwctvzc91f659drss3x8bo0yb')+'<hr/>'+Punycode.encode('他們爲什麽不說中文')
    4240 //(rC=Punycode.decode(testC))+'<hr/>'+(rC=Punycode.encode(rC))+'<hr/>'+(testC==rC?'OK':'<b style="color:red">FAILED</b>:<br/>'+testC+'<br/>'+rC)
    4241 );
    4242 */
    4243
    4244
    4245
    4246 /*	一個非常不好的 deal onload 方法。只在onload不具有arguments時有用，應該亦可用setTimeout('~',0)
    4247 	where	0:back,1:front
    4248
    4249 for IE:
    4250 <!--[if IE]><script defer type="text/javascript">
    4251 //	onload code
    4252 </script><![endif]-->
    4253
    4254 c.f.	http://www.brothercake.com/	http://simonwillison.net/2004/May/26/addLoadEvent/
    4255 	GO1.1 Generic onload by Brothercake
    4256 	window.addEventListener,document.addEventListener,typeof window.attachEvent
    4257 c.f.	setTimeout('~',0);	不過這不能確定已經load好
    4258 */
    4259 /*
    4260 function addonload(s,where){
    4261  if(!s||typeof window!='object')return 1;
    4262  if(typeof s=='function'){
    4263   s=parseFunction(s);
    4264   if(!s||!s.funcName)return 2;
    4265   s=s.funcName+'()';
    4266  }
    4267  var o=window.onload?typeof window.onload=='string'?window.onload:parseFunction(window.onload).contents:'';
    4268  window.onload=new Function(where?s+';\n'+o:o+';\n'+s);
    4269 }
    4270 */
    4271
    4272
    4273 CeL.net.web
    4274 .
    4275 DOM_loaded = function () {
    4276 	if (document.body)
    4277 		return _.DOM_loaded = function () { return true; };
    4278 	else
    4279 		return false;
    4280 };
    4281
    4282
    4283 /*
    4284 // The DOM ready check for Internet Explorer
    4285 try{document.documentElement.doScroll('left');}
    4286 catch(e){setTimeout(arguments.callee, 50);return;}
    4287
    4288 */
    4289 CeL.net.web
    4290 .
    4291 /**
    4292  * 比較好點的 add onload。
    4293  * 比起 add_listener()，本函數在已經 load 時依然會執行，而 add_listener 因為是用榜定的方法，因此 load 完就不再觸發(?)。
    4294  * 這東西頂多只能擺在 include 的 JS file 中，不能 runtime include。
    4295  * @example
    4296  * CeL.use('net.web');
    4297  * CeL.on_load(function(){sl(1);},'sl(2);');
    4298  * @requires	_.add_listener,_.DOM_loaded
    4299  * @see
    4300  * jQuery: $(document).ready(listener);
    4301  * DOMContentLoaded	http://webdesign.piipo.com/jquery/jquery_events
    4302  * 可直接參考 SWFObject。
    4303  * TODO:
    4304  * <a href="http://javascript.nwbox.com/IEContentLoaded/" accessdate="2010/6/3 11:15" title="IEContentLoaded - An alternative for DOMContentLoaded on Internet Explorer">IEContentLoaded</a>
    4305  * DOMContentLoaded是firefox下特有的Event, 當所有DOM解析完以後會觸發這個事件。
    4306  * DOMContentLoaded與DOM中的onLoad事件與其相近。但onload要等到所有頁面元素加載完成才會觸發, 包括頁面上的圖片等等。
    4307  * <a href="http://blog.darkthread.net/blogs/darkthreadtw/archive/2009/06/05/jquery-ready-vs-load.aspx" accessdate="2010/6/3 11:17">jQuery ready vs load - 黑暗執行緒</a>
    4308  * $(document).ready(fn)發生在"網頁本身的HTML"載入後就觸發，而$(window).load(fn)則會等到"網頁HTML 標籤中引用的圖檔、內嵌物件(如Flash)、IFrame"等拉哩拉雜的東西都載入後才會觸發。
    4309  * @memberOf	CeL.net.web
    4310  */
    4311 on_load = function on_load() {
    4312 	var _s = _.on_load, loaded=_.DOM_loaded(),i = 0, a = arguments, l = a.length;
    4313 	for (; i < l; i++)
    4314 		if(loaded)
    4315 			a[i].call(document);
    4316 		else
    4317 			_.add_listener('load', a[i], document);
    4318 };
    4319
    4320
    4321 CeL.net.web
    4322 .
    4323 /**
    4324  * bind/add listener. register event control, setup code to run.
    4325  * listener 應該加上 try{}catch{}，否則會搞不清楚哪裡出問題。
    4326  * **	對同樣的 object，事件本身還是會依照 call add_listener() 的順序跑，不會因為 p_first 而改變。
    4327  * **	NOT TESTED!!
    4328  * TODO:
    4329  * removeEventListener,
    4330  * remove_listener(),
    4331  * default 'this'
    4332  * 自訂 event
    4333  *
    4334  * @param {string} type	listen to what event type. event name/action
    4335  * @param listener	listener function/function array/function string,
    4336  * 				須 String 之 recursive function 時可 "(function(){return function f(){f();};})()"
    4337  * 			function(e){var target=e?e.target:(e=window.event).srcElement;if(e.stopPropagation)e.stopPropagation();else e.cancelBubble=true;if(e.preventDefault)e.preventDefault();else e.returnValue=false;return false;}
    4338  * @param [target_element]	bind/attach to what HTML element
    4339  * @param [p_first]	parentNode first
    4340  * @return
    4341  * @since	2010/1/20 23:42:51
    4342  * @see
    4343  * c.f., GEvent.add_listener()
    4344  * @memberOf	CeL.net.web
    4345  */
    4346 add_listener = function add_listener(type, listener, target_element, p_first) {
    4347 	if (!type || !listener)
    4348 		return;
    4349
    4350 	if (typeof listener === 'string')
    4351 		listener = new Function('e', listener);
    4352
    4353 	if (typeof target_element === 'string')
    4354 		target_element = _.get_element(target_element);
    4355
    4356 	var _s = _.add_listener, i, adder;
    4357
    4358 	if(typeof p_first !== 'bool')
    4359 		p_first = typeof p_first === 'undefined' ? _s.p_first : !!p_first;
    4360
    4361 	//	進階功能
    4362 	if (library_namespace.is_Object(type))
    4363 		// usage: add_listener({unload:Unload});
    4364 		// usage: add_listener({load:{true:[function(){sl(1);},'sl(2);']}});
    4365 		for (i in type)
    4366 			_s(i, type[i], target_element, p_first);// ,sl(i+': '+type[i])
    4367
    4368 	//	Array or Object
    4369 	else if (library_namespace.is_Object(listener))
    4370 		// usage: add_listener('unload',{true:Unload1});
    4371 		// usage: add_listener('unload',[Unload1,Unload2]);
    4372 		// 因為 Array 會從最小的開始照順序出，所以這邊不再判別是否為 Array。
    4373 		for (i in listener)
    4374 			// if(isNaN(f))sl('add_listener: to '+i),_s.p_first=i==='true';//||i==1||i===true
    4375 			_s(type, listener[i], target_element,
    4376 					i === 'true' || (i === 'false' ? false : undefined));// ,sl((typeof i)+' ['+i+'] '+_s.p_first)
    4377
    4378 	else if(library_namespace.is_Function(listener)){
    4379 		/*
    4380 		 * 先設定好 native listener adding function
    4381 		 */
    4382 		if (target_element)
    4383 			adder = target_element.addEventListener;
    4384 		else if (!(adder = _s.global_adder) && adder !== null)
    4385 			_s.global_adder = adder = _s.get_adder();
    4386
    4387 		//$(document).ready(listener);
    4388
    4389 		//	使 listener 能以 this 取得 target_element
    4390 		i = function(e) {
    4391 			if(!e)
    4392 				e = window.event;
    4393
    4394 			//	正規化 Document Object Model (DOM) Level 3 Events
    4395 			//	http://www.w3.org/TR/2009/WD-DOM-Level-3-Events-20090908/#interface-Event
    4396 			if(!e.currentTarget)
    4397 				e.currentTarget = target_element;
    4398 			if(!e.target)
    4399 				e.target = e.srcElement || target_element;
    4400
    4401 			//	from fix in jQuery
    4402
    4403 			// check if target is a textnode (safari)
    4404 			if ( e.target.nodeType === 3 )
    4405 				e.target = e.target.parentNode;
    4406
    4407 			// Add relatedTarget, if necessary
    4408 			if ( !e.relatedTarget && e.fromElement )
    4409 				e.relatedTarget = e.fromElement === e.target ? e.toElement : e.fromElement;
    4410
    4411 			//	取得滑鼠座標
    4412 			//	http://hartshorne.ca/2006/01/23/javascript_cursor_position/
    4413 			//	http://hartshorne.ca/2006/01/18/javascript_events/
    4414 			if ( isNaN(e.pageX) && !isNaN(e.clientX) ) {
    4415 				var s = _.get_window_status.scroll();
    4416 				e.pageX = e.clientX + s[0] - s[2];
    4417 				e.pageY = e.clientY + s[1] - s[3];
    4418 			}
    4419
    4420 			listener.call(target_element, e);
    4421 		};
    4422
    4423 		// 主要核心動作設定之處理
    4424 		//	TODO: 在 onload 時使 target_element = null
    4425 		// sl(type+' ('+((typeof p_first=='undefined'?_s.p_first:p_first?true:false)?'p_first':'run first')+'): '+listener);
    4426 		if(adder){
    4427 			try{
    4428 				//	直接用 target_element.addEventListener 不會有問題。
    4429 				//	.call(window.document): for Chrome 'Illegal invocation' issue
    4430 				//	http://stackoverflow.com/questions/1007340/javascript-function-aliasing-doesnt-seem-to-work
    4431 				//	但 IE9 需要 .call(target_element) 或者別用 .call，否則會得到 "Invalid procedure call or argument"
    4432 				adder.call(target_element, type, i, p_first);
    4433 			}catch(e){
    4434 				adder.call(window.document, type, i, p_first);
    4435 			}
    4436 			return;
    4437 		}
    4438
    4439 		return target_element && (adder = target_element.attachEvent) ?
    4440 			// http://msdn.microsoft.com/en-us/library/ms536343(VS.85).aspx
    4441 			adder('on' + type, i)
    4442
    4443 		: _s.default_adder(type, i, p_first, target_element)
    4444 		;
    4445 	}
    4446
    4447 };
    4448
    4449 CeL.net.web
    4450 .
    4451 /**
    4452  * useCapture: parentNode first
    4453  * @see
    4454  * <a href="http://www.w3.org/TR/DOM-Level-3-Events/#event-flow" accessdate="2010/4/16 22:40">Document Object Model (DOM) Level 3 Events Specification</a>,
    4455  * <a href="http://www.w3.org/TR/DOM-Level-3-Events/#interface-EventTarget" accessdate="2010/4/16 22:42">Interface EventTarget</a>
    4456  */
    4457 add_listener.p_first = false;
    4458
    4459 CeL.net.web
    4460 .
    4461 /**
    4462  * get (native) global listener adding function.
    4463  * TODO: 只設定一次
    4464  * historical for Netscape Navigator, mozilla: window.captureEvents, document.captureEvents
    4465  */
    4466 add_listener.get_adder = function() {
    4467 	/**
    4468 	 * moz (gecko), safari 1.2, ow5b6.1, konqueror, W3C standard: window.addEventListener
    4469 	 * @ignore
    4470 	 * @see
    4471 	 * <a href="https://developer.mozilla.org/en/DOM/element.addEventListener" accessdate="2010/4/16 22:35">element.addEventListener - MDC</a>
    4472 	 * <a href="http://simonwillison.net/2004/May/26/addLoadEvent/" accessdate="2010/4/16 22:36">Executing JavaScript on page load</a>
    4473 	 */
    4474 	return window.addEventListener ||
    4475 	/*
    4476 	 * opera 7.50, ie5.0w, ie5.5w, ie6w: window.attachEvent
    4477 	 * opera 7.50: document.attachEvent
    4478 	 */
    4479 	window.attachEvent ? function(t, l) {
    4480 		window.attachEvent('on' + t, l);
    4481 	} :
    4482 	/*
    4483 	 * MSN/OSX, opera 7.50, safari 1.2, ow5b6.1: document.addEventListener
    4484 	 */
    4485 	document.addEventListener ||
    4486 	/*
    4487 	 * ie5m, MSN/OSX, ie5.0w, ie5.5w ie6w: document.onreadystatechange
    4488 	 */
    4489 	null;
    4490
    4491 };
    4492
    4493 CeL.net.web
    4494 .
    4495 /**
    4496  * 含括其他情況。
    4497  * all: window.onload.
    4498  * TODO: use queue
    4499  * @param type	listen to what event type
    4500  * @param listener	listener function/function array
    4501  * @param [p_first]	parentNode first
    4502  * @param [target_element]	bind/attach to what HTML element
    4503  * @return
    4504  * @see
    4505  * http://blog.othree.net/log/2007/02/06/third-argument-of-addeventlistener/
    4506  */
    4507 add_listener.default_adder = function(type, listener, p_first, target_element) {
    4508 	if(!target_element)
    4509 		target_element = window;
    4510
    4511 	var old = target_element[type = 'on' + type];
    4512
    4513 	return target_element[type] =
    4514 		old ?
    4515 			//	TODO: typeof old==='string'
    4516 			p_first ? function(e) {
    4517 				old.call(target_element, e || window.event);
    4518 				listener.call(target_element, e || window.event);
    4519 			} : function(e) {
    4520 				listener.call(target_element, e || window.event);
    4521 				old.call(target_element, e || window.event);
    4522 			}
    4523 		:
    4524 			listener
    4525 		;
    4526 };
    4527
    4528 CeL.net.web
    4529 .
    4530 /**
    4531  * TODO:
    4532  * listener list.
    4533  * 當無法執行 DOM 操作時（尚未載入、版本太舊不提供支援等）以此為主。
    4534  * add_listener.list[node][event type]=[listener list]
    4535  */
    4536 add_listener.list = {};
    4537
    4538 CeL.net.web
    4539 .
    4540 /**
    4541  * TODO:
    4542  * 觸發函數.
    4543  * 當無法執行 DOM 操作時（尚未載入、版本太舊不提供支援等）以此為主。
    4544  * add_listener.list[type]=[listener list]
    4545  */
    4546 add_listener.list = {};
    4547
    4548
    4549
    4550 CeL.net.web
    4551 .
    4552 /**
    4553  * 阻止 JavaScript 事件冒泡傳遞，使 event 不傳到 parentNode。
    4554  * @param e	event handle
    4555  * @param c	cancel bubble
    4556  * @see
    4557  * http://www.jb51.net/html/200705/23/9858.htm
    4558  * @memberOf	CeL.net.web
    4559  */
    4560 stop_event = function(e, c) {
    4561 	if (!e)
    4562 		e = window.event;
    4563
    4564 	if(e.preventDefault)
    4565 		e.preventDefault();
    4566 	else
    4567 		e.returnValue = false;
    4568
    4569 	if(c)
    4570 		// cancelBubble 在IE下有效，stopPropagation 在 Firefox 下有效。
    4571 		// 停止冒泡，事件不會上升，我們就可以獲取精確的鼠標進入元素。 http://realazy.org/lab/bubble/
    4572 		if(e.stopPropagation)
    4573 			e.stopPropagation();
    4574 		else
    4575 			e.cancelBubble = true;
    4576 };
    4577
    4578
    4579
    4580 CeL.net.web
    4581 .
    4582 /**
    4583  * 獲取頁面上選中的選取區資訊。
    4584  *
    4585  * @example
    4586  * CeL.add_listener('mouseup', function (e) { var s = CeL.get_selection(); if (s && s.text) CeL.debug('select @' + this + '(' + s.element + ')' + ' (' + s.left + '+' + s.width + ',' + s.top + '+' + s.height + '), (' + e.pageX + ',' + e.pageY + '): ' + s.text); }, target_element);
    4587  *
    4588  * @param	{Number} [index]	TODO: 第幾選取區, default: all or 0 if there's only ONE/ZERO selection
    4589  * @return	{Object}
    4590  * 	{
    4591  * 		left: {Number} in px,
    4592  * 		top: {Number} in px,
    4593  * 		width: {Number} in px,
    4594  * 		height: {Number} in px,
    4595  * 		text: {String} 文字,
    4596  * 		element: {HTMLElement},
    4597  * 		selection: selection object (browser dependent)
    4598  * 	}
    4599  * @return	{undefined}	error.
    4600  * @see
    4601  * http://plugins.jquery.com/project/selectedText,
    4602  * Gecko: https://developer.mozilla.org/en/DOM/Selection
    4603  * @memberOf	CeL.net.web
    4604  */
    4605 get_selection = function(index) {
    4606 };
    4607
    4608
    4609 try{
    4610
    4611 	if (window.getSelection)
    4612 		_.get_selection = function(index) {
    4613 			//	Firefox, Opera, Safari
    4614 			//	http://help.dottoro.com/ljcvonpc.php
    4615 			//	Although the selection object is supported by Opera, it is only partially suppported. The window.getSelection method provides more complex functionality in that browser.
    4616 			//	http://www.dotvoid.com/2001/03/using-the-range-object-in-mozilla/
    4617 			var e = document.activeElement,
    4618 			//	在 Opera 中，e 為 [object Text]
    4619 			tag = e && e.tagName && e.tagName.toLowerCase(),
    4620 			s = window.getSelection();
    4621 			if(!s.rangeCount)
    4622 				//	點擊而無選擇?
    4623 				//	最起碼回應能得知的資訊
    4624 				return {
    4625 					text : '',
    4626 					element: s,
    4627 					selection: s
    4628 				};
    4629
    4630 			//	超出範圍可能會 Error: INDEX_SIZE_ERR: DOM Exception 1
    4631 			s = s.getRangeAt(!isNaN(index) && 0 <= index
    4632 					&& index < s.rangeCount ? index : 0);
    4633
    4634 			//	Gecko: https://developer.mozilla.org/en/DOM/range
    4635 			//	除了 Gecko 外，都有 s.getBoundingClientRect 但無 s.endContainer.getBoundingClientRect。
    4636 			//	Gecko 可以取 mouse event 作 workaround
    4637 			//library_namespace.debug(s.endContainer.parentNode);
    4638 			var offset = _.get_node_offset(
    4639 					s.getBoundingClientRect ? s : s.endContainer.parentNode
    4640 				);
    4641
    4642 			return {
    4643 				//	TODO: offset
    4644 				//	TODO: do test
    4645 				//s.startOffset,
    4646 				left : offset.left,
    4647 				top : offset.top,
    4648 				//s.endOffset,
    4649 				width : offset.width,
    4650 				height : offset.height,
    4651 				text : tag === 'textarea' || tag === 'input' || tag === 'select'
    4652 						? e.value.substring(e.selectionStart, e.selectionEnd)
    4653 						: s.toString(),
    4654 				element: s,//s.endContainer,
    4655 				selection: s
    4656 			};
    4657
    4658 		};
    4659
    4660 	else if (document.selection && document.selection.createRange) {
    4661 		// Internet Explorer
    4662 		// http://msdn.microsoft.com/en-us/library/ms534692%28VS.85%29.aspx
    4663 		// TODO: http://help.dottoro.com/ljefwsqm.php
    4664
    4665 		document.execCommand
    4666 		&& document.execCommand('MultipleSelection', true, true);
    4667
    4668 		_.get_selection = function(input) {
    4669 			var s = document.selection.createRange();
    4670
    4671 			return s.type !== 'None' && {
    4672 				//	TODO: do test
    4673 				//	http://msdn.microsoft.com/en-us/library/ms535872%28v=VS.85%29.aspx
    4674 				//	s.offsetLeft, s.offsetTop 較不準
    4675 				left : s.boundingLeft,
    4676 				top : s.boundingTop,
    4677 				width : s.boundingWidth,
    4678 				height : s.boundingHeight,
    4679 				text : s.text,
    4680 				//	TODO
    4681 				//element: null,
    4682 				selection: s
    4683 			};
    4684
    4685 		};
    4686
    4687 	} else if (document.getSelection)
    4688 		_.get_selection = function(input) {
    4689 			return {
    4690 				//	TODO: get offset from mouse location
    4691 				text : document.getSelection()
    4692 			};
    4693 		};
    4694
    4695 }catch (e) {
    4696 	// TODO: handle exception
    4697 }
    4698
    4699 /*
    4700 	↑HTML only	-------------------------------------------------------
    4701 */
    4702
    4703
    4704
    4705 var is_IE=/*@cc_on!@*/!true;
    4706
    4707 /*
    4708 http://www.real-blog.com/programming/259
    4709 http://fettig.net/weblog/2006/10/09/detecting-ie7-in-javascript/
    4710
    4711 if(typeof window.XMLHttpRequest!="undefined"){
    4712  // IE 7, mozilla, safari, opera 9
    4713 }else{
    4714  // IE6, older browsers
    4715 }
    4716 */
    4717
    4718
    4719
    4720
    4721
    4722 /*
    4723 http://www.cnlei.org/blog/article.asp?id=337
    4724 在IE下：
    4725 >> 支持keyCode
    4726 >> 不支持which和charCode,二者值為 undefined
    4727
    4728 在Firefox下：
    4729 >> 支持keyCode，除功能鍵外，其他鍵值始終為 0
    4730 >> 支持which和charCode，二者的值相同
    4731
    4732 在Opera下：
    4733 >> 支持keyCode和which，二者的值相同
    4734 >> 不支持charCode，值為 undefined
    4735
    4736 */
    4737 CeL.net.web
    4738 .
    4739 /**
    4740  * 條碼器(Barcode Scanner)/雷射讀碼器的輸入可用 onkeypress 取得
    4741  * @param callback	callback
    4742  * @return
    4743  * @since	2008/8/26 23:10
    4744  * @example
    4745  * //	usage:
    4746  * deal_barcode(function(t) {
    4747  * 	if (t.length > 9 && t.length < 17)
    4748  * 		document.getElementById("p").value = t,
    4749  * 		document.forms[0].submit();
    4750  * });
    4751  * @memberOf	CeL.net.web
    4752  */
    4753 deal_barcode = function (callback) {
    4754 	var k, lt = 0, st = 0;
    4755 	document.onkeypress = function(e) {
    4756 		var c = new Date();
    4757 		if (
    4758 				// 前後不超過 800，
    4759 				c - st > 800 ||
    4760 				// 與上一輸入不超過 90
    4761 				c - lt > 90) {
    4762 			st = c;
    4763 			k = "";
    4764 		}
    4765 		lt = c;
    4766 		c = e || window.event;
    4767 		c = c.keyCode || c.which || c.charCode;
    4768 		if (c > 32 && c < 120)
    4769 			k += String.fromCharCode(c);
    4770 		else if (c == 13)
    4771 			callback(k, e);
    4772 	};
    4773
    4774 };
    4775
    4776
    4777
    4778 //	https://addons.mozilla.org/js/search-plugin.js
    4779 //	TODO, & Chrome
    4780 function addEngine(){
    4781 }
    4782
    4783
    4784
    4785 //	for string encoding	-------------------------------------------------------
    4786 //	將HTML:&#ddd; → Unicode text
    4787 //	此函數只能用一次，為輸入資料良好之情況下使用。完整版： HTML_to_Unicode
    4788 //turnUnicode[generateCode.dLK]='setTool,getText';
    4789 function turnUnicode(b){
    4790  //s=s.replace(/&#(\d+);/g,String.fromCharCode("$1"));//行不通
    4791  var s=this.valueOf().replace(/ /g,' ').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"').replace(/'/g,"'"),m,t;
    4792
    4793  //舊版本
    4794  //if(m=s.match(/&#(\d{2,7});/g))for(var i=0;i<m.length;i++)s=s.replace(m[i],String.fromCharCode(parseInt(m[i].slice(2,-1))));
    4795
    4796  s=s	//.replace(/&#(0*38|[xX]0*26);/g,"\0")	//預防&：&=&
    4797  //	.replace(/�*38;([^\d;]|$)/g,"\0$1").replace(/&#[xX]0*26;?([^a-fA-F\d;]|$)/g,"\0$1")
    4798
    4799  .replace(/�*(\d{2,7});/g,function($0,$1){return String.fromCharCode($1);})	//JScript 5.5~
    4800  //	.replace(/�*(\d{2,7});/g,function($0,$1){return $1>1114111?$0:String.fromCharCode($1);})	//預防error之版本,~10FFFF=1114111
    4801
    4802  //if(mode=='x')
    4803  //.replace(/&#[xX]0*([a-fA-F\d]{2,6});/g,function($0,$1){return String.fromCharCode(parseInt($1,16));})	//$x111;之版本
    4804  //	.replace(/&#[xX]0*([a-fA-F\d]{2,6});/g,function($0,$1){var t=parseInt($1,16);return t>1114111?$0:String.fromCharCode(t);})
    4805
    4806  //.replace(/\0/g,"&")	//預防&回復
    4807  ;
    4808  if(b)s=s.gText();
    4809  return s;
    4810 };
    4811 //	可適用perl: HTML::Entities::encode_entities()
    4812 //	需要escape的: [\<\>\"\'\%\;\)\(\&\+], tr/A-Za-z0-9\ //dc	http://www.cert.org/tech_tips/malicious_code_mitigation.html
    4813 CeL.net.web
    4814 .
    4815 /**
    4816  * Translate HTML code to Unicode text
    4817  * @param {String} HTML	HTML code
    4818  * @param {Boolean} only_digital
    4819  * @returns
    4820  * @memberOf	CeL.net.web
    4821  */
    4822 HTML_to_Unicode=function (HTML, only_digital) {
    4823 	//	使用\0可能會 Warning: non-octal digit in an escape sequence that doesn't match a back-reference
    4824 	var t = HTML.valueOf();
    4825
    4826 	if (!only_digital)
    4827 		t = t
    4828 			//	自動clip null character
    4829 			.replace(/\0\0/g, '')
    4830 			.replace(/ /g, ' ')
    4831 			.replace(/</g, '<')
    4832 			.replace(/>/g, '>')
    4833 			.replace(/"/g, '"')
    4834 			.replace(/'/g, "'")
    4835 			.replace(/®/g, "®")
    4836 			;
    4837
    4838 	t = t
    4839 		//預防&：&=&
    4840 		.replace(/&#(0*38|[xX]0*26);/g, "\0\0")
    4841 		//預防error之版本,~10FFFF=1114111
    4842 		.replace(/�*(\d{2,7});/g, function ($0, $1) { return $1 > 1114111 ? $0 : String.fromCharCode($1); })
    4843 		.replace(/&#[xX]0*([a-fA-F\d]{2,6});/g, function ($0, $1) { var t = parseInt($1, 16); return t > 1114111 ? $0 : String.fromCharCode(t); })
    4844 		;
    4845
    4846 	if (!only_digital)
    4847 		t = t
    4848 			//預防&回復
    4849 			.replace(/\0\0/g, "&")
    4850 			.replace(/&/g, '&')
    4851 			;
    4852
    4853 	return t;
    4854 };
    4855
    4856 CeL.net.web
    4857 .
    4858 /**
    4859  * Translate Unicode text to HTML
    4860  * @param {String} text	Unicode text
    4861  * @param mode	mode='x':&#xhhh;
    4862  * @return {String}	HTML
    4863  * @memberOf	CeL.net.web
    4864  */
    4865 to_HTML=function (text, mode) {
    4866 	var html = '', t, i = 0;
    4867 	for (; i < text.length; i++)
    4868 		t = text.charCodeAt(i), html += '&#' + (mode === 'x' ? 'x' + t
    4869 				.toString(16) : t) + ';';
    4870 	return html;
    4871 };
    4872 CeL.net.web
    4873 .
    4874 /**
    4875  * Translate Unicode text to HTML code
    4876  * @param text	Unicode text
    4877  * @param flags	flags, f&1!=0: turn \t, (f&2)==0: \n→<br/>, f==4: to quoted
    4878  * @param	ignore_tags	e.g., {object:{src:/^https?:\/\//},img:{src:/^https?:\/\//},a:{href:/^https?:\/\//}}
    4879  * @return
    4880  * @memberOf	CeL.net.web
    4881  */
    4882 Unicode_to_HTML=function (text, flags, ignore_tags) {
    4883 	text = ('' + text)
    4884 		.replace(/&/g, '&')
    4885 		//	就是會出現這奇怪情況。
    4886 		.replace(/&amp;/gi, '&')
    4887 		.replace(/>/g, '>')
    4888 		.replace(/"/g, '"')
    4889 		;
    4890
    4891 	if (ignore_tags)
    4892 		text = text.replace(
    4893 		/<([^>]+)>/g,
    4894 		function($0, $1) {
    4895 			if (!($1 in ignore_tags))
    4896 				return '<' + $1;
    4897 			var s = $1.split(/ /), i = 1, l = s.length, c = ignore_tags[$1];
    4898 			for (; i < l; i++) {
    4899 				m = s[i].match(/^([^=]+)(.+?)/);
    4900 				if (!(m[1] in c)
    4901 						|| !(library_namespace.is_type(
    4902 								c[m[1]], 'RegExp')
    4903 								&& c[m[1]].test(m[2]) || library_namespace
    4904 								.is_Function(c[m[1]])
    4905 								&& c[m[1]](m[2])))
    4906 					s[i] = '';
    4907 				return s.join(' ');
    4908 			}
    4909 		});
    4910 	else
    4911 		text = text.replace(/</g, '<');
    4912
    4913 	if (flags == 4) return text;
    4914
    4915 	text = text.replace(/ /g, ' ');
    4916
    4917 	//if(!f)f=0;
    4918 	if (flags & 1)
    4919 		text = text.replace(/	/g, '<span style="margin-left:3em;"> </span>');
    4920 	if (!(flags & 2))
    4921 		text = text.replace(/(\r?\n)/g, '<br/>$1'); //+'<br/>\n';
    4922 	return text;
    4923 };
    4924
    4925 // Ucode:\uhhhh及\xhh之意
    4926 function UcodeToTxt(U) {
    4927 	var T = U.replace(/\\\\|\\u005[cC]|\\x5[cC]|\\134/g, "\0")
    4928 		/*
    4929 		//way 1
    4930 		.replace(/\\u([a-fA-F\d]{4})/g,function($0,$1){return String.fromCharCode(parseInt($1,16));})
    4931 		.replace(/\\x([a-fA-F\d]{2})/g,function($0,$1){return String.fromCharCode(parseInt($1,16));})
    4932 		.replace(/\\([0-7]{1,3})/g,function($0,$1){return String.fromCharCode(parseInt($1,16));})
    4933 		//way 2
    4934 		.replace(/\\(u[a-fA-F\d]{4}|x[a-fA-F\d]{2})/g,function($0,$1){return String.fromCharCode(parseInt($1.substr(1),16));})
    4935 		.replace(/\\([0-7]{1,3})/g,function($0,$1){return String.fromCharCode(parseInt($1,16));})
    4936 		*/
    4937 		//way 3
    4938 		.replace(/\\(u[a-fA-F\d]{4}|x[a-fA-F\d]{2}|[0-7]{1,3})/g, function ($0, $1) { var t = $1.charAt(0); return String.fromCharCode(parseInt(t == 'u' || t == 'x' ? $1.substr(1) : $1, 16)); })
    4939 		;
    4940
    4941 	if (T.indexOf("\\") != -1)
    4942 		T = T
    4943 			.replace(/\\t/g, "<Tab>")
    4944 			.replace(/\\n/g, "<Line Feed>")
    4945 			.replace(/\\v/g, "<Vertical Tab>")
    4946 			.replace(/\\f/g, "<Form Feed>")
    4947 			.replace(/\\r/g, "<Carriage Return>")
    4948 			.replace(/\\(.)/g, "$1");
    4949
    4950 	return T.replace(/\0/g, "\\");
    4951 }
    4952 function TxtToUcode(T, l) {
    4953 	var i = 0, U = '', t;
    4954 	if (!l) l = 0;
    4955 	for (; i < T.length; i++)
    4956 		U += (t = T.charCodeAt(i)) < l ? T.charAt(i) :  "\\u0000".substr(0, 6 - (t = t.toString(16)).length) + t;
    4957 	return U;
    4958 }
    4959 function CSSToTxt(C) {
    4960 	return C.replace(/\\\\|\\0{0,4}5[cC][ \t\r\n\f]?/g, "\0")
    4961 		.replace(/\\([a-fA-F\d]{1,6})[ \t\r\n\f]?/g, function ($0, $1) { return String.fromCharCode(parseInt($1, 16)); })
    4962 		.replace(/\\(.)/g, "$1").replace(/\0/g, "\\");
    4963 }
    4964 function TxtToCSS(T, r, sp) {
    4965 	//	r:radio,sp:separator
    4966 	var i = 0, C = '', t, p = r && r > 3 && r < 9 ? '0'.x(r - 1) : '';
    4967 	if (!sp) sp = ''; sp += '\\';
    4968
    4969 	for (; i < T.length; i++)
    4970 		t = T.charCodeAt(i).toString(16)
    4971 		, C += sp + p.substr(0, r - t.length) + t; //(p&&r>t.length?p.substr(0,r-t.length):''):如果length是0或負值，會傳回空字串。
    4972 	return C.slice(sp.length - 1);
    4973 }
    4974
    4975
    4976 CeL.net.web
    4977 .
    4978 /**
    4979  * Translate a query string to a native Object contains key/value pair set.
    4980  * @param	{String} query_string	query string. default: location.search
    4981  * @param	{Object} add_to	append to this object
    4982  * @return	key/value pairs
    4983  * @type	Object
    4984  * @since	2010/6/16 15:18:50
    4985  * @memberOf	CeL.net.web
    4986  * @see
    4987  */
    4988 get_query = function(query_string, add_to) {
    4989 	if (!query_string)
    4990 		query_string = window/* self */.location.search.slice(1);
    4991 	// else if(typeof query_string!=='string')..
    4992
    4993 	var i, q = query_string.replace(/\+/g, ' ').split('&'), p, s = add_to || {}, k, v;
    4994 	for (i in q)
    4995 		try {
    4996 			if (p = q[i].match(/^([^=]*)=(.*)$/)) {
    4997 				k = decodeURIComponent(p[1]);
    4998 				v = decodeURIComponent(p[2]);
    4999 				if (k in s)
    5000 					if (typeof s[k] === 'string')
    5001 						s[k] = [ s[k], v ];
    5002 					else
    5003 						s[k].push(v);
    5004 				else
    5005 					s[k] = v;
    5006 			} else
    5007 				s[decodeURIComponent(q[i])] = undefined;
    5008 		} catch (e) {
    5009 			// TODO: handle exception
    5010 		}
    5011
    5012 	return s;
    5013 };
    5014
    5015
    5016 CeL.net.web
    5017 .
    5018 /**
    5019  * Translate a native Object contains key/value pair set to a query string.
    5020  * TODO
    5021  * @param	{Object} query_Object	query Object.
    5022  * @return	{String} query string
    5023  * @type	String
    5024  * @memberOf	CeL.net.web
    5025  * @see
    5026  * jQuery.param
    5027  */
    5028 to_query_string = function(query_Object) {
    5029 	;
    5030 };
    5031
    5032 /*	簡化 HTML (word)
    5033 	simplify HTML
    5034 	目標：剩下語意部分，去掉 style。
    5035 TODO:
    5036 保留 b, em
    5037 */
    5038
    5039 //	保留 color: return style string to add
    5040 //reduceHTML.keep_color=
    5041 reduceHTML._keep_color =
    5042 	function (c) {
    5043 		if (c !== 'black')
    5044 			return c;
    5045 	};
    5046 reduceHTML.file = function (FP, enc) {
    5047 	//sl('reduceHTML [' + FP + ']');
    5048 	var t = simpleRead(FP, enc || simpleFileAutodetectEncode), l;
    5049 	if (!t) {
    5050 		err('Open [' + FP + '] failed.');
    5051 		return;
    5052 	}
    5053
    5054 	l = t.length;
    5055 	t = this(t);
    5056
    5057 	FP = FP.replace(/\.s?html?$/i, function ($0) { return '.reduced' + $0; });
    5058 	//sl('reduceHTML: ' + l + '→' + t.length + ' (' + parseInt(100 * t.length / l) + '%)' + ', save to [<a href="' + encodeURI(FP) + '">' + FP + '</a>].');
    5059 	simpleWrite(FP, t, 'utf-8');
    5060 };
    5061 function reduceHTML(t) {
    5062 	if (!t)
    5063 		return;
    5064 	var _f = reduceHTML, f = function($0, $1, $2) {
    5065 		return $1 != $2 || ($1.toLowerCase() in {
    5066 			a : 1,
    5067 			p : 1,
    5068 			head : 1
    5069 		}) ? $0 : '';
    5070 	};
    5071 	//if(m=t.match(/<!--\[if [^\]]+\]>(.|\n)*?<!\[endif\]-->/))sl(m[0].replace(/</g,'<'));
    5072 	//if(m=t.match(/<!\[if !vml\]>((.|\n)*?)<!\[endif\]>/))sl(m[0]);
    5073
    5074 	t = t
    5075 		.replace(/[\s\n]*<(t[dh])([^>]+)>[\s\n]*/ig, function ($0, $1, $2) { var a = $2.match(/[\s\n](col|row)span=['"]?\d{1,3}['"]?/ig); return '<' + $1 + (a ? a.join('') : '') + '>'; })
    5076 		.replace(/<\?xml:namespace[^>]+>/g, '')
    5077 		.replace(/[\s\n]*(<\/t[dh]>)[\s\n]*/ig, '$1')
    5078 		.replace(/<wbr([^>]*)>/ig, '<br/>')
    5079 		.replace(/<([bh]r)[\s\n]+([^>]*)\/?>/ig, function ($0, $1, $2) { var m = $2.match(/[\s\n;"'][\s\n]*page-break-before[\s\n]*:[\s\n]*([^\s\n;"']+)/); return '<' + $1 + (m ? ' style="page-break-before:' + m[1] + '"' : '') + '>'; })
    5080 		.replace(/<(span|font|p|div|b|u|i)[\s\n]+([^>]*)>/ig, function ($0, $1, $2) {
    5081 			var t = '<' + $1, s = '', m;
    5082 			if (
    5083 					//	/Italic/i.test($2)
    5084 					$2.indexOf('Italic') !== -1)
    5085 				s += 'font-style:italic;';
    5086 			//	TODO: <u>, <b>
    5087 			if (_f.keep_color && (m = $2.match(/[\s\n;"'][\s\n]*color[\s\n]*:[\s\n]*([^\s\n;"']+)/)) && (m = _f.keep_color(m[1])))
    5088 				//	保留 color
    5089 				s += 'color:' + m + ';';
    5090 			return t + (s ? ' style="' + s + '"' : '') + '>';
    5091 		})
    5092 		.replace(/<(tr|table)[\s\n]+([^>]*)>/ig, '<$1>')
    5093 		.replace(/<span>((.|\n)*?)<\/span>/ig, '$1')	//	不能用 .+|\n ，IE8 sometimes crash
    5094 		.replace(/<span>((.|\n)*?)<\/span>/ig, '$1')	//	need several times
    5095 		.replace(/<font>((.|\n)*?)<\/font>/ig, '$1')
    5096 		.replace(/<([a-z\d]+)>[\s\n]*<\/([a-z\d]+)>/ig, f)
    5097 		.replace(/<([a-z\d]+)>[\s\n]*<\/([a-z\d]+)>/ig, f)	//	2 times
    5098 		.replace(/<o:p>((.|\n)*?)<\/o:p>/ig, '$1')
    5099 		.replace(/<st1:[^>]+>((.|\n)*?)<\/st1:[^>]+>/ig, '$1')
    5100 		.replace(/<!\[if !vml\]>((.|\n)*?)<!\[endif\]>/ig, '$1')
    5101 		.replace(/<o:SmartTagType [^>]+\/>/ig, '')
    5102 		/*
    5103 		<td>
    5104 		<p> </p>
    5105 		</td>
    5106 		*/
    5107 		.replace(/<(span|p|div|t[dr])([^>]*>)<(span|p)>(([\s\n]+| )*?)<\/(span|p)><\/(span|p|div|t[dr])>/ig, '<$1$2$4</$7>')
    5108 		.replace(/<link rel=(File-List|colorSchemeMapping|themeData|Edit-Time-Data)[^>]+>/ig, '')
    5109 		.replace(/^\s*<html[^>]*>(\r?\n)*/, '<html>')
    5110 		.replace(/(\r?\n)*<body[^>]+>(\r?\n)*/, '<body>')
    5111 		.replace(/(\r?\n)*<!--\[if [^\]]+\]>(.|\n)*?<!\[endif\]-->(\r?\n)*/ig, '')
    5112 		.replace(/(\r?\n)*<style[^>]*>(.|\n)*?<\/style>(\r?\n)*/ig, '')
    5113 		.replace(/(\r?\n)*<meta[\s\n][^>]+>(\r?\n)*/ig, '')
    5114
    5115 		//	from HTML_to_Unicode()
    5116 		.replace(/�*(\d{2,7});/ig, function ($0, $1) { return $1 > 1114111 ? $0 : String.fromCharCode($1); })	//預防error之版本,~10FFFF=1114111
    5117 		.replace(/([\s\n]+| )+$|^([\s\n]+| )+/g, '')
    5118 		;
    5119
    5120 	if (/<table[\s>\r\n]/.test(t))
    5121 		//sl('Has table'),
    5122 		t = t.replace(/<\/head>/i, '<style type="text/css">table,th,td{border:1px solid #888;border-collapse:collapse;}</style></head>');
    5123
    5124 	return t;
    5125 };
    5126
    5127
    5128 CeL.net.web
    5129 .
    5130 /**
    5131  * 將 BIG5 日文假名碼修改為 Unicode 日文假名。
    5132  * @param {String} text	Unicode text
    5133  * @return
    5134  * @see
    5135  * from Unicode 補完計畫 jrename.js
    5136  */
    5137 Big5_kana_fix = function(text) {
    5138 	var H = '', t, i = 0;
    5139 	for (; i < text.length; i++)
    5140 		t = c.charCodeAt(0)
    5141 		// 某次破解Windows Installer所用的資料
    5142 		// ,H+=String.fromCharCode(t>61300?t-48977:t);
    5143 		, H += t === 63219 ? 'ー' : String.fromCharCode(
    5144 				// ひらがな
    5145 				t >= 63223 && t <= 63305 ? t - 50870 :
    5146 				// カタカナ
    5147 				t >= 63306 && t <= 63391 ? t - 50857 :
    5148 				// text.charAt(i);
    5149 				t);
    5150 	return H;
    5151 };
    5152
    5153
    5154 //	↑for string encoding	-----------------------------------------------
    5155
    5156
    5157
    5158
    5159 return (
    5160 	CeL.net.web
    5161 );
    5162 };
    5163
    5164 //===================================================
    5165
    5166 CeL.setup_module(module_name, code_for_including);
    5167
    5168 };
    5169