1 
  2 /**
  3  * @name	CeL data function
  4  * @fileoverview
  5  * 本檔案包含了 data 處理的 functions。
  6  * @since	
  7  */
  8 
  9 
 10 if (typeof CeL === 'function')
 11 CeL.setup_module('data',
 12 {
 13 require : 'data.native.to_fixed',
 14 code : function(library_namespace, load_arguments) {
 15 
 16 //	requiring
 17 var to_fixed;
 18 eval(library_namespace.use_function(this));
 19 
 20 
 21 /**
 22  * null module constructor
 23  * @class	data 處理的 functions
 24  */
 25 CeL.data
 26 = function() {
 27 	//	null module constructor
 28 };
 29 
 30 /**
 31  * for JSDT: 有 prototype 才會將之當作 Class
 32  */
 33 CeL.data
 34 .prototype = {
 35 };
 36 
 37 
 38 
 39 
 40 /*
 41 	eval(uneval(o)): IE 沒有 uneval
 42 	http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
 43 
 44 way1:
 45 return YAHOO.lang.JSON.parse( YAHOO.lang.JSON.stringify( obj ) );
 46 
 47 TODO:
 48 1.
 49 防止交叉參照版: try
 50 var a=function(){this.a=1,this.b={a:this.a},this.a={b:this.b};},b=cloneObject(a);
 51 .or.
 52 var a={},b;
 53 a.a={a:1};
 54 a.b={a:a.a};
 55 a.a={b:a.b};
 56 b=cloneObject(a);
 57 
 58 恐須改成
 59 =new cloneObject();
 60 
 61 
 62 2.
 63 equal()
 64 
 65 */
 66 CeL.data
 67 .
 68 clone_object =
 69 /**
 70  * clone native Object
 71  * @param {Object} object
 72  * @param {Boolean} not_trivial
 73  * @return
 74  * @since	2008/7/19 11:13:10
 75  */
 76 function clone_object(object, not_trivial) {
 77 	if (!object || !(object instanceof Object)
 78 			// || typeof(object) != 'object'
 79 			)
 80 		return object;
 81 	var i, r = new object.constructor(object); // o.constructor()
 82 	for (i in object)
 83 		// o[i]===o: 預防 loop, 但還是不能防止交叉參照
 84 		r[i] = not_trivial/* ||o[i]===o */? object[i] : clone_object(object[i], deep);
 85 	return r;
 86 };
 87 
 88 
 89 /*	2004/5/5
 90 	輸入('"','dh"fdgfg')得到2:指向"的位置
 91 */
 92 function getQuoteIndex(quote,str){	//	quote:['"/],[/]可能不太適用,除非將/[/]/→/[\/]/
 93  var i,l=0;
 94  while(i=str.indexOf(quote,l),i>0&&str.charAt(i-1)=='\\')
 95   if( str.slice(l,i-2).match(/(\\+)$/) && RegExp.$1.length%2 )break;
 96   else l=i+1;
 97  return i;
 98 }
 99 
100 
101 
102 
103 
104 //{var a=[],b,t='',i;a[20]=4,a[12]=8,a[27]=4,a[29]=4,a[5]=6,a.e=60,a.d=17,a.c=1;alert(a);b=sortValue(a);alert(a+'\n'+b);for(i in b)t+='\n'+b[i]+'	'+a[b[i]];alert(t);}
105 //	依值排出key array…起碼到現在,我還看不出此函數有啥大功用。
106 //	array,否則會出現error!	mode=1:相同value的以','合併,mode=2:相同value的以array填入
107 function sortValue(a,mode){
108 	var s=[],r=[],i,j,b,k=[];
109 	// 使用(i in n)的方法,僅有數字的i會自動排序;這樣雖不必用sort(),但數字亦會轉成字串。
110 	for(i in a)
111 		if((b=isNaN(i)?i:parseFloat(i)),typeof s[j=isNaN(j=a[i])?j:parseFloat(j)]=='undefined')
112 			k.push(j),s[j]=b;
113 		else if(typeof s[j]=='object')s[j].push(b);
114 		else s[j]=[s[j],b];
115 	// sort 方法會在原地排序 Array 物件
116 	for(i=0,k.sort(function(a,b){return a-b;});i<k.length;i++)
117 		if(typeof(b=s[k[i]])=='object')
118 			if(mode==1)
119 				// b.join(',')與''+b效能相同
120 				r.push(b.join(','));
121 			else if(mode==2)r.push(b);
122 			else for(j in b)r.push(b[j]);
123 		else r.push(b);
124 	return r;
125 }
126 
127 
128 /*	2005/7/18 21:26
129 	依照所要求的index(sortByIndex_I)對array排序。
130 	sortByIndex_Datatype表某index為數字/字串或function
131 	先設定sortByIndex_I,sortByIndex_Datatype再使用array.sort(sortByIndex);
132 
133 	example:
134 var array=[
135 '123	avcf	334',
136 '131	hj	562',
137 '657	gfhj	435',
138 '131	ajy	52',
139 '345	fds	562',
140 '52	gh	435',
141 ];
142 sortByIndex_I=[0,1],sortByIndex_Datatype={0:1,2:1};
143 for(i in array)array[i]=array[i].split('	');
144 array.sort(sortByIndex);
145 alert(array.join('\n'));
146 */
147 var sortByIndex_I,sortByIndex_Datatype;
148 function sortByIndex(a,b){
149  //alert(a+'\n'+b);
150  for(var i=0,n;i<sortByIndex_I.length;i++)
151   if(sortByIndex_Datatype[n=sortByIndex_I[i]]){
152    if(typeof sortByIndex_Datatype[n]=='function'){
153     if(n=sortByIndex_Datatype[n](a[n],b[n]))return n;
154    }else if(n=a[n]-b[n])return n;
155   }else if(a[n]!=b[n])return a[n]>b[n]?1:-1;
156  return 0;
157 }
158 
159 /*	2005/7/18 21:26
160 	依照所要求的index對array排序,傳回排序後的index array。
161 	**假如設定了separator,array的元素會先被separator分割!
162 
163 	example:
164 var array=[
165 '123	avcf	334',
166 '131	hj	562',
167 '657	gfhj	435',
168 '131	ajy	52',
169 '345	fds	562',
170 '52	gh	435',
171 ];
172 alert(getIndexSortByIndex(array,'	',[0,1],[0,2]));
173 alert(array.join('\n'));	//	已被separator分割!
174 
175 */
176 function getIndexSortByIndex(array, separator, indexArray, isNumberIndex) {
177 	//	判定與事前準備(設定sortByIndex_I,sortByIndex_Datatype)
178 	if (typeof indexArray === 'number') sortByIndex_I = [indexArray];
179 	else if (typeof indexArray !== 'object' || indexArray.constructor != Array) sortByIndex_I = [0];
180 	else sortByIndex_I = indexArray;
181 	var i, sortByIndex_A = [];
182 	sortByIndex_Datatype = {};
183 	if (typeof isNumberIndex == 'object') {
184 		if (isNumberIndex.constructor == Array) {
185 			sortByIndex_Datatype = {};
186 			for (i = 0; i < isNumberIndex.length; i++) sortByIndex_Datatype[isNumberIndex[i]] = 1;
187 		} else sortByIndex_Datatype = isNumberIndex;
188 		for (i in sortByIndex_Datatype)
189 			if (isNaN(sortByIndex_Datatype[i]) || parseInt(sortByIndex_Datatype[i]) != sortByIndex_Datatype[i]) delete sortByIndex_Datatype[i];
190 	}
191 	if (typeof array != 'object') return;
192 
193 	//	main work: 可以不用重造array資料的話..
194 	for (i in array) {
195 		if (separator) array[i] = array[i].split(separator);
196 		sortByIndex_A.push(i);
197 	}
198 	sortByIndex_A.sort(function (a, b) { return sortByIndex(array[a], array[b]); });
199 
200 	/*	for: 重造array資料
201 	var getIndexSortByIndexArray=array;
202 	for(i in getIndexSortByIndexArray){
203 	if(separator)getIndexSortByIndexArray[i]=getIndexSortByIndexArray[i].split(separator);
204 	sortByIndex_A.push(i);
205 	}
206 	sortByIndex_A.sort(function (a,b){return sortByIndex(getIndexSortByIndexArray[a],getIndexSortByIndexArray[b]);});
207 	*/
208 
209 	return sortByIndex_A;
210 }
211 
212 
213 //simpleWrite('char_frequency report3.txt',char_frequency(simpleRead('function.js')+simpleRead('accounts.js')));
214 //{var t=reduceCode(simpleRead('function.js')+simpleRead('accounts.js'));simpleWrite('char_frequency source.js',t),simpleWrite('char_frequency report.txt',char_frequency(t));}	//	所費時間:十數秒(…太扯了吧!)
215 CeL.data
216 .
217 /**
218  * 測出各字元的出現率。 普通使用字元@0-127:9-10,13,32-126,reduce後常用:9,32-95,97-125
219  * 
220  * @param {String} text
221  *            文檔
222  * @return
223  * @memberOf CeL.data
224  */
225 char_frequency=function (text) {
226 	var i, a, c = [], d, t = '' + text, l = t.length, used = '', unused = '', u1 = -1, u2 = u1;
227 	for (i = 0; i < l; i++)
228 		if (c[a = t.charCodeAt(i)])
229 			c[a]++;
230 		else
231 			c[a] = 1;
232 	for (i = u1; i < 256; i++)
233 		if (c[i]) {
234 			if (u2 + 1 === i)
235 				used += ',' + i, unused += (u2 < 0 ? '' : '-' + u2);
236 			u1 = i;
237 		} else {
238 			if (u1 + 1 === i)
239 				unused += ',' + i, used += (u1 < 0 ? '' : '-' + u1);
240 			u2 = i;
241 		}
242 	//	若是reduceCode()的程式,通常在120項左右。
243 	for (i = 0, t = 'used:' + used.substr(1) + '\nunused:' + unused.substr(1)
244 			+ '\n', d = sortValue(c, 2).reverse(); i < d.length; i++) {
245 		t += NewLine
246 				+ (a = d[i])
247 				+ '['
248 				+ fromCharCode(a).replace(/\0/g, '\\0').replace(/\r/g, '\\r')
249 						.replace(/\n/g, '\\n').replace(/\t/g, '\\t') + ']'
250 				+ ':	' + (a = c[typeof a === 'object' ? a[0] : a]) + '	'
251 				+ (100 * a / l);
252 		//if(200*v<l)break;	//	.5%以上者←選購
253 	}
254 	alert(t);
255 	return t;
256 };
257 
258 /*	
259 flag:
260 	(flag&1)==0	表情符號等不算一個字
261 	(flag&1)==1	連表情符號等也算一個字
262 	(flag&2)==1	將 HTML tag 全部消掉
263 
264 可讀性/適讀性
265 http://en.wikipedia.org/wiki/Flesch-Kincaid_Readability_Test
266 http://en.wikipedia.org/wiki/Gunning_fog_index
267 Gunning-Fog Index:簡單的來說就是幾年的學校教育才看的懂你的文章,數字越低代表越容易閱讀,若是高於17那表示你的文章太難囉,需要研究生才看的懂,我是6.08,所以要受過6.08年的學校教育就看的懂囉。
268 Flesch Reading Ease:這個指數的分數越高,表示越容易了解,一般標準的文件大約介於60~70分之間。
269 Flesch-Kincaid grade level:和Gunning-Fog Index相似,分數越低可讀性越高,越容易使閱讀者了解,至於此指數和Gunning-Fog Index有何不同,網站上有列出計算的演算法,有興趣的人可以比較比較。
270 
271 DO.normalize(): 合併所有child成一String, may crash IE6 Win!	http://www.quirksmode.org/dom/tests/splittext.html
272 */
273 CeL.data
274 .
275 /**
276  * 計算字數 count words.
277  * 
278  * @param {String} text
279  *            文檔
280  * @param {Number} flag	文檔格式/處理方法
281  * @return	{Number} 字數 
282  * @memberOf CeL.data
283  */
284 count_word = function(text, flag) {
285 	var is_HTML = flag & 2;
286 
287 	//	is HTML object
288 	if (typeof text === 'object')
289 		if (text.innerText)
290 			text = text.innerText, is_HTML = 0;
291 		else if (text.innerHTML)
292 			text = text.innerHTML, is_HTML = 1;
293 
294 	if (typeof text !== 'string')
295 		return 0;
296 
297 	//	和perl不同,JScript常抓不到(.*?)之後還接特定字串的東西,大概因為沒有s。(.*?)得改作((.|\n)*?)? 或者該加/img?
298 	if (is_HTML)
299 		text = text
300 				.replace(/<!--((.|\n)*?)-->/g, '')
301 				.replace(/<[\s\n]*\/?[\s\n]*[a-z][^<>]*>/gi, '');
302 
303 	if (flag & 1)
304 		//	連表情符號或 '(~。),' / 破折號 '——' / 刪節號 '……' 等標點符號也算一個字
305 		text = text.replace(/[\+\-–*\\\/?!,;.<>{}\[\]@#$%^&_|"'~`—…、,;。!?:()()「」『』“”‘’]{2,}/g, ';');
306 
307 	return text
308 			//	去掉注解用的括弧、書名號、專名號、印刷符號等
309 			.replace(/[()()《》〈〉*#]+/g, '')
310 			//	將英文、數字等改成單一字母。[.]: 縮寫
311 			//	http://en.wikibooks.org/wiki/Unicode/Character_reference/0000-0FFF
312 			.replace(/[a-zA-ZÀ-ÖØ-öø-ʨ\-–'.\d]{2,}/g, 'w')
313 			//	date/time or number
314 			.replace(/[\d:+\-–\.\/,]{2,}/g, '0')
315 			//	再去掉*全部*空白
316 			.replace(/[\s\n ]+/g, '')
317 			.length;
318 };
319 
320 
321 
322 
323 
324 
325 
326 CeL.data
327 .
328 /**
329  * 運算式值的二進位表示法	已最佳化:5.82s/100000次dec_to_bin(20,8)@300(?)MHz,2.63s/100000次dec_to_bin(20)@300(?)MHz
330  * @param {Number} number	number
331  * @param places	places,字元數,使用前置0來填補回覆值
332  * @return
333  * @example
334  * {var d=new Date,i,b;for(i=0;i<100000;i++)b=dec_to_bin(20);alert(gDate(new Date-d));}
335  * @memberOf	CeL.data
336  */
337 dec_to_bin = function(number, places) {
338 	if (places && number + 1 < (1 << places)) {
339 		var h = '', b = number.toString(2), i = b.length;
340 		for (; i < places; i++)
341 			h += '0';
342 		return h + b;
343 	}
344 	//	native code 還是最快!
345 	return number.toString(2);
346 
347 	//	上兩代:慢	var b='',c=1;for(p=p&&n<(p=1<<p)?p:n+1;c<p;c<<=1)b=(c&n?'1':'0')+b;return b;	//	不用'1:0',型別轉換比較慢.不用i,多一個變數會慢很多
348 	//	上一代:慢	if(p&&n+1<(1<<p)){var h='',c=1,b=n.toString(2);while(c<=n)c<<=1;while(c<p)c<<=1,h+='0';return h+(n?n.toString(2):'');}
349 };
350 
351 
352 
353 
354 
355 /*
356 	value	(Array)=value,(Object)value=
357 	[null]=value	累加=value
358 	value=[null]	value=''
359 
360 	type: value type	['=','][int|float|_num_]
361 	*前段
362 		以[']或["]作分隔重定義指定號[=]與分隔號[,]
363 	*後段
364 		數字表累加
365 		'int'表整數int,累加1
366 		'float'表示浮點數float,累加.1	bug:應該用.to_fixed()
367 		不輸入或非數字表示string
368 
369 	mode
370 	_.set_obj_value.F.object
371 	_.set_obj_value.F.array(10進位/當做數字)
372 	number: key部分之base(10進位,16進位等)
373 
374 	example:
375 	set_obj_value('UTCDay','Sun,Mon,Tue,Wed,Thu,Fri,Sat','int');	//	自動從0開始設,UTCDay.Tue=2
376 	set_obj_value('UTCDay','Sun,Mon,Tue,Wed,Thu,Fri,Sat');	//	UTCDay.Sun=UTCDay.Fri=''
377 	set_obj_value('add','a=3,b,c,d',2);	//	累加2。add.b=5
378 	set_obj_value('add','a,b,c,d',1,_.set_obj_value.F.array);	//	add[2]='c'
379 	set_obj_value('add','4=a,b,c,d',2,_.set_obj_value.F.array);	//	累加2。add[8]='c'
380 
381 */
382 CeL.data
383 .
384 /**
385  * 設定object之值,輸入item=[value][,item=[value]..]。
386  * value未設定會自動累加。
387  * 使用前不必需先宣告…起碼在現在的JS版本中
388  * @param obj	object name that need to operate at
389  * @param value	valueto set
390  * @param type	累加 / value type
391  * @param mode	mode / value type
392  * @return
393  * @memberOf	CeL.data
394  */
395 set_obj_value = function(obj, value, type, mode) {
396 	if (!value || typeof o !== 'string')
397 		return 1;
398 
399 	var a, b, i = 0, p = '=', sp = ',', e = "if(typeof " + obj + "!='object')"
400 			+ obj + "=new " + (mode ?
401 				//	"[]":"{}"
402 				//	Array之另一種表示法:[value1,value2,..], Object之另一種表示法:{key1:value1,key2:value2,..}
403 				"Array" : "Object")
404 			+ ";",
405 		//	l: item, n: value to 累加
406 		n, Tint = false, cmC = '\\u002c', eqC = '\\u003d';
407 	if (type) {
408 		if (typeof a === 'string') {
409 			a = type.charAt(0);
410 			if (a === '"' || a === "'") {
411 				a = type.split(a);
412 				p = a[1], sp = a[2], type = a[3];
413 			}
414 		}
415 		if (type === 'int')
416 			type = 1, Tint = true;
417 		else if (type === 'float')
418 			type = .1;
419 		else if (isNaN(type))
420 			type = 0;
421 		else if (type == parseInt(type))
422 			type = parseInt(type), Tint = true;
423 		else
424 			type = parseFloat(type); // t被設成累加數
425 	}
426 	//else t=1;
427 
428 	if (typeof value === 'string')
429 		value = value.split(sp);
430 	// escape regex characters from jQuery
431 	cmC = new RegExp(cmC.replace(
432 			/([\.\\\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1"), 'g'),
433 			eqC = new RegExp(eqC.replace(
434 					/([\.\\\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1"), 'g');
435 
436 	if (type)
437 		//	n: 現在count到..
438 		n = -type;
439 
440 	for (; i < value.length; i++) {
441 		if (value[i].indexOf(p) === -1)
442 			value[i] = mode ? p + value[i] : value[i] + p;// if(v[i].indexOf(p)==-1&&m)v[i]=p+v[i];//
443 			if (mode && value[i] === p) {
444 				n += type;
445 				continue;
446 			}
447 			a = value[i].split(p);
448 			if (!mode && !a[0])
449 				//	去掉不合理的(Array可能有NaN index,所以不設條件。)
450 				continue;
451 			a[0] = a[0].replace(cmC, ',').replace(eqC, '='), a[1] = a[1].replace(
452 					cmC, ',').replace(eqC, '=');
453 			if (type)
454 				if (mode) {
455 					if (!a[0])
456 						a[0] = (n += type);
457 					else if (!isNaN(b = mode > 0 ? parseInt(a[0], mode) : a[0]))
458 						n = Tint ? (a[0] = parseInt(b)) : parseFloat(b);
459 				} else if (!a[1])
460 					a[1] = (n += type);
461 				else if (!isNaN(a[1]))
462 					n = Tint ? parseInt(a[1]) : parseFloat(a[1]);
463 					if (!type || Tint && isNaN(b = parseInt(a[1]))
464 							|| isNaN(b = parseFloat(a[1])))
465 						b = a[1];
466 					a = a[0];
467 					e += obj + '[' + (!type || isNaN(a) ? dQuote(a) : a) + ']='
468 						+ (!type || isNaN(b) ? dQuote(b) : b) + ';';
469 	}
470 
471 	try {
472 		//if(o=='kk')alert(e.slice(0,500));
473 		//	因為沒想到其他方法可存取Global的object,只好使用eval..可以試試obj=set_obj_value(0,..){this=new Aaaray/Object}
474 		library_namespace.eval_code(e);
475 	} catch (e) {
476 		library_namespace.err('Error @ ' + obj);
477 		library_namespace.err(e);
478 		return 2;
479 	}
480 };
481 
482 _.set_obj_value.F = {
483 	// object is default
484 	'object' : 0,
485 	'array' : -1
486 };
487 
488 
489 
490 CeL.data
491 .
492 /**
493  * 將字串組分作 Object
494  * @param {String} value_set	字串組, e.g., 'a=12,b=34'
495  * @param assignment_char	char to assign values, e.g., '='
496  * @param end_char	end char of assignment
497  * @return
498  * @since	2006/9/6 20:55, 2010/4/12 23:06:04
499  * @memberOf	CeL.data
500  */
501 split_String_to_Object = function(value_set, assignment_char, end_char) {
502 	if (typeof value_set !== 'string' || !value_set)
503 		return {};
504 
505 	value_set = value_set.split(end_char || /[,;]/);
506 
507 	if (!assignment_char)
508 		assignment_char = /[=:]/;
509 
510 	var a, o = {}, _e = 0, l = value_set.length;
511 	for (; _e < l; _e++) {
512 		//	http://msdn.microsoft.com/library/en-us/jscript7/html/jsmthsplit.asp
513 		a = value_set[_e].split(assignment_char, 2);
514 		//library_namespace.debug(value_set[_e] + '\n' + a[0] + ' ' + a[1], 2);
515 		if (a[0] !== '')
516 			o[a[0]] = a[1];
517 	}
518 	return o;
519 };
520 
521 
522 
523 
524 
525 
526 /*	2003/10/1 15:46
527 	比較string:m,n從起頭開始相同字元數
528 	return null: 格式錯誤,-1: !m||!n
529 	若一開始就不同:0
530 
531 
532 TODO:
533 
534 test starting with
535 
536 2009/2/7 7:51:58
537 看來測試 string 的包含,以 .indexOf() 最快。
538 即使是比較 s.length 為極小常數的情況亦復如此
539 
540 下面是快到慢:
541 
542 //	long,short
543 var contain_substring=[
544 function(l,s){
545  var a=0==l.indexOf(s);
546  return a;
547 }
548 ,function(l,s){
549  return 0==l.indexOf(s);
550 }
551 ,function(l,s){
552  return s==l.slice(0,s.length);
553 }
554 ,function(l,s){
555  return l.match(s);
556 }
557 ,function(l,s){
558  for(var i=0;i<s.length;i++)
559   if(s.charAt(i)!=l.charAt(i))return 0;
560  return 1;
561 }
562 ];
563 
564 function test_contain_substring(){
565  for(var i=0;i<contain_substring.length;i++){
566   var t=new Date;
567   for(var j=0;j<50000;j++){
568    contain_substring[i]('sdfgjk;sh*dn\\fj;kgsamnd nwgu!eoh;nfgsj;g','sdfgjk;sh*dn\\fj;kgsamnd nwgu!');
569    contain_substring[i]('sdbf6a89* /23hsauru','sdbf6a89* /23');
570   }
571   sl(i+': '+(new Date-t));
572  }
573 }
574 
575 
576 //	極小常數的情況:
577 //	long,short
578 var contain_substring=[
579 function(l,s){
580  var a=0==l.indexOf(s);
581  return a;
582 }
583 ,function(l,s){
584  return 0==l.indexOf(s);
585 }
586 ,function(l,s){
587  return s==l.slice(0,1);
588 }
589 ,function(l,s){
590  return s.charAt(0)==l.charAt(0);
591 }
592 ,function(l,s){
593  return l.match(/^\//);
594 }
595 ];
596 
597 function test_contain_substring(){
598  for(var i=0;i<contain_substring.length;i++){
599   var t=new Date;
600   for(var j=0;j<50000;j++){
601    contain_substring[i]('a:\\sdfg.dfg\\dsfg\\dsfg','/');
602    contain_substring[i]('/dsfg/adfg/sadfsdf','/');
603   }
604   sl(i+': '+(new Date-t));
605  }
606 }
607 
608 
609 */
610 
611 CeL.data
612 .
613 /**
614  * test if 2 string is at the same length
615  * @param s1	string 1
616  * @param s2	string 2
617  * @return
618  * @memberOf	CeL.data
619  */
620 same_length=function(s1, s2) {
621 	if (typeof m !== 'string' || typeof n !== 'string')
622 		return;
623 	if (!s1 || !s2)
624 		return 0;
625 
626 	var i = s1.length, b = 0, s = s2.length;
627 	if (i < s) {
628 		if (
629 				//m==n.slice(0,i=m.length)
630 				0 === s2.indexOf(s1))
631 			return i;
632 	} else if (
633 			//s2==s1.slice(0,i=s2.length)
634 			i = s, 0 === s1.indexOf(s2))
635 		return i;
636 
637 	//sl('*same_length: start length: '+i);
638 	while ((i = (i + 1) >> 1) > 1 && (s = s2.substr(b, i)))
639 		//{sl('same_length: '+i+','+b+'; ['+m.substr(b)+'], ['+s+'] of ['+n+']');
640 		if (s1.indexOf(s, b) === b)
641 			b += i;
642 	//sl('*same_length: '+i+','+b+'; ['+m.charAt(b)+'], ['+n.charAt(b)+'] of ['+n+']');
643 	//var s_l=i&&m.charAt(b)==n.charAt(b)?b+1:b;
644 	//sl('*same_length: '+s_l+':'+m.slice(0,s_l)+',<em>'+m.slice(s_l)+'</em>; '+n.slice(0,s_l)+',<em>'+n.slice(s_l)+'</em>');
645 	return i && s1.charAt(b) === s2.charAt(b) ? b + 1 : b;
646 };
647 
648 
649 
650 //-----------------------------------------------------------------------------
651 
652 
653 
654 /*	
655 	http://www.bipm.org/en/si/si_brochure/chapter3/prefixes.html
656 	http://en.wikipedia.org/wiki/International_System_of_Units
657 	http://www.merlyn.demon.co.uk/js-maths.htm#RComma
658 	http://physics.nist.gov/cuu/Units/prefixes.html
659 	http://www.uni-bonn.de/~manfear/numbers_names.php
660 	http://wawa.club.hinet.net/cboard1/HCB_Dis.asp?BrdNo=78&SubNo=78761&Club=0&ClsName=%B1%D0%A8%7C%BE%C7%B2%DF
661 	http://bbs.thu.edu.tw/cgi-bin/bbscon?board=English&file=M.1046073664.A&num=106
662 */
663 //to_SI_prefix[generateCode.dLK]='setTool,to_fixed,-to_SI_prefix.n,-to_SI_prefix.v';
664 
665 
666 CeL.data
667 .
668 /**
669  * 將數字轉為 K, M, G 等 SI prefixes 表示方式,例如 6458 轉成 6.31K。
670  * @param {Number} number	數字
671  * @param {Number} digits	to fixed digit
672  * @type	{String}
673  * @return	{String}	SI prefixes 表示方式
674  * @requires	setTool,to_fixed
675  * @memberOf	CeL.data
676  */
677 to_SI_prefix = function (number, digits) {
678 	function to_SI_prefix(number, digits) {
679 		var p = 1, v = to_SI_prefix.v;
680 		if (number < v[0])
681 			return number;
682 
683 		while (number >= v[p])
684 			p++;
685 
686 		return to_fixed.call(number / v[--p], isNaN(digits) ? 2 : digits)
687 				+ to_SI_prefix.s[p];
688 	}
689 
690 	//	Initialization
691 	//	在 IE5 中,因為 base 沒有預先定義,因此在這邊會出現錯誤。
692 	var _s = _.to_SI_prefix, base = _s.base,
693 	N = base, v = to_SI_prefix.v = [ base ],
694 	l = (to_SI_prefix.s = _s.symbol.split(',')).length;
695 	while (l--)
696 		v.push(N *= base);
697 
698 	return library_namespace.replace_function(_, 'to_SI_prefix', to_SI_prefix);
699 };
700 
701 //	define what is "1k"
702 _.to_SI_prefix.base = 1024;
703 _.to_SI_prefix.symbol = 'k,M,G,T,P,E,Z,Y';
704 
705 
706 //	將漢字轉為阿拉伯數字表示法(0-99999)
707 function turnKanjiToNumbers(num) {
708 	if (!num) return 0;
709 	if (!isNaN(num)) return num;
710 	var i = 0, l, m, n = '〇,一,二,三,四,五,六,七,八,九'.split(','), d = '萬,千,百,十,'.split(','), r = 0
711 	//	O, ○=[〇]	http://zh.wikipedia.org/wiki/%E6%97%A5%E8%AA%9E%E6%95%B8%E5%AD%97
712 	, p = ('' + num).replace(/\s/g, '').replace(/[O○]/g, '〇')
713 	;
714 	for (; i < n.length; i++) n[n[i]] = i;
715 	for (i = 0; i < d.length; i++) {
716 		if (p && (m = d[i] ? p.indexOf(d[i]) : p.length) != -1)
717 			if (!m && d[i] === '十') r += 1, p = p.slice(1); else if (isNaN(l = n[p.slice(0, m).replace(/^〇+/, '')])) return num; else r += l, p = p.slice(m + 1);
718 		if (d[i]) r *= 10;
719 	}
720 	return r;
721 }
722 //alert(turnKanjiToNumbers('四萬〇三百七十九'));
723 //alert(turnKanjiToNumbers('十'));
724 
725 //	將阿拉伯數字轉為中文數字大、小兩種表示法/讀法	,to_Chinese_numeralD,to_Chinese_numeralInit,"to_Chinese_numeralInit();",_to_Chinese_numeral,to_Chinese_numeral
726 var to_Chinese_numeralD;
727 //to_Chinese_numeralInit[generateCode.dLK]='to_Chinese_numeralD';
728 function to_Chinese_numeralInit(){
729  to_Chinese_numeralD={
730   'num':['〇,一,二,三,四,五,六,七,八,九'.split(','),'零,壹,貳,參,肆,伍,陸,柒,捌,玖'.split(',')]	//	數字	叄
731   //	http://zh.wikipedia.org/wiki/%E4%B8%AD%E6%96%87%E6%95%B0%E5%AD%97	http://zh.wikipedia.org/wiki/%E5%8D%81%E8%BF%9B%E5%88%B6	http://zh.wikipedia.org/wiki/%E4%B8%AD%E6%96%87%E6%95%B0%E5%AD%97	http://lists.w3.org/Archives/Public/www-style/2003Apr/0063.html	http://forum.moztw.org/viewtopic.php?t=3043	http://www.moroo.com/uzokusou/misc/suumei/suumei.html	http://espero.51.net/qishng/zhao.htm	http://www.nchu.edu.tw/~material/nano/newsbook1.htm
732   //	十億(吉),兆(萬億),千兆(拍),百京(艾),十垓(澤),秭(堯),秭:禾予;溝(土旁);,無量大數→,無量,大數;[載]之後的[極]有的用[報]	異體:阿僧[禾氏],For Korean:阿僧祗;秭:禾予,抒,杼,For Korean:枾	For Korean:不可思議(不:U+4E0D→U+F967)
733   //	Espana應該是梵文所譯 因為根據「大方廣佛華嚴經卷第四十五卷」中在「無量」這個數位以後還有無邊、無等、不可數、不可稱、不可思、不可量、不可說、不可說不可說,Espana應該是指上面其中一個..因為如果你有心查查Espana其實應該是解作西班牙文的「西班牙」
734   ,'d':',萬,億,兆,京,垓,秭,穰,溝,澗,正,載,極,恒河沙,阿僧祇,那由他,不可思議,無量,大數,Espana'	//	denomination, 單位
735   //	http://zh.wikipedia.org/wiki/%E5%8D%81%E9%80%80%E4%BD%8D
736   //	比漠微細的,是自天竺的佛經上的數字。而這些「佛經數字」已成為「古代用法」了。
737   //	小數單位(十退位):分,釐(厘),毫(毛),絲,忽,微,纖,沙,塵(納),埃,渺,漠(皮),模糊,逡巡,須臾(飛),瞬息,彈指,剎那(阿),六德(德),虛,空,清,淨	or:,虛,空,清,淨→,空虛,清淨(仄),阿賴耶,阿摩羅,涅槃寂靜(攸)
738   ,'bd':0	//	暫時定義
739  };
740  with(to_Chinese_numeralD)
741   bd=[(',十,百,千'+to_Chinese_numeralD.d).split(','),(',拾,佰,仟'+to_Chinese_numeralD.d).split(',')]	//	base denomination
742   ,d=d.split(',');
743 }
744 to_Chinese_numeralInit();
745 /*	處理1-99999的數,尚有bug
746 	東漢時期的《數述記遺》
747 		一是上法,為自乘系統: 萬萬為億,億億為兆,兆兆為京。
748 		二是中法,為萬進系統,皆以萬遞進
749 		三是下法,為十進系統,皆以十遞進←現代的科學技術上用的“兆”,以及_to_Chinese_numeral()用的
750 */
751 //_to_Chinese_numeral[generateCode.dLK]='to_Chinese_numeralD,*to_Chinese_numeralInit();';
752 function _to_Chinese_numeral(numStr, kind) {
753 	if (!kind)
754 		kind = 0;
755 	// 用r=[]約多花一倍時間!
756 	var i = 0, r = '', l = numStr.length - 1, d, tnum = to_Chinese_numeralD.num[kind], tbd = to_Chinese_numeralD.bd[kind], zero = tnum[0];
757 	for (; i <= l; i++)
758 		// if(d=parseInt(numStr.charAt(i)))比較慢
759 		if ((d = numStr.charAt(i)) != '0')
760 			// '〇一二三四五六七八'.charAt(d) 比較慢
761 			r += tnum[d] + tbd[l - i];
762 		else if (r.slice(-1) != zero)
763 			if (Math.floor(numStr.substr(i + 1)))
764 				r += zero;
765 			else
766 				break;
767 	return r;
768 }
769 //2.016,2.297,2.016
770 //{var d=new Date,v='12345236',i=0,a;for(;i<10000;i++)a=to_Chinese_numeral(v);alert(v+'\n→'+a+'\ntime:'+gDate(new Date-d));}
771 
772 //to_Chinese_numeral[generateCode.dLK]='to_Chinese_numeralD,to_Chinese_numeralInit,_to_Chinese_numeral,to_Chinese_numeral';//,*to_Chinese_numeralInit();
773 /**
774  * 將數字轉為漢字表示法。
775  * num>1京時僅會取概數,此時得轉成string再輸入!
776  * TODO:
777  * 統整:尚有bug。
778  * 廿卅
779  * @param num
780  * @param kind
781  * @returns
782  */
783 function to_Chinese_numeral(num, kind) {
784 	// num=parseFloat(num);
785 	if (typeof num == 'number')
786 		num = num.toString(10);
787 	num = ('' + num).replace(/[,\s]/g, '');
788 	if (isNaN(num))
789 		return '(非數值)';
790 	if (num.match(/(-?[\d.]+)/))
791 		num = RegExp.$1;
792 	if (!kind)
793 		kind = 0;
794 
795 	var j, i, d = num.indexOf('.'), k, l, m, addZero = false, tnum = to_Chinese_numeralD.num[kind], zero = tnum[0], td = to_Chinese_numeralD.d;// i:integer,整數;d:decimal,小數
796 	if (d == -1)
797 		d = 0;
798 	else
799 		for (num = num.replace(/0+$/, ''), i = num.substr(d + 1), num = num
800 				.slice(0, d), d = '', j = 0; j < i.length; j++)
801 			// 小數
802 			d += tnum[i.charAt(j)];
803 
804 	// 至此num為整數
805 	if (num.charAt(0) == '-')
806 		i = '負', num = num.substr(1);
807 	else
808 		i = '';
809 	num = num.replace(/^0+/, '');
810 
811 	m = num.length % 4, j = m - 4, l = (num.length - (m || 4)) / 4;
812 	// addZero=false, l=Math.floor((num.length-1)/4)
813 	for (; j < num.length; m = 0, l--)
814 		// 這邊得用 parseInt( ,10): parseInt('0~')會用八進位,其他也有奇怪的效果。
815 		if (Math.floor(m = m ? num.slice(0, m) : num.substr(j += 4, 4))) {
816 			m = _to_Chinese_numeral(m, kind);
817 			if (addZero = addZero && m.charAt(0) != zero)
818 				i += zero + m + td[l], addZero = false;
819 			else
820 				i += m + td[l];
821 		} else
822 			addZero = true;
823 
824 	return (i ? i.slice(0, 2) == '一十' ? i.substr(1) : i : zero)
825 			+ (d ? '點' + d : '');
826 }
827 
828 //	轉換成金錢表示法
829 //turnToMoney[generateCode.dLK]='to_Chinese_numeral';
830 function turnToMoney(num){
831  var i=(num=to_Chinese_numeral(num,1)).indexOf('點');
832  return i==-1?num+'圓整':num.slice(0,i)+'圓'+num.charAt(++i)+'角'+(++i==num.length?'':num.charAt(i++)+'分')+num.substr(i);
833 }
834 
835 
836 //	分斷行	2003/1/25 22:40
837 function getText() {//html→text
838 	//<.+?>	<[^>]+>	<\s*\/?\s*[a-zA-Z](.*?)>	<!	過慢?
839 	return this.valueOf().replace(/<s>[^<]*<\/s>/gi, '').replace(/<w?br[^>]*>/gi, '\n').replace(/<\/?[A-Za-z][^>]*>/g, '');
840 }
841 function trimStr_(s, l, m) {
842  var lt,lt2,gt,i=0,c=l,t='',I=0;//less than,great than,index,left count index(left length now),text now,text index
843  while(I<s.length){
844   //將lt,gt定在下一label之首尾,i為下一次搜尋起點.label定義:/<.+?>/
845   if(i!=-1)if((lt=s.indexOf('<',i))!=-1){
846    if((gt=s.indexOf('>',lt+1))==-1)i=lt=-1;
847    else{i=gt+1;while(lt!=-1&&(lt2=s.indexOf('<',lt+1))!=-1&&lt2<gt)lt=lt2;}
848   }else i=lt=-1;
849   //if(s.indexOf('')!=-1)alert(i+','+lt+','+gt+';'+l+','+c+'\n'+t);
850   if(lt==-1)gt=lt=s.length;
851   //未來:考慮中英文大小,不分隔英文字。前提:'A'<'z'..或許不用
852   while(I+c<=lt){t+=s.substr(I,c)+(m?'\n':'<br/>');I+=c;c=l;}
853   t+=s.slice(I,gt+1);c-=lt-I;I=gt+1;
854  }
855  return t;
856 }
857 /*	將字串以長l分隔
858 	m==0: html用, 1:text
859 */
860 //trimStr[generateCode.dLK]='trimStr_';
861 function trimStr(l,m){
862  var s=this.valueOf(),t=[],sp='<br/>';
863  if(!s||!l||l<1||!String.fromCharCode)return m?s.gText():s;//||!String.charCodeAt:v5.5
864  s=s.turnU(m);//(m):這樣就不用再費心思了.不過既然都作好了,就留著吧..不,還是需要
865  if(s.length<=l)return s;
866  if(!m)s=s.replace(/<w?br([^>]*)>/gi,sp);
867 
868  s=s.split(sp=m?'\n':sp);//deal with line
869  try{
870   //	預防JS5不能push
871   for(var i=0;i<s.length;i++)t.push(trimStr_(s[i],l,m));
872  }catch(e){return this.valueOf();}
873  return t.join(sp);
874 }
875 
876 
877 
878 
879 
880 //-----------------------------------------------------------------------------
881 
882 
883 //mode=1:不取空字串
884 //	.split() appears from Internet Explorer 4.0
885 //	<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>
886 function strToArray(s, mode) {
887 	var a = [], last = 0, i;
888 	while ((i = s.indexOf(sp, last)) != -1) {
889 		if (mode == 0 || last != i) a[a.length] = s.slice(last, i);
890 		last = i + 1;
891 	}
892 	if (mode == 0 || last != s.length) a[a.length] = s.slice(last);
893 	return a;
894 }
895 
896 //去除s之空白,包括字與字之間的
897 function disposeSpace(s) {
898 	if (!s) return s;
899 	var r = "", i, last;
900 	while ((i = s.indexOf(' ', last)) != -1)
901 		r += s.slice(last, i), last = i + 1;
902 	r += s.slice(last);
903 	return r;
904 }
905 
906 //以label,mode:m置換s,先找到先贏
907 //輸入t['$k']=..會有問題,需用t['\\$k']=..
908 function changeV(s, l, m) {
909 	var i, r, re, t; //var I='';
910 	if (!m) m = 'g';
911 	if (s && (t = l ? l : label)) for (i in t) {
912 		//I+=', '+i+'='+t[i];
913 		re = new RegExp(i, m);
914 		s = s.replace(re, t[i]); //r=s.replace(re,t[i]);s=r;
915 	}
916 	//pLog(I.substr(2));
917 	//pLog('changeV:'+s);
918 	return s;
919 }
920 
921 /*
922 //以label置換s,先找到先贏
923 function changeV(s) {
924 	for (var i, j = 0; j < labelN.length; j++)
925 		if ((i = s.indexOf(labelN[j])) != -1)
926 			s = s.slice(0, i) + labelV[j] + s.slice(i + labelN[j].length)
927 			, j = 0; //research from begin
928 	return s;
929 }
930 */
931 
932 
933 
934 //TODO: Object.keys(obj)
935 //	https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys
936 CeL.data
937 .
938 get_Object_key = function(o) {
939 	if (_.is_Array(o))
940 		return o;
941 	//if (!_.is_Object(o)) return;
942 	var i, l = [];
943 	for(i in o)
944 		l.push(i);
945 	return l;
946 };
947 
948 CeL.data
949 .
950 get_Object_value = function(o) {
951 	if (_.is_Array(o))
952 		return o;
953 	//if (!_.is_Object(o)) return;
954 	var i, l = [];
955 	for(i in o)
956 		l.push(o[i]);
957 	return l;
958 };
959 
960 
961 
962 
963 
964 return (
965 	CeL.data
966 );
967 }
968 
969 
970 });
971 
972