1 
  2 /*
  3 
  4 ********	class template		********
  5 
  6  7 =function(){}()
  8 似乎亦可,見 SWFObject 2.2
  9 */
 10 
 11 var ClassT={};	//	class template set	讓 addCode 也可以讀通
 12 
 13 
 14 
 15 //	===================================================
 16 /*
 17 	** class description: class template (simple version)
 18 
 19 _=this
 20 
 21 TODO:
 22 
 23 
 24 HISTORY:
 25 2008/7/21 16:12:32	create
 26 */
 27 var
 28 classT=
 29 
 30 (ClassT.classT=function(initF){
 31 
 32 var
 33 
 34 //	class private	-----------------------------------
 35 
 36 
 37 //	instance constructor	---------------------------
 38 instanceL=[],
 39 initI=function(a){
 40  var _t=this,_p=pv(_t);
 41  instanceL.push(_t);	//	for destructor
 42  //_p.vars=a
 43 
 44  //	initial instance object
 45 },_=function(){initI.apply(this,arguments);initF&&initF.apply(this,arguments);},
 46 
 47 
 48 //	(instance private handle)	不要 instance private 的把這函數刪掉即可。
 49 _p='_'+(''+Math.random()).replace(/\./,''),
 50 //	get private variables (instance[,destroy]), init private variables (instance[,access function list[, instance destructor]])
 51 pv=function(i,d,k){var V,K=_p('k');return arguments.callee.caller===_p('i')?(V=_p(i[K]=_p()),V.O=i,V.L={}):(K in i)&&(V=_p(i[K]))&&i===V.O?d?(_p(i[K],1),delete i[K]):V.L:{};};
 52 
 53 //	class destructor	---------------------------
 54 /*
 55 please call at last (e.g., window.unload)
 56 
 57 usage:
 58 classT=classT.destroy();
 59 or if you has something more to do:
 60 classT.destroy()&&classT=null;
 61 */
 62 
 63 _.destroy=function(){for(var i=0,l=instanceL.length;i<l;i++)instanceL[i].destroy();_p();};
 64 
 65 //	(instance private handle, continue)
 66 eval('_p=(function(){var '+_p+'={a:pv,d:_.destroy,c:0,k:"+pv+'+Math.random()+'",i:initI};return function(i,d){var f=arguments.callee.caller;if(f==='+_p+'.a){if(!d)return i in '+_p+'?'+_p+'[i]:('+_p+'[i='+_p+'.c++]={},i);'+_p+'[i]={};}if(f==='+_p+'.d)'+_p+'={};}})();');
 67 _p.toString=function(){return'';};
 68 
 69 
 70 //	class public interface	---------------------------
 71 
 72 //	func
 73 _.func=function(){
 74  var _t=this;
 75  
 76 };
 77 
 78 //	class constructor	---------------------------
 79 
 80 // do something others
 81 
 82 
 83 _.prototype={
 84 //	應該盡量把東西放在 class,instance 少一點…?
 85 //	** important ** 這邊不能作 object 之 initialization,否則因為 object 只會 copy reference,因此 new 時東西會一樣。initialization 得在 _() 中作!
 86 
 87 //	instance public interface	-------------------
 88 
 89 setV:function(a){
 90  var _t=this,_p=pv(_t);
 91  //_p.vars=a
 92 },
 93 
 94 
 95 //	instance destructor	---------------------------
 96 /*
 97 usage:
 98 instance=instance.destroy();
 99 or if you has something more to do:
100 instance.destroy()&&instance=null;
101 */
102 destroy:function(){pv(this,1);}
103 };	//	_.prototype=
104 
105 return _;
106 })();	//	function(initF){
107 
108 //	===================================================
109 
110 
111 
112 
113 
114 
115 //	解析
116 
117 
118 
119 //	===================================================
120 
121 /*
122 	** class description: class template
123 
124 _=this
125 
126 TODO:
127 .constructor 設定
128 inherits:
129 	http://www.cnblogs.com/birdshome/archive/2005/01/28/95933.html
130 	http://www.blogjava.net/zkjbeyond/archive/2006/05/08/45108.html
131 
132 
133 HISTORY:
134 2008/7/21 16:12:32	create
135 7/24 15:14:16	enhanced by set .toString. But.. If we use delete _p.toString, than we still can..
136 		eval('a = pv',some_instance);
137 		eval('var s=_p.toString;delete _p.toString;sl("** test1 _p: "+_p);_p.toString=s;sl("** test2 _p: "+_p);',a);
138 7/26 11:38:6	className
139 
140 TOTRY:
141 直接對 eval 下手,使 delete 掉 eval 則 lost data
142 */
143 var
144 classT_debug=
145 
146 //	若是不須讓 addCode 也可以讀通,不加 ClassT.~ 也沒關係。
147 (ClassT.classT=function(initF){	//	initF: additional initialization function
148 
149 var
150 
151 //	class private	-----------------------------------
152 className='',//classT
153 
154 //	variables
155 vars=7,
156 //	function
157 doLog=function(m){
158  var _t=_;
159  sl((className?className+': ':'>> ')+m);	//	this+': '
160 },
161 
162 
163 
164 //	instance constructor	---------------------------
165 instanceL=[],	// 實例 list
166 initI=function(a){
167  var _t=this,//	這裡面有用的是 this,不是 arguments.callee。
168 	_p=pv(_t);//pv(_t,[func1,func2,..],_.destroy);	//	init private variables
169  instanceL.push(_t);	//	for destructor
170 
171  //	initial instance object
172  _t.property1=[];
173 
174  _t.testV=a;
175  doLog('class create: '+a);
176 
177  //return this;
178 },
179 
180 //	盡量減少 instance 體積…有用嗎?
181 _=function(){
182 	initI.apply(this,arguments);
183 	initF&&initF.apply(this,arguments);
184 },
185 
186 
187 //	(instance private handle)	不要 instance private 的把這函數刪掉即可。
188 /*
189 更完整的防治:比對 arguments.callee.caller 的程式碼,確定登錄過才給予存取。
190 …在 eval() 的第二 argument 下無用武之地。
191 */
192 
193 _p='_'+(''+Math.random()).replace(/\./,''),
194 
195 pv=function(i,d,k){	//	get private variables (instance[,destroy]), init private variables (instance[,access function list[, instance destructor]])
196  var	V,K=_p('k');
197 /*	V: get variables
198 
199 V.L	variables {}
200 V.O	instance
201 
202 for full version:
203 V.F	可存取函數的程式碼 list {}
204 V.D	instance destructor
205 */
206 
207 //	simple version
208  if(0)return arguments.callee.caller===_p('i')?
209 	(V=_p(i[K]=_p()),V.O=i,V.L={})
210 	:(K in i)&&(V=_p(i[K]))&&i===V.O?
211 		d?(_p(i[K],1),delete i[K]):V.L
212 		:{};	//	竄改就會出 trouble
213 
214 
215 //	full version
216  var c=arguments.callee.caller,j=0,l;
217  doLog('pv: '+(c===_p('i')?'init':d?'destory':'get variables')+' by '+c);
218  if(c===_p('i')){
219   V=_p(i[K]=_p());
220   V.O=i;
221   if(k)V.D=k;	//	instance destructor
222   //	登錄可存取函數的程式碼。更狠的:不用 {} 而用 d,確定是 *完全相同* 的 function。
223   if(d instanceof Array)	//	[]: no access!!
224    for(k=V.F={},l=d.length;j<l;j++)
225     k[d[j]]=1;
226   return V.L={};
227  }
228 
229  //	預防竄改,找尋本來應該的 index。
230  if(!(K in i)||!(V=_p(i[K]))||i!==V.O)
231   for(k=_p('c');j<k;j++)
232    if(i===_p(j).O){
233     doLog('pv: correct index: '+i[K]+' to '+j);
234     i[K]=j;
235     break;
236    }
237 
238  if((K in i)&&(V=_p(i[K]))&&i===V.O)
239   if(d){
240    //	call from instance destructor
241    if(!V.D||c===V.D)_p(i[K],1),delete i[K];
242    //else throw new Error(3,'Error calling to destroy.');
243   }else if(!V.F||V.F[c]){
244    doLog('pv: get index '+i[K]+'.');
245    //if(!V.L)throw new Error(1,'Error to get variables! Maybe it was already destroyed?');//private variables
246    return V.L;
247   }
248 
249  return {};	//	throw new Error(1,'Illegal access!');
250 };	//	of pv=function(
251 
252 
253 //	(for inherits)
254 /*
255 不要 inherit 的把這段刪掉即可。
256 usage:
257 //	模擬 inherits
258 newClass=oldClass.clone();
259 //	prevent re-use. 防止再造 
260 delete oldClass.clone;
261 */
262 (_.clone=arguments.callee).toString=function(){return '[class_template]';};
263 
264 
265 //	class destructor	---------------------------
266 /*
267 please call at last (e.g., window.unload)
268 
269 usage:
270 classT=classT.destroy();
271 or if you has something more to do:
272 classT.destroy()&&classT=null;
273 */
274 
275 _.destroy=function(){
276  doLog('destroy: Destroy class.');
277  for(var i=0,l=instanceL.length;i<l;i++)
278   instanceL[i].destroy();
279  _p();
280 };
281 
282 
283 //	class public interface	---------------------------
284 
285 //	variables
286 _.variables={};
287 //	func
288 _.func=function(){
289  var _t=this;
290  
291 };
292 
293 
294 //	(instance private handle, continue)
295 //	.a: accessable caller function, .d: class destructor, c:count, .k: private variables keyword, .i: init function, m: accessable class members
296 //	destructor: (index,1)	Warning: 某些環境中 Array 可能無法用 delete?
297 eval('_p=(function(){var '+_p+'={a:pv,d:_.destroy,c:0,k:"+pv+'+Math.random()+'",i:initI,m:{_:{}}}; (function(m,i){for(i=0;i<m.length;i++)if(m[i])'+_p+'.m[m[i]]=1;})(['
298 	//'func1,func2'	//	在這裡填上需要 call 隱藏數值的 class private function。若無,可考慮合併到 _.destroy 前。
299 	+']); return function(i,d){var f=arguments.callee.caller;if(f==='+_p+'.a){if(!d)return i in '+_p+'?'+_p+'[i]:('+_p+'[i='+_p+'.c++]={},i);'+_p+'[i]={};}if('+_p+'.m[f])return '+_p+'.m._;if(f==='+_p+'.d)'+_p+'={};}})();');
300 _p.toString=function(){return '';};
301 
302 
303 //	class constructor	---------------------------
304 
305 // do something others
306 
307 
308 _.prototype={
309 //	應該盡量把東西放在 class,instance 少一點…?
310 
311 //	instance public interface	-------------------
312 
313 //	** important ** 這邊不能作 object 之 initialization,否則因為 object 只會 copy reference,因此 new 時東西會一樣。initialization 得在 _() 中作!
314 property1:[],
315 
316 setV:function(m){
317  var _t=this,_p=pv(_t);
318  doLog('setV: class vars='+(vars=m)+', this.vars='+(_p.vars=m));
319 },
320 
321 getV:function(){
322  var _t=this,_p=pv(_t);
323  doLog('getV: class vars='+vars+', this.vars='+_p.vars);
324 },
325 
326 
327 //	instance destructor	---------------------------
328 
329 /*
330 usage:
331 instance=instance.destroy();
332 or if you has something more to do:
333 instance.destroy()&&instance=null;
334 
335 TODO: Need *auto* detect if the object is destroyed.
336 */
337 destroy:function(){
338  //	If you need to do something (e.g, destroy sub-sub-objects) before destroy it, you need to call pv(this) first here.
339  pv(this,1);
340 }
341 
342 };	//	_.prototype=
343 
344 //	class name	---------------------------
345 if(className){
346  _.prototype.toString=_.toString=function(){return '[class '+className+']';};//classT
347  //eval('var className=_',this);	//	行不通
348 }
349 
350 return _;
351 })();	//	(function(){
352 
353 
354 //	===================================================
355 
356 
357 /*
358 //	test suit
359 sl('<hr/>');
360 var c1=new classT(123),c2=new classT(456);
361 
362 c1.setV('Hello');
363 c2.setV('World');
364 c1.getV();
365 c2.getV();
366 
367 sl(c1.testV+','+c2.testV);
368 
369 c1.destroy();
370 c2.destroy();
371 classT.destroy();
372 */
373 
374 
375 
376 
377 
378 /*
379 繼承
380 http://www.cnblogs.com/birdshome/archive/2005/01/28/95933.html
381 
382 
383 引入arguments.length:這代表傳入引數個數(長度),arguments.callee.length:這代表(function)自身定義的引數個數(長度)
384 function fn(){
385  var _f=arguments.callee;	//	f: function, flag	引入arguments.callee:這代表(function)自身
386  //	以 _f.* 替代 fn.*
387  alert('fn: _f.val='+_f.val);
388 }
389 fn.subfn=function(){
390  var _f=arguments.callee;	//	function, flag
391  //	當不用 new 時,以 _f.* 替代 fn.subfn.*,this.* 替代 fn.*。但在 (fn.subfn=function(){ .. }) 中間就不能用 this, _f
392  alert('fn.subfn: this.val='+this.val);	//	*** !!WARNING!! 在 eval() 中 this 可能表示 window,這時就無法用 this 來得到 fn 了。
393  alert('fn.subfn: _f.val='+_f.val);
394 };
395 fn.subfn.val='test value: fn.subfn.val';
396 fn.val='test value: fn.val';
397 fn.prototype={
398 constructor:fn,	//	need to adjust
399 subfn:function(){
400  var _f=arguments.callee;	//	function, flag
401  //	當不用 new 時,以 _f.* 替代 fn.subfn.*,this.* 替代 fn.*
402  alert('fn.prototype.subfn: this.val='+this.val);
403  alert('fn.prototype.subfn: _f.val='+_f.val);
404  alert('fn.prototype.subfn: this.constructor.val='+this.constructor.val);
405 },
406 val:'test value: fn.prototype.val'
407 };	//	fn.prototype={
408 fn.prototype.subfn.val='test value: fn.prototype.subfn.val';
409 var inst=new fn;
410 //inst.constructor.subfn();
411 inst.subfn();
412 
413 
414 var obj={
415  val:34,
416  fn:function(){
417   var _f=arguments.callee;	//	function, flag
418   //	以 _f.* 替代 obj.subfn.*,this.* 替代 obj.*
419   alert(this.val);
420  }
421 };
422 ww.ee();
423 
424 
425 
426 to hack @ Firefox 3.0:	https://bugzilla.mozilla.org/show_bug.cgi?id=442333
427 假設 scope obj.fn 裡有一個 foo 變數,在 Firefox 上可以使用 var a; eval('a = foo', obj.fn) 把 foo 變數抓到 a 裡面,所以你如果有使用這種方法來放與安全性有關的東西,就得重新檢查一次程式碼:Module Pattern Provides No Privacy…at least not in JavaScript(TM)。在一陣討論後,這個功能打算在 Firefox 3.1 拿掉:Remove eval's optional second argument。
428 
429 */
430 
431 
432 /*
433 實作class:
434 	http://www.remus.dti.ne.jp/~a-satomi/bunsyorou/ArekorePopup.html
435 	http://www.klstudio.com/post/32.html
436 function classA(){
437  //	define property
438  //	array
439  this.attrs=['title','href','cite','datetime'];
440  //	object
441  this.ns={
442 	xhtml1:'http://www.w3.org/1999/xhtml',
443 	xhtml2:'http://www.w3.org/2002/06/xhtml2',
444  };
445  return this;
446 }
447 classA.prototype={
448  //	function
449  launch:function(){},
450  init:function(){},
451  //	object
452  scanNode:{
453   recursive:function(node){}
454  },
455  //	http://dean.edwards.name/weblog/2005/10/add-event/
456  addEvent:function(obj,type,listener){
457   if (obj.addEventListener) // Std DOM Events
458    obj.addEventListener(type, listener, false);
459   else if (obj.attachEvent) // IE
460    obj.attachEvent(
461     'on' + type,
462     function() { listener( {
463      type		: window.event.type,
464      target		: window.event.srcElement,
465      currentTarget	: obj,
466      clientX		: window.event.clientX,
467      clientY		: window.event.clientY,
468      pageY		: document.body.scrollTop + window.event.clientY,
469      keyCode		: window.event?window.event.keyCode:e?e.which:0,
470      shiftKey		: window.event.shiftKey,
471      stopPropagation	: function() { window.event.cancelBubble=true; }
472     } ) }
473    );
474  }
475 };
476 var A=new classA();
477 
478 
479 */
480 
481 
482