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