      1 ﻿
      2 /**
      3  * @name	CeL function for compatibility
      4  * @fileoverview
      5  * 本檔案包含了相容性 test 專用的 functions。
      6  * @since
      7  * @see
      8  * <a href="http://msdn.microsoft.com/en-us/library/s4esdbwz%28v=VS.85%29.aspx" accessdate="2010/4/16 20:4">Version Information (Windows Scripting - JScript)</a>
      9  */
     10
     11 /*
     12 http://www.comsharp.com/GetKnowledge/zh-CN/It_News_K875.aspx
     13 8進制數字表示被禁止， 010 代表 10 而不是 8
     14 引入 JSON
     15 Array 對象內置了一些標準函數，如 indexOf(), map(), filter(), reduce()
     16 # Object.keys() 會列出對象中所有可以枚舉的屬性
     17 # Object.getOwnPropertyNames() 會列出對象中所有可枚舉以及不可枚舉的屬性
     18 # Object.getPrototypeof() 返回給定對象的原型
     19
     20 http://jquerymobile.com/gbs/
     21 */
     22
     23 if (typeof CeL === 'function')
     24 CeL.setup_module('data.code.compatibility',
     25 function(library_namespace, load_arguments) {
     26
     27 //	no requiring
     28
     29
     30 /**
     31  * null module constructor
     32  * @class	相容性 test 專用的 functions
     33  */
     34 CeL.data.code.compatibility
     35 = function() {
     36 	//	null module constructor
     37 };
     38
     39 /**
     40  * for JSDT: 有 prototype 才會將之當作 Class
     41  */
     42 CeL.data.code.compatibility
     43 .prototype = {
     44 };
     45
     46
     47
     48
     49
     50
     51 /*	對於舊版沒有Array.push()等函數時之判別及處置,舊版adapter
     52 	從(typeof object.reverse=='function')可偵測object是否為Array
     53 	http://www.coolcode.cn/?p=126
     54 */
     55 //oldVadapter[generateCode.dLK]='*oldVadapter();';
     56 function oldVadapter(){
     57  //var _Global=typeof window=='object'?window:this;
     58  // Global undefined variable
     59 /*
     60  if(typeof _Global=='undefined')window.undefined=_Global;
     61  else _Global.undefined=_Global.undefined;
     62 */
     63
     64  if(!Array.prototype.push&&typeof Apush=='function')Array.prototype.push=Apush;
     65  if(!Array.prototype.pop&&typeof Apop=='function')Array.prototype.pop=Apop;
     66  if(!Array.prototype.shift&&typeof Ashift=='function')Array.prototype.shift=Ashift;
     67  if(!Array.prototype.unshift&&typeof Aunshift=='function')Array.prototype.unshift=Aunshift;
     68  //	apply & call: after ECMAScript 3rd Edition	不直接用undefined: for JS5
     69  if(typeof Function.prototype.apply=='undefined'&&typeof Fapply=='function')Function.prototype.apply=Fapply;
     70  if(typeof Function.prototype.call=='undefined'&&typeof Fcall=='function')Function.prototype.call=Fcall;
     71  //if(typeof isNaN!='function'&&typeof NisNaN=='function')isNaN=NisNaN;
     72  if(typeof encodeURI!='function'&&typeof escape=='function')encodeURI=escape;
     73  if(typeof decodeURI!='function'&&typeof unescape=='function')decodeURI=unescape;
     74  if(typeof encodeURIComponent!='function'&&typeof encodeURI=='function')encodeURIComponent=encodeURI;
     75  if(typeof decodeURIComponent!='function'&&typeof decodeURI=='function')decodeURIComponent=decodeURI;
     76 }
     77
     78 //	在 FF3 僅用 this[this.length]=o; 效率略好於 Array.push()，但 Chrome 6 相反。
     79 function Apush(o){this[this.length]=o;return this.length;}
     80 //	將 element_toPush 加入 array_pushTo 並篩選重複的（本來已經加入的並不會變更）
     81 //	array_reverse[value of element_toPush]=index of element_toPush
     82 function pushUnique(array_pushTo,element_toPush,array_reverse){
     83  if(!array_pushTo||!element_toPush)return array_pushTo;
     84  var i;
     85  if(!array_reverse)
     86   for(array_reverse=new Array,i=0;i<array_pushTo;i++)
     87    array_reverse[array_pushTo[i]]=i;
     88
     89  if(typeof element_toPush!='object')
     90   i=element_toPush,element_toPush=new Array,element_toPush.push(i);
     91
     92  var l;
     93  for(i in element_toPush)
     94   if(!array_reverse[element_toPush])
     95    //array_pushTo.push(element_toPush),array_reverse[element_toPush]=array_pushTo.length;
     96    array_reverse[array_pushTo[l = array_pushTo.length] = element_toPush[i]] = l;
     97
     98  return array_pushTo;
     99 }
    100
    101 //	e.g., Array.prototype.concat does not change the existing arrays, it only returns a copy of the joined arrays.
    102 function Aappend(a) {
    103 	var t = this, s = t.length, i = 0, l = a && a.length || 0;
    104 	for (; i < l; i++)
    105 		t[s + i] = a[i];
    106 	return t;
    107 }
    108
    109 function Apop(){
    110  if(!this.length)return;
    111  var t=this.slice(-1);this.length--;return t;//不能用return this[--this.length];
    112 }
    113 function Ashift(){
    114  //var t=this[0],s=this.join('\0');s=s.substr(s.indexOf('\0')+1);this.length=0;this.push(s.split('\0'));return t;
    115  var t=this[0];
    116  this.value=this.slice(1);	//	ECMAScript 不允許設定 this=
    117  return t;
    118 }
    119 function Aunshift(o){
    120  if(!this.length)return;
    121  //var t=this.join('\0');this.length=0;this.push(o);this.push(t.split('\0'));return this;
    122  return this.value=[o].concat(this);	//	ECMAScript 不允許設定 this=
    123 }	//	不能用t=this.valueOf(); .. this.push(t);
    124 //	奇怪的是，這個版本(5.1版)尚不提供isNaN。(should be isNaN, NOT isNAN)
    125 //	變數可以與其本身比較。如果比較結果不相等，則它會是 NaN。原因是 NaN 是唯一與其本身不相等的值。
    126 //function NisNaN(v){var a=typeof v=='number'?v:parseInt(v);return /*typeof v=='number'&&*/a!=a;}//parseFloat(v)	alert(typeof a+','+a+','+(a===a));
    127 //oldVadapter();
    128
    129 /*	http://www.cnblogs.com/sunwangji/archive/2007/06/26/791428.html	http://www.cnblogs.com/sunwangji/archive/2006/08/21/482341.html
    130 	http://msdn.microsoft.com/en-us/library/4zc42wh1(VS.85).aspx
    131 	http://www.interq.or.jp/student/exeal/dss/ejs/3/1.html
    132 	http://blog.mvpcn.net/fason/
    133 	http://d.hatena.ne.jp/m-hiyama/20051017/1129510043
    134 	http://noir.s7.xrea.com/archives/000203.html
    135
    136 http://msdn.microsoft.com/en-us/library/4zc42wh1(VS.85).aspx
    137 傳回某物件的方法，以另一個物件取代目前的物件。
    138 apply是將現在正在執行的function其this改成apply的引數。所有函數內部的this指針都會被賦值為oThis，這可實現將函數作為另外一個對象的方法運行的目的
    139 xxx.apply(oThis,arrayArgs): 執行xxx，執行時以oThis作為 this，arrayArgs作為 arguments
    140
    141 http://www.tohoho-web.com/js/object.htm#inheritClass
    142 クラスを継承する	親のクラスが持っている機能をすべて使用することができます。
    143
    144 to make classChild inheritance classParent:	http://www.interq.or.jp/student/exeal/dss/ejs/3/2.html
    145 function classChild(_args1,_args2,..){
    146  處理arguments：arguments.pop() or other way
    147
    148  classParent.call(this,_args1,_args2,..);	//	way1
    149  classParent.apply(this,arguments);	//	way2
    150  //this.constructor=classChild;	//	maybe needless
    151
    152  // ..
    153 }
    154 classChild.prototype=new classParent;	//	for (objChild instanceof objParent)	關鍵字: 繼承，原型
    155 classChild.prototype.methodOfParent=function(..){..};	//	オーバーライド
    156
    157 var objChild=new classChild(_args);
    158 classParent.prototype.methodOfParent.call(objChild, ..);	//	基底プロトタイプのメソッドを呼び出す。ただしこの呼び出し自体は Programmer が Person を継承しているかどうかを何も考慮していません。
    159
    160
    161 因 arguments 非instanceof Array，arguments.join(sp) → Array.prototype.join.call(arguments,sp)
    162 */
    163 /**
    164  * @ignore
    165  */
    166 if(0)
    167 function Fapply(/* object */ oThis /* = null */, /* Array */ arrayArgs /* = null */) {
    168  if(oThis == null || oThis == undefined)	//	グローバルオブジェクトに適用
    169   return arrayArgs == null || arrayArgs == undefined? this(): this(arrayArgs);
    170  if(!(oThis instanceof Object))
    171   return undefined;	//	実際は throw TypeError();
    172
    173  oThis.$_funcTmp000 = this;
    174
    175  var oReturn;
    176  if(arrayArgs == null || arrayArgs == undefined)
    177   oReturn = oThis.$_funcTmp000();
    178  else if(arrayArgs instanceof Array){
    179   var i=0,args=[];
    180   for(;i<arrayArgs.length;i++)
    181    args[i]='arrayArgs['+i+']';//args.push('arrayArgs['+i+']');
    182   oReturn = eval("oThis.$_funcTmp000("+args.join(",")+");");	//	因為arrayArgs[i]之type不固定，故不能直接用arrayArgs.join(",")
    183  }//else{delete oThis.$_funcTmp000;throw TypeError();}
    184
    185  delete oThis.$_funcTmp000;
    186  return oReturn;
    187 }
    188 /*	http://msdn.microsoft.com/library/CHT/jscript7/html/jsmthcall.asp
    189 call 方法是用來呼叫代表另一個物件的方法。call 方法可讓您將函式的物件內容從原始內容變成由 thisObj 所指定的新物件。
    190 如果未提供 thisObj 的話，將使用 global 物件作為 thisObj。
    191 */
    192 /**
    193  * @ignore
    194  */
    195 if(0)
    196 function Fcall(/* object */ oThis /* = null [, arg1[, arg2[, ... [, argN]]]]] */){
    197  var argu=[];//Array.prototype.slice.call(arguments);
    198  for(var i=1;i<arguments.length;i++)
    199   argu[i-1]=arguments[i];	//	argu.push(arguments[i]);
    200  return this.apply(oThis, argu);
    201 }
    202
    203
    204
    205
    206 CeL.data.code.compatibility
    207 .
    208 /**
    209  * Are we in a web environment?
    210  * @param W3CDOM	Are we in a W3C DOM environment?
    211  * @return	We're in a web environment.
    212  * @since	2009/12/29 19:18:53
    213  * @see
    214  * use lazy evaluation
    215  * @memberOf	CeL.data.code.compatibility
    216  */
    217 is_web = function is_web(W3CDOM) {
    218 	var _s = is_web;
    219 	if (!('web' in _s))
    220 		_s.W3CDOM =
    221 				(
    222 				_s.web = typeof window === 'object'
    223 						&& typeof document === 'object'
    224 						&& window.document === document
    225 						// 下兩個在 IE5.5 中都是 Object
    226 						//&& library_namespace.is_type(window, 'global')
    227 						//&& library_namespace.is_type(document, 'HTMLDocument')
    228 				)
    229 				// W3CDOM, type: Object @ IE5.5
    230 				&& document.createElement
    231 				// &&!!document.createElement
    232 				//	type: Object @ IE5.5
    233 				&& document.getElementsByTagName;
    234
    235 	return W3CDOM ? _s.W3CDOM : _s.web;
    236 };
    237
    238
    239 CeL.data.code.compatibility
    240 .
    241 /**
    242  * 判斷為 DOM。
    243  * @param	name	various name @ name-space window. e.g., document, location
    244  * @return	{Boolean}	various is object of window
    245  * @since	2010/1/14 22:04:37
    246  * @memberOf	CeL.data.code.compatibility
    247  */
    248 is_DOM = function(name) {
    249 	var r = _.is_web();
    250 	if (!r || !name)
    251 		return r;
    252
    253 	// CeL.debug(CeL.is_type(window[name]));
    254 	try {
    255 		r = eval(name + '===window.' + name);
    256 	} catch (e) {
    257 		r = false;
    258 	}
    259 	return r;
    260 };
    261
    262
    263 //is_HTA[generateCode.dLK]='is_web';
    264 CeL.data.code.compatibility
    265 .
    266 /**
    267  * Are we run in HTA?<br/>
    268  * ** HTA 中應該在 onload 中呼叫，否則 document.getElementsByTagName 不會有東西！
    269  * @param [id]	HTA tag id (only used in low version that we have no document.getElementsByTagName)
    270  * @return	We're in HTA
    271  * @require	is_web
    272  * @since	2009/12/29 19:18:53
    273  * @memberOf	CeL.data.code.compatibility
    274  * @see
    275  * http://msdn2.microsoft.com/en-us/library/ms536479.aspx
    276  * http://www.microsoft.com/technet/scriptcenter/resources/qanda/apr05/hey0420.mspx
    277  * http://www.msfn.org/board/lofiversion/index.php/t61847.html
    278  * lazy evaluation
    279  * http://peter.michaux.ca/articles/lazy-function-definition-pattern
    280  */
    281 is_HTA = function is_HTA(id) {
    282 	var _s = is_HTA, a;
    283 	if ('HTA' in _s)
    284 		return _s.HTA;
    285
    286 	if (is_web(1)) {
    287 		a = document.getElementsByTagName('APPLICATION');
    288 		a = a && a.length === 1 && a[0];
    289 	} else
    290 		a = is_web() && id && document.all && document.all[id];
    291
    292 	return _s.HTA = a;
    293 };
    294
    295
    296
    297 //	版本檢查
    298 function checkVer(ver) {
    299 	if (!ver || ver < 5)
    300 		ver = 5; // WScript.FullName,WScript.Path
    301 	with (WScript)
    302 	if (Version < ver)
    303 		with (WshShell) {
    304 		var promptTitle = Locale == 0x411 ? 'アップグレードしませんか？'
    305 				: '請升級', promptC = Locale == 0x411 ? "今使ってる "
    306 						+ WScript.Name
    307 						+ " のバージョンは古過ぎるから、\nMicrosoft Windows スクリプト テクノロジ Web サイトより\nバージョン "
    308 						+ Version + " から " + ver + " 以上にアップグレードしましょう。"
    309 						: "正使用的 "
    310 							+ WScript.Name
    311 							+ " 版本過舊，\n請至 Microsoft Windows 網站將版本由 "
    312 							+ Version + " 升級到 " + ver + " 以上。", url = /* Locale==0x411? */"http://www.microsoft.com/japan/developer/scripting/default.htm";
    313 		if (1 == Popup(promptC, 0, promptTitle, 1 + 48))
    314 			Run(url);
    315 		Quit(1);
    316 	}
    317 }
    318
    319
    320
    321
    322
    323
    324
    325 /*	2008/12/21 18:53:42
    326 value to json
    327 JavaScript Object Notation	ECMA-262 3rd Edition
    328
    329 http://stackoverflow.com/questions/1500745/how-to-pass-parameters-in-eval-in-an-object-form
    330 json={name:'~',values:..,description:'~'}
    331 window[json.name].apply(null, json.values)
    332
    333
    334 usage:
    335 json(value)
    336
    337 parse:
    338 data=eval('('+data+')');	//	字串的前後記得要加上刮號 ()，這是用來告知 Javascript Interpreter 這是個物件描述，不是要執行的 statement。
    339 eval('data='+data);
    340
    341 TODO:
    342
    343 useObj
    344 加入function object成員，.prototype可用with()。加入函數相依性(dependency)
    345
    346 array用name:
    347 (function(){
    348 var o;
    349 o=[..];
    350 var i,v={..};
    351 for(i in v)o[i]=v[i];
    352 return o;
    353 })()
    354
    355
    356 recursion 循環參照
    357 (function(){
    358 var o;
    359 o={a:[]};
    360 o['b']=[o['a']],
    361 o['a'].push([o['b']]);
    362 return o;
    363 })()
    364
    365
    366
    367 BUG:
    368 function 之名稱被清除掉了，這可能會產生問題！
    369 (function(){
    370 var f=function(){..};
    371 f.a=..;
    372 f.b=..;
    373 f.prototype={
    374 a:..,
    375 b:..
    376 }
    377 return f;
    378 })()
    379
    380
    381 */
    382 //json[generateCode.dLK]='qNum,dQuote';
    383
    384
    385
    386 /*
    387 var a=[],b;a.push(b=[a]);json(a);
    388
    389 test recursion 循環參照
    390 (function(){
    391 var o=[],_1=[o];
    392 o.push(_1);
    393 return o;
    394 })();
    395
    396 */
    397
    398 /*
    399 改用 window.JSON, jQuery.parseJSON
    400 據說toJSONString跟parseJSON有可能成為ECMAScript第四版的標準
    401
    402 須判別來源是否為 String or Number!
    403
    404
    405 九个PHP很有用的功能 | 酷壳 - CoolShell.cn
    406 http://coolshell.cn/?p=2394
    407 你是否會把一個比較複雜的數據結構存到數據庫或是文件中？你並不需要自己去寫自己的算法。PHP早已為你做好了，其提供了兩個函數：?serialize()  和 unserialize()
    408 JSON越來越流行，所以在PHP5.2以後，PHP開始支持JSON，你可以使用 json_encode() 和 json_decode() 函數。但是對於一些非常複雜的數據結構，可能會造成數據丟失。
    409
    410
    411 json.dL='dependencyList';	//	dependency List Key
    412 json.forceArray=1;
    413
    414 json.indentString='	';
    415 json.NewLine='\n';
    416 json.separator=' ';
    417 function json(val,name,type){	//	type==2: inside object, treat undefined as ''
    418 var _f=json,expA=[],expC=[],vType=typeof val
    419 ,addE=function(o,l,n){
    420 	if(l){
    421 	 o=_f(o,0,2);
    422 	 n=typeof n=='undefined'||n===''?''
    423 		:(/^(\d{1,8})?(\.\d{1,8})?$/.test(n)||/^[a-z_][a-z_\d]{0,30}$/i.test(n)?n:dQuote(n))+':'+_f.separator;
    424 	 expA.push(n,o[1]);
    425
    426 	 //expC.push(_f.indentString+n+o[0].join(_f.NewLine+_f.indentString)+',');
    427 	 o=o[0];
    428 	 o[0]=n+(typeof o[0]=='undefined'?'':o[0]);
    429 	 o[o.length-1]+=',';
    430 	 for(var i=0;i<o.length;i++)
    431 	  o[i]=_f.indentString+(typeof o[i]=='undefined'?'':o[i]);
    432 	 expC=expC.concat(o);
    433 	}else expA.push(o),expC.push(o);
    434 }
    435 //	去掉最後一組的 ',' 並作結
    436 ,closeB=function(c){
    437 	var v=expC[expC.length-1];
    438 	if(v.charAt(v.length-1)==',')
    439 	 expC[expC.length-1]=v.slice(0,v.length-1);
    440 	addE(c);
    441 };
    442
    443 switch(vType){
    444 case 'number':
    445 //	http://msdn2.microsoft.com/zh-tw/library/y382995a(VS.80).aspx
    446 //	isFinite(value) ? String(value)
    447 var k=0,m='MAX_VALUE,MIN_VALUE,NEGATIVE_INFINITY,POSITIVE_INFINITY,NaN'.split(','),t=0;
    448 if(val===NaN||val===Infinity||val===-Infinity)t=''+val;
    449 else for(;k<m.length;k++)
    450  if(val===Number[m[k]]){t='Number.'+m[k];break;}
    451 if(!t){
    452  //	http://msdn2.microsoft.com/zh-tw/library/shydc6ax(VS.80).aspx
    453  for(k=0,m='E,LN10,LN2,LOG10E,LOG2E,PI,SQRT1_2,SQRT2'.split(',');k<m.length;k++)
    454   if(val===Math[m[k]]){t='Math.'+m[k];break;}
    455  if(!t)
    456   if(k=(''+val).match(/^(-?\d*[1-9])(0{3,})$/))
    457    t=k[1]+'e'+k[2].length;
    458   else{
    459
    460    //	有理數判別
    461    k=qNum(val);
    462
    463    //	小數不以分數顯示. m==1:非分數
    464    m=k[1];
    465    while(m%2==0)m/=2;
    466    while(m%5==0)m/=5;
    467
    468    t=k[2]==0 && m!=1?k[0]+'/'+k[1]:
    469 	//	TODO: 加速(?)
    470 	(t=Math.floor(val))==val&&(''+t).length>(t='0x'+val.toString(16)).length?t:val;
    471   }
    472
    473 }
    474 addE(t);
    475 break;
    476 case 'null':
    477 addE(''+val);
    478 break;
    479 case 'boolean':
    480 addE(val);
    481 break;
    482 case 'string':
    483 addE(dQuote(val));
    484 break;
    485 case 'undefined':
    486 addE(type==2?'':'undefined');
    487 break;
    488
    489 case 'function':
    490 //	加入function object成員，.prototype可用with()。加入函數相依性(dependency)
    491 var toS,f;
    492 //	這在多執行緒有機會出問題！
    493 if(typeof val.toString!='undefined'){toS=val.toString;delete val.toString;}
    494 f=''+val;
    495 if(typeof toS!='undefined')val.toString=toS;
    496
    497 f=f.replace(/\r?\n/g,_f.NewLine);	//	function 才會產生 \r\n 問題，所以先處理掉
    498 var r=/^function\s+([^(\s]+)/,m=f.match(r),t;
    499 if(m)m=m[1],addE('//	function ['+m+']'),t=f.replace(r,'function'+_f.separator);
    500 if(m&&t.indexOf(m)!=-1)alert('function ['+m+'] 之名稱被清除掉了，這可能會產生問題！');
    501 addE(t||f);
    502 //	UNDO
    503 break;
    504
    505 case 'object':
    506 try{
    507 if(val===null){addE(''+val);break;}
    508 var c=val.constructor;
    509 if(c==RegExp){
    510  addE(val);
    511  break;
    512 }
    513 if(c==Date || vType=='date'){	//	typeof val.getTime=='function'
    514  //	與 now 相隔過短(<1e7, 約3h)視為 now。但若是 new Date()+3 之類的會出現誤差！
    515  addE('new Date'+((val-new Date)>1e7?'('+val.getTime()+')':''));	//	date被當作object
    516  break;
    517 }
    518 if((''+c).indexOf('Error')!=-1){
    519  addE('new Error'+(val.number||val.description?'('+(val.number||'')+(val.description?(val.number?',':'')+dQuote(val.description):'')+')':''));
    520  break;
    521 }
    522
    523 var useObj=0;
    524 if(c==Array){
    525  var i,l=0;
    526  if(!_f.forceArray)for(i in val)
    527   if(isNaN(i)){useObj=1;break;}else l++;
    528
    529  if(_f.forceArray || !useObj && l>val.length*.8){
    530   addE('[');
    531   for(i=0;i<val.length;i++)
    532    addE(val[i],1);
    533   closeB(']');
    534   break;
    535  }else useObj=1;
    536 }
    537
    538 if(useObj||c==Object){// instanceof
    539  addE('{');
    540  for(var i in val)
    541   addE(val[i],1,i);
    542  closeB('}');
    543  break;
    544 }
    545 addE(dQuote(val));
    546 break;
    547 }catch(e){
    548 if(28==(e.number&0xFFFF))
    549  alert('json: Too much recursion?\n循環參照？');
    550 return;
    551 }
    552
    553 case 'unknown':	//	sometimes we have this kind of type
    554 default:
    555 alert('Unknown type: ['+vType+'] (constructor: '+val.constructor+'), please contract me!\n'+val);
    556 break;
    557 //alert(vType);
    558 }
    559 return type?[expC,expA]:expC.join(_f.NewLine);
    560 }
    561
    562 */
    563
    564
    565
    566
    567
    568
    569
    570
    571 return (
    572 	CeL.data.code.compatibility
    573 );
    574 }
    575
    576
    577 );
    578
    579