OSDN Git Service

f9a6a771f8b4b343f41e654b06c3c50043b37a7e
[pettanr/clientJs.git] / 0.5.x / javascripts / system.js
1 /*
2  * pettanR system.js
3  *   version 0.5.41
4  *
5  * gadgetOS
6  *   author:
7  *     itozyun
8  *   licence:
9  *     3-clause BSD
10  */
11
12 ( function( window, document, undefined ){
13         
14         var body           = document.getElementsByTagName( 'body' )[ 0 ]; //( document.compatMode || '' ) !== 'CSS1Compat' ? document.body : document.documentElement;// 
15         var SERVICE_LIST   = [];
16         var SUPER_USER_KEY = { getUID: function(){ return 0; }};
17         var API_USER_LIST  = [ SUPER_USER_KEY ];
18         var numApiUser     = 1;
19         
20         function EMPTY_FUNCTION(){};
21         
22         function isApiUser( _user ){
23                 return _user === SUPER_USER_KEY ||
24                         File.isDriver( _user ) === true ||
25                         Application.isApplicationInstance( _user ) === true;
26         };
27         
28         var Const = {
29                 FILE: {
30                         TYPE: {
31                                 UNKNOWN:        0,
32                                 FOLDER:         1,
33                                 IMAGE:          2,
34                                 TEXT:           3,
35                                 HTML:           4,
36                                 CSV:            5,
37                                 JSON:           6,
38                                 XML:            7
39                         },
40                         STATE: {
41                                 UNKNOWN:        0,
42                                 OK:                     1,
43                                 LOADING:        2,
44                                 ERROR:          3,
45                                 BROKEN:         4
46                         },
47                         UPDATE_POLICY: {
48                                 _____:          parseInt( '00000', 2 ),
49                                 ____C:          parseInt( '00001', 2 ), // hasCreateMenu
50                                 ___W_:          parseInt( '00010', 2 ), // isWritable
51                                 ___WC:          parseInt( '00011', 2 ), // isWritable
52                                 __R__:          parseInt( '00100', 2 ), // isRenamable
53                                 __R_C:          parseInt( '00101', 2 ), // hasCreateMenu
54                                 __RW_:          parseInt( '00110', 2 ), // isWritable
55                                 __RWC:          parseInt( '00111', 2 ), // isWritable
56                                 _S___:          parseInt( '01000', 2 ), // childrenIsSortable
57                                 _S__C:          parseInt( '01001', 2 ),
58                                 _S_W_:          parseInt( '01010', 2 ),
59                                 _S_WC:          parseInt( '01011', 2 ),
60                                 _SR__:          parseInt( '01100', 2 ),
61                                 _SR_C:          parseInt( '01101', 2 ),
62                                 _SRW_:          parseInt( '01110', 2 ),
63                                 _SRWC:          parseInt( '01111', 2 ),
64                                 D____:          parseInt( '10000', 2 ),
65                                 D___C:          parseInt( '10001', 2 ), // hasCreateMenu
66                                 D__W_:          parseInt( '10010', 2 ), // isWritable
67                                 D__WC:          parseInt( '10011', 2 ), // isWritable
68                                 D_R__:          parseInt( '10100', 2 ), // isRenamable
69                                 D_R_C:          parseInt( '10101', 2 ), // hasCreateMenu
70                                 D_RW_:          parseInt( '10110', 2 ), // isWritable
71                                 D_RWC:          parseInt( '10111', 2 ), // isWritable
72                                 DS___:          parseInt( '11000', 2 ), // childrenIsSortable
73                                 DS__C:          parseInt( '11001', 2 ),
74                                 DS_W_:          parseInt( '11010', 2 ),
75                                 DS_WC:          parseInt( '11011', 2 ),
76                                 DSR__:          parseInt( '11100', 2 ),
77                                 DSR_C:          parseInt( '11101', 2 ),
78                                 DSRW_:          parseInt( '11110', 2 ),
79                                 DSRWC:          parseInt( '11111', 2 ),
80                                 CREATE:         1,
81                                 WRAITE:         2,
82                                 RENAME:         4,
83                                 SORT:           8,
84                                 DELETE:         16
85                         },
86                         EVENT: {
87                                 UPDATE_ATTRIVUTE:       'onFileUpdate',
88                                 GET_SEQENTIAL_FILES:'gotSeqentilFiles'
89                         },
90                         DATA_PROPERTY_RESERVED: [
91                                 'children', 'driver', 'state', 'type'
92                         ]                       
93                 },
94                 TREE: {
95                         EVENT: {
96                                 UPDATE:                         'onTreeUpdate'
97                         }
98                 },
99                 KEY: {
100                         EVENT: {
101                                 KEY_DOWN:                       'keydown',
102                                 KEY_UP:                         'keyup',
103                                 KEY_CHANGE:                     'keychange',
104                                 CURSOL:                         'cursol'
105                         }
106                 },
107                 APP: {
108                         TYPE: {
109                                 GENERAL : 0,
110                                 OVERLAY : 1,
111                                 PAGE    : 2
112                         }
113                 }
114         };
115
116 /**
117  * Class を定義し システムの管理下に置く.
118  * 全てのクラスと pool が有効の場合インスタンスへの参照が保持される.
119  *  1. Class.create( def, opt_final, opt_pool, opt_abstract ) でクラスを登録.
120  *  2. コンストラクタ となるメソッドは、Constructor : function( arg ){ ... }, に書く.
121  *  3. 通常通り new で インスタンス生成
122  *  4. kill() でオブジェクトをクリーンして削除、pool が有効の場合は pool される.
123  *  5. pool が有効の場合、new で pool されたインスタンスが返される.
124  *  6. 
125  * 
126  */
127 var Class = ( function(){
128         var CLASS_LIST         = [],
129                 DEF_LIST           = [],
130                 PRIVATE_CLASS_LIST = [],
131                 PRIVATE_DEF_LIST   = [],
132                 CONSTRUCTOR        = 'Constructor',
133                 GET_INDEX          = Util.getIndex,
134                 abstractFlag       = true,
135                 privateFlag        = true,
136                 f                  = true,
137                 c                  = Util.copyArray,
138                 a; /* arguments */
139         
140         function getClass( instance ){
141                 var cList    = CLASS_LIST,
142                         i        = cList.length,
143                         klass;
144                 for( ; i; ){
145                         klass = cList[ --i ];
146                         if( instance instanceof klass ) return klass;
147                 };
148                 cList = PRIVATE_CLASS_LIST;
149                 i     = cList.length;
150                 for( ; i; ){
151                         klass = cList[ --i ];
152                         if( instance instanceof klass ) return klass;
153                 };
154                 
155                 if( GET_INDEX( cList, instance ) !== -1 ) return instance;
156                 if( GET_INDEX( CLASS_LIST, instance ) !== -1 ) return instance;
157         };
158         
159         function getClassDef( KlassOrInstance ){
160                 var getIndex = GET_INDEX,
161                         i        = getIndex( CLASS_LIST, KlassOrInstance );
162                 if( i === -1 ) i = getIndex( CLASS_LIST, getClass( KlassOrInstance ) );
163                 if( i !== -1 ) return DEF_LIST[ i ];
164                 
165                 i = getIndex( PRIVATE_CLASS_LIST, KlassOrInstance );
166                 if( i === -1 ) i = getIndex( PRIVATE_CLASS_LIST, getClass( KlassOrInstance ) );
167                 if( i !== -1 ) return PRIVATE_DEF_LIST[ i ];
168                 
169                 if( GET_INDEX( DEF_LIST, KlassOrInstance ) !== -1 ) return KlassOrInstance;
170                 if( GET_INDEX( PRIVATE_DEF_LIST, KlassOrInstance ) !== -1 ) return KlassOrInstance;
171         };
172         
173         /* over のプロパティを target にコピーする.ただし target の プロパティが優先, force で解除 */
174         function override( target, over, force ){
175                 for( var p in over ){
176                         if( p === CONSTRUCTOR ) continue;
177                         if( force === true || typeof target[ p ] === 'undefined' ){
178                                 target[ p ] = over[ p ];
179                         };
180                 };
181                 return target;
182         };
183         
184         /* サブクラスを作るメソッド  
185          * var subClass = superClass.inherits( ... ) 
186          * http://d.hatena.ne.jp/m-hiyama/20051018/1129605002
187          */
188         function inherits( /* displayName, classSetting, opt_PrivateClass, props */ ){
189                 var args         = c( arguments ),
190                         params       = [],
191                         Super        = this,
192                         superDef     = getClassDef( Super ),
193                         displayName  = args[ 0 ],
194                         classSetting,
195                         opt_super,
196                         klass;
197                 if( superDef.Final === true ) throw new Error( 'Class is final!' );
198                 
199                 if( Type.isString( displayName ) === true ){
200                         args.shift();
201                 } else {
202                         displayName = 'SubClass of ' + superDef.displayName;
203                 };
204                 params.push( displayName );
205                 
206                 classSetting = args[ 0 ];
207                 if( Type.isNumber( classSetting ) === true ){
208                         opt_super = !!( classSetting & Class.SUPER_ACCESS );
209                         params.push( args.shift() );
210                 };
211                 if( getClassDef( args[ 0 ] ) ){
212                         params.push( args.shift() );
213                 } else {
214                         superDef.privateClass && params.push( superDef.privateClass );
215                 };
216                 params.push( override( new Super(), args[ 0 ], true ) ); /* props */
217                 
218                 abstractFlag = false;
219                 klass = Class.create.apply( null, params );
220                 abstractFlag = true;
221                 if( opt_super === true ) getClassDef( klass ).Super = Super.prototype;
222                 return klass;
223         };
224         
225         /* Class.create で作られたクラスのインスタンスが共通で備えるメソッド */
226         var ClassBase = {
227                 kill : function(){
228                         var instance = this,
229                                 klass = getClass( instance ),
230                                 def   = getClassDef( klass ),
231                                 privateData, p, i;
232                         Type.isFunction( instance.onKill ) === true && instance.onKill();
233                         for( p in instance ){
234                                 if( instance.hasOwnProperty && !instance.hasOwnProperty( p ) ) continue;
235                                 delete instance[ p ];
236                         };
237                         if( def.pool ){
238                                 def.live && def.live.splice( GET_INDEX( def.live, instance ), 1 );
239                                 def.pool.push( instance );
240                         };
241                         if( def.privateClass ){
242                                 privateData = klass.getPrivateData( instance );
243                                 if( privateData ){
244                                         privateData.kill();
245                                         i = GET_INDEX( def.dataList, privateData );
246                                         def.dataList.splice( i, 1 );
247                                         def.userList.splice( i, 1 );
248                                 };
249                         };
250                         // myCallback の削除
251                         // myCallback を受け取った API への通知
252                 },
253                 getMyCallback : function( callback ){
254                         var def       = getClassDef( this ),
255                                 iList     = def.callbackInstanceList,
256                                 rList     = def.callbackRegisterList,
257                                 i, cList, myCallback;
258                         if( !iList ){
259                                 iList = def.callbackInstanceList = [];
260                                 rList = def.callbackRegisterList = [];
261                         };
262                         i = GET_INDEX( iList, this );
263                         if( index === -1 ){
264                                 index = iList.length;
265                                 cList = [];
266                                 iList.push( this );
267                                 rList.push( cList );
268                         } else {
269                                 cList = rList[ i ];
270                                 for( i = cList.length; i; ){
271                                         if( cList[ --i ].callback === callback ) return cList[ i ];
272                                 };
273                         };
274                         myCallback = new Callback( this, callback );
275                         cList.push( myCallback );
276                         return myCallback;
277                 },
278                 releaseMyCallback : function( callback ){
279                         var def       = getClassDef( this ),
280                                 iList     = def.callbackInstanceList,
281                                 rList     = def.callbackRegisterList,
282                                 i, cList, myCallback;
283                         if( !iList ) return;
284                         i = GET_INDEX( iList, this );
285                         if( index === -1 ) return;
286                         cList = rList[ i ];
287                         i     = GET_INDEX( cList, callback );
288                         if( i !== -1 ) return;
289                         myCallback = cList[ i ];
290                         cList.splice( i, 1 );
291                         myCallback.kill();
292                 }
293         };
294
295         /* privateDataclass をもつクラスに追加されるメソッド */
296         function newPrivateData( /* instance, args */ ){
297                 var args         = c( arguments ),
298                         user         = args.shift(),
299                         def          = getClassDef( user ),
300                         privateClass = def.privateClass,
301                         privateDef   = getClassDef( privateClass ),
302                         i            = -1,
303                         data;
304                 if( def.userList ){
305                         i = GET_INDEX( def.userList, user );
306                 } else {
307                         def.userList = [];
308                         def.dataList = [];
309                 };
310                 if( i !== -1 ){
311                         throw new Error( 'PrivateData already exist!' );
312                 };
313                 privateFlag = false;
314                 data        = new privateClass();
315                 privateFlag = false;
316                 def.dataList.push( data );
317                 def.userList.push( user );
318                 privateDef[ CONSTRUCTOR ] && privateDef[ CONSTRUCTOR ].apply( data, args );
319                 return data;
320         };
321         function getPrivateData( instance ){
322                 var def = getClassDef( instance ),
323                         i   = GET_INDEX( def.userList, instance );
324                 if( i !== -1 ) return def.dataList[ i ];
325         };
326         
327         /*
328          * new の実体.コンストラクタの機能は instance.Constructor に書く.
329          * これにより pool された オブジェクト(破棄されたインスタンス) を再利用できる
330          */
331         /* Constructor Real for GeneralClass */
332         function G(){
333                 var klass = this,
334                         def   = getClassDef( klass ),   
335                         instance;       
336                 if( def.pool && def.pool.length > 0 ){
337                         instance = def.pool.shift();
338                 } else {
339                         f = false;
340                         instance = new klass();
341                         f = true;
342                 };
343                 if( def.Super && !instance.Super ){
344                         instance.Super = def.Super;
345                 };
346                 def.live && def.live.push( instance );
347                 def[ CONSTRUCTOR ] && def[ CONSTRUCTOR ].apply( instance, c( arguments ) );
348                 return instance;
349         };
350         
351         /* Constructor Real for PrivateClass */
352         function P(){
353                 var klass = this,
354                         def   = getClassDef( klass ),   
355                         instance;
356                 if( privateFlag === true ){
357                         throw new Error( 'use class.newPrivateData( instance, args )!' );
358                 };              
359                 if( def.pool && def.pool.length > 0 ){
360                         instance = def.pool.shift();
361                 } else {
362                         f = false;
363                         instance = new klass();
364                         f = true;
365                 };
366                 if( def.Super && !instance.Super ){
367                         instance.Super = def.Super;
368                 };
369                 return instance;
370         };
371         /* Constructor Real for AbstractClass */
372         function A(){
373                 var klass = this,
374                         instance;
375                 if( abstractFlag === true ){
376                         throw new Error( 'AbstractClass!' );
377                 };
378                 f = false;
379                 instance = new klass();
380                 f = true;
381                 return instance;
382         };
383         
384         
385         return {
386                 POOL_OBJECT  : 1,
387                 ABSTRACT     : 2,
388                 FINAL        : 4,
389                 SUPER_ACCESS : 8,
390                 PRIVATE_DATA : 16,
391                 create : function( /* displayName, classSetting, opt_PrivateClass, props */ ){
392                         var args        = c( arguments ),
393                                 displayName = args[ 0 ],
394                                 classSetting,
395                                 opt_pool, opt_abstract, opt_final, opt_private,
396                                 privateDef,
397                                 props,
398                                 klass,
399                                 classDef = {};
400                         if( Type.isString( displayName ) === true ){
401                                 classDef.displayName = displayName;
402                                 args.shift();
403                         };
404                         classSetting = args[ 0 ];
405                         if( Type.isNumber( classSetting ) === true ){
406                                 opt_pool     = !!( classSetting & Class.POOL_OBJECT  );
407                                 opt_abstract = !!( classSetting & Class.ABSTRACT     );
408                                 opt_final    = !!( classSetting & Class.FINAL        );
409                                 opt_private  = !!( classSetting & Class.PRIVATE_DATA );
410                                 if( opt_final === true && opt_abstract === true ){
411                                         throw new Error( 'final & Abstract!' );
412                                 };                              
413                                 args.shift();
414                         };
415                         privateDef = getClassDef( args[ 0 ] );
416                         if( privateDef ){
417                                 if( privateDef.isPrivate !== true ){
418                                         throw new Error( 'PrivateClass not found! please, Class.createPrivateData().' );
419                                 } else
420                                 if( privateDef.Abstract === true ){
421                                         throw new Error( 'PrivateClass is Abstract!' );
422                                 };
423                                 classDef.privateClass = args.shift();
424                         };
425                         props = args[ 0 ];
426                         if( props === null || Type.isObject( props ) === false ){
427                                 throw new Error( 'No Class Def!' );
428                         };
429                         
430                         if( Type.isFunction( props[ CONSTRUCTOR ] ) === true ){
431                                 classDef[ CONSTRUCTOR ] = props[ CONSTRUCTOR ];
432                         };
433
434                         if( opt_abstract === true ){
435                                 klass = function(){ a = arguments; if( f ) return A.apply( a.callee, c( a ) )};
436                                 classDef.Abstract = true;
437                         } else
438                         if( opt_private === true ){
439                                 klass = function(){ a = arguments; if( f ) return P.apply( a.callee, c( a ) )};
440                                 if( opt_pool === true ) classDef.pool = [];
441                         } else {
442                                 klass = function(){ a = arguments; if( f ) return G.apply( a.callee, c( a ) )};
443                                 if( opt_pool === true ){
444                                         classDef.pool = [];
445                                         classDef.live = [];
446                                 };
447                         };
448                         klass.prototype = override( override( {}, props, true ), ClassBase, false );
449                         
450                         if( opt_final === true ){
451                                 classDef.Final = true;
452                         } else {
453                                 klass.inherits = inherits;
454                         };                      
455                         if( opt_private === true ){
456                                 if( classDef.privateClass ){
457                                         throw new Error( 'Private Data Class has no PrivateClass!' );
458                                 };
459                                 classDef.isPrivate = true;
460                                 PRIVATE_CLASS_LIST.push( klass );
461                                 PRIVATE_DEF_LIST.push( classDef );
462                         } else {
463                                 if( classDef.privateClass ){
464                                         klass.newPrivateData  = newPrivateData;
465                                         klass.getPrivateData  = getPrivateData; 
466                                 };
467                                 CLASS_LIST.push( klass );
468                                 DEF_LIST.push( classDef );                              
469                         };
470                         return klass;
471                 },
472                 onShutdown : function(){
473                         
474                 },
475                 getClass : function( instance ){
476                         
477                 },
478                 getClassDef : function(){
479                         
480                 }
481         };
482 })();
483
484 /**
485  * Callback 時に thisObject や args を指定したい場合に使用. 
486  */
487 var Callback = Class.create(
488         Class.POOL_OBJECT | Class.FINAL, {
489         Constructor : function( thisObject, callback, opt_args ){
490                 if( Type.isFunction( callback ) === false ){
491                         throw new Error( 'Not function!' );
492                 };
493                 this.callback = callback;
494                 if( thisObject ) this.thisObject = thisObject;
495                 if( Type.isArray( opt_args ) === true ){
496                         this.args = opt_args;
497                 } else
498                 if( opt_args !== undefined ){
499                         this.arg = opt_args;
500                 };
501         },
502         fire : function( /* args */ ){
503                 var thisObject = this.thisObject || window,
504                         args       = Util.copyArray( arguments );
505                 if( 0 < args.length ){
506                         if( this.args !== undefined ){
507                                 args.push.apply( args, this.args );
508                         } else
509                         if( this.arg !== undefined ){
510                                 args.push( this.arg );
511                         };
512                         this.callback.apply( thisObject, args );
513                 } else {
514                         if( this.args !== undefined ){
515                                 this.callback.apply( thisObject, this.args );
516                         } else
517                         if( this.arg !== undefined ){
518                                 this.callback.call( thisObject, this.arg );
519                         } else {
520                                 this.callback.call( thisObject );
521                         };
522                 };
523         },
524         registerUser : function( user ){
525                 if( !this.userList ){
526                         this.userList = [ user ];
527                 } else {
528                         Util.getIndex( this.userList, user ) === -1 && this.userList.push( user );
529                 };
530         },
531         onKill : function(){
532                 var instance = this.thisObject;
533                 this.userList && Class.getClass( instance ) && instance.releaseMyCalllback( this );
534         }
535 });
536
537
538 /* --------------------------------------------------------------
539  * System Timer
540  * 
541  */
542
543 var SystemTimer = ( function(){
544         var setTimeout    = window.setTimeout;
545         var clearTimeout  = window.clearTimeout;
546         var INTERVAL_TIME = 16;
547         var TICKET_LIST   = [];
548         var timerId       = undefined;
549         var next          = 0;
550         
551         function loop(){
552                 var i    = 0,
553                         list = TICKET_LIST;
554             for( i = 0; i < list.length; ){
555                 if( list[ i ].fire( next ) !== false ) ++i;
556             };
557             timerId = undefined;
558             update();
559         };
560         function update(){
561                 var list = TICKET_LIST,
562                         l    = list.length,
563                         n    = 99999999,
564                         c;
565                 if( l === 0 ){
566                         timerId !== undefined && clearTimeout( timerId );
567                         timerId = undefined;
568                         return;
569                 };
570             for( ; l; ){
571                 c = list[ --l ].count;
572                 if( n > c ) n = c;
573             };
574             if( next > n || timerId === undefined ){
575                 timerId !== undefined && clearTimeout( timerId );
576                 timerId = setTimeout( loop, INTERVAL_TIME * n );
577                 next = n;
578             };
579         };
580         
581         var TimerTicket = Class.create(
582                 Class.POOL_OBJECT, {
583                         Constructor : function( apiuser, callback, time, once, opt_thisObject ){
584                                 this.apiuser  = apiuser;
585                                 this.callback = callback;
586                                 this.time     = time;
587                                 this.count    = time;
588                                 if( once ) this.once = once;
589                                 this.thisObj  = opt_thisObject || apiuser;
590                         },
591                         fire : function( c ){
592                                 this.count -= c;
593                                 if( 0 < this.count ) return;
594                                 this.callback.call( this.thisObj );
595                                 if( this.once === true ){
596                                         this.destroy();
597                                         TICKET_LIST.splice( Util.getIndex( TICKET_LIST, this ), 1 );
598                                         return false;
599                                 } else {
600                                         this.count = this.time;
601                                 };
602                         },
603                         destroy : function( apiuser, callback ){
604                                 if( apiuser  && apiuser  !== this.apiuser )  return false;
605                                 if( callback && callback !== this.callback ) return false;
606                                 
607                                 this.kill();
608                                 return true;
609                         }
610                 }
611         );
612         
613         return {
614                 add: function( _apiuser, _handler, _time, _once, opt_thisObject ){
615                         if( Type.isNumber( _time ) === false || _time < INTERVAL_TIME ) _time = INTERVAL_TIME;
616                         
617                     var _ticket = new TimerTicket( _apiuser, _handler, Math.ceil( _time / INTERVAL_TIME ), _once, opt_thisObject );
618                     TICKET_LIST.push( _ticket );
619                     
620                     update();
621                 },
622                 remove: function( _apiuser, _handler ){
623                         var _ticket,
624                                 i = 0;
625                         while( _ticket = TICKET_LIST[ i ] ){
626                                 if( _ticket.destroy( _apiuser, _handler ) === true ){
627                                         TICKET_LIST.splice( i, 1 );
628                                 } else {
629                                         ++i;
630                                 };
631                         };
632                     update();
633                 }
634         };
635 })();
636
637 /* --------------------------------------------------------------
638  * Async Callback
639  * 
640  */
641 var AsyncCall = ( function(){
642         var CALLBACK_LIST = [];
643         
644         var CallbackTicket = Class.create(
645                 Class.POOL_OBJECT, {
646                 Constructor : function( apiuser, callback, args, thisObject ){
647                         this.apiuser  = apiuser;
648                         this.callback = callback;
649                         this.args     = args;
650                         this.thisObj  = thisObject || apiuser;
651                 },
652                 fire : function(){
653                         var f = this.callback,
654                                 a = this.args,
655                                 t = this.thisObj;
656                         this.destroy();
657                         if( Type.isArray( a ) === true ){
658                                 f.apply( t, a );
659                         } else {
660                                 f.call( t, a );
661                         };
662                 },
663                 destroy : function( apiuser, callback ){
664                         if( apiuser  && apiuser  !== this.apiuser ) return false;
665                         if( callback && callback !== this.callback ) return false;
666                         
667                         this.kill();
668                         return true;
669                 }
670         });
671
672         function dispatch(){
673                 var _ticket = CALLBACK_LIST.shift();
674                 if( _ticket ){
675                         _ticket.fire();
676                         CALLBACK_LIST.length !== 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true );
677                 };
678         };
679
680         return {
681                 add: function( _apiuser, _callback, _argments, _thisObject ){
682                         CALLBACK_LIST.length === 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true );
683                         CALLBACK_LIST.push( new CallbackTicket( _apiuser, _callback, _argments, _thisObject ) );
684                 },
685                 remove: function( _apiuser, _callback ){
686                         var _ticket,
687                                 i = 0;
688                         while( _ticket = CALLBACK_LIST[ i ] ){
689                                 if( _ticket.destroy( _apiuser, _callback ) === true ){
690                                         CALLBACK_LIST.splice( i, 1 );
691                                 } else {
692                                         ++i;
693                                 };
694                         };
695                 }
696         };
697 })();
698
699 /* -----------------------------------------------------------
700  * 画像一覧は
701  *      お気に入り画像一覧 > tag:ペン次郎 > ペン次郎:笑う
702  *  最近アップロードされた画像 > images
703  *  最近使われた画像 > images
704  *  キャラクター画像庫 > アニマル系 > tag:ペン次郎 > ペン次郎:笑う
705  *  風景画像庫 >
706  *  効果画像庫 >
707  *  アイテム画像庫 >
708  *  
709  * 画像一覧を読み込むタイミング
710  */
711 var File = ( function(){
712         var DRIVER_LIST             = [];
713         
714         var FILE_TYPE_IS_FOLDER     = Const.FILE.TYPE.FOLDER,
715                 numFileType             = Const.FILE.TYPE.XML,
716                 FILEDATA_RESITER        = [],                   // store all of fileData( json object )
717                 FILEDATA_ACCESS         = [],                   // file operations for Kernel only ! hide from Out of File
718                 FILE_OBJECT_POOL        = [],
719                 EVENT_LISTENER_REGISTER = [],
720                 TREE_ARRAY              = [],
721                 TREE_ACCESS_ARRAY       = [];
722         
723         var REQUEST_CONTROLER = ( function(){
724                 var REQUEST_TICKET_RESISTER = [],
725                         currentTicket           = null,
726                         currentData             = null,
727                         DATA_TYPE_ARRAY         = 'json,xml,html,text'.split( ',' ),
728                         DATA_IS_JSON            = 0,
729                         DATA_IS_XML             = 1,
730                         DATA_IS_HTML            = 2,
731                         DATA_IS_TEXT            = 3,
732                         numError                = 0;
733                 
734                 var RequestTicket = Class.create(
735                         Class.POOL_OBJECT, {
736                         Constructor : function( apiuser, type, data, url, onLoad, onError ){
737                                 this.apiuser = apiuser;
738                                 this.type    = type;
739                                 this.data    = data;
740                                 this.url     = url;
741                                 this.onLoad  = onLoad;
742                                 this.onError = onError;
743                                 this.state   = 0;
744                         },
745                         load : function( data ){
746                                 AsyncCall.add( this.apiuser, this.onLoad, [ this.data, data ] );
747                         },
748                         error : function(){
749                                 AsyncCall.add( this.apiuser, this.onError, this.data );
750                         }
751                 });
752                 
753                 function request(){
754                         if( currentTicket !== null || REQUEST_TICKET_RESISTER.length === 0 ) return;
755                         currentTicket = REQUEST_TICKET_RESISTER.shift();
756                         $.ajax({
757                                 url:            currentTicket.url,
758                                 dataType:       DATA_TYPE_ARRAY[ currentTicket.type ],
759                                 success:        onSuccess,
760                                 error:          onError
761                         });
762                 };
763                 function onSuccess( _data ){
764                         currentTicket.load( _data );
765                         currentTicket.kill();
766                         currentTicket = null;
767                         request();
768                 };
769                 function onError(){
770                         ++numError;
771                         currentTicket.error();
772                         currentTicket.kill(); // retry
773                         currentTicket = null;
774                         request();
775                 };
776
777                 return {
778                         getNumTask: function(){
779                                 return REQUEST_TICKET_RESISTER.length;
780                         },
781                         getNumError: function(){
782                                 return numError;
783                         },
784                         getJson: function( _apiuser, _data, _url, _onLoad, _onError ){
785                                 REQUEST_TICKET_RESISTER.push( new RequestTicket( _apiuser, DATA_IS_JSON, _data, _url, _onLoad, _onError ));
786                                 currentTicket === null && request();
787                         }
788                 };
789         })();
790
791         var FILE_CONTROLER = {
792                 createTree: function( _apiuser, _rootFileData ){
793                         var _tree = new TreeClass( _apiuser, _rootFileData );
794                         TREE_ARRAY.push( _tree );
795                         return _tree;
796                 },
797                 getFileUID: function( FILEDATAorFILE ){
798                         if( FILEDATAorFILE instanceof FileClass ){
799                                 return FILEDATAorFILE.getUID();
800                         };
801                         
802                         var uid = Util.getIndex( FILEDATA_RESITER, FILEDATAorFILE );
803                         if( uid === -1 ){
804                                 uid = FILEDATA_RESITER.length;
805                                 FILEDATA_RESITER.push( FILEDATAorFILE );
806                         };
807                         return uid;
808                 },
809                 getFileDataAccess: function( UIDorFILEorFILEDATA ){
810                         var _uid, _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA ), _access;
811
812                         if( _data === null || typeof _data !== 'object' ) return null;
813                         for( var i=0, l = FILEDATA_ACCESS.length; i<l; ++i ){
814                                 _access = FILEDATA_ACCESS[ i ];
815                                 if( _access.DATA === _data ) return _access;
816                         };
817                         return null;
818                 },      
819                 getFileData: function( UIDorFILEorFILEDATA ){
820                         if( typeof UIDorFILEorFILEDATA === 'number' ){
821                                 return FILEDATA_RESITER[ UIDorFILEorFILEDATA ] || null;
822                         } else
823                         if( UIDorFILEorFILEDATA instanceof FileClass ){
824                                 return FILEDATA_RESITER[ UIDorFILEorFILEDATA.getUID() ] || null;
825                         } else
826                         if( Util.getIndex( FILEDATA_RESITER, UIDorFILEorFILEDATA ) !== -1 ){
827                                 return UIDorFILEorFILEDATA;
828                         };
829                         return null;
830                 },
831                 getChildren: function( UIDorFILEorFILEDATA ){
832                         var _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA );
833                         return _data !== null ? _data.children || null : null;
834                 },
835                 getDriver: function( _file ){
836                         var _data = FILE_CONTROLER.getFileData( _file );
837                         return _data !== null && _data.driver ? _data.driver : BASE_DRIVER;
838                 },
839                 getUpdateFlag: function( _file, _bit ){
840                         var _driver = FILE_CONTROLER.getDriver( _file ),
841                                 _policy;
842                         if( typeof _driver.getUpdatePolicy === 'function' ){
843                                 _policy = _driver.getUpdatePolicy( _file );
844                                 
845                         }
846                         if( typeof _policy !== 'number' ) {
847                                 _policy = BASE_DRIVER.getUpdatePolicy( _file )
848                         }
849                         return _policy % ( _bit * 2 ) >= _bit;
850                 },
851                 move: function( _prentUID, _targetfile, _newFolder, _newIndex, _opt_callback ){
852                         var _parentData = FILE_CONTROLER.getFileDataAccess( _prentUID ),
853                                 _parentType = _parentData.TYPE,
854                                 _targetData = FILE_CONTROLER.getFileDataAccess( _targetfile ),
855                                 _targetType = _targetData.TYPE;
856                 },
857                 replace: function( _uid, _file, _newIndex ){
858                         
859                 },
860                 addEventListener: function( FILEorNULL, _eventType, _callback, opt_thisObject ){
861                         var _uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL;
862                         EVENT_LISTENER_REGISTER.push( new FileEventTicket( _uid, _eventType, _callback, opt_thisObject ));
863                 },
864                 removeEventListener: function( FILEorNULL, eventType, callback ){
865                         var uid  = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL,
866                                 list = EVENT_LISTENER_REGISTER,
867                                 i    = 0,
868                                 ticket;
869                         for( ; i < list.length; ){
870                                 ticket = list[ i ];
871                                 if( ticket.fileUID === uid && ticket.eventType === eventType && ticket.callBack === callback ){
872                                         list.splice( i, 1 );
873                                         ticket.kill();
874                                 } else {
875                                         ++i;
876                                 };
877                         };
878                 },
879                 getTreeAccess: function(){
880                         
881                 },
882                 fileEventRellay: function( _uid, _event ){
883                         var _fileAccess = FILE_CONTROLER.getFileDataAccess( _uid );
884                         if( _fileAccess === null ) return;
885                         var _treeUID    =  _fileAccess.TREE.getUID(),
886                                 _treeAccess = TREE_ACCESS_ARRAY[ _treeUID ],
887                                 _data       = _fileAccess.DATA,
888                                 _tree;
889                         if( !_treeAccess ) return;
890                         _treeAccess.dispatchFileEvent( _event );
891                         for( var i=0, l = TREE_ARRAY.length; i<l; ++i ){
892                                 if( i !== _treeUID ){
893                                         _tree = TREE_ARRAY[ i ];
894                                         if( FILE_CONTROLER.getFileData( _tree.getCurrentFile() ) === _data ){
895                                                 _treeAccess = TREE_ACCESS_ARRAY[ _tree.getUID() ];
896                                                 _treeAccess && _treeAccess.dispatchFileEvent( _event );
897                                         };
898                                 };
899                         };
900                 }
901         };
902         
903         var TreeClass = function( apiuser, rootFileData ){
904                 var PARENT_FILE_RESITER = [],
905                         ACCESS = {
906                                 apiuser          : apiuser,
907                                 dispatchFileEvent: dispatchFileEvent
908                         },
909                         EVENT_LISTENER_ARRAY = [],
910                         instance             = this,
911                         rootFile             = new FileClass( instance, null, rootFileData ),
912                         currentFile          = rootFile;
913                 
914                 currentFile.getSeqentialFiles();
915                 TREE_ACCESS_ARRAY.push( ACCESS );
916                 
917                 function dispatchFileEvent( e ){
918                         var _eventType  = e.eventType,
919                                 _targetFile = e.targetFile,
920                                 _uid        = _targetFile.getUID(),
921                                 _ticket, _type, _callback;
922                         for( var i=0, l = EVENT_LISTENER_REGISTER.length; i<l; ++i ){
923                                 _ticket   = EVENT_LISTENER_REGISTER[ i ];
924                                 _type     = _ticket.eventType;
925                                 _callback = _ticket.callBack;
926                                 if( _eventType === _type && _uid === _ticket.fileUID ){
927                                         AsyncCall.add( apiuser, _callback, [ _eventType, _targetFile, e.key, e.value ], _ticket.thisObject || _targetFile );
928                                 } else
929                                 if( _type === Const.TREE.EVENT.UPDATE && _eventType === Const.FILE.EVENT.GET_SEQENTIAL_FILES ){
930                                         //_callback( _eventType, _targetFile );
931                                         AsyncCall.add( apiuser, _callback, [ _eventType, _targetFile ], _ticket.thisObject || instance );
932                                 };
933                         };
934                 };
935                 
936                 this.getUID = function(){
937                         return Util.getIndex( TREE_ACCESS_ARRAY, ACCESS );
938                 };
939                 this.getRootFile = function(){
940                         return rootFile;
941                 };
942                 this.getCurrentFile = function(){
943                         return currentFile;
944                 };
945                 this.hierarchy = function(){
946                         return PARENT_FILE_RESITER.length;
947                 };
948                 this.getParentFileAt = function( _index ){
949                         var l = PARENT_FILE_RESITER.length;
950                         if( typeof _index !== 'number' || _index < 0 || _index >= l ) return null;
951                         return PARENT_FILE_RESITER[ l -1 -_index ];
952                 };
953                 this.down = function( _index ){
954                         if( typeof _index !== 'number' || _index < 0 || _index >= currentFile.getChildFileLength()) return;
955                         PARENT_FILE_RESITER.unshift( currentFile );
956                         currentFile = currentFile.getChildFileAt( _index );
957                         currentFile.getSeqentialFiles();
958                         return currentFile;
959                 };
960                 this.up = function( _index ){
961                         var l = PARENT_FILE_RESITER.length;
962                         if( l === 0 ) return null;
963                         
964                         if( currentFile ){
965                                 var _currentFile = currentFile;
966                                 currentFile = null;
967                                 _currentFile.destroy();
968                         };
969                         if( typeof _index === 'number' ){
970                                 if( _index >= l ) return null;
971                                 currentFile = this.getParentFileAt( _index );
972                                 PARENT_FILE_RESITER.splice( 0, l -_index);
973                         } else {
974                                 currentFile = PARENT_FILE_RESITER.shift();
975                         };
976                         currentFile.getSeqentialFiles();
977                         return currentFile;     
978                 };
979                 this.addTreeEventListener = function( _eventType, _callback, opt_thisObject ){
980                         FILE_CONTROLER.addEventListener( null, _eventType, _callback, opt_thisObject );
981                 };
982                 this.removeTreeEventListener = function( _eventType, _callback ){
983                         FILE_CONTROLER.removeEventListener( null, _eventType, _callback );
984                 };
985                 this.destroy = function( _apiuser ){
986                         if( _apiuser && apiuser !== _apiuser ) return false;
987                         // removeEvent
988                         var _currentFile = currentFile;
989                         currentFile = rootFile = rootFileData = null;
990                         // currentFile, rootFile を null にしないと .File.destroy() ができない.
991                         _currentFile.destroy();
992                         while( PARENT_FILE_RESITER.length > 0 ){
993                                 _currentFile = PARENT_FILE_RESITER.shift();
994                                 _currentFile.destroy();
995                         };
996                         
997                         AsyncCall.remove( apiuser );
998                         instance = apiuser = null;
999                         return true;
1000                 };
1001         };
1002         
1003         var FileEventTicket = Class.create(
1004                 Class.POOL_OBJECT, {
1005                 Constructor : function( uid, eventType, callback, opt_thisObject ){
1006                         this.fileUID    = uid;
1007                         this.eventType  = eventType;
1008                         this.callBack   = callback;
1009                         this.thisObject = opt_thisObject;
1010                 }       
1011         });
1012         
1013         var FileEventClass = function( eventType, file, key, value ){
1014                 this.eventType        = eventType;
1015                 this.targetFile       = file;
1016                 this.updatedAttribute = key;
1017                 this.updatedValue     = value;
1018         };
1019
1020 /*
1021  * file の data は object で保持している。
1022  * File の外からファイルをみるときは、FileClassを通して操作する。
1023  * fileの変更、それに付随して追加されたイベントは、TreeClassで管理される。
1024  * treeがdestryされると、fileのイベントリスナーも全て削除される。
1025  * 他の tree も data の共通する currentFile に対してのみは、file の変更イベントを受け取って流す.
1026  * 
1027  */
1028         
1029         var FileClass = function( tree, parentData, data ){
1030                 var uid = FILE_CONTROLER.getFileUID( data );
1031                 
1032                 FILEDATA_ACCESS.push( {
1033                         TREE:                           tree,
1034                         parentData:                     parentData,
1035                         DATA:                           data
1036                 } );
1037                 
1038                 tree = parentData = data = null;
1039
1040                 this.getUID = function(){
1041                         return uid;
1042                 };
1043         };
1044         
1045         FileClass.prototype = {
1046                 isChildFile: function( _FILEorFILEDATA ){
1047                         return this.getChildFileIndex( _FILEorFILEDATA) !== -1;
1048                 },
1049                 getSeqentialFiles: function(){
1050                         var _driver = FILE_CONTROLER.getDriver( this );
1051                         if( _driver !== null && typeof _driver.getSeqentialFiles === 'function' ){
1052                                 _driver.getSeqentialFiles( this );
1053                         }
1054                 },
1055                 addEventListener: function( _eventType, _callback ){
1056                         FILE_CONTROLER.addEventListener( this, _eventType, _callback );
1057                 },
1058                 removeEventListener: function( _eventType, _callback ){
1059                         FILE_CONTROLER.removeEventListener( this, _eventType, _callback );
1060                 },
1061                 dispatchEvent: function( e ){
1062                         e instanceof FileEventClass && FILE_CONTROLER.fileEventRellay( this.getUID(), e );
1063                 },
1064                 getChildFileLength: function(){
1065                         var children = FILE_CONTROLER.getChildren( this );
1066                         return Type.isArray( children ) === true ? children.length : -1;
1067                 },
1068                 getChildFileIndex: function( _FILEorFILEDATA ){
1069                         var children = FILE_CONTROLER.getChildren( this );
1070                         if( Type.isArray( children ) === false ) return -1;
1071                         var l = children.length,
1072                                 _fileData = FILE_CONTROLER.getFileData( _FILEorFILEDATA );
1073                         if( _fileData === null ) return -1;
1074                         for( var i=0; i<l; ++i ){
1075                                 if( children[ i ] === _fileData ) return i;
1076                         }
1077                         return -1;
1078                 },
1079                 getChildFileAt: function( _index ){
1080                         var _access = FILE_CONTROLER.getFileDataAccess( this ),
1081                                 _children = FILE_CONTROLER.getChildren( this );
1082                         if( typeof _index !== 'number' || _index < 0 || Type.isArray( _children ) === false || _index >= _children.length ) return null;
1083                         var _file = new FileClass( _access.TREE, _access.DATA, _children[ _index ]);
1084                         // _file.init();
1085                         return _file;
1086                 },
1087                 getName: function(){
1088                         var driver = FILE_CONTROLER.getDriver( this );
1089                         if( typeof driver.getName === 'function'){
1090                                 return driver.getName( this );
1091                         }
1092                         return BASE_DRIVER.getName( this);
1093                 },
1094                 getThumbnail: function(){
1095                         var driver = FILE_CONTROLER.getDriver( this );
1096                         if( typeof driver.getThumbnail === 'function'){
1097                                 return driver.getThumbnail( this );
1098                         }
1099                         return BASE_DRIVER.getThumbnail( this );
1100                 },
1101                 getType: function(){
1102                         var _data = FILE_CONTROLER.getFileData( this );
1103                         return typeof _data.type === 'number' ? _data.type : Const.FILE.TYPE.UNKNOWN;
1104                 },
1105                 getState: function(){
1106                         var _data = FILE_CONTROLER.getFileData( this );
1107                         return typeof _data.state === 'number' ? _data.state : Const.FILE.STATE.OK;
1108                 },
1109                 getSummary: function(){
1110                         var driver = FILE_CONTROLER.getDriver( this );
1111                         if( typeof driver.getSummary === 'function'){
1112                                 return driver.getSummary( this );
1113                         }
1114                         return BASE_DRIVER.getSummary( this );
1115                 },
1116                 isWritable: function(){
1117                         return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.WRITE );
1118                 },
1119                 isSortable: function(){
1120                         return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.SORT );
1121                 },              
1122                 isCreatable: function(){
1123                         return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.CREATE );
1124                 },
1125                 isRenamable: function(){
1126                         return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.RENAME );
1127                 },
1128                 isDeletable: function(){
1129                         return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.DELETE );
1130                 },
1131                 read: function(){
1132                         // simpleDeepCopy
1133                         var driver = FILE_CONTROLER.getDriver( this ),
1134                                 data;
1135                         if( typeof driver.read === 'function'){
1136                                  data = driver.read( this );
1137                         }
1138                         return BASE_DRIVER.read( data || this );
1139                 },
1140                 write: function( _newData, _onUpdateFunction ){
1141                         var driver = FILE_CONTROLER.getDriver( this );
1142                         if( typeof driver.write === 'function'){
1143                                 return driver.write( this, _newData, _onUpdateFunction );
1144                         }
1145                         return BASE_DRIVER.write( this, _newData, _onUpdateFunction );
1146                 },
1147                 viewerApplicationList: function(){
1148                         var driver = FILE_CONTROLER.getDriver( this );
1149                         if( typeof driver.viewerApplicationList === 'function'){
1150                                 return driver.viewerApplicationList( this );
1151                         }
1152                         return BASE_DRIVER.viewerApplicationList( this );
1153                 },
1154                 editorApplicationList: function(){
1155                         var driver = FILE_CONTROLER.getDriver( this );
1156                         if( typeof driver.editorApplicationList === 'function'){
1157                                 return driver.editorApplicationList( this );
1158                         }
1159                         return BASE_DRIVER.viwerApps( this );
1160                 },
1161                 create: function(){
1162                         
1163                 },
1164                 sort: function(){
1165                         
1166                 },
1167                 onCopy: function(){
1168                         
1169                 },
1170                 onDelete: function(){
1171                         
1172                 },
1173                 move: function( _newFolder, _newIndex, opt_callback ){
1174                         var _access = FILE_CONTROLER.getFileDataAccess( this );
1175                         _access.TREE.move( _access.parentData, this.getUID(), _newFolder, _newIndex, opt_callback );
1176                 },
1177                 replace: function( _newIndex, opt_callback ){
1178                         var _access = FILE_CONTROLER.getFileDataAccess( this );
1179                         _access.TREE.replace( _access.parentData, this.getUID(), _newIndex, opt_callback);
1180                 },
1181                 /**
1182                  * サーチ
1183                  * 探しているファイルの属性と値を指定.一致する child の index を配列で返す.
1184                  */
1185                 search: function( obj, rule ){
1186                         var _children = FILE_CONTROLER.getChildren( this ),
1187                                 _child,
1188                                 ret = [], k, c;
1189                         for( var i=0, l=_children.length; i<l; ++i ){
1190                                 _child = _children[ i ];
1191                                 c = true;
1192                                 for( k in obj ){
1193                                         if( obj[ k ] !== _child[ k ] ){
1194                                                 c = false;
1195                                                 break;
1196                                         }
1197                                 }
1198                                 c === true && ret.push( i );
1199                         }
1200                         return ret;
1201                 },
1202                 destroy: function(){
1203                         var _access = FILE_CONTROLER.getFileDataAccess( this );
1204                         var _tree = _access.TREE;
1205                         if( _tree.getCurrentFile() === this ) return;
1206                         if( _tree.getRootFile() === this ) return;
1207                         for( var i=0, l = _tree.hierarchy(); i<l; ++i ){
1208                                 if( _tree.getParentFileAt( i ) === this ){
1209                                         return;
1210                                 }
1211                         }
1212                         var _index = Util.getIndex( FILEDATA_ACCESS, _access );
1213                         if( _index === -1 ) return;
1214                         // event の 削除
1215                         FILEDATA_ACCESS.splice( _index, 1 );
1216                         delete _access.DATA;
1217                         delete _access.TREE;
1218                         delete _access.parentData;
1219                 }
1220         };
1221
1222         /*
1223          * FileDriverBase
1224          */
1225         var FileDriverBase = function( driverClass ){
1226                 this.getUID = function(){
1227                         return Util.getIndex( API_USER_LIST, driverClass );
1228                 };
1229                 this.getSeqentialFiles = function( _file ){
1230                 };
1231                 this.getName = function( _file ){
1232                         var _data = FILE_CONTROLER.getFileData( _file );
1233                         return _data.name || 'No Name';
1234                 };
1235                 this.getThumbnail = function( _file ){
1236                         var _data = FILE_CONTROLER.getFileData( _file ),
1237                                 _type = _data.type,
1238                                 _className = '';
1239                         if( _type === Const.FILE.TYPE.FOLDER ){
1240                                 _className = 'folder';
1241                         } else
1242                         if( _type === Const.FILE.TYPE.IMAGE ){
1243                                 
1244                         } else
1245                         if( _type === Const.FILE.TYPE.TEXT ){
1246                                 
1247                         } else
1248                         if( _type === Const.FILE.TYPE.HTML ){
1249                                 
1250                         } else
1251                         if( _type === Const.FILE.TYPE.CSV ){
1252                                 
1253                         } else
1254                         if( _type === Const.FILE.TYPE.JSON ){
1255                                 
1256                         } else
1257                         if( _type === Const.FILE.TYPE.XML ){
1258                                 
1259                         };
1260                         return {
1261                                 image:          null,
1262                                 className:      ' file-type-' + _className
1263                         };
1264                 };
1265                 this.getSummary = function( _file ){
1266                         var _data = FILE_CONTROLER.getFileData( _file ),
1267                                 _type = _data.type;
1268                         if( _type === Const.FILE.TYPE.FOLDER ){
1269                                 return 'folder';
1270                         } else
1271                         if( _type === Const.FILE.TYPE.IMAGE ){
1272                                 return 'image file';
1273                         } else
1274                         if( _type === Const.FILE.TYPE.TEXT ){
1275                                 return 'text file';
1276                         } else
1277                         if( _type === Const.FILE.TYPE.HTML ){
1278                                 return 'html document file';
1279                         } else
1280                         if( _type === Const.FILE.TYPE.CSV ){
1281                                 return 'csv daat file';
1282                         } else
1283                         if( _type === Const.FILE.TYPE.JSON ){
1284                                 return 'json data file';
1285                         } else
1286                         if( _type === Const.FILE.TYPE.XML ){
1287                                 return 'xml data file';
1288                         }
1289                         return '';
1290                 };
1291                 this.getUpdatePolicy = function( _file ){
1292                         // debug用 全てのメニューを許可
1293                         return Const.FILE.UPDATE_POLICY.DSRWC;
1294                 };
1295                 this.read = function( _FILEorDATA ){
1296                         var data,
1297                                 protects = Const.FILE.DATA_PROPERTY_RESERVED;                   
1298                         if( _FILEorDATA instanceof FileClass ){
1299                                 data = FILE_CONTROLER.getFileData( _FILEorDATA )
1300                         } else {
1301                                 data = _FILEorDATA;
1302                         }
1303
1304                         function clone( src ) {
1305                                 var ret;
1306                                 if( Type.isArray(src) === true ){
1307                                         ret = [];
1308                                 } else
1309                                 if( Type.isObject(src) === true ){
1310                                         ret = {};
1311                                 } else
1312                                 if( Type.isNumber(src) === true || Type.isString(src) === true || Type.isBoolean( src ) === true ){
1313                                         return src;
1314                                 } else {
1315                                         return null;
1316                                 }
1317                                 for( var key in src ){
1318                                         if( Util.getIndex( protects, key ) === -1 ){
1319                                                 ret[ key ] = clone( src[ key ]);
1320                                         }
1321                                 }
1322                                 return ret;
1323                         };
1324                                 
1325                         return clone( data );
1326                 };
1327                 this.write = function( _file, _newData, _onUpdateFunction ){
1328                         var _data = FILE_CONTROLER.getFileData( _file ),
1329                                 _type = _data.type;
1330                         return false;
1331                 };
1332                 this.viewerApplicationList = function(){
1333                         return [];
1334                 };
1335                 this.editorApplicationList = function(){
1336                         return [];
1337                 };
1338                 this.onCreate = function(){
1339                         
1340                 };
1341                 this.onSort = function(){
1342                         
1343                 };
1344                 this.onCopy = function(){
1345                         
1346                 };
1347                 this.onDelete = function(){
1348                         
1349                 };
1350         };
1351         
1352         var BASE_DRIVER   = new FileDriverBase();
1353         
1354         var ROOT_FILEDATA = {
1355                         name:           'system root',
1356                         type:           FILE_TYPE_IS_FOLDER,
1357                         children:       []
1358                 },
1359                 SYSTEM_TREE = FILE_CONTROLER.createTree( SUPER_USER_KEY, ROOT_FILEDATA ),
1360                 ROOT_FILE   = SYSTEM_TREE.getRootFile();
1361
1362         function createFileTypeID(){
1363                 return ++numFileType;
1364         };
1365         
1366         var FileAPIClass = function( driver ){
1367                 var constObject;
1368                 this.createFolderUnderRoot = function( _fileData ){
1369                         if( _fileData !== null && Type.isObject( _fileData ) === true ){
1370                                 ROOT_FILEDATA.children.push( _fileData );
1371                                 ROOT_FILE.dispatchEvent( new FileEventClass( Const.FILE.EVENT.GET_SEQENTIAL_FILES, ROOT_FILE, 'children', null ));
1372                         }
1373                 };
1374                 this.createFileEvent   = function( _eventType, _file, _key, _value ){
1375                         return new FileEventClass( _eventType, _file, _key, _value );
1376                 };
1377                 this.createFileTypeID  = createFileTypeID;
1378                 this.getFileDataAccess = FILE_CONTROLER.getFileDataAccess;
1379                 this.getFileData       = FILE_CONTROLER.getFileData;
1380                 this.getJson           = function( _data, _url, _onLoad, _onError ){
1381                         REQUEST_CONTROLER.getJson( driver, _data, _url, _onLoad, _onError );
1382                 };
1383                 this.createTree        = function( _rootFile ){
1384                         return FILE_CONTROLER.createTree( driver, _rootFile );
1385                 };
1386                 this.isTreeInstance    = function( _tree ){
1387                         return _tree instanceof TreeClass;
1388                 };
1389                 this.isFileInstance    = function( _file ){
1390                         return _file instanceof FileClass;
1391                 };
1392                 this.isFileEvent       = function( _event ){
1393                         return _event instanceof FileEventClass;
1394                 };
1395                 this.getConst          = function(){
1396                         return Const; // constObject = constObject || clone( Const )
1397                 };
1398         };
1399         
1400         return {
1401                 registerDriver: function( _class ){
1402                         _class.prototype = new FileDriverBase( _class );
1403                         var _driver = new _class();
1404                         
1405                         DRIVER_LIST.push( _driver );
1406                         API_USER_LIST.push( _class );
1407
1408                         return new FileAPIClass( _driver );
1409                 },
1410                 isDriver: function( _driver ){
1411                         return _driver instanceof FileDriverBase;
1412                 },
1413                 isTreeInstance: function( _tree ){
1414                         return _tree instanceof TreeClass;
1415                 },
1416                 isFileInstance: function( _file ){
1417                         return _file instanceof FileClass;
1418                 }
1419         }
1420 })();
1421
1422
1423 /* ----------------------------------------------------
1424  * ApplicationManager
1425  * window resize event, overlayApplication currentAplication に流す
1426  */     
1427
1428 var APPLICATION_LIST = [];
1429
1430 var ApplicationPrivateData = function(){};
1431 ApplicationPrivateData.prototype = {
1432         appClass      : null,
1433         application   : null,
1434         displayName   : null,
1435         isOverlay     : false,
1436         rootElement   : null,
1437         bgColor       : '#C1CACF',
1438         uiList        : null,
1439         formList      : null,
1440         finderList    : null,
1441         styleCursor   : null,
1442         eventRoot     : null,
1443         fetchResource : 0,
1444         bootParams    : null,
1445         phase         : 0,
1446         cursor        : '',
1447         w             : 0,
1448         h             : 0,
1449         init          : function( appClass, displayName, isOverlay ){
1450                 this.appClass    = appClass;
1451                 // this.application = app;
1452                 this.displayName = displayName;
1453                 this.isOverlay   = isOverlay;
1454                 this.rootElement = document.createElement( 'div' );
1455                 this.styleCursor = this.rootElement.style;
1456                 ApplicationPrivateData.list.push( this );
1457         },
1458         detect : function(){
1459                 if( this.rootElement.firstChild && this.fetchResource === 0 ){
1460                         SystemTimer.remove( this.application, this.detect );
1461                         this.onOpen();
1462                 };
1463         },
1464         onOpen : function(){
1465                 this.rootElement.style.display = '';
1466                 
1467                 // this.layer !== null && this.layer.onResize( this.w, this.h );
1468                 
1469                 if( this.application.MIN_WIDTH > this.w || this.application.MIN_HEIGHT > this.h ){
1470                         if( Type.isHTMLElement( this.rootElement ) === true ){
1471                                 // 小さすぎる!、と表示
1472                         };
1473                 };
1474                 if( this.bootParams.length > 2 ){
1475                         this.application.onOpen.apply( this.application, this.bootParams );
1476                 } else {
1477                         this.application.onOpen( this.w, this.h );
1478                 };
1479                 this.phase = 4; 
1480         },
1481         fetchResourceComplete : function(){
1482                 --this.fetchResource;
1483         }
1484 };
1485 ApplicationPrivateData.list = [];
1486 ApplicationPrivateData.get = function( app ){
1487         var list = ApplicationPrivateData.list,
1488                 i    = list.length;
1489         for( ; i; ){
1490                 if( app instanceof list[ --i ].appClass ) return list[ i ];
1491         };
1492         return null;
1493 };
1494
1495 var AbstractApplication = function( appClass, displayName, isOverlay ){
1496         ( new ApplicationPrivateData() ).init( appClass, displayName, isOverlay );
1497 };
1498 AbstractApplication.prototype = {
1499         getUID : function(){
1500                 var data = ApplicationPrivateData.get( this );
1501                 return Util.getIndex( API_USER_LIST, data.appClass );
1502         },
1503         init : function(){
1504                 var data = ApplicationPrivateData.get( this );
1505                 // this.rootElement = data.rootElement;
1506                 // data.application = this;
1507                 data.phase = 1;
1508                 data.appClass === Page.appClass && Page.show();
1509                 this.onInit();
1510                 data.phase = 2;
1511         },
1512         open : function( w, h /*, _option */ ){
1513                 var data = ApplicationPrivateData.get( this );
1514                 data.phase      = 3;
1515                 data.bootParams = Util.copyArray( arguments );
1516                 data.w          = w;
1517                 data.h          = h;
1518                 if( data.rootElement.innerHTML && data.rootElement.innerHTML.length > 0 ){
1519                         SystemTimer.add( this, data.detect, 16, false, data );
1520                 } else {
1521                         data.onOpen();
1522                 };
1523         },
1524         resize : function( w, h ){
1525                 var data = ApplicationPrivateData.get( this );
1526                 if( data.phase !== 4 ) return;
1527                 if( this.MIN_WIDTH > w || this.MIN_HEIGHT > h ){
1528                         if( Type.isHTMLElement( this.rootElement ) === true ){
1529                                 // 小さすぎる!、と表示
1530                         };
1531                         return;
1532                 };
1533                 this.onPaneResize( w, h );
1534         },
1535         close : function(){
1536                 var data = ApplicationPrivateData.get( this );
1537                 data.phase = 5;
1538                 if( this.onClose() === false ){
1539                         return false;
1540                 };
1541                 if( data.uiList ){ 
1542                         while( data.uiList.length > 0 ) data.uiList.shift().destroy();
1543                 };
1544                 if( data.finderList ){
1545                         while( data.finderList.length > 0 ) data.finderList.shift().destroy();
1546                 };              
1547                 
1548                 data.eventRoot && PointingDeviceEventTree.destroyTree( data.eventRoot );
1549                 MouseEvent.remove( this );
1550                 KeyEvent.remove( this );
1551                 SystemTimer.remove( this );
1552                 AsyncCall.remove( this );
1553                 StyleSheet.unload( this );
1554
1555                 var elm = this.rootElement;
1556                 Util.removeAllChildren( elm );
1557                 elm.parentNode.removeChild( elm );
1558                 
1559                 Application.shutdown( this, data.isOverlay );
1560                 
1561                 data.appClass === Page.appClass && Page.hide();
1562
1563                 data.phase = 6;
1564                 
1565                 var list = ApplicationPrivateData.list;
1566                 list.splice( Util.getIndex( list, data ), 1 );
1567         },
1568         createUIGroup : function( node ){
1569                 var data = ApplicationPrivateData.get( this ),
1570                         ui = UI.createUIGroup( this, node );
1571                 if( data.uiList === null ) data.uiList = [];
1572                 data.uiList.push( ui );
1573                 return ui;
1574         },
1575         createUIForm : function( nodeOrElm, opt_elmForm ){
1576                 var data = ApplicationPrivateData.get( this ),
1577                         form = UIForm.createForm( this, nodeOrElm, opt_elmForm );
1578                 if( data.formList === null ) data.formList = [];
1579                 data.formList.push( form );
1580                 return form;
1581         },
1582         createFinder : function( _elmTarget, _tree, _onSelect, _viewerOption, _editorOption ){
1583                 var data   = ApplicationPrivateData.get( this ),
1584                         finder = Finder.create( this, _elmTarget, _tree, _onSelect, _viewerOption, _editorOption );
1585                 if( data.finderList === null ) data.finderList = [];
1586                 data.finderList.push( finder );
1587                 return finder;
1588         },
1589         createDHTML : function( _elm ){
1590                 return DHTML.create( this, _elm );
1591         },
1592         addEventListener : function( element, eventType, handler, opt_thisObject ){
1593                 MouseEvent.add( this, element, eventType, handler, opt_thisObject );
1594         },
1595         removeEventListener : function( element, eventType, handler ){
1596                 MouseEvent.remove( this, element, eventType, handler );
1597         },
1598         getPointingDeviceEventTreeRoot : function(){
1599                 var data = ApplicationPrivateData.get( this );
1600                 if( data.phase === 1 ){
1601                         data.eventRoot   = PointingDeviceEventTree.create( this );
1602                         data.styleCursor = PointingDeviceEventTree._getNodePrivateData( data.eventRoot ).elmMouseCatch.style;
1603                 };              
1604                 return data.eventRoot;
1605         },
1606         updateCoursor : function( _cursor ){
1607                 var data = ApplicationPrivateData.get( this );
1608                 if( data.cursor !== _cursor ){
1609                         data.styleCursor.cursor = data.cursor = _cursor;
1610                 };
1611         },
1612         fetchCSS : function( url, opt_onload, opt_onerror ){
1613                 var data = ApplicationPrivateData.get( this );
1614                 if( data.phase === 1 ){
1615                         ++data.fetchResource;
1616                         StyleSheet.load( this, url, data.fetchResourceComplete, data.fetchResourceComplete, data );
1617                 };
1618         },
1619         onInit : function(){},
1620         onOpen : function(){},
1621         onClose : function(){ return true; },
1622         onPaneResize : function( w, h ){},
1623         addKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){
1624                 KeyEvent.add( this, _eventType, _handler, _keyCode, _shift, _ctrl );
1625         },
1626         removeKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){
1627                 KeyEvent.remove( this, _eventType, _handler, _keyCode, _shift, _ctrl );
1628         },
1629         shiftEnabled : function(){
1630                 return KeyEvent.shiftEnabled;
1631         },
1632         ctrlEnabled : function(){
1633                 return KeyEvent.ctrlEnabled;
1634         },
1635         addTimer : function( handler, time, once ){
1636                 SystemTimer.add( this, handler, time, !!once );
1637         },
1638         removeTimer : function( handler ){
1639                 SystemTimer.remove( this, handler );
1640         },
1641         addAsyncCall : function( _callback, _argments, _thisObject ){
1642                 AsyncCall.add( this, _callback, _argments, _thisObject );
1643         },
1644         removeAsyncCall : function( _callback ){
1645                 AsyncCall.remove( this, _callback );
1646         },
1647         fetchHTMLElement : function( id ){
1648                 var elm = document.getElementById( id );
1649                 if( elm ){
1650                         elm.removeAttribute( 'id' );
1651                         elm.parentNode.removeChild( elm );
1652                         return elm;
1653                 };
1654         }
1655 };
1656
1657 var PointingDeviceEventTree = ( function(){
1658         var ROOT_LIST       = [],
1659                 currentRootData = null,
1660                 targetNodeData  = null,
1661                 forceNodeData   = null,
1662                 hoverList       = [];
1663         
1664         function eventRellay( e ){
1665                 var data = forceNodeData, // || targetNodeData,
1666                         x    = e.clientX,
1667                         y    = e.clientY,
1668                         type = e.type,
1669                         list = hoverList,
1670                         i    = 0,
1671                         ret, systemOnly = false, addClass, removeClass,
1672                         parent;
1673                 if( data && data.dispatchEvent( e, type, true ) === true ) return false;
1674                 if( currentRootData === null ) return;
1675                 targetNodeData = currentRootData;
1676                 currentRootData._capcher( x, y );
1677                 targetNodeData.apiuser.updateCoursor( targetNodeData._cursor );
1678                 data = targetNodeData;
1679                 while( data ){
1680                         ret = data.dispatchEvent( e, type, true, systemOnly );
1681                         if( ret === true || ret === false ) break; // systemOnly = true;
1682                         data = data.parentData;
1683                 };
1684                 
1685                 addClass    = Util.addClass;
1686                 removeClass = Util.removeClass;
1687                 for( ; i < list.length; ){
1688                         parent = data = list[ i ];
1689                         while( parent.parentData && parent === parent.parentData.hitChild ){
1690                                 parent = parent.parentData;
1691                         };
1692                         if( parent !== currentRootData ){
1693                                 data.hover === true && removeClass( data.elm, data.hoverClass );
1694                                 delete data.isHover;
1695                                 data.events && data.events.mouseout && data.fire( e, 'mouseout', false );
1696                                 delete data.hitSelf;
1697                                 list.splice( i, 1 );
1698                                 continue;
1699                         };
1700                         if( data.hover === true && data.isHover === false ){
1701                                 addClass( data.elm, data.hoverClass );
1702                                 data.isHover = true;
1703                         };
1704                         if( data.hitSelf === false ){
1705                                 data.events && data.events.mouseover && data.fire( e, 'mouseover', true );
1706                                 data.hitSelf = true;
1707                         };
1708                         ++i;
1709                 };
1710                 return false;
1711         };      
1712         
1713         var NodeClass = function( apiuser, rootData, /*parentLayer,*/ parentData, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){
1714                 ( new NodePrivateData() ).init( apiuser, rootData, /*parentLayer,*/ parentData, this, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop );
1715         };
1716         NodeClass.prototype = {
1717                 createNode : function( rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ){
1718                         var data = NodePrivateData.get( this ),
1719                                 elm;
1720                         if( Type.isHTMLElement( rangeOrElmData ) === true ){
1721                                 elm = rangeOrElmData;
1722                         } else
1723                         if( Type.isString( rangeOrElmData ) === true ){
1724                                 elm = document.getElementById( rangeOrElmData );
1725                                 if( !elm ){
1726                                         elm = Util.pullHtmlAsTemplete( rangeOrElmData );
1727                                 };
1728                                 if( !elm || Type.isHTMLElement( elm ) === false || elm.nodeType !== 1 ){
1729                                         throw new Error( "invalid HTMLElement." );
1730                                 };
1731                         } else
1732                         if( Type.isObject( rangeOrElmData ) === false || Type.isFinite( rangeOrElmData.x ) === false || Type.isFinite( rangeOrElmData.y ) === false ){
1733                                 throw new Error( "No range" );
1734                         };
1735                         
1736                         if( elm && data.elm === null ){
1737                                 throw new Error( "MetaLayer don't containe HTMLElement-Layer." );
1738                         };
1739                         if( data.elm && data.elm.style.hasLayout === false ){
1740                                 throw new Error( "[ie] OffsetParent is hasLayout === false." );
1741                         };
1742                         
1743                         var newNode = new NodeClass( data.apiuser, data.rootData, data, elm || rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ),
1744                                 newData = NodePrivateData.get( newNode );
1745                         
1746                         if( data.childData === null ) data.childData = [];
1747                         data.childData.push( newData );
1748                         return newNode;
1749                 },
1750                 createNodeAt : function(){
1751                 },
1752                 remove : function(){
1753                         NodePrivateData.get( this ).remove();
1754                 },
1755                 nodeIndex : function( v ){
1756                         return NodePrivateData.get( this ).nodeIndex( v );
1757                 },
1758                 numNode : function(){
1759                         return NodePrivateData.get( this ).numNode();
1760                 },
1761                 disabled : function( v ){
1762                         return NodePrivateData.get( this ).disabled( v );
1763                 },
1764                 childrenDisabled : function( v ){
1765                         return NodePrivateData.get( this ).disabled( v );
1766                 },
1767                 mesure : function(){
1768                         NodePrivateData.get( this ).mesure();
1769                 },
1770                 mesureChildren : function(){
1771                         NodePrivateData.get( this ).mesureChildren();
1772                 },
1773                 update : function( x, y, w, h ){
1774                         NodePrivateData.get( this ).update( x, y, w, h );
1775                 },
1776                 setPosition : function( x, y ){
1777                         NodePrivateData.get( this ).setPosition( x, y );
1778                 },
1779                 setSize : function( w, h ){
1780                         NodePrivateData.get( this ).setSize( w, h );
1781                 },
1782                 cursor : function( v ){
1783                         return NodePrivateData.get( this ).cursor( v );
1784                 },
1785                 x : function( x ){
1786                         return NodePrivateData.get( this ).positionX( x );
1787                 },
1788                 y : function( y ){
1789                         return NodePrivateData.get( this ).positionY( y );
1790                 },
1791                 width : function( w ){
1792                         return NodePrivateData.get( this ).width( w );
1793                 },
1794                 height : function( h ){
1795                         return NodePrivateData.get( this ).height( h );
1796                 },
1797                 getAbsolutePositionX : function(){
1798                         return NodePrivateData.get( this ).getAbsolutePositionX();
1799                 },
1800                 getAbsolutePositionY : function(){
1801                         return NodePrivateData.get( this ).getAbsolutePositionY();
1802                 },
1803                 addEventListener : function( type, handler, opt_thisObject ){
1804                         NodePrivateData.get( this ).addEventListener( type, handler, opt_thisObject );
1805                 },
1806                 removeEventListener : function( type, handler ){
1807                         NodePrivateData.get( this ).removeEventListener( type, handler );
1808                 },
1809                 scrollTo : function( x, y ){
1810                         NodePrivateData.get( this ).scrollTo( x, y );
1811                 },
1812                 scrollX : function( v ){
1813                         return NodePrivateData.get( this ).scrollX( v );
1814                 },
1815                 scrollY : function( v ){
1816                         return NodePrivateData.get( this ).scrollY( v );
1817                 },
1818                 invalidateScrollbar : function(){
1819                         ScrollBarManager.update( NodePrivateData.get( this ) );
1820                 }
1821         };
1822
1823         /**
1824          * clip : true の場合、子ノードの変更によってヒットエリアを変化させない.elm には overflow:hidden としておくのが通常.
1825          */
1826         var NodePrivateData = function(){};
1827         NodePrivateData.prototype = {
1828                 elmMouseCatch : null, // rootData only
1829                 eventCounter  : null, // rootData only
1830                 cursorStyle   : null, // rootData only
1831                 node          : null,
1832                 apiuser       : null,
1833                 rootData      : null,
1834                 elm           : null, // resizeTarget
1835                 elmScroll     : null,
1836                 elmScroller   : null,
1837                 elmScrollbar  : null,
1838                 x             : 0,
1839                 y             : 0,
1840                 w             : 0,
1841                 h             : 0,
1842                 t             : 0, // top
1843                 l             : 0, // left
1844                 b             : 0, // bottom
1845                 r             : 0, // right
1846                 absoluteX     : 0,
1847                 absoluteY     : 0,
1848                 _scrollX      : 0,
1849                 _scrollY      : 0,
1850                 scrollingX    : 0,
1851                 scrollingY    : 0,
1852                 _cursor       : '',
1853                 // parentLayer   : null,
1854                 parentData    : null,
1855                 childData     : null,
1856                 events        : null,
1857                 hitChild      : null,
1858                 hitSelf       : false,
1859                 _disabled     : false,
1860                 _childDisabled: false,
1861                 layoutManager : null,
1862                 through       : false,
1863                 clip          : false,
1864                 hover         : false,
1865                 hoverClass    : null,
1866                 isHover       : false,
1867                 scroll        : false,
1868                 dragdrop      : false,
1869                 tooltip       : null,
1870                 init: function( apiuser, rootData, /*parentLayer,*/ parentData, node, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){
1871                         this.apiuser     = apiuser;
1872                         this.rootData    = rootData || this;
1873                         // this.parentLayer = parentLayer;
1874                         this.parentData  = parentData;
1875                         this.node        = node;
1876                         this.through     = through;
1877                         this.clip        = !!clip;
1878                         if( cursor ) this._cursor = cursor;   
1879
1880                         if( Type.isHTMLElement( rangeOrElm ) === true ){
1881                                 this.elm        = rangeOrElm;
1882                                 this.hover      = !!hover;
1883                                 this.hoverClass = hover;
1884                                 this.scroll     = clip && scroll;                               
1885                                 this.mesure();
1886                                 this.scroll === true && ScrollBarManager.register( this );
1887                         } else {
1888                                 this.update( rangeOrElm.x, rangeOrElm.y, rangeOrElm.w, rangeOrElm.h );
1889                         };
1890                         
1891                         NodePrivateData.dataList.push( this );
1892                 },
1893                 mesure : function(){
1894                         var x, y, w, h, parent, _this, _parent;
1895                         if( this.elm ){
1896                                 w = this.elm.offsetWidth;
1897                                 h = this.elm.offsetHeight;
1898                                 _this   = Position.cumulativeOffset( this.elm );
1899                                 _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ];
1900                                 x  = _this[ 0 ] - _parent[ 0 ];
1901                                 y  = _this[ 1 ] - _parent[ 1 ];                         
1902                                 if( this.x !== x || this.y !== y || this.w !== w || this.h !== h ){
1903                                         this.x = x;
1904                                         this.y = y;
1905                                         this.w = w;
1906                                         this.h = h;
1907                                         parent = this.parentData;
1908                                         parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY );
1909                                         this._updateRectangle();
1910                                 };                      
1911                         } else {
1912                                 this._updateRectangle();
1913                         };
1914                 },
1915                 mesureChildren : function(){
1916                         var nodes, i;
1917                         if( nodes = this.childData ){
1918                                 for( i = nodes.length; i; ){
1919                                         nodes[ --i ].mesure();
1920                                 };
1921                         };
1922                 },
1923                 update : function( x, y, w, h ){
1924                         var updateXY = false,
1925                                 _this, _parent,
1926                                 parent;
1927                         
1928                         if( this.elm ){
1929                                 // width
1930                                 if( Type.isFinite( w ) === true ){
1931                                         this.elm.style.width = w + 'px';
1932                                 } else
1933                                 if( Type.isString( w ) === true ){
1934                                         this.elm.style.width = w;
1935                                         w = this.elm.offsetWidth;
1936                                 };
1937                                 //update = this.w !== w;
1938         
1939                                 // height
1940                                 if( Type.isFinite( h ) === true ){
1941                                         this.elm.style.height = h + 'px';
1942                                 } else
1943                                 if( Type.isString( h ) === true ){
1944                                         this.elm.style.height = w;
1945                                         h = this.elm.offsetHeight;
1946                                 };
1947                                 //update = update || this.h !== h;
1948                                 
1949                                 // x
1950                                 if( Type.isFinite( x ) === true ){
1951                                         this.elm.style.left = x + 'px';
1952                                 } else
1953                                 if( Type.isString( x ) === true ){
1954                                         this.elm.style.left = x;
1955                                         updateXY = true;
1956                                 } else {
1957                                         updateXY = true;
1958                                 };
1959                                 
1960                                 // y
1961                                 if( Type.isFinite( y ) === true ){
1962                                         this.elm.style.top = y + 'px';
1963                                 } else
1964                                 if( Type.isString( y ) === true ){
1965                                         this.elm.style.top = y;
1966                                         updateXY = true;
1967                                 } else {
1968                                         updateXY = true;
1969                                 };
1970                                 if( updateXY === true ){
1971                                         _this   = Position.cumulativeOffset( this.elm );
1972                                         _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ];
1973                                         x       = _this[ 0 ] - _parent[ 0 ];
1974                                         y       = _this[ 1 ] - _parent[ 1 ];
1975                                 };
1976                                 //update = update || this.x !== x;
1977                                 //update = update || this.y !== y;
1978                                 
1979                                 //update === true && this._updateRectangle();
1980                                 // return;
1981                         };
1982                         x = Type.isFinite( x ) === true ? x : this.x;
1983                         y = Type.isFinite( y ) === true ? y : this.y;
1984                         w = Type.isFinite( w ) === true ? w : this.w;
1985                         h = Type.isFinite( h ) === true ? h : this.h;
1986                         if( this.x !== x || this.y !== y ){
1987                                 this.x = x;
1988                                 this.y = y;
1989                                 //console.log( 'xy  ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h + ' absX:' + this.parentData.absoluteX )
1990                                 parent = this.parentData;
1991                                 parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY );
1992                                 this.w === w && this.h === h && this._updateRectangle();
1993                         };
1994                         if( this.w !== w || this.h !== h ){
1995                                 this.w = w;
1996                                 this.h = h;
1997                                 //console.log( 'wh  ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h )
1998                                 this._updateRectangle();
1999                         };
2000                         
2001                         ScrollBarManager.update( this );
2002                 },
2003                 _updateAbsoluteXY : function( x, y, sX, sY ){
2004                         var nodes, i;
2005                         this.absoluteX = x = this.x + x;
2006                         this.absoluteY = y = this.y + y;
2007                         if( nodes = this.childData ){
2008                                 for( i = nodes.length; i; ){
2009                                         nodes[ --i ]._updateAbsoluteXY( x, y, this.scrollingX, this.scrollingY );
2010                                 };
2011                         };
2012                 },
2013                 _updateRectangle : function(){
2014                         var w = this.w,
2015                                 h = this.h,
2016                                 x = this.x,
2017                                 y = this.y,
2018                                 l = x,
2019                                 t = y,
2020                                 r = x + w,
2021                                 b = y + h,
2022                                 nodes = this.childData,
2023                                 i, node;
2024                         // self;
2025                         // childnodes
2026                         if( this.clip === false && nodes ){
2027                                 for( i = nodes.length; i; ){
2028                                         node = nodes[ --i ];
2029                                         if( node.l + x < l ) l = x + node.l;
2030                                         if( node.t + y < t ) t = y + node.t;
2031                                         if( r < node.r + x ) r = x + node.r;
2032                                         if( b < node.b + y ) b = y + node.b;
2033                                 };
2034                         };
2035                         // update
2036                         if( b !== this.b || r !== this.r || t !== this.t || l !== this.l ){
2037                                 this.l = l;
2038                                 this.t = t;
2039                                 this.r = r;
2040                                 this.b = b;
2041                                 // this.w = r - x;
2042                                 // this.h = b - y;
2043                                 this.parentData && this.parentData.clip === false && this.parentData._updateRectangle();
2044                                 return true;
2045                         };
2046                 },
2047                 setPosition : function( x, y ){
2048                         this.update( x, y );
2049                 },
2050                 setSize : function( w, h ){
2051                         this.update( undefined, undefined, w, h );
2052                 },
2053                 positionX : function( x ){
2054                         x !== undefined && this.update( x );
2055                         return this.x;
2056                 },
2057                 positionY : function( y ){
2058                         y !== undefined && this.update( undefined, y );
2059                         return this.y;
2060                 },
2061                 width : function( w ){
2062                         w !== undefined && this.update( undefined, undefined, w );
2063                         return this.w;
2064                 },
2065                 height : function( h ){
2066                         h !== undefined && this.update( undefined, undefined, undefined, h );
2067                         return this.h;
2068                 },
2069                 getAbsolutePositionX : function(){
2070                         return this.absoluteX;
2071                 },
2072                 getAbsolutePositionY : function(){
2073                         return this.absoluteY;
2074                 },
2075                 cursor : function( v ){
2076                         if( Type.isString( v ) === true ){
2077                                 this._cursor = v;
2078                                 this === targetNodeData && this.apiuser.updateCoursor( v );
2079                         };
2080                         return this._cursor;
2081                 },
2082                 addEventListener : function( eventType, handler, opt_thisObject ){
2083                         var node    = this.node,
2084                                 counter = this.rootData.eventCounter,
2085                                 list, i;
2086                         if( this.events === null ) this.events = {};
2087                         list = this.events[ eventType ];
2088                         if( !list ){
2089                                 list = this.events[ eventType ] = [];
2090                         } else {
2091                                 for( i = list.length; i; ){
2092                                         if( list[ --i ].match( eventType, handler ) === true ){
2093                                                 return;
2094                                         };
2095                                 };                              
2096                         };
2097                         list.push( new EventTicketClass( this.node, eventType, handler, opt_thisObject ) );
2098                         if( eventType !== 'mouseout' && eventType !== 'mouseover' ){
2099                                 if( counter[ eventType ] ){
2100                                         ++counter[ eventType ];
2101                                 } else {
2102                                         //console.log( eventType );
2103                                         counter[ eventType ] = 1;
2104                                         MouseEvent.add( this.apiuser, this.rootData.elmMouseCatch, eventType, eventRellay );
2105                                 };                              
2106                         };
2107                 },
2108                 removeEventListener : function( eventType, handler ){
2109                         var events  = this.events,
2110                                 counter = this.rootData.eventCounter,
2111                                 type, list, i = 0;
2112                         if( events === null ) return;
2113                         console.log( ' *** remove ' + eventType );
2114                         for( type in events ){
2115                                 list = events[ type ];
2116                                 if( eventType && eventType !== type ) continue;
2117                                 for( ; i < list.length; ){
2118                                         if( list[ i ].destroy( type, handler ) === true ){
2119                                                 console.log( ' *** removed! ' + type );
2120                                                 list.splice( i, 1 );
2121                                         } else {
2122                                                 ++i;
2123                                         };
2124                                 };
2125                                 if( list.length === 0 ){
2126                                         // delete this[ type ];
2127                                         delete events[ type ];
2128                                 };
2129                                 if( counter[ type ] ){
2130                                         --counter[ type ];
2131                                         if( counter[ type ] === 0 ){
2132                                                 MouseEvent.remove( this.apiuser, this.rootData.elmMouseCatch, type, eventRellay );
2133                                                 delete counter[ type ];
2134                                         };
2135                                 };
2136                         };
2137                 },
2138                 _capcher : function( x, y ){
2139                         var t = this, nodes, child, _x, _y, hit, i;
2140                         if( t._disabled === true ) return false;
2141                         delete t.hitChild;
2142                         x -= t.x;
2143                         y -= t.y;
2144                         if( nodes = t.childData ){
2145                                 _x = x - t.scrollingX;
2146                                 _y = y - t.scrollingY;
2147                                 for( i = nodes.length; i; ){
2148                                         child = nodes[ --i ];
2149                                         if( child._disabled === false && child.l <= _x && _x < child.r && child.t <= _y && _y < child.b && child._capcher( _x, _y ) === true ){
2150                                                 t.hitChild = child;
2151                                                 break;
2152                                         };
2153                                 };
2154                         };
2155                         if( t.through === true ){
2156                                 t.hitChild && t.hitSelf === false && hoverList.push( t );
2157                                 return !!t.hitChild;
2158                         };
2159                         hit = 0 <= x && x < t.w && 0 <= y && y < t.h;
2160                         ( t.hitChild || hit ) && t.hitSelf === false && hoverList.push( t );
2161                         if( hit === true && t.hitChild === null ) targetNodeData = t;
2162                         return hit || !!t.hitChild;
2163                 },
2164                 fire : function( e, eventType, hit ){
2165                         var list = this.events[ eventType ],
2166                                 i    = list.length;
2167                         e = NodePrivateData.createEvent( e, eventType, this, hit );
2168                         for( ; i; ) list[ --i ].fire( e );
2169                         // console.log( eventType + ' x:' + x + ' y:' + y );
2170                 },
2171                 dispatchEvent : function( e, eventType, hit ){
2172                         var ret, list, i, p, child;
2173                         if( !this.events || !( list = this.events[ eventType ] ) ) return;
2174                         
2175                         child = !!this.hitChild;
2176                         e = NodePrivateData.createEvent( e, eventType, this, hit );
2177                         for( i = list.length; i; ){
2178                                 ret = list[ --i ].fire( e );
2179                                 if( ret === true && child === false ){
2180                                         forceNodeData = this;
2181                                         return true;
2182                                 };
2183                                 if( ret === false ) return false;
2184                         };
2185                         forceNodeData  = null;
2186                 },
2187                 scrollTo : function( x, y ){
2188                         this._scrollX = x;
2189                         this._scrollY = y;
2190                         ScrollBarManager.update( this );
2191                 },
2192                 scrollX : function( v ){
2193                         if( Type.isFinite( v ) === true ){
2194                                 this._scrillX = v;
2195                                 ScrollBarManager.update( this );
2196                         };
2197                         return this.scrollingX; // this._scrollX;
2198                 },
2199                 scrollY : function( v ){
2200                         if( Type.isFinite( v ) === true ){
2201                                 this._scrillY = v;
2202                                 ScrollBarManager.update( this );
2203                         };
2204                         return this.scrollingY; // this._scrollY;
2205                 },
2206                 nodeIndex : function( v ){
2207                         var list, i;
2208                         if( !this.parentData ) return 0;
2209                         
2210                         list = this.parentData.childData;
2211                         i    = Util.getIndex( list, this );
2212                         if( Type.isFinite( v ) === false || i === v && v < 0 && list.length <= v ) return i;
2213                         
2214                         list.splice( i, 1 );
2215                         list.length === v ? list.push( this ) : list.splice( v, 0, this );
2216                         this._free();
2217                         return v;
2218                 },
2219                 _free : function(){
2220                         if( this.parentData.hitChild === this ){
2221                                 this.parentData.hitChild = null;
2222                                 this.isHover === true && hoverList.splice( Util.getIndex( hoverList, this ), 1 ) && Util.removeClass( this.elm, this.hoverClass );
2223                                 this.isHover = false;
2224                                 if( forceNodeData === this ) forceNodeData = null;
2225                                 if( targetNodeData  === this ) targetNodeData  = null;
2226                         };                      
2227                 },
2228                 numNode : function(){
2229                         return this.childData ? this.childData.length : 0;
2230                 },
2231                 disabled : function( v ){
2232                         if( Type.isBoolean( v ) === true ){
2233                                 this._disabled = v;
2234                                 if( v === false ){
2235                                         this._free();
2236                                 };
2237                         };
2238                         return this._disabled;
2239                 },
2240                 childrenDisabled : function( v ){
2241                         if( Type.isBoolean( v ) === true ){
2242                                 this._childDisabled = v;
2243                         };
2244                         return this._childDisabled;
2245                 },
2246                 remove : function(){
2247                         if( this === this.rootData ) return;
2248                         var parent = this.parentData,
2249                                 nodes  = parent.childData;
2250                         this._destroy();
2251                         if( parent.hitChild === this ) delete parent.hitChild;
2252                         nodes.splice( Util.getIndex( nodes, this ), 1 );
2253                         if( nodes.length === 0 ) delete parent.childData;       
2254                         parent.clip === false && parent._updateRectangle();
2255                 },
2256                 _destroy : function(){
2257                         var nodes = this.childData,
2258                                 list  = NodePrivateData.dataList,
2259                                 node;
2260                         this.removeEventListener();
2261                         ScrollBarManager.remove( this );
2262                         if( nodes ){
2263                                 while( node = nodes.shift() ) node._destroy();
2264                                 delete this.childData;
2265                         };
2266                         list.splice( Util.getIndex( list, this ), 1 );
2267                 }
2268         };
2269         NodePrivateData.dataList = [];
2270         NodePrivateData.get = function( node ){
2271                 // if( node instanceof NodePrivateData ) return node;
2272                 // return NodePrivateData.dataList[ layer._getUID() ];
2273                 var list = NodePrivateData.dataList;
2274                 for( var i = list.length; i; ){
2275                         if( list[ --i ].node === node ) return list[ i ];
2276                 };
2277                 return null;
2278         };
2279         NodePrivateData.createEvent = function( e, eventType, data, hit ){
2280                 var _e = {
2281                         layerX      : e.clientX - data.absoluteX,
2282                         layerY      : e.clientY - data.absoluteY,
2283                         clientX     : e.clientX,
2284                         clientY     : e.clientY,
2285                         dragOffsetX : e.dragOffsetX,
2286                         dragOffsetY : e.dragOffsetY,
2287                         dragPhase   : e.dragPhase,                                      
2288                         eventType   : eventType,
2289                         hit         : hit,
2290                         node        : data.node,
2291                         wheelDelta  : e.wheelDelta,
2292                         target      : forceNodeData ? forceNodeData.node : targetNodeData ? targetNodeData.node : null
2293                 };
2294                 return _e;
2295         };
2296         
2297         var EventTicketClass = function( node, eventType, handler, opt_thisObject ){
2298                 this.node    = node;
2299                 this.type    = eventType;
2300                 this.handler = handler;
2301                 this.thisObj = opt_thisObject || node;
2302         };
2303         EventTicketClass.prototype = {
2304                 match : function( eventType, handler ){
2305                         if( handler && this.handler !== handler ) return false;
2306                         if( eventType && this.type !== eventType ) return false;
2307                         return true;
2308                 },
2309                 destroy : function( eventType, handler ){
2310                         if( this.match( eventType, handler ) === false ) return false;
2311                         delete this.node;
2312                         delete this.type;
2313                         delete this.handler;
2314                         delete this.thisObj;
2315                         return true;
2316                 },
2317                 fire : ( function(){
2318                         if( Function.prototype.call ){
2319                                 return function( e ){
2320                                         return this.handler.call( this.thisObj, e );
2321                                 };                              
2322                         };
2323                         return function( e ){
2324                                 var ret;
2325                                 this.thisObj._currentHandler = this.handler;
2326                                 ret = this.thisObj._currentHandler( e );
2327                                 delete this.thisObj._currentHandler;
2328                                 return ret;                                     
2329                         };
2330                 })()
2331         };
2332         
2333 /*-------------------------------------
2334  *  StayHelper
2335  */
2336         var StayEventTicketClass = function( node, data, stayhandler, opt_thisObject ){
2337                 node.addEventListener( 'mouseover', this.mouseoverHandler, this );
2338                 this.node       = node;
2339                 this.data       = data;
2340                 this.handler    = stayhandler;
2341                 this.thisObject = opt_thisObject;
2342         };
2343         StayEventTicketClass.prototype = Util.extend( new EventTicketClass( null, 'mousestay' ), {
2344                 // type : 'mousestay',
2345                 e    : null,
2346                 mouseoverHandler : function( e ){
2347                         this.e = NodePrivateData.createEvent( e, this.type, this.data, true );
2348                         this.node.addEventListener( 'mouseout',  this.mousestayHandler, this );
2349                         this.node.addEventListener( 'mousemove', this.mousemoveHandler, this );
2350                         SystemTimer.add( this.data.apiuser, this.timeoutHandler, null, this );
2351                 },
2352                 timeoutHandler : function(){
2353                         this.mouseoutHandler();
2354                         return this.fire( this.e );
2355                 },
2356                 mousemoveHandler : function( e ){
2357                         this.e = NodePrivateData.createEvent( e, this.type, this.data, true );
2358                         SystemTimer.remove( this.data.apiuser, this.timeoutHandler );
2359                         SystemTimer.add( this.data.apiuser, this.timeoutHandler, null, this );
2360                 },
2361                 mouseoutHandler : function( e ){
2362                         this.node.removeEventListener( 'mouseout', this.mousestayHandler );
2363                         this.node.removeEventListener( 'mousemove', this.mousemoveHandler );
2364                         SystemTimer.remove( this.data.apiuser, this.timeoutHandler );
2365                         delete this.e;
2366                 }
2367         });
2368         
2369         var ScrollBarManager = ( function(){
2370                 var elmScroller     = document.createElement( 'div' ),
2371                         elmBar          = document.createElement( 'div' ),
2372                         smoothList      = [],
2373                         dragPhase       = 2,
2374                         dragOut         = false,
2375                         currentNodeData = null,
2376                         dragStartY      = 0,
2377                         currentEvent;
2378                 
2379                 function tick(){
2380                         var list = smoothList,
2381                                 i, data, y;
2382                         for( i = 0; i < list.length; ){
2383                                 data = list[ i ];
2384                                 if( data.scrollingY !== data._scrollY ){
2385                                         y = data.scrollingY += data.smoothY;
2386                                         if( data.smoothY < 0 ){
2387                                                 y = y < data._scrollY ? data._scrollY : y;
2388                                         } else {
2389                                                 y = data._scrollY < y ? data._scrollY : y;
2390                                         };
2391                                         data.scrollingY    = y;
2392                                         data.elm.scrollTop = -y;
2393                                         data.events && data.events.scroll && data.fire( currentEvent, 'scroll', true );
2394                                 };
2395                                 if( data.scrollingY === data._scrollY ){
2396                                         list.splice( i, 1 );
2397                                         // data.events && data.events.scroll && data.fire( currentEvent, 'scroll', true );
2398                                 } else {
2399                                         ++i;
2400                                 };
2401                         };
2402                         list.length === 0 && SystemTimer.remove( SUPER_USER_KEY, tick );
2403                         currentEvent.type = 'updateAfterScroll';
2404                         AsyncCall.add( data.apiuser, eventRellay, currentEvent ); // スクロール後の更新        
2405                 };
2406                 
2407                 function scrollReady( e ){
2408                         var data = this;
2409                         
2410                         dragOut = false;
2411                         if( data === currentNodeData || dragPhase !== 2 ) return; // Drag中の場合は 他にスクロールを作らない
2412                         currentNodeData && scrollRelease();
2413
2414                         dragPhase = 2;
2415                         data.elm.parentNode.appendChild( elmScroller );
2416                         elmScroller.appendChild( data.elm );
2417                         
2418                         elmScroller.style.cssText = 'position:absolute;left:0;top:0;';
2419                         elmScroller.appendChild( elmBar );      
2420                         
2421                         data.elm.scrollTop = -data.scrollingY;
2422                         data.rootData.addEventListener( 'mousewheel', onMouseWheelScroll, data );
2423                         data.rootData.addEventListener( 'mousedrag',  onMouseDragScroll, data );
2424                         data.addEventListener( 'mouseout',   onMouseOut, data );
2425                         currentNodeData = data;
2426                         ScrollBarManager.update( data );
2427                 };
2428                 function scrollRelease(){
2429                         var data   = currentNodeData;
2430                         var parent = elmScroller.parentNode;
2431                         parent.appendChild( currentNodeData.elm );
2432                         parent.removeChild( elmScroller );
2433                         currentNodeData.elm.scrollTop = -data.scrollingY;
2434                         
2435                         data.rootData.removeEventListener( 'mousewheel', onMouseWheelScroll, data );
2436                         data.rootData.removeEventListener( 'mousedrag',  onMouseDragScroll, data );
2437                         data.removeEventListener( 'mouseout',   onMouseOut, data );
2438                         currentNodeData = null;
2439                 };
2440                 function onMouseOut( e ){
2441                         dragOut = true;
2442                         console.log( 'mouseOut ' + dragPhase );
2443                         dragPhase === 2 && scrollRelease(); // Dragしてのアウトの場合, scroll をリリースしない
2444                 };
2445                 function onMouseWheelScroll( e ){
2446                         var data = this;
2447                         this._scrollY += e.wheelDelta;
2448                         ScrollBarManager.update( this );
2449                         currentEvent = e;
2450                         return true;
2451                 };
2452                 function onMouseDragScroll( e ){
2453                         var data = this;
2454                         //e.dragOffsetY;
2455                         currentEvent = e;
2456                         dragPhase = e.dragPhase;
2457                         switch( dragPhase ){
2458                                 case 0:
2459                                         dragStartY = this.scrollingY;
2460                                         data.rootData.removeEventListener( 'mousewheel', onMouseWheelScroll, data );
2461                                 case 1:
2462                                         this._scrollY = dragStartY + e.dragOffsetY;
2463                                         ScrollBarManager.update( this );                                
2464                                         return true;
2465                                 case 2:
2466                                         dragOut === true ? scrollRelease() : data.rootData.addEventListener( 'mousewheel', onMouseWheelScroll, data );
2467                                         return false;
2468                         };
2469                 };
2470                 
2471                 return {
2472                         register : function( data ){
2473                                 data.addEventListener( 'mouseover', scrollReady, data );
2474                         },
2475                         update : function( data ){
2476                                 // if( data !== currentNodeData ) return;
2477                                 var isCurrent = data === currentNodeData;
2478                                 
2479                                 var contentH = data._scrollH = data.elm.scrollHeight,
2480                                         clipH    = data.h,
2481                                         offsetH  = contentH - clipH,
2482                                         scrollY  = data._scrollY = 0 < data._scrollY ? 0 : ( data._scrollY < -offsetH ? -offsetH : data._scrollY ),
2483                                         barH, barY;
2484                                 if( isCurrent === true ){
2485                                         elmScroller.style.width  = data.w + 'px';
2486                                         elmScroller.style.height = clipH + 'px';                                        
2487                                 };
2488                                 
2489                                 if( offsetH < 1 ){
2490                                         data._scrollY = scrollY = 0;
2491                                         if( isCurrent === true ) elmBar.style.display = 'none';
2492                                 } else
2493                                 if( isCurrent === true ){
2494                                         barH     = Math.floor( clipH * ( clipH / contentH ) );
2495                                         barY     = Math.floor( ( clipH - barH ) * - scrollY / offsetH );
2496                                         elmBar.style.cssText = [
2497                                                 'position:absolute;',
2498                                                 'width:10px;',
2499                                                 'background-color:#333;',
2500                                                 'right:2px;',
2501                                                 'font-size:0;line-height:0;',
2502                                                 'height:', barH, 'px;',
2503                                                 'top:', data.y + barY, 'px;'
2504                                         ].join( '' );                                   
2505                                 };
2506                                 data.smoothY = ( scrollY - data.scrollingY ) / 10;
2507                                 if( data.scrollingY !== scrollY && Util.getIndex( smoothList, data ) === -1 ){
2508                                         smoothList.length === 0 && SystemTimer.add( SUPER_USER_KEY, tick, 16 );
2509                                         smoothList.push( data );
2510                                 };
2511                         },
2512                         remove : function( data ){
2513                                 var list = smoothList,
2514                                         i    = Util.getIndex( list, data );
2515                                 data === currentNodeData && scrollRelease();
2516                                 i !== -1 && list.splice( i, 1 );
2517                         }
2518                 };
2519         })();
2520         
2521         return {
2522                 create : function( apiuser ){
2523                         var     elm  = document.createElement( 'div' ),
2524                                 root, data;
2525                         body.appendChild( elm );
2526                         
2527                         root = new NodeClass( apiuser, null, null, elm );
2528                         data = NodePrivateData.get( root );
2529                         
2530                         // elm.style.cssText = 'position:absolute;top:0;left:0;height:100%;';
2531                         elm.className      = 'mouse-operation-catcher';
2532                         elm.unselectable   = 'on';
2533                         data.elmMouseCatch = elm;
2534                         
2535                         data.eventCounter  = {};
2536                         ROOT_LIST.push( data );
2537                         currentRootData    = data;
2538                         targetNodeData     = null;
2539                         forceNodeData      = null;
2540                         
2541                         MouseEvent.add( apiuser, elm, 'mousemove', eventRellay );
2542                         return root;
2543                 },
2544                 onCurrentApplicationChange : function( _application ){
2545                         currentRootData    = null;
2546                         targetNodeData     = null;
2547                         forceNodeData      = null;
2548                         for( var i = ROOT_LIST.length; i; ){
2549                                 if( ROOT_LIST[ --i ].apiuser === _application ){
2550                                         currentRootData = ROOT_LIST[ i ];
2551                                         return;
2552                                 };
2553                         };
2554                 },
2555                 destroyTree : function( root ){
2556                         var data = NodePrivateData.get( root );
2557                         MouseEvent.remove( data.apiuser, data.elmMouseCatch, 'mousemove', eventRellay );
2558                         body.removeChild( data.elmMouseCatch );
2559                         data._destroy();
2560                         ROOT_LIST.splice( Util.getIndex( ROOT_LIST, data ), 1 );
2561                         if( currentRootData === data ){
2562                                 currentRootData    = null;
2563                                 targetNodeData     = null;
2564                                 forceNodeData      = null;      
2565                         };
2566                 },
2567                 onSystemShutdown : function(){
2568                         
2569                 },
2570                 isNodeInstance : function( node ){
2571                         return node instanceof NodeClass;
2572                 },
2573                 _getNodePrivateData : function( node ){ // system only
2574                         return NodePrivateData.get( node );
2575                 }
2576         };
2577 })();
2578
2579 var Application = ( function(){
2580         
2581         var LIVE_APPLICATION_LIST = [];
2582         
2583         var currentApplication    = null,
2584                 coveredApplication    = null,
2585                 winW                  = 0,
2586                 winH                  = 0;
2587         
2588         var ApplicationReference = function( appClass, isOverlay, displayName, id, thumbnailUrl, tailColor ){
2589                 var self          = this;
2590                 var application   = null;
2591                 this.id           = id;
2592                 this.displayName  = displayName;
2593                 this.thumbnailUrl = thumbnailUrl;
2594                 this.tailColor    = tailColor;
2595                 
2596                 function asyncBoot(){
2597                         application = Application.boot( appClass, displayName, self.getUID(), isOverlay, Util.copyArray( arguments ) );
2598                 };
2599                 this.getUID = function(){
2600                         return Util.getIndex( API_USER_LIST, appClass );
2601                 };
2602                 this.getDisplayName = function(){
2603                         return this.displayName;
2604                 };
2605                 this.boot = function( /* _option */ ){
2606                         AsyncCall.add( this, asyncBoot, Util.copyArray( arguments ) );
2607                 };
2608                 this.shutdown = function(){
2609                         if( !application ) return false;
2610                         
2611                         AsyncCall.add( application, ( isOverlay === true ? Overlay.hide : application.close ) );
2612                 };
2613         };
2614         
2615         function asyncBootHome(){
2616                 currentApplication === null && Home.boot();
2617         };
2618         function asyncOpen( /* arguments */ ){
2619                 var _arg = Util.copyArray( arguments );
2620                 _arg.unshift( winW, winH );
2621                 currentApplication.open.apply( currentApplication, _arg );
2622         };
2623         return {
2624                 register: function( _class, _overlay, _tail, _displayName, _id, _thumbnailUrl, _tailColor ){
2625                         APPLICATION_LIST.push( _class );
2626                         API_USER_LIST.push( _class );
2627                         var _ref = new ApplicationReference( _class, _overlay, _displayName, _id, _thumbnailUrl, _tailColor );
2628                         _tail === true && Home.add( _ref );
2629                         return _ref;
2630                 },
2631                 isApplicationInstance: function( app ){
2632                         return ApplicationPrivateData.get( app ) !== null;
2633                 },
2634                 isApplicationReference: function( _reference ){
2635                         return _reference instanceof ApplicationReference;
2636                 },
2637                 isCurrentAppplication: function( app ){
2638                         return app === currentApplication;
2639                 },
2640                 boot: function( appClass, displayName, uid, isOverlay, arg ){
2641                         if( currentApplication ){
2642                                 if( currentApplication.getUID() === uid ) return null;
2643                                 if( isOverlay === false && currentApplication.close() === false ) return null;
2644                         };
2645
2646                         appClass.prototype = new AbstractApplication( appClass, displayName, isOverlay );
2647                         
2648                         var application = new appClass(),
2649                                 data = ApplicationPrivateData.get( application );
2650                         
2651                         application.rootElement = data.rootElement;
2652                         data.application = application;
2653                         
2654                         coveredApplication = isOverlay === true ? currentApplication : null;
2655                         
2656                         Application.onCurrentApplicationChange( application );
2657                         
2658                         if( isOverlay === false ){
2659                                 body.style.backgroundColor = application.bgColor;
2660                                 
2661                                 body.appendChild( data.rootElement );
2662                                 data.rootElement.style.display = 'none';
2663                                 application.init();
2664
2665                                 application.addAsyncCall( asyncOpen, arg );
2666                         } else {
2667                                 Overlay.show( application, arg );
2668                         };
2669                         
2670                         return application;
2671                 },
2672                 shutdown: function( _application, isOverlay ){
2673                         if( isOverlay === false ){
2674                                 currentApplication = null;
2675                                 AsyncCall.add( SUPER_USER_KEY, asyncBootHome );
2676                         } else {
2677                                 Application.onCurrentApplicationChange( coveredApplication );
2678                                 coveredApplication = null;
2679                         };
2680                 },
2681                 onCurrentApplicationChange: function( _application ){
2682                         if( Application.isApplicationInstance( _application ) === false ) return;
2683                         if( currentApplication === _application ) return;
2684                         currentApplication = _application;
2685                         MouseEvent.onCurrentApplicationChange( _application );
2686                         PointingDeviceEventTree.onCurrentApplicationChange( _application );
2687                         KeyEvent.updateCurrentListener( _application );
2688                         // InteractiveLayer.onCurrentApplicationChange( _application );
2689                 },
2690                 onApplicationShutdown: function( _application ){
2691                         LIVE_APPLICATION_LIST.splice( Util.getIndex(  LIVE_APPLICATION_LIST, _application ) );
2692                 },
2693                 onWindowResize: function( w, h ){
2694                         winW = w;
2695                         winH = h;
2696                         currentApplication && currentApplication.resize( w, h );
2697                         Overlay.onWindowResize( w, h );
2698                         UI.onWindowResize( w, h );
2699                 },
2700                 onSystemShutdown: function(){
2701                         
2702                 }
2703         }
2704 })();
2705
2706 /* --------------------------------------------------------------
2707  * Home
2708  * 
2709  */
2710         var Home = ( function(){
2711                 var APP_REF_LIST    = [];
2712                 var ELM_TAIL_ORIGIN = ( function(){
2713                         var ret = document.createElement( 'div' ),
2714                                 h2  = document.createElement( 'h2' );
2715                         ret.className = 'tail-wrapper';
2716                         ret.appendChild( h2 );
2717                         h2.appendChild( document.createTextNode( 'appName' ) );
2718                         return ret;
2719                 })();
2720                 
2721                 var TailClass = function( appRef ){
2722                         this.elm = ELM_TAIL_ORIGIN.cloneNode( true );
2723                         this.destroy = function(){
2724                                 appRef = self = elmName = null;
2725                         };                      
2726                         
2727                         var self    = this,
2728                                 elmName = this.elm.getElementsByTagName( 'h2' )[ 0 ].firstChild;
2729                         
2730                         this.elm.style.backgroundColor = appRef.tailColor;
2731                         elmName.data = appRef.displayName;
2732                 };
2733                 
2734                 var ref = Application.register( function(){
2735                         var self     = this,
2736                                 winW     = 0,
2737                                 winH     = 0,
2738                                 tailList = [],
2739                                 elmContainer, elmHeader;
2740                         
2741                         function draw(){
2742                                 var tail, elm;
2743                                 for( var i=0, l=APP_REF_LIST.length; i<l; ++i ){
2744                                         tail = new TailClass( APP_REF_LIST[ i ] );
2745                                         tailList.push( tail );
2746                                         elm  = tail.elm;
2747                                         elmContainer.appendChild( elm );
2748                                         self.addEventListener( elm, 'click', onTailClick );
2749                                 };
2750                         };
2751                         
2752                         function onTailClick( e ){
2753                                 var _children = elmContainer.getElementsByTagName( 'div' );
2754                                 for( var i=0, l=_children.length; i<l; ++i ){
2755                                         if( this === _children[ i ] ){
2756                                                 APP_REF_LIST[ i ].boot();
2757                                                 break;
2758                                         };
2759                                 };
2760                         };
2761                         
2762                         this.bgColor     = '#0F6D39';
2763                         this.MIN_WIDTH   = 320;
2764                         this.MIN_HEIGHT  = 320;
2765                         this.onInit = function(){
2766                                 self.rootElement.id = 'home-root';
2767                                 
2768                                 elmContainer        = document.createElement( 'div' );
2769                                 self.rootElement.appendChild( elmContainer );
2770                                 elmContainer.id     = 'home-tail-container';
2771                                 
2772                                 elmHeader           = document.createElement( 'div' );
2773                                 self.rootElement.appendChild( elmHeader );
2774                                 elmHeader.id        = 'home-header';
2775                         };
2776                         this.onOpen = function( _w, _h ){
2777                                 winW = _w;
2778                                 winH = _h;
2779                                 draw();
2780                         };
2781                         this.onPaneResize = function( _w, _h ){
2782                                 
2783                         };
2784                         this.onClose = function(){
2785                                 self.removeEventListener();
2786                                 while( tailList.length > 0 ){
2787                                         tailList.shift().destroy();
2788                                 }
2789                                 self = tailList = elmContainer = null;
2790                         };
2791                 }, false, false, 'home', 'home', null );
2792                 
2793                 return {
2794                         add: function( _appRef ){
2795                                 if( Application.isApplicationReference( _appRef ) === false ) return;
2796                                 Util.getIndex( APP_REF_LIST, _appRef ) === -1 && APP_REF_LIST.push( _appRef );
2797                         },
2798                         boot: function(){
2799                                 ref.boot();
2800                         }
2801                 }
2802         })();
2803
2804         var Page = ( function(){
2805                 var pageNodes = [],
2806                         appClass, ref,
2807                         ignoreTagList = [ 'script', 'noscript', 'style' ];
2808                 
2809                 var MemoryClass = function( node ){
2810                         this.node = node;
2811                 };
2812                 MemoryClass.prototype = {
2813                         init: function(){
2814                                 var node      = this.node,
2815                                         _nodeType = node.nodeType;
2816                                 if( _nodeType === 1 && Util.getIndex( ignoreTagList, node.tagName.toLowerCase() ) === -1 ){
2817                                         this.type    = _nodeType;
2818                                         this.display = node.style.display;
2819                                 } else
2820                                 if( _nodeType === 3 ){
2821                                         if( node.data.replace( /\s/g, '' ).length !== 0 ){
2822                                                 this.type    = _nodeType;
2823                                                 this.before  = pageNodes.length === 0 ? null : pageNodes[ pageNodes.length - 1 ].node;
2824                                         } else {
2825                                                 body.removeChild( node );
2826                                                 return false;
2827                                         }
2828                                 } else {
2829                                         // body.removeChild( node );
2830                                         return false;
2831                                 };
2832                         },
2833                         show: function(){
2834                                 if( this.type === 1 ){
2835                                         if( this.display ){
2836                                                 this.node.style.display = this.display;
2837                                         } else {
2838                                                 this.node.style.display = '';
2839                                         }
2840                                 } else {
2841                                         if( this.before ){
2842                                                 body.insertBefore( this.node, this.before );
2843                                         } else {
2844                                                 body.appendChild( this.node );
2845                                         };
2846                                 };
2847                         },
2848                         hide: function(){
2849                                 if( !this.node.parentNode ){
2850                                         return;
2851                                 };
2852                                 if( this.type === 1 ){
2853                                         this.node.style.display = 'none';
2854                                 } else {
2855                                         body.removeChild( this.node );
2856                                 };
2857                         }
2858                 };
2859                 
2860                 return {
2861                         onReady: function(){
2862                                 var _children = Util.copyArray( body.childNodes ),
2863                                         _mem;
2864                                 for( var i = 0, l = _children.length; i<l; ++i ){
2865                                         _mem = new MemoryClass( _children[ i ] );
2866                                         _mem.init() !== false && pageNodes.push( _mem );
2867                                 };
2868                                 if( pageNodes.length !== 0 ){
2869                                         if( Type.isFunction( gOS.PageApplicationClass ) === true ){
2870                                                 Page.appClass = gOS.PageApplicationClass;
2871                                                 Page.appClass.bgColor    = Page.appClass.bgColor;
2872                                                 Page.appClass.MIN_WIDTH  = Page.appClass.MIN_WIDTH  || 240;
2873                                                 Page.appClass.MIN_HEIGHT = Page.appClass.MIN_HEIGHT || 240;
2874                                         } else {
2875                                                 Page.appClass = function(){
2876                                                         var self     = this;
2877                                                         
2878                                                         this.bgColor      = '#ffffff';
2879                                                         this.MIN_WIDTH    = 200;
2880                                                         this.MIN_HEIGHT   = 200;
2881                                                         this.onInit       = function(){};
2882                                                         this.onOpen       = function( _w, _h ){
2883                                                                 KeyEvent.add( self, Const.KEY.EVENT.KEY_DOWN, ref.shutdown, 27 ); // 27.esc
2884                                                         };
2885                                                         this.onPaneResize = function( _w, _h ){};
2886                                                         this.onClose      = function(){};
2887                                                 };
2888                                         };
2889                                         ref = Application.register( Page.appClass, false, true, document.title, 'page', null, Page.appClass.tailColor || '#999999' );
2890                                         if( Type.isFunction( gOS.PageApplicationClass ) === true ){
2891                                                 gOS.PageApplicationRef = ref;
2892                                         }; 
2893                                 };
2894                                 delete Page.onReady;
2895                         },
2896                         show: function(){
2897                                 for( var i = pageNodes.length; i; ){
2898                                         pageNodes[ --i ].show();
2899                                 };
2900                         },
2901                         hide: function(){
2902                                 for( var i = pageNodes.length; i; ){
2903                                         pageNodes[ --i ].hide();
2904                                 };                              
2905                         },
2906                         boot: function(){
2907                                 ref && ref.boot();
2908                         },
2909                         registered: function(){
2910                                 return !!ref;
2911                         },
2912                         appClass: null
2913                 }
2914         })();
2915
2916 /* --------------------------------------------------------------
2917  * Event
2918  * 
2919  *  screenX
2920  *  スクリーン座標は、コンピュータのディスプレイの左上を原点とする座標系である。screenX, screenY属性で取得できる。Javascritpでは、同名のプロパティとして実装されている。
2921  *  しかし、これは、現実的には、何の役に立たない。ブラウザ自体がディスプレイのどの位置にいるのかがわからないので、画面上の位置を知ったところで、何にもならないからだ。 
2922  * 
2923  *  clientX
2924  *  ウインドウ座標とは、現在のブラウザのウインドウの、ドキュメントを表示している部分の左上原点とした座標である。
2925  *  問題は、ウインドウは、必ずしもドキュメント全体を表示するとは限らない。スクロールと呼ばれるUIによって、ドキュメントの一部だけを表示しているかもしれない。
2926  */
2927         var XBrowserEvent = ( function(){
2928                 var wrappedHandlerClass,
2929                         wrappedEventClass,
2930                         tmp;
2931                 
2932                 if( window.addEventListener ){
2933                         wrappedHandlerClass = function( ticket ){
2934                                 this.handler = function( e ){
2935                                         if( ticket.fire( e ) !== false ) return;
2936                                         e.preventDefault();
2937                                         e.stopPropagation();
2938                                         return false;
2939                                 };
2940                                 this.destroy = function(){
2941                                         ticket = null;
2942                                         delete this.handler;
2943                                         delete this.destroy;
2944                                 };
2945                         };
2946                 } else {
2947                         wrappedEventClass = function( e, element ){
2948                                 this._event        = e;
2949                                 this.type          = e.type;
2950                                 this.target        = e.srcElement;
2951                                 this.currentTarget = element;
2952                                 this.relatedTarget = e.formElement ? e.formElement : e.toElement;
2953                                 this.eventPhase    = e.srcElement === element ? 2: 3;
2954                                 
2955                                 this.clientX       = e.clientX;
2956                                 this.clientY       = e.clientY;
2957                                 this.screenX       = e.screenX;
2958                                 this.screenY       = e.screenY;
2959                                 
2960                                 this.keyCode       = e.keyCode;
2961                                 this.altKey        = e.altKey;
2962                                 this.ctrlKey       = e.ctrlKey;
2963                                 this.shiftKey      = e.shiftKey;
2964                                 
2965                                 this.wheelDelta    = e.wheelDelta;
2966                         };
2967                         wrappedEventClass.prototype.stopPropagation = function(){
2968                                 this._event.cancelBubble = true;
2969                         };
2970                         wrappedEventClass.prototype.preventDefault  = function(){
2971                                 this._event.returnValue = false;
2972                         };
2973
2974                         if( document.attachEvent ){
2975                                 wrappedHandlerClass = function( ticket ){
2976                                         this.handler = function(){
2977                                                 if( ticket === null ) alert( window.event.type )
2978                                                 if( ticket.fire( new wrappedEventClass( window.event, ticket.element ) ) !== false ) return;
2979                                                 // e.preventDefault();
2980                                                 // e.stopPropagation();
2981                                                 window.event.cancelBubble = true;
2982                                                 window.event.returnValue  = false;
2983                                                 return false;
2984                                         };
2985                                         this.destroy = function(){
2986                                                 ticket = null;
2987                                                 delete this.handler;
2988                                                 delete this.destroy;
2989                                         };
2990                                 };
2991                         } else {
2992                                 tmp = {
2993                                         list: [],
2994                                         find: function( _ticket ){
2995                                                 for( var i=0, l= tmp.list.length, _item; i<l; ++i ){
2996                                                         _item = tmp.list[ i ];
2997                                                         if( _item.element === _ticket.element && _item.eventType === _ticket.eventType ){
2998                                                                 return _item;
2999                                                         };
3000                                                 };
3001                                                 return null;
3002                                         }
3003                                 };
3004                                 tmp.TicketClass = function( _ticket ){
3005                                         var self = this;
3006                                         this.element   = _ticket.element;
3007                                         this.eventType = _ticket.eventType;
3008                                         this.tickets   = [ _ticket ];
3009                                         this.onDestroy = function(){ self = null; };
3010                                         
3011                                         this.element[ 'on' + this.eventType ] = function( e ){ return self.fire( e );};
3012                                         _ticket = null;
3013                                 };
3014                                 tmp.TicketClass.prototype = {
3015                                         add: function( _ticket ){
3016                                                 Util.getIndex( this.tickets, ticket ) === -1 && this.tickets.push( _ticket );
3017                                         },
3018                                         remove: function( _ticket ){
3019                                                 var i = Util.getIndex( this.tickets, _ticket );
3020                                                 i !== -1 && this.tickets.splice( i, 1 );
3021                                                 this.tickets.length === 0 && this.destroy();
3022                                         },
3023                                         fire: function( e ){
3024                                                 e = e || new wrappedEventClass( window.event, this.element );
3025                                                 var i = this.tickets.length,
3026                                                         cancel;
3027                                                 for( ; i; ){
3028                                                         if( this.tickets[ --i ].fire( e ) === false ) cancel = false;
3029                                                 };
3030                                                 return cancel;
3031                                         },
3032                                         destroy: function(){
3033                                                 this.onDestroy();
3034                                                 this.element[ 'on' + this.eventType ] = '';
3035                                                 tmp.list.splice( Util.getIndex( tmp.list, this ), 1 );
3036                                                 delete this.element;
3037                                                 delete this.eventType;
3038                                                 delete this.tickets;
3039                                                 delete this.onDestroy;
3040                                         }
3041                                 };
3042                         };
3043                 };
3044
3045                 return {
3046                         add: function( _ticket ){
3047                                 if( document.addEventListener ){
3048                                         XBrowserEvent.add = function( _ticket ){
3049                                                 _ticket.wrappedHandler = new wrappedHandlerClass( _ticket );
3050                                                 _ticket.element.addEventListener( _ticket.eventType, _ticket.wrappedHandler.handler, false );
3051                                         };
3052                                 } else
3053                                 if( document.attachEvent ){
3054                                         XBrowserEvent.add = function( _ticket ){
3055                                                 _ticket.wrappedHandler = new wrappedHandlerClass( _ticket );
3056                                                 _ticket.element.attachEvent( 'on' + _ticket.eventType, _ticket.wrappedHandler.handler );
3057                                         };
3058                                 } else {
3059                                         XBrowserEvent.add = function( _ticket ){
3060                                                 var t = tmp.find( _ticket );
3061                                                 if( t !== null ){
3062                                                         t.add( _ticket );
3063                                                 } else {
3064                                                         tmp.list.push( new tmp.TicketClass( _ticket ) );
3065                                                 };
3066                                         };
3067                                 };
3068                                 
3069                                 XBrowserEvent.add( _ticket );
3070                         },
3071                         remove: function( _ticket ){
3072                                 if( document.removeEventListener ){
3073                                         XBrowserEvent.remove = function( _ticket ){
3074                                                 _ticket.element.removeEventListener( _ticket.eventType, _ticket.wrappedHandler.handler, false );
3075                                                 _ticket.wrappedHandler.destroy();
3076                                         };
3077                                 } else
3078                                 if( document.detachEvent ){
3079                                         XBrowserEvent.remove = function( _ticket ){
3080                                                 _ticket.element.detachEvent( 'on' + _ticket.eventType, _ticket.wrappedHandler.handler );
3081                                                 _ticket.wrappedHandler.destroy();
3082                                         };
3083                                 } else {
3084                                         XBrowserEvent.remove = function( _ticket ){
3085                                                 var t = tmp.find( _ticket );
3086                                                 if( t !== null ){
3087                                                         t.remove( _ticket );
3088                                                 };
3089                                         };
3090                                 };
3091                                 
3092                                 XBrowserEvent.remove( _ticket );
3093                         }
3094                 }
3095         })();
3096
3097 /*
3098  * EventTicketClass
3099  */
3100         var EventTicketClass = function( _element, _eventType, _handler, opt_thisObject ){
3101                 this.element        = _element;
3102                 this.eventType      = _eventType;
3103                 this.handler        = _handler;
3104                 this.wrappedHandler = null;
3105                 this.thisObject     = opt_thisObject;
3106                 XBrowserEvent.add( this );
3107         };
3108         EventTicketClass.prototype = {
3109                 fire : ( function(){
3110                         if( Function.prototype.call ){
3111                                 return function( e ){
3112                                         return this.handler.call( this.thisObject || this.element, e );
3113                                 };                              
3114                         };
3115                         return function( e ){
3116                                 var thisObj = this.thisObject || this.element,
3117                                         ret;
3118                                 thisObj._currentHandler = this.handler;
3119                                 ret = thisObj._currentHandler( e );
3120                                 delete thisObj._currentHandler;
3121                                 return ret;                                     
3122                         };
3123                 })(),
3124                 match: function( _element, _eventType, _handler ){
3125                         if( _handler   && _handler   !== this.handler )   return false;
3126                         if( _eventType && _eventType !== this.eventType ) return false;
3127                         if( _element   && _element   !== this.element )   return false;
3128                         
3129                         return true;
3130                 },
3131                 destroy: function( _element, _eventType, _handler ){
3132                         if( this.match( _element, _eventType, _handler ) === false ) return false;
3133                         
3134                         XBrowserEvent.remove( this );
3135                         
3136                         delete this.element;
3137                         delete this.eventType;
3138                         delete this.handler;
3139                         delete this.wrappedHandler;
3140                         delete this.thisObject;
3141                         return true;
3142                 }
3143         };
3144
3145 var ReadyEvent = ( function(){
3146         var ticketReady,
3147                 ticketLoad;
3148
3149         function webkitDetect(){
3150                 var state = document.readyState;
3151                 if( state === 'loaded' || state === 'complete' ){
3152                         SystemTimer.remove( SUPER_USER_KEY, webkitDetect );
3153                         timer = null;
3154                         onReady();
3155                 };
3156         };
3157         function ieDetect(){
3158                 if( this.readyState === 'complete' ){ // this.readyState === 'loaded' || 
3159                         this.onreadystatechange = new Function();
3160                         this.onreadystatechange = null;
3161                         AsyncCall.remove( SUPER_USER_KEY, ieScroll );
3162                         onReady();
3163                 };
3164         };
3165         function ieScroll(){
3166                 try {
3167                         document.documentElement.doScroll( 'left' );
3168                 } catch( e ){
3169                         AsyncCall.add( SUPER_USER_KEY, ieScroll );
3170                         return;
3171                 };
3172                 // no errors, fire
3173                 document.onreadystatechange = new Function();
3174                 document.onreadystatechange = null;
3175                 onReady();              
3176         };
3177                 
3178         function onReady(){
3179                 ticketReady && ticketReady.destroy();
3180                 ticketLoad  && ticketLoad.destroy();
3181                 ticketReady = ticketLoad = null;
3182                 Page.onReady();
3183                 if( Page.registered() === true ){
3184                         Page.boot();
3185                 } else {
3186                         Home.boot();
3187                 };
3188         };
3189         
3190         // Apple WebKit (Safari, OmniWeb, ...)
3191         if( document.readyState && !!UA.WEBKIT ){
3192                 SystemTimer.add( SUPER_USER_KEY, webkitDetect, 50 );
3193         /* } else
3194                 if( document.readyState && UA.isIE && UA.ieVersion < 9 ){
3195                 ieScroll();
3196                 document.onreadystatechange = ieDetect; */
3197         } else {
3198                 ticketReady = new EventTicketClass( document, 'DOMContentLoaded', onReady );
3199                 ticketLoad  = new EventTicketClass( window, 'load', onReady );
3200         };
3201 })();
3202
3203
3204
3205
3206 /* =====================================================
3207  *  ResizeEvent
3208  * 
3209  */
3210
3211 var ResizeEvent = ( function(){
3212         var _globalLock = 0;
3213         var _resize;
3214         var root = window;
3215         var w = 0, h = 0;
3216         
3217         function getInnerSize(){
3218                 return {
3219                         w : root.innerWidth || root.clientWidth,
3220                         h : root.innerHeight || root.clientHeight
3221                 };
3222         }
3223         function unlock(){
3224                 _globalLock = 0;
3225         }
3226         
3227         if( document.uniqueID ){
3228                 _resize = function(){
3229                         root = (document.compatMode || "") !== "CSS1Compat" ? document.body : document.documentElement;
3230
3231                         // resize agent
3232                         function loop(){
3233                                 if( !_globalLock++ ){
3234                                         var size = getInnerSize();
3235                                         if( w !== size.w || h !== size.h ){// resized
3236                                                 w = size.w;
3237                                                 h = size.h;
3238                                                 // update
3239                                                 Application.onWindowResize( w, h );
3240                                         }
3241                                         window.setTimeout( unlock, 0 );
3242                                         // delay unlock
3243                                 }
3244                                 window.setTimeout( loop, 100 );
3245                         }
3246                         loop();
3247                 };
3248         } else {
3249                 _resize = function(){
3250                         new EventTicketClass( window, 'resize', onResize );
3251                         
3252                         function onResize(){
3253                                 if( !_globalLock++ ) {
3254                                         var size = getInnerSize();
3255                                         if( w !== size.w || h !== size.h ){// resized
3256                                                 w = size.w;
3257                                                 h = size.h;
3258                                                 // update
3259                                                 Application.onWindowResize( w, h );
3260                                         }
3261                                         window.setTimeout( unlock, 0 );
3262                                 }
3263                         }
3264                         onResize();
3265                 };
3266         }
3267         AsyncCall.add( SUPER_USER_KEY, _resize );
3268         
3269         return {
3270                 getSize: getInnerSize,
3271                 onSystemShutdown: function(){
3272                         
3273                 }
3274         }
3275 })();
3276
3277
3278 /* =====================================================
3279  *  MouseEvent
3280  * 
3281  */
3282         var MouseEvent = ( function(){
3283                 var CLICK_OFFSET   = 2 * 2,
3284                         DRAG_OFFSET    = 4 * 4;         
3285                 
3286                 var EVENT_LIST_MAP = [],
3287                         TMP = {},
3288                         currentEventList;
3289         /*-------------------------------------
3290          * ClickHelper
3291          * mousedown, mouseup, の移動距離を調べて clickハンドラ を呼ぶ
3292          */
3293                 var ClickEventTicketClass = function( element, clickhandler, opt_thisObject ){
3294                         this.mousedownTicket = new EventTicketClass( element, 'mousedown', this.mousedownHandler, this );
3295                         this.element         = element;
3296                         this.handler         = clickhandler;
3297                         this.thisObject      = opt_thisObject;
3298                 };
3299                 ClickEventTicketClass.prototype = {
3300                         element          : null,
3301                         handler          : null,
3302                         thisObject       : null,
3303                         startX           : 0,
3304                         startY           : 0,
3305                         mousedownTicket  : null,
3306                         mousemoveTicket  : null,
3307                         mouseupTicket    : null,
3308                         mouseoutTicket   : null,
3309                         eventType        : 'click',
3310                         fire             : EventTicketClass.prototype.fire,
3311                         match            : EventTicketClass.prototype.match,
3312                         mousedownHandler : function( e ){
3313                                 this.startX = e.clientX;
3314                                 this.startY = e.clientY;
3315                                 
3316                                 this.mousemoveTicket = new EventTicketClass( this.element, 'mousemove', this.mousemoveHandler, this );
3317                                 this.mouseupTicket   = new EventTicketClass( this.element, 'mouseup',   this.mouseupHandler,   this );
3318                                 this.mouseoutTicket  = new EventTicketClass( this.element, 'mouseout',  this.mouseoutHandler,  this );
3319                                 return false;                   
3320                         },
3321                         mousemoveHandler : function( e ){
3322                                 var offsetX = e.clientX - this.startX,
3323                                         offsetY = e.clientY - this.startY;                              
3324                                 offsetX * offsetX + offsetY * offsetY >= CLICK_OFFSET && this.mouseoutHandler();
3325                                 return false;
3326                         },
3327                         mouseupHandler : function( e ){
3328                                 this.mouseoutHandler();
3329                                 return this.fire( ClickEventTicketClass.createEvent( e ) );
3330                         },
3331                         mouseoutHandler : function( e ){
3332                                 this.mousemoveTicket && this.mousemoveTicket.destroy();
3333                                 this.mouseupTicket   && this.mouseupTicket.destroy();
3334                                 this.mouseoutTicket  && this.mouseoutTicket.destroy();
3335                                 if( this.mousemoveTicket ) delete this.mousemoveTicket;
3336                                 if( this.mouseupTicket  )  delete this.mouseupTicket;
3337                                 if( this.mouseoutTicket )  delete this.mouseoutTicket;
3338                                 return false;
3339                         },
3340                         destroy : function( _element, _eventType, _handler ){
3341                                 if( this.match( _element, _eventType, _handler ) === false ) return false;
3342                                 
3343                                 this.mouseoutHandler();
3344                                 this.mousedownTicket.destroy();
3345
3346                                 delete this.element;
3347                                 delete this.handler;
3348                                 delete this.thisObject;
3349                                 delete this.mousedownTicket;    
3350                                 return true;
3351                         }
3352                 };
3353                 if( document.createEvent ){
3354                         ClickEventTicketClass.createEvent = function( e ){
3355                                 var _e = document.createEvent( 'MouseEvents' );
3356                                 _e.initMouseEvent(
3357                                         'click' , false, true, e.view, 
3358                                         e.detail, e.screenX, e.screenY, e.clientX, e.clientY, 
3359                                         e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 
3360                                         e.button, e.relatedTarget
3361                                 );
3362                                 return _e;
3363                         };                                      
3364                 } else
3365                 if( document.attachEvent ){
3366                         ClickEventTicketClass.createEvent = function( e ){
3367                                 e.type = 'click';
3368                                 return e;
3369                         };
3370                 } else {
3371                         
3372                 };
3373                 
3374         /*-------------------------------------
3375          *  WheelHelper
3376          */
3377                 var WheelEventTicketClass = ( function(){
3378                         if( UA.GECKO ){
3379                                 return function( element, wheelhandler, opt_thisObject ){
3380                                         this.wheelTicket = new EventTicketClass( element, 'DOMMouseScroll', this.onGeckoWheel, this );
3381                                         this.element     = element;
3382                                         this.handler     = wheelhandler;
3383                                         this.thisObject  = opt_thisObject;
3384                                 };
3385                         } else
3386                         if( true || UA.isIE ){
3387                                 return function( element, wheelhandler, opt_thisObject ){
3388                                         this.wheelTicket = new EventTicketClass( element, this.eventType, wheelhandler );
3389                                         this.element     = element;
3390                                         this.handler     = wheelhandler;
3391                                         this.thisObject  = opt_thisObject;
3392                                 };
3393                         } else {
3394                                 TMP.wheelHandlerList = [];
3395                                 TMP.wheelThisObjList = [];
3396                                 //TMP.wheelLegacy = undefined;
3397                                 TMP.onWheel   = function( e ){
3398                                         e = e || window.event;
3399                                         var cancel = true,
3400                                                 f = TMP.wheelLegacy;
3401                                         if( f ) cancel = f.call( this, e );
3402                                         
3403                                         for( i = TMP.wheelHandlerList.length; i; ){
3404                                                 if( TMP.wheelHandlerList[ --i ].call( TMP.wheelThisObjList[ i ] || this, e ) === false ) cancel = false;
3405                                         };
3406                                         return cancel;
3407                                 };
3408                                 return function( element, wheelhandler, opt_thisObject ){
3409                                         this.element     = element;
3410                                         this.handler     = wheelhandler;
3411                                         this.thisObject  = opt_thisObject;
3412                                         
3413                                         if( TMP.wheelHandlerList.length === 0 ){
3414                                                 //TMP.wheelLegacy     = Type.isFunction( window.onmousewheel ) === true ? window.onmousewheel : undefined;
3415                                                 element.onmousewheel = TMP.onWheel;
3416                                         };
3417                                         TMP.wheelHandlerList.push( wheelhandler );
3418                                         TMP.wheelThisObjList.push( opt_thisObject )
3419                                 };
3420                         };
3421                 })();
3422                 WheelEventTicketClass.prototype = {
3423                         eventType : 'mousewheel',
3424                         match     : EventTicketClass.prototype.match,
3425                         destroy   : function( _element, _eventType, _handler ){
3426                                 if( this.match( _element, _eventType, _handler ) === false ) return false;
3427                                 
3428                                 this.wheelTicket && this.wheelTicket.destroy();
3429                                 
3430                                 delete this.wheelTicket;
3431                                 delete this.element;
3432                                 delete this.handler;
3433                                 delete this.thisObject;
3434                                 
3435                                 this.onDestroy && this.onDestroy();
3436                                 return true;
3437                         }
3438                 };
3439                 if( UA.GECKO ){
3440                         WheelEventTicketClass.prototype.onGeckoWheel = function( e ){
3441                                 var _e = document.createEvent( 'MouseEvents' );
3442                                 _e.initMouseEvent(
3443                                         'mousewheel' , false, true, e.view, 
3444                                         e.detail, e.screenX, e.screenY, e.clientX, e.clientY, 
3445                                         e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 
3446                                         e.button, e.relatedTarget
3447                                 );
3448                                 _e.wheelDelta = e.detail * -40;
3449                                 return this.handler.call( this.thisObject || this.element, _e );
3450                         };
3451                 } else
3452                 if( true || UA.isIE ){
3453
3454                 } else {
3455                         WheelEventTicketClass.prototype.onDestroy = function(){
3456                                 TMP.wheelHandlerList.splice( Util.getIndex( TMP.wheelHandlerList, this.handler ), 1 );
3457                                 TMP.wheelThisObjList.splice( Util.getIndex( TMP.wheelThisObjList, this.handler ), 1 );
3458                                 if( TMP.wheelHandlerList.length === 0 ) this.element.onmousewheel = '';
3459                         };                      
3460                 };
3461                 
3462         /*-------------------------------------
3463          *  DragHelper
3464          */
3465                 var DragEventTicketClass = function( element, draghandler, opt_thisObject ){
3466                         this.mousedownTicket = new EventTicketClass( element, 'mousedown', this.mousedownHandler, this );
3467                         this.element         = element;
3468                         this.handler         = draghandler;
3469                         this.thisObject      = opt_thisObject;
3470                 };
3471                 DragEventTicketClass.prototype = {
3472                         element         : null,
3473                         handler         : null,
3474                         thisObject      : null,
3475                         startX          : 0,
3476                         startY          : 0,
3477                         dragging        : false,
3478                         mousedownTicket : null,
3479                         mousemoveTicket : null,
3480                         mouseupTicket   : null,
3481                         mouseoutTicket  : null,
3482                         eventType       : 'mousedrag',
3483                         fire            : EventTicketClass.prototype.fire,
3484                         match           : EventTicketClass.prototype.match,
3485                         mousedownHandler: function( e ){
3486                                 this.startX = e.clientX;
3487                                 this.startY = e.clientY;
3488                                 
3489                                 this.mousemoveTicket = new EventTicketClass( this.element, 'mousemove', this.dragMoveHandler, this );
3490                                 this.mouseupTicket   = new EventTicketClass( this.element, 'mouseup',   this.dragEndHandler,  this );
3491                                 this.mouseoutTicket  = new EventTicketClass( this.element, 'mouseout',  this.dragEndHandler,  this );                                   
3492                         
3493                                 return false;
3494                         },
3495                         dragMoveHandler : function( e ){
3496                                 var offsetX = e.clientX - this.startX,
3497                                         offsetY = e.clientY - this.startY;
3498                                 if( this.dragging === false ){
3499                                         if( offsetX * offsetX + offsetY * offsetY < DRAG_OFFSET ) return;
3500                                         console.log( 'Drag start' );
3501                                         // dragStart
3502                                         this.dragging = true;
3503                                         return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 0 ) );
3504                                 };
3505                                 return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 1 ) );
3506                         },
3507                         dragEndHandler  : function( e ){
3508                                 if( this.dragging === true ){
3509                                         console.log( 'Drag End ' + e.type );
3510                                         this.removeEvents();
3511                                         // dragEnd
3512                                         return this.fire( DragEventTicketClass.createEvent( e, e.clientX - this.startX, e.clientY - this.startY, 2 ) );
3513                                 };
3514                                 this.removeEvents();
3515                                 return false;
3516                         },
3517                         removeEvents : function(){
3518                                 this.dragging = false;
3519                                 if( this.mousemoveTicket ){
3520                                         this.mousemoveTicket.destroy();
3521                                         delete this.mousemoveTicket;
3522                                 };
3523                                 if( this.mouseupTicket ){
3524                                         this.mouseupTicket.destroy();
3525                                         delete this.mouseupTicket;
3526                                 };
3527                                 if( this.mouseoutTicke ){
3528                                         this.mouseoutTicket.destroy();
3529                                         delete this.mouseoutTicket;
3530                                 };                              
3531                         },
3532                         destroy : function( _element, _eventType, _handler ){
3533                                 if( this.match( _element, _eventType, _handler ) === false ) return false;
3534                                 
3535                                 this.removeEvents();
3536                                 this.mousedownTicket.destroy();
3537
3538                                 delete this.element;
3539                                 delete this.handler;
3540                                 delete this.thisObject;
3541                                 delete this.mousedownTicket;    
3542                                 return true;
3543                         }
3544                 };
3545                 if( document.createEvent ){
3546                         DragEventTicketClass.createEvent = function( e, offsetX, offsetY, dragPhase ){
3547                                 var _e = document.createEvent( 'MouseEvents' );
3548                                 _e.initMouseEvent(
3549                                         DragEventTicketClass.prototype.eventType , false, true, e.view, 
3550                                         e.detail, e.screenX, e.screenY, e.clientX, e.clientY, 
3551                                         e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 
3552                                         e.button, e.relatedTarget
3553                                 );
3554                                 _e.dragPhase   = dragPhase;
3555                                 _e.dragOffsetX = offsetX;
3556                                 _e.dragOffsetY = offsetY;
3557                                 return _e;
3558                         };                                      
3559                 } else
3560                 if( document.attachEvent ){
3561                         DragEventTicketClass.createEvent = function( e, offsetX, offsetY, dragPhase ){
3562                                 e.type        = DragEventTicketClass.prototype.eventType;
3563                                 e.dragPhase   = dragPhase;
3564                                 e.dragOffsetX = offsetX;
3565                                 e.dragOffsetY = offsetY;
3566                                 return e;
3567                         };
3568                 } else {
3569                         
3570                 };
3571
3572                 return {
3573                         add: function( _apiuser, _element, _eventType, _handler, opt_thisObject ){
3574                                 if( isApiUser( _apiuser ) === true &&
3575                                         ( Type.isHTMLElement( _element ) === true || _element === window || _element === document ) &&
3576                                         Type.isString( _eventType ) === true &&
3577                                         Type.isFunction( _handler ) === true
3578                                 ){
3579                                         var _uid    = _apiuser.getUID(),
3580                                                 _events = EVENT_LIST_MAP[ _uid ];
3581                                         if( Type.isArray( _events ) === false ){
3582                                                 _events = EVENT_LIST_MAP[ _uid ] = [];
3583                                         } else {
3584                                                 // 2重登録の禁止
3585                                                 for( var i=0, l=_events.length; i<l; ++i ){
3586                                                         if( _events[ i ].match( _element, _eventType, _handler ) === true ) return;
3587                                                 };
3588                                         };
3589                                         switch( _eventType ){
3590                                                 case 'click':
3591                                                         _events.push( new ClickEventTicketClass( _element, _handler, opt_thisObject ) );
3592                                                         break;
3593                                                 case 'mousewheel':
3594                                                         _events.push( new WheelEventTicketClass( _element, _handler, opt_thisObject ) );
3595                                                         break;
3596                                                 case 'mousedrag':
3597                                                         _events.push( new DragEventTicketClass( _element, _handler, opt_thisObject ) );
3598                                                         break;
3599                                                 default:
3600                                                         _events.push( new EventTicketClass( _element, _eventType, _handler, opt_thisObject ) );
3601                                         };
3602                                 };
3603                         },
3604                         remove: function( apiuser, element, eventType, handler ){
3605                                 if( isApiUser( apiuser ) === true ){
3606                                         var uid  = apiuser.getUID(),
3607                                                 list = EVENT_LIST_MAP[ uid ],
3608                                                 i    = 0;
3609                                         if( Type.isArray( list ) === false ) return;
3610                                         for( ;i < list.length; ){
3611                                                 if( list[ i ].destroy( element, eventType, handler ) === true ){
3612                                                         list.splice( i, 1 );
3613                                                 } else {
3614                                                         ++i;
3615                                                 };
3616                                         };
3617                                         if( list.length === 0 ){
3618                                                 EVENT_LIST_MAP[ uid ] = null;
3619                                         };
3620                                 };
3621                         },
3622                         onCurrentApplicationChange: function(){
3623                                 
3624                         },
3625                         onApplicationShutdown: function(){
3626                                 
3627                         },
3628                         onSystemShutdown: function(){
3629                                 
3630                         }
3631                 }
3632         })();
3633
3634 /* ----------------------------------------
3635  * KEY
3636  * 
3637  *  - EDITABLE_TEXT_CONTROL
3638  * 
3639  *    .SHIFT_DOWN_EVENT:        'shiftDown',
3640  *    .SHIFT_UP_EVENT:          'shiftUp',
3641  *    .CTRL_DOWN_EVENT:         'ctrlDown',
3642  *    .CTRL_UP_EVENT:           'ctrlUp',
3643  *    .SPACE_DOWN_EVENT:        'spaceDown',
3644  *    .SPACE_UP_EVENT:          'spaceUp',
3645  *    .init:                            function,
3646  *    .addKeyDownEvent:         function,
3647  *    .keyEventDispatcher:      function,
3648  * 
3649  * ショートカットキーの監視とテキスト入力(input, textarea)、チェックボックスを管理する。
3650  * キー入力はdocumentで受けて、テキスト編集中(input, textarea)はそちらにキーイベント流す。
3651  * 
3652  */
3653 var KeyEvent = ( function(){
3654         var EVENT_LIST_MAP = [],
3655                 LOCK_UP        = [],
3656                 LOCK_DOWN      = [],
3657                 application    = null,
3658                 currentList    = null;
3659
3660         window.focus();
3661         
3662         var focusTicket    = null,
3663                 keydownTicket  = null,
3664                 keyupTicket    = null,
3665                 keyPress       = null,
3666                 keypressTicket = null;
3667         
3668         function unlock( lock, key ){
3669                 lock.splice( Util.getIndex( lock, key ), 1 );
3670         };
3671         
3672         function onKeyChange( e ){
3673                 var cancel         = false,
3674                         type           = e.type,
3675                         key            = e.keyCode, // || e.which,
3676                         shift          = Type.isBoolean( e.shiftKey ) === true ? e.shiftKey : ( e.modifiers & Event.SHIFT_MASK ),
3677                         ctrl           = Type.isBoolean( e.ctrlKey  ) === true ? e.ctrlKey  : ( e.modifiers & Event.CONTROL_MASK ),
3678                         lock           = type === 'keyup' ? LOCK_UP : LOCK_DOWN,
3679                         i, t;
3680                         
3681                 // block chattering
3682                 if( Util.getIndex( lock, key ) !== -1 ) return;
3683                 lock.push( key );
3684                 AsyncCall.add( SUPER_USER_KEY, unlock, [ lock, key ] );
3685                 
3686                 if( key === 16 || shift === true ){
3687                         KeyEvent.shiftEnabled = type !== 'keyup';
3688                 };
3689                 if( key === 17 || ctrl === true ){
3690                         KeyEvent.ctrlEnabled  = type !== 'keyup';
3691                 };
3692                 for( i = currentList.length; i; ){
3693                         t = currentList[ --i ];
3694                         if( Type.isFunction( t[ type ] ) === true && t.keyCode === key && ( t.shift === undefined || t.shift === shift ) && ( t.ctrl === undefined || t.ctrl === ctrl )){
3695                                 if( t[ type ].call( t.apiuser, e ) === false ){
3696                                         cancel = true;
3697                                         break;
3698                                 };
3699                         };
3700                 };
3701                 if( cancel === true || key === 18 || key === 9 || key === 27 || e.altKey === true ){ // 13.enter 18.esc 9.tab 27.esc   || ( key === 13 && overlayEnabled === false)
3702                         return false;
3703                 };
3704         };
3705         
3706         if( UA.isIE === true && UA.ieRenderingVersion < 9 ){
3707                 keyPress = function( e ){
3708                         var key = e.keyCode;
3709                         if( key === 13 || key === 27 ){
3710                                 e.type = 'keydown';
3711                                 return onKeyChange( e );
3712                         };
3713                 };
3714         };
3715         
3716         var KeyEventTicketClass = function( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ){
3717                 this.apiuser = _apiuser;
3718                 this.type    = _type;
3719                 this.keydown = _onKeydown;
3720                 this.keyup   = _onKeyup;                
3721                 this.keyCode = _keyCode;
3722                 this.shift   = _shift;
3723                 this.ctrl    = _ctrl;
3724                 _apiuser = _onKeydown = _onKeyup = null;
3725         }
3726         KeyEventTicketClass.prototype = {
3727                 match: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3728                         if( _apiuser  && _apiuser  !== this.apiuser ) return false;
3729                         if( _type     && _type     !== this.type )    return false;
3730                         if( _handler ){
3731                                 if( this.type === 'keydown' ){
3732                                         if( _handler !== this.keydown ) return false;
3733                                 } else {
3734                                         if( _handler !== this.keyup )   return false;
3735                                 };
3736                         };
3737                         if( _keyCode  && _keyCode  !== this.keyCode ) return false;
3738                         if( _shift    && _shift    !== this.shift )   return false;
3739                         if( _ctrl     && _ctrl     !== this.ctrl )    return false;
3740                         return true;
3741                 },
3742                 destroy: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3743                         if( this.match( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ) === false ) return false;
3744                         
3745                         delete this.apiuser;
3746                         delete this.keydown;
3747                         delete this.keyup;
3748                         
3749                         return true;
3750                 }
3751         };
3752         
3753         function registerEvent( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ){
3754                 var _uid  = _apiuser.getUID(),
3755                         _list = EVENT_LIST_MAP[ _uid ];
3756                 if( Type.isArray( _list ) === false ){
3757                         _list = EVENT_LIST_MAP[ _uid ] = [];
3758                 }
3759                 for( var i=0, l=_list.length; i<l; ++i ){
3760                         if( _list[ i ].match( _apiuser, _type, _onKeydown || _onKeyup, _keyCode, _shift, _ctrl ) === true ) return;
3761                 }
3762                 _list.push( new KeyEventTicketClass( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ));
3763                 
3764                 if( _apiuser === application ) KeyEvent.updateCurrentListener( _apiuser );
3765         };
3766         
3767         return {
3768                 add: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3769                         if( _type === 'keydown' ){
3770                                 registerEvent( _apiuser, _type, _handler, null, _keyCode, _shift, _ctrl );
3771                         } else
3772                         if( _type === 'keyup' ){
3773                                 registerEvent( _apiuser, _type, null, _handler, _keyCode, _shift, _ctrl );
3774                         } else
3775                         if( _type === 'keychange' ){
3776                                 registerEvent( _apiuser, _type, _handler, _handler, _keyCode, _shift, _ctrl );
3777                         } else
3778                         if( _type === 'cursol' ){
3779                                 
3780                         };
3781                 },
3782                 remove: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3783                         var _list = EVENT_LIST_MAP[ _apiuser.getUID() ],
3784                                 i = 0;
3785                         if( Type.isArray( _list ) === true ){
3786                                 while( i < _list.length ){
3787                                         if( _list[ i ].destroy( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ) === true ){
3788                                                 _list.splice( i, 1 );
3789                                         } else {
3790                                                 ++i;
3791                                         }
3792                                 }
3793                         }
3794                         if( _apiuser === application ) KeyEvent.updateCurrentListener( _apiuser );
3795                 },
3796                 shiftEnabled: false,
3797                 ctrlEnabled:  false,
3798                 /*
3799                  * currentListener
3800                  *  currrentApplication ( overlay Application ) or
3801                  *  superuser ( UI )
3802                  */
3803                 updateCurrentListener: function( _apiuser ){
3804                         application = _apiuser;
3805                         var _uid    = _apiuser.getUID();
3806                         currentList = EVENT_LIST_MAP[ _uid ] || ( EVENT_LIST_MAP[ _uid ] = [] );
3807                         
3808                         var _ticket,
3809                                 _down = false,
3810                                 _up   = false;
3811                         for( var i=currentList.length; _ticket = currentList[ --i ]; ){
3812                                 if( _down === false ) _down = !!_ticket.keydown;
3813                                 if( _up   === false ) _up   = !!_ticket.keyup;
3814                                 if( _down && _up ) break;
3815                         }
3816                         if( _down === true ){
3817                                 keydownTicket = new EventTicketClass( document, 'keydown', onKeyChange );
3818                                 keypressTicket = keyPress !== null ? new EventTicketClass( document, 'keypress', keyPress ) : null;
3819                         } else {
3820                                 keydownTicket && keydownTicket.destroy();
3821                                 keypressTicket && keypressTicket.destroy();
3822                                 keydownTicket = keypressTicket = null;
3823                         }
3824                         if( _up === true ){
3825                                 keyupTicket   = new EventTicketClass( document, 'keyup', onKeyChange );
3826                         } else {
3827                                 keyupTicket && keyupTicket.destroy();
3828                                 keyupTicket = null;
3829                         }
3830                         
3831                         if( _down === true || _up === true ){
3832                                 focusTicket   = new EventTicketClass( document, 'mouseenter', window.focus );
3833                         } else {
3834                                 focusTicket && focusTicket.destroy();
3835                                 focusTicket = null;
3836                         }
3837                 },
3838                 onApplicationShutdown: function( _apiuser ){
3839                         KeyEvent.remove( _apiuser );
3840                 },
3841                 onSystemShutdown: function(){
3842                         
3843                 }
3844         }
3845 })();
3846
3847 /**
3848  * 
3849  * http://thudjs.tumblr.com/post/637855087/stylesheet-onload-or-lack-thereof
3850  */
3851
3852 var StyleSheet = ( function(){
3853         var head = document.getElementsByTagName( 'head' )[ 0 ];
3854         
3855         var TICKET_LIST = [];
3856         var STATE_LIST  = 'loaded,complete,uninitialized'.split( ',' );
3857         
3858         var cssRules, sheet;
3859         
3860         var FetchCssTicketClass = function( _apiuser, _url, _elm, _onload, _onerror, opt_thisObject ){
3861                 this.apiusers = [ _apiuser ];
3862                 this.url      = _url;
3863                 this.elm      = _elm;
3864                 this.onload   = [ _onload ];
3865                 this.onerror  = [ _onerror ];
3866                 this.thisObj  = [ opt_thisObject ];
3867                 this.time     = 0;
3868         };
3869         FetchCssTicketClass.prototype = {
3870                 match: function( _apiuser, _url ){
3871                         if( _apiuser  && Util.getIndex( this.apiusers, _apiuser ) === -1 ) return false;
3872                         if( _url      && _url      !== this.url     ) return false;
3873                         return true;
3874                 },
3875                 destroy: function( _apiuser, _url ){
3876                         if( this.match( _apiuser, _url ) === false ) return false;
3877                         
3878                         var i = Util.getIndex( this.apiusers, _apiuser );
3879                         
3880                         this.apiusers.splice( i, 1 );
3881                         this.onload.splice( i, 1 );
3882                         this.onerror.splice( i, 1 );
3883                         this.thisObj.splice( i, 1 );
3884                         
3885                         if( this.apiusers.length !== 0 ) return false;
3886                         
3887                         head.removeChild( this.elm );
3888                         this.elm.onreadystatechange = new Function();
3889                         this.elm.onload = null;
3890                         
3891                         delete this.apiusers;
3892                         delete this.url;
3893                         delete this.elm;
3894                         delete this.onload;
3895                         delete this.onerror;
3896                         delete this.thisObj;
3897                         delete this.time;
3898                         
3899                         return true;
3900                 },
3901                 loaded: function(){
3902                 for( var i = this.onload.length, f; i; ){
3903                         f = this.onload[ --i ];
3904                         Type.isFunction( f ) === true && AsyncCall.add( this.apiusers[ i ], f, this.url, this.thisObj[ i ] || this.apiusers[ i ] );
3905                         this.onload[ i ] = this.onerror[ i ] = null;
3906                 };
3907                 },
3908                 error: function(){
3909                 for( var i = this.onerror.length, f; i; ){
3910                         f = this.onerror[ --i ];
3911                         Type.isFunction( f ) === true && AsyncCall.add( this.apiusers[ i ], f, this.url, this.thisObj[ i ] || this.apiusers[ i ] );
3912                         this.onload[ i ] = this.onerror[ i ] = null;
3913                 };
3914                 },
3915                 check: function(){
3916                         var el = this.elm;
3917                         try {
3918                                 return el[ sheet ] && el[ sheet ][ cssRules ].length > 0;
3919                         } catch( e ){
3920                                 return false;
3921                         };
3922                 },
3923                 done: false
3924         };
3925         
3926         function getTicket( elm ){
3927                 for( var i = TICKET_LIST.length, t; i; ){
3928                         t = TICKET_LIST[ --i ];
3929                         if( t.elm === elm ) return t;
3930                 };
3931         };
3932         
3933         function detect(){
3934                 var t = getTicket( this ), rs = this.readyState, c;
3935                 if( t && t.done === false && ( !rs || Util.getIndex( STATE_LIST, rs ) !== -1 ) ){
3936                         t.done = true;
3937                 t.loaded();
3938                 this.onreadystatechange = new Function();
3939                 this.onload = null;
3940                 };
3941         };
3942         
3943         function checkTimer(){
3944                 var l = TICKET_LIST.length,
3945                         n = 0;
3946                 for( var i = 0; i < l; ++i ){
3947                         t = TICKET_LIST[ i ];
3948                         ++t.time;
3949                         if( t.check() === true ){
3950                                 t.loaded();
3951                                 ++n;
3952                         } else
3953                         if( t.time > 99 ){
3954                                 t.error();
3955                         } else {
3956                                 
3957                         };
3958                 };
3959                 l === n && SystemTimer.remove( SUPER_USER_KEY, checkTimer );
3960         };
3961         
3962         return {
3963                 load: function( _apiuser, _url, opt_onload, opt_onerror, opt_thisObject ){
3964                         _url = Util.getAbsolutePath( _url );
3965                         var t;
3966                         for( var i=TICKET_LIST.length; i; ){
3967                                 t = TICKET_LIST[ --i ];
3968                                 if( t.match( null, _url ) === true ){
3969                                         if( t.match( _apiuser, _url ) === false ){
3970                                                 t.apiusers.push( _apiuser );
3971                                                 t.onload.push( opt_onload );
3972                                                 t.onerror.push( opt_onerror );
3973                                                 t.thisObj.push( opt_thisObject );
3974                                         };
3975                                         SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 );
3976                                         return;
3977                                 };
3978                         };
3979                         var elm = document.createElement( 'link' );
3980                         head.appendChild( elm );
3981                         elm.rel  = 'stylesheet';
3982                         elm.type = 'text\/css';
3983                         elm.onreadystatechange = elm.onload = detect;
3984                         elm.href = _url;
3985                         
3986                         if( !sheet ){ // only assign these once
3987                                 cssRules = 'cssRules';
3988                                 sheet    = 'sheet';
3989                                 if ( !( sheet in elm ) ) { // MSIE uses non-standard property names
3990                                         cssRules = 'rules';
3991                                         sheet    = 'styleSheet';
3992                                 };
3993                         };
3994                         
3995                         TICKET_LIST.push( new FetchCssTicketClass( _apiuser, _url, elm, opt_onload, opt_onerror, opt_thisObject ) );
3996                         
3997                         SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 );
3998                 },
3999                 unload: function( _apiuser, _url ){
4000                         _url = _url ? Util.getAbsolutePath( _url ) : null;
4001                         for( var i = 0; i < TICKET_LIST.length; ){
4002                                 t = TICKET_LIST[ i ];
4003                                 if( t.destroy( _apiuser, _url ) === true ){
4004                                         TICKET_LIST.splice( i, 1 );
4005                                 } else {
4006                                         ++i;
4007                                 }
4008                         };
4009                         if( TICKET_LIST.length === 0 ){
4010                                 SystemTimer.remove( SUPER_USER_KEY, checkTimer );
4011                         }
4012                 }
4013         }
4014 })();
4015
4016 /*
4017  * AssetLoader
4018  * fetchCSS
4019  * fetchJson
4020  * fetchHtml
4021  * fetchImage
4022  * fetchLocalFile
4023  * fetchLocalStorage
4024  */
4025
4026 var Image = ( function(){
4027         var TASK_LIST = [];
4028         /* 
4029          * FetchClass original is
4030          * 
4031          * LICENSE: MIT?
4032          *  URL: http://d.hatena.ne.jp/uupaa/20080413/1208067631
4033          *  AUTHOR: uupaa.js@gmail.com
4034          * 
4035          */
4036         function detect(){
4037                 for( var i=0, t; i < TASK_LIST.length; ){
4038                         t = TASK_LIST[ i ];
4039                         if( t.complete() === true ){
4040                                 TASK_LIST.splice( i, 1 );
4041                         } else {
4042                                 ++i;
4043                         };
4044                 };
4045                 TASK_LIST.length === 0 && SystemTimer.remove( SUPER_USER_KEY, detect );
4046         };
4047         function getTask( img ){
4048                 for( var i = TASK_LIST.length; i; ){
4049                         if( TASK_LIST[ --i ].img === img ) return TASK_LIST[ i ];
4050                 };
4051         };
4052         function onError(){
4053                 var task = getTask( this );
4054                 if( task.finish === true ) return;
4055                 task.finish = true;
4056                 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
4057         };
4058         function onLoad(){
4059                 // if( finish === true ) return; // これがあると firefox3.6 で駄目、、、
4060                 // if( timer ) return; // これがあると safari3.2 で駄目、、、
4061                 var task = getTask( this );
4062                 task.finish = true;
4063                 TASK_LIST.splice( Util.getIndex( TASK_LIST, task ), 1 );
4064                 if( window.opera && !task.img.complete ){
4065                         AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
4066                         return;
4067                 };
4068                 task.size = Util.getImageSize( this );
4069                 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
4070         };
4071
4072
4073         var FetchClass = function( apiuser, abspath, onLoadCallback, onErrorCallback, timeout ){
4074                 this.apiuser         = apiuser;
4075                 this.abspath         = abspath;
4076                 this.onLoadCallback  = onLoadCallback;
4077                 this.onErrorCallback = onErrorCallback;
4078                 this.timeout         = timeout;
4079                 this.tick            = 0;
4080         };
4081         FetchClass.prototype = {
4082                 img: null,
4083                 size: null,
4084                 tick: 0,
4085                 finish: false,
4086                 load: function(){
4087                         var img     = this.img = document.createElement( 'img' ); //var img = new Image(); ではieでimgのsizeが取れない、、、removeChildも失敗し、imgSizeGetterにimgが残る
4088                         img.onabort = img.onerror = onError;
4089                         img.onload  = onLoad;
4090                         img.src     = this.abspath;
4091                 },
4092                 complete: function(){
4093                         if( this.finish === true ) return true;
4094                         if( this.img.complete ){
4095                                 this.finish = true;
4096                                 if( this.img.width ) return true;
4097                                 AsyncCall.add( this.apiuser, this.asyncCallback, null, this );
4098                                 return true;
4099                         };
4100                         if( ( this.tick += 250 ) > this.timeout ){
4101                                 this.finish = true;
4102                                 AsyncCall.add( this.apiuser, this.asyncCallback, null, this );
4103                                 return true;
4104                         };
4105                 },
4106                 asyncCallback: function(){
4107                         this.size ? this.onLoadCallback( this.abspath, this.size.width, this.size.height ) : this.onErrorCallback( this.abspath );
4108                         this.destroy();
4109                 },
4110                 destroy: function(){
4111                         this.finish  = true;
4112                         this.img.src = this.img.onload = this.img.onabort = this.img.onerror = '';
4113                         delete this.img;
4114                         delete this.size;
4115                         delete this.onLoadCallback;
4116                         delete this.onErrorCallback;
4117                 },
4118                 stop: function(){
4119                         timer !== null && window.clearTimeout( timer );
4120                         destroy();
4121                 }
4122         };
4123         
4124         return {
4125                 load: function( URLorELM, onLoad, onError, opt_timeout ){
4126                         var src, fetch;
4127                         if( Type.isString( URLorELM ) === true ){
4128                                 src = URLorELM;
4129                         } else
4130                         if( Type.isHTMLElement( URLorELM ) === true && URLorELM.tagName.toLowerCase() === 'img' ){
4131                                 src = URLorELM.src;
4132                         } else {
4133                                 return;
4134                         };
4135                         
4136                         fetch = new FetchClass(
4137                                 Util.getAbsolutePath( src ),
4138                                 onLoad, onError,
4139                                 Type.isFinite( opt_timeout ) === true ? opt_timeout : undefined
4140                         );
4141                         TASK_LIST.push( fetch );
4142                         
4143                         SystemTimer.add( SUPER_USER_KEY, detect, 250 );
4144                 },
4145                 unload: function(  ){
4146                         
4147                 }
4148         };
4149 })();
4150
4151
4152 /* ----------------------------------------
4153  * 
4154  */
4155
4156 var Overlay = ( function(){
4157         var elmContainer, elmShadow, elmCloseButton,
4158                 bootParams,
4159                 application    = null,
4160                 visible        = false,
4161                 bodyOverflow   = '',
4162                 windowW, windowH;
4163
4164         function onCloseClick( e ){
4165                 Overlay.hide();
4166                 return false;
4167         };
4168         function asyncInit( /* arguments */ ){
4169                 application.init();
4170                 //application.rootElement.style.display = 'none';
4171                 
4172                 elmContainer.style.cssText = "top:" + body.scrollTop + 'px;display:none;';
4173                 $( elmContainer ).stop().fadeIn( onFadeInComplete );            
4174         };
4175         function asyncOpen( /* arguments */ ){
4176
4177                 
4178                 
4179         };
4180         function onFadeInComplete(){
4181                 KeyEvent.add( application, Const.KEY.EVENT.KEY_DOWN, Overlay.hide, 27 ); // 27.esc
4182                 MouseEvent.add( application, elmCloseButton, 'click', onCloseClick );
4183                 
4184                 var _arg = bootParams; //Util.copyArray( arguments );
4185                 _arg.unshift( windowW, windowH );
4186                 application.open.apply( application, _arg );            
4187         };
4188         function onFadeOutComplete(){   
4189                 Util.removeAllChildren( elmContainer );
4190                 body.removeChild( elmContainer );
4191                 elmContainer = elmShadow = elmCloseButton = null;
4192         };
4193         return {
4194                 show: function( _application, _bootParams ){
4195                         if( visible === true && application === _application ) return;
4196                         if( Application.isApplicationInstance( _application ) === false ) return;
4197                         
4198                         elmContainer = document.createElement( 'div' );
4199                         body.appendChild( elmContainer );
4200                         
4201                         elmContainer.id = 'overlay-container';
4202                         
4203                         bodyOverflow        = body.style.overflow;
4204                         body.style.overflow = 'hidden';
4205                         
4206                         elmShadow = document.createElement( 'div' );
4207                         elmContainer.appendChild( elmShadow );
4208                         elmShadow.id = 'overlay-shadow';
4209                         
4210                         elmCloseButton  = document.createElement( 'div' );
4211                         elmContainer.appendChild( elmCloseButton );
4212                         elmCloseButton.id = 'overlay-close-button';
4213                         elmCloseButton.appendChild( document.createTextNode( 'x' ) );
4214                         
4215                         elmContainer.style.display = 'none'; // hide for fadeIn
4216                         
4217                         visible     = true;
4218                         application = _application;
4219                         
4220                         //asyncInit();
4221                         elmContainer.insertBefore( application.rootElement, elmCloseButton );
4222                         _application.addAsyncCall( asyncInit );
4223                         // _application.addAsyncCall( asyncOpen,  );
4224                         
4225                         bootParams = _bootParams;                       
4226                 },
4227                 hide: function(){
4228                         if( visible === false ) return;
4229                         if( application.close() === false ) return false;
4230                         
4231                         body.style.overflow = bodyOverflow;
4232                         
4233                         $( elmContainer ).stop().css( {
4234                                 filter:         '',
4235                                 opacity:        ''
4236                         }).fadeOut( onFadeOutComplete );
4237                         visible = false;
4238                         
4239                         application = null;
4240                 },
4241                 onWindowResize: function( _windowW, _windowH ){
4242                         windowW = _windowW;
4243                         windowH = _windowH;                     
4244                         
4245                         if( application === null ) return;
4246                         
4247                         elmContainer.style.height = _windowH + 'px';
4248                         elmContainer.style.top    = body.scrollTop + 'px';
4249
4250                         elmShadow.style.height = _windowH + 'px';
4251
4252                         AsyncCall.add( application, application.resize, [ _windowW, _windowH ] );
4253                 }
4254         }
4255 })();
4256
4257 /* ----------------------------------------
4258  * UI
4259  * 
4260  * keyEventRellay
4261  *  form -> overlay -> view
4262  * 
4263  */
4264
4265 var UI = ( function(){
4266         var UI_LIST     = [],
4267                 currentUser = null,
4268                 currentList = null,
4269                 currentUi   = null,
4270                 currentItem = null,
4271                 windowW     = 0,
4272                 windowH     = 0;
4273
4274         var CLASSNAME_COMBOBOX_OPTION = 'combobox-option',
4275                 CLASSNAME_COMBOBOX_OPTION_CURRENT = CLASSNAME_COMBOBOX_OPTION + ' combobox-option-current',
4276                 ELM_COMBOBOX = ( function(){
4277                         var ret       = document.createElement( 'a' ),
4278                                 elmToggle = document.createElement( 'span' ),
4279                                 elmValue  = document.createElement( 'span' );
4280                         ret.href = '#';
4281                         ret.appendChild( elmToggle );
4282                         ret.appendChild( elmValue );
4283                         elmToggle.className = 'combobox-toggle';
4284                         elmValue.className  = 'combobox-value';
4285                         
4286                         elmToggle.appendChild( document.createTextNode( '▼' ));
4287                         elmValue.appendChild( document.createTextNode( 'null' ));
4288                         return ret;
4289                 })();
4290         
4291         var UIItemPrivateData = function(){};
4292         UIItemPrivateData.prototype = {
4293                 groupData   : null,
4294                 item        : null,
4295                 elm         : null,
4296                 node        : null,
4297                 focus       : false,
4298                 visible     : true,
4299                 enabled     : true,
4300                 value       : null,
4301                 onUpdate    : null,
4302                 validator   : null,
4303                 elmValue    : null,
4304                 elmBox      : null,
4305                 elmA        : null,
4306                 elmToggle   : null,
4307                 elmValue    : null,
4308                 selectIndex : 0,
4309                 optionList  : null,
4310                 init    : function( groupData, item, elm, value, onUpdate, validator, focus, visible, enabled ){
4311                         this.groupData = groupData;
4312                         this.item      = item;
4313                         this.elm       = elm;
4314                         this.value     = value;
4315                         this.onUpdate  = onUpdate;
4316                         this.validator = validator;                     
4317                         this.focus     = !!focus;
4318                         this.visible   = !!visible;
4319                         this.enabled   = !!enabled;
4320                         UIItemPrivateData.list.push( this );
4321                 },
4322                 destroy : function(){
4323                         var list = UIItemPrivateData.list;
4324                         list.splice( Util.getIndex( list, this ), 1 );
4325                         
4326                         list = this.groupData.itemList;
4327                         var i = Util.getIndex( list, this.item );
4328                         i !== -1 && list.splice( i, 1 );
4329                         
4330                         this.node && this.node.remove();
4331                 }
4332         };
4333         UIItemPrivateData.list = [];
4334         UIItemPrivateData.get = function( item ){
4335                 var list = UIItemPrivateData.list;
4336                 for( i = list.length; i; ){
4337                         if( list[ --i ].item === item ) return list[ i ];
4338                 };
4339                 return null;
4340         };
4341         
4342 /* --------------------------------
4343  * TextInputManager
4344  */
4345         var TextInputManager = ( function(){
4346                 var elmInput = ( function(){
4347                         var ret  = document.createElement( 'input' );
4348                         ret.type = 'text';
4349                         ret.id   = 'ui-textinput';
4350                         return ret;
4351                 })();
4352                 var currentData;
4353                 
4354                 function updateWrapperPosition(){
4355                         var p = Position.cumulativeOffset( currentData.elmValue ),
4356                                 w = currentData.elmValue.offsetWidth - 2,
4357                                 _w;             
4358                         elmInput.style.cssText = [
4359                                 'left:',   p[ 0 ], 'px;',
4360                                 'top:',    p[ 1 ], 'px;',//,
4361                                 'width:',  w, 'px;'//,
4362                                 //'height:', data.elmValue.offsetHeight, 'px;',
4363                                 //'position:absolute;'
4364                         ].join( '' );
4365                         
4366                         //_w = elmInput.offsetWidth;
4367                         //if( w !== _w ) elmInput.style.width = ( w - ( _w - w ) ) + 'px;';     
4368                 };
4369                 
4370                 return {
4371                         show: function( data ){
4372                                 // this.groupData.node.addEventListener( 'mouseout' );
4373                                 currentData = data;
4374
4375                                 body.appendChild( elmInput );
4376                                 elmInput.value = data.value;
4377                                 updateWrapperPosition();
4378                                 
4379                                 elmInput.focus();
4380                                 elmInput.select();
4381                                 
4382                                 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4383                         },
4384                         hide : function( data ){
4385                                 if( currentData !== data ) return;
4386                                 currentData = null;
4387                                 body.removeChild( elmInput );
4388                                 var ret = elmInput.value;
4389                                 elmInput.value = '';
4390                                 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition );
4391                                 return ret;
4392                         },
4393                         update : function( data ){
4394                                 elmInput.value = data.value;
4395                         },
4396                         onWindowResize: function( _w, _h ){
4397                                 AsyncCall.add( currentUser, updateWrapperPosition );
4398                         }
4399                 };
4400         })();
4401         
4402         var TextInputClass = function( groupData, elmWrapper, elmValue, onUpdate, validater ){
4403                 var data = new UIItemPrivateData();
4404                 data.init( groupData, this, elmWrapper, elmValue.innerHTML, onUpdate, validater, false, true, true );
4405                 Util.addClass( elmValue, 'editable-text' );
4406                 data.elmValue = elmValue;
4407                 this.value( data.value );
4408                 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-inpittext-hover', 'pointer' );
4409                 data.node.addEventListener( 'click', this.focus, this );
4410                 //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', instance.focus );
4411         };
4412         TextInputClass.prototype = {
4413                 value : function( value ){
4414                         var data = UIItemPrivateData.get( this );
4415                         if( Type.isString( value ) === true || Type.isNumber( value ) === true ){
4416                                 data.elmValue.innerHTML = data.value = '' + value;
4417                                 data.focus === true && TextInputManager.update( data );
4418                         };
4419                         data.focus === true && this.blur();
4420                         return data.value;
4421                 },
4422                 focus : function( e ){
4423                         var data = UIItemPrivateData.get( this );
4424                         data.focus = true;
4425                         start( data );
4426                         TextInputManager.show( data );
4427                         return false;
4428                 },
4429                 blur : function( keep ){
4430                         var data = UIItemPrivateData.get( this ),
4431                                 newValue;
4432                         if( data.focus === false ) return;
4433                         newValue = TextInputManager.hide( data );
4434                         newValue = keep !== 27 ? ( data.validater ? '' + data.validater( newValue ) : newValue ) : data.value; // 27:ESC
4435
4436                         data.elmValue.innerHTML = newValue;
4437                         
4438                         data.onUpdate && newValue !== data.value && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ newValue, data.value ], this );
4439                         
4440                         data.value = newValue;
4441                         data.focus = false;
4442                         finish( data );
4443                 },
4444                 enabled : function( v ){
4445                         var data = UIItemPrivateData.get( this );
4446                         if( Type.isBoolean( v ) === true && data.enabled !== v ){
4447                                 Util.toggleClass( data.elm, 'ui-textinput-disabled', !v );
4448                                 if( data.focus === true && v === false ) this.blur();
4449                                 data.enabled = v;
4450                                 data.node.disabled( !( data.visible && v ) );
4451                         };
4452                         return data.enabled;
4453                 },
4454                 visible : function( v ){
4455                         var data = UIItemPrivateData.get( this );
4456                         if( Type.isBoolean( v ) === true && data.visible !== v ){
4457                                 data.elm.style.display = v ? '' : 'none';
4458                                 if( data.focus === true && v === false ) this.blur();
4459                                 data.visible = v;
4460                                 data.node.disabled( !( data.enabled && v ) );
4461                         };
4462                         return data.visible;
4463                 },
4464                 destroy : function(){
4465                         var data = UIItemPrivateData.get( this );
4466                         data.focus === true && TextInputManager.hide( data );
4467                         data.destroy();
4468                 }
4469         };
4470
4471 /* --------------------------------
4472  * TextInputManager
4473  */
4474         var FileInputManager = ( function(){
4475                 var currentData,
4476                         elmForm,
4477                         elmFileInput,
4478                         elmWrap,
4479                         evt;
4480                 
4481                 function updateWrapperPosition(){
4482                         var p = Position.cumulativeOffset( currentData.elmValue ),
4483                                 w = currentData.elmValue.offsetWidth,
4484                                 _w;             
4485                         elmWrap.style.cssText = [
4486                                 'left:',   p[ 0 ], 'px;',
4487                                 'top:',    p[ 1 ], 'px;',//,
4488                                 'width:',  w, 'px;'//,
4489                                 //'height:', data.elmValue.offsetHeight, 'px;',
4490                                 //'position:absolute;'
4491                         ].join( '' );
4492                         
4493                         _w = elmWrap.offsetWidth;
4494                         if( w !== _w ) elmWrap.style.width = ( w - ( _w - w ) ) + 'px'; 
4495                 };
4496                 
4497                 function change( e ){
4498                         var data = currentData,
4499                                 file = data.elmFileInputReal.value;
4500                         file = file.split( '\\' );
4501                         file = file[ file.length - 1 ];
4502                         if( data.value !== file ){
4503                                 data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ file, data.value ], this );
4504                                 data.elmValue.innerHTML = data.value = file;
4505                         };
4506                         currentData.item.blur();
4507                 };
4508                 function asyncMouseout(){
4509                         currentData && currentData.item.blur();
4510                 };
4511                 function onClick(){
4512                         MouseEvent.remove( currentUser, elmFileInput, 'mouseout', asyncMouseout );
4513                         MouseEvent.remove( currentUser, elmFileInput, 'click', onClick );       
4514                 };
4515                 return {
4516                         show : function( data ){
4517                                 currentData = data;
4518                                 
4519                                 elmFileInput = data.elmFileInputReal;
4520                                 elmWrap      = elmFileInput.parentNode;
4521                                 // 
4522                                 
4523                                 updateWrapperPosition();
4524                                 elmFileInput.focus();
4525                                 //data.node.addEventListener( 'change', change, data );
4526                                 evt = new EventTicketClass( elmFileInput, 'change', change );
4527                                 MouseEvent.add( currentUser, elmFileInput, 'mouseout', asyncMouseout );
4528                                 MouseEvent.add( currentUser, elmFileInput, 'click', onClick );
4529                                 // currentData.elmFileInputReal.onchange = change;
4530                                 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4531                         },
4532                         hide : function( data ){
4533                                 if( currentData !== data ) return;
4534                                 // data.node.removeEventListener( 'change', change );
4535                                 evt.destroy();
4536                                 // MouseEvent.remove( currentUser, elmFileInput, 'mouseout', asyncMouseout );
4537                                 onClick();
4538                                 //currentData.elmFileInputReal.onchange = null;
4539                                 elmWrap.style.display = 'none';
4540                                 currentData = elmFileInput = null;
4541                                 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition );
4542                         },
4543                         onWindowResize: function( _w, _h ){
4544                                 AsyncCall.add( currentUser, updateWrapperPosition );
4545                         }
4546                 };
4547         })();
4548         
4549         var FileInputClass = function( groupData, elmWrapper, onUpdate, validater, elmFileInputReal, elmValue ){
4550                 var data = new UIItemPrivateData();
4551                 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4552                 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-fileinput-hover', 'pointer' );
4553                 data.elmValue = elmValue;
4554                 data.elmFileInputReal = elmFileInputReal;
4555                 data.node.addEventListener( 'mouseover', this.focus, this );
4556         };
4557         FileInputClass.prototype = {
4558                 value : function(){
4559                         return data.value;
4560                 },
4561                 focus : function(){
4562                         var data = UIItemPrivateData.get( this );
4563                         data.focus = true;
4564                         Util.addClass( data.elm, 'fileinput-has-focus' );
4565                         start( data );
4566                         FileInputManager.show( data );
4567                 },
4568                 blur : function( keyCode ){
4569                         var data = UIItemPrivateData.get( this );
4570                         Util.removeClass( data.elm, 'fileinput-has-focus' );
4571                         data.focus = false;
4572                         FileInputManager.hide( data );
4573                         finish( data );
4574                 },
4575                 enabled : function( v ){
4576                         var data = UIItemPrivateData.get( this );
4577                         if( Type.isBoolean( v ) === true && data.enabled !== v ){
4578                                 if( data.focus === true && v === false ) this.blur();
4579                                 Util.toggleClass( data.elm, 'fileinput-disabled', !v );
4580                                 data.enabled = v;
4581                                 data.node.disabled( !( data.visible && v ) );
4582                         };
4583                         return data.enabled;
4584                 },
4585                 visible : function( v ){
4586                         var data = UIItemPrivateData.get( this );
4587                         if( Type.isBoolean( v ) === true && data.visible !== v ){
4588                                 if( data.focus === true && v === false ) this.blur();
4589                                 data.elm.style.display = v ? '' : 'none';
4590                                 data.visible = v;
4591                                 data.node.disabled( !( data.enabled && v ) );
4592                         };
4593                         return data.visible;
4594                 },
4595                 destroy : function(){
4596                         var data = UIItemPrivateData.get( this );
4597                         data.focus === true && FileInputManager.hide( data );
4598                         data.destroy();
4599                 }
4600         };
4601         
4602         var ButtonClass = function( groupData, elmWrapper, onUpdate ){
4603                 var data = new UIItemPrivateData();
4604                 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4605                 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-button-hover', 'pointer' );
4606                 data.node.addEventListener( 'click', onUpdate );
4607                 //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', onUpdate );
4608         };
4609         ButtonClass.prototype = {
4610                 focus : function(){
4611                         var data = UIItemPrivateData.get( this );
4612                         data.focus = true;
4613                         Util.addClass( data.elm, 'button-has-focus' );
4614                         start( data );
4615                 },
4616                 blur : function( keyCode ){
4617                         var data = UIItemPrivateData.get( this );
4618                         keyCode === 13 && data.onUpdate && data.onUpdate();
4619                         Util.removeClass( data.elm, 'button-has-focus' );
4620                         data.focus = false;
4621                         finish( data );
4622                 },
4623                 enabled : function( v ){
4624                         var data = UIItemPrivateData.get( this );
4625                         if( Type.isBoolean( v ) === true && data.enabled !== v ){
4626                                 Util.toggleClass( data.elm, 'button-disabled', !v );
4627                                 data.enabled = v;
4628                                 data.node.disabled( !( data.visible && v ) );
4629                         };
4630                         return data.enabled;
4631                 },
4632                 visible : function( v ){
4633                         var data = UIItemPrivateData.get( this );
4634                         if( Type.isBoolean( v ) === true && data.visible !== v ){
4635                                 data.elm.style.display = v ? '' : 'none';
4636                                 data.visible = v;
4637                                 data.node.disabled( !( data.enabled && v ) );
4638                         };
4639                         return data.visible;
4640                 },
4641                 destroy : function(){
4642                         var data = UIItemPrivateData.get( this );
4643                         // MouseEvent.remove( data.groupData.apiuser, data.elm );
4644                         data.destroy();
4645                 }
4646         };
4647
4648         var ComboBoxClass = function( groupData, elmWrapper, onUpdate ){
4649                 var elmA   = ELM_COMBOBOX.cloneNode( true ),
4650                         data   = new UIItemPrivateData();
4651                 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4652                 
4653                 data.elmBox      = Util.getElementsByClassName( elmWrapper, 'combobox' )[ 0 ];
4654                 data.elmBox.appendChild( elmA );
4655                 data.elmA        = elmA;
4656                 data.elmToggle   = Util.getElementsByClassName( elmA, 'combobox-toggle' )[ 0 ];
4657                 data.elmValue    = Util.getElementsByClassName( elmA, 'combobox-value' )[ 0 ].firstChild;
4658                 data.selectIndex = 0;
4659                 data.optionList  = [];
4660
4661                 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-combobox-hover', 'pointer' );
4662                 data.node.addEventListener( 'click', this.focus, this );
4663         };
4664         ComboBoxClass.prototype = {
4665                 focus : function( e ){
4666                         var data = UIItemPrivateData.get( this );
4667                         data.node.removeEventListener( 'click', this.focus );
4668                         data.focus = true;
4669                         data.elmA.className = 'combobox-has-focus';
4670                         start( data );
4671                         OptionControl.show( data );
4672                         return false;
4673                 },
4674                 blur : function( keyCode ){
4675                         var data = UIItemPrivateData.get( this );
4676                         OptionControl.hide( this );
4677                         data.focus = false;
4678                         data.elmA.className = '';
4679                         finish( data );
4680                         data.node.addEventListener( 'click', this.focus, this );
4681                 },
4682                 enabled : function( v ){
4683                         var data = UIItemPrivateData.get( this );
4684                         if( Type.isBoolean( v ) === true && data.enabled !== v ){
4685                                 Util.toggleClass( data.elm, 'ui-combobox-disabled', !v );
4686                                 if( data.focus === true && v === false ) this.blur();
4687                                 data.enabled = v;
4688                                 data.node.disabled( !( data.visible && v ) );
4689                         };
4690                         return data.enabled;
4691                 },
4692                 visible : function( v ){
4693                         var data = UIItemPrivateData.get( this );
4694                         if( Type.isBoolean( v ) === true && data.visible !== v ){
4695                                 data.elm.style.display = v ? '' : 'none';
4696                                 if( data.focus === true && v === false ) this.blur();
4697                                 data.visible = v;
4698                                 data.node.disabled( !( data.enabled && v ) );
4699                         };
4700                         return data.visible;
4701                 },
4702                 value : function( _value ){
4703                         var data = UIItemPrivateData.get( this ),
4704                                 i    = 0,
4705                                 list = data.optionList,
4706                                 l    = list.length,
4707                                 _option;
4708                         if( Type.isString( _value ) === true && data.value !== _value ){
4709                                 for( ; i < l; ++i ){
4710                                         _option = list[ i ];
4711                                         if( _value === _option.value ){
4712                                                 data.value = _value;
4713                                                 data.index = i;
4714                                                 data.elmValue.data = _option.displayValue;
4715                                                 if( data.focus === true ){
4716                                                         OptionControl.update( this, _value );
4717                                                 };
4718                                                 data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, _value, this );
4719                                                 break;
4720                                         };
4721                                 };
4722                         };
4723                         return data.value;
4724                 },
4725                 selectIndex : function(){
4726                         var data = UIItemPrivateData.get( this );
4727                         return data.selectIndex;
4728                 },
4729                 createOption : function( _displayValue, _value, _isSelected ){
4730                         var data   = UIItemPrivateData.get( this ),
4731                                 option = null,
4732                                 list   = data.optionList,
4733                                 i      = list.length,
4734                                 _option, i;
4735                         _value      = _value || _displayValue;
4736                         _isSelected = !!_isSelected;
4737                         for( ; i; ){
4738                                 _option = list[ --i ];
4739                                 if( _value === _option.value ){
4740                                         option = _option;
4741                                         break;
4742                                 };
4743                         };
4744                         if( _isSelected === true ){
4745                                 data.selectIndex   = list.length;
4746                                 data.elmValue.data = _displayValue;
4747                         };                      
4748                         option === null && list.push( new OptionDataClass( _displayValue, _value, _isSelected ) );
4749                 },
4750                 destroy : function(){
4751                         var data   = UIItemPrivateData.get( this );
4752                         data.focus === true && OptionControl.hide( this );
4753                         // this.blur();
4754                         // MouseEvent.remove( data.groupData.apiuser, data.elm );
4755                         data.optionList.length = 0;
4756                         data.destroy();
4757                 }
4758         };
4759         var OptionDataClass = function( displayValue, value, isCurrent ){
4760                 this.displayValue = displayValue;
4761                 this.value        = value || displayValue;
4762                 this.current      = isCurrent;
4763                 displayValue = value = null;
4764         };
4765
4766         var OptionControl = ( function(){
4767                 var ELM_OPTION_WRAPPER = ( function(){
4768                                 var ret = document.createElement( 'div' );
4769                                 ret.className = 'option-container';
4770                                 return ret;
4771                         })(),
4772                         ELM_OPTION_ORIGIN = ( function(){
4773                                 var ret = document.createElement( 'a' );
4774                                 ret.appendChild( document.createTextNode( 'option' ) );
4775                                 ret.href = '#';
4776                                 return ret;
4777                         })();
4778
4779                 var OptionClass = function( option ){
4780                         this.elm     = ELM_OPTION_ORIGIN.cloneNode( true );
4781                         this.data    = option;
4782                         this.init();
4783                 };
4784                 OptionClass.prototype = {
4785                         init: function(){
4786                                 ELM_OPTION_WRAPPER.appendChild( this.elm );
4787                                 this.elm.firstChild.data = this.data.displayValue;
4788                                 this.current( this.data.current );
4789                                 MouseEvent.add( SUPER_USER_KEY, this.elm, 'mousedown', onOptionSelect );// onclick では 選択ボックス 隠すように body に設定した onmouseup が先に動いてしまう!
4790                         },
4791                         current: function( _current ){
4792                                 this.elm.className = _current === true ? CLASSNAME_COMBOBOX_OPTION_CURRENT : CLASSNAME_COMBOBOX_OPTION;
4793                                 this.data.current  = _current;
4794                                 currentOption      = _current === true ? this : currentOption;
4795                         },
4796                         destroy: function(){
4797                                 MouseEvent.remove( SUPER_USER_KEY, this.elm );
4798                                 Util.removeAllChildren( this.elm );
4799                                 ELM_OPTION_WRAPPER.removeChild( this.elm );
4800                                 delete this.elm;
4801                                 delete this.data;
4802                         }
4803                 };
4804                 
4805                 function onOptionSelect( e ){
4806                         var i = 0,
4807                                 l = OPTION_LIST.length,
4808                                 _option;
4809                         for( ; i < l; ++i ){
4810                                 _option = OPTION_LIST[ i ];
4811                                 if( this === _option.elm ){
4812                                         updateCurrrentOption( _option.data.value, true );
4813                                         currentCombobox.blur();
4814                                         break;
4815                                 };
4816                         };
4817                         return false;
4818                 };
4819                 
4820                 var OPTION_LIST     = [],
4821                         currentCombobox = null,
4822                         apiuser,
4823                         elm,
4824                         currentOption,
4825                         currentIndex;
4826                 
4827                 function updateCurrrentOption( _value, _updateCombobox ){
4828                         var _option,
4829                                 i = OPTION_LIST.length;
4830                         for( ; i; ){
4831                                 _option = OPTION_LIST[ --i ];
4832                                 if( _value === _option.data.value ){
4833                                         currentOption && currentOption.current( false );
4834                                         _option.current( true );
4835                                         currentOption = _option;
4836                                         currentIndex  = i;
4837                                         _updateCombobox === true && currentCombobox.value( _value );
4838                                         break;
4839                                 };
4840                         };
4841                 };
4842                 function bodyMouseupHandler(){
4843                         currentCombobox.blur();
4844                         OptionControl.hide( currentCombobox );
4845                 };
4846                 function updateWrapperPosition(){
4847                         var position = Util.getAbsolutePosition( elm );
4848
4849                         ELM_OPTION_WRAPPER.style.cssText = [
4850                                 'width:', elm.offsetWidth - 2, 'px;',
4851                                 'left:',  position.x, 'px;',
4852                                 'top:',   position.y + elm.offsetHeight, 'px;'
4853                         ].join( '' );
4854                 };
4855                 function change( e ){
4856                         var l   = OPTION_LIST.length,
4857                                 i   = currentIndex + ( e.keyCode === 40 ? -1 : 1 );
4858                         if( currentCombobox === null || l < 2 ) return;
4859                         i = i < 0 ?
4860                                         l - 1 :
4861                                         i < l ? i : 0;
4862                         updateCurrrentOption( OPTION_LIST[ i ].data.value, true );
4863                         return false;
4864                 };
4865                 return {
4866                         show: function( data ){
4867                                 var combobox = data.item,
4868                                         list     = data.optionList,
4869                                         i        = 0,
4870                                         l        = list.length;
4871                                 if( currentItem !== combobox || currentCombobox === combobox ) return;
4872                                 currentCombobox && currentCombobox.blur();
4873                                 
4874                                 apiuser         = data.groupData.apiuser;
4875                                 currentCombobox = combobox;
4876                                 elm             = data.elmBox;
4877                                 
4878                                 for( ; i < l; ++i ){
4879                                         OPTION_LIST.unshift( new OptionClass( list[ i ] ) );
4880                                 };
4881                                 MouseEvent.add( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler );
4882                                 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 38 );
4883                                 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 40 );
4884                                 //KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter, 13 );
4885                                 //KeyEvent.updateCurrentListener( SUPER_USER_KEY );
4886                                 
4887                                 body.appendChild( ELM_OPTION_WRAPPER );
4888                                 
4889                                 updateCurrrentOption( combobox.value(), false );
4890                                 updateWrapperPosition();
4891                                 
4892                                 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4893                         },
4894                         hide: function( _combobox ){
4895                                 if( currentCombobox !== _combobox || currentCombobox === null ) return;
4896
4897                                 var _option;
4898                                 while( _option = OPTION_LIST.shift() ){
4899                                         _option.destroy();
4900                                 };
4901                                 
4902                                 body.removeChild( ELM_OPTION_WRAPPER );
4903                                 
4904                                 MouseEvent.remove( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler );
4905                                 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change );
4906                                 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change );
4907                                 //KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter );
4908                                 //KeyEvent.updateCurrentListener( apiuser );
4909                                 
4910                                 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition, 500 );
4911                                 
4912                                 apiuser         = null;
4913                                 currentCombobox = null;
4914                                 currentOption   = null;
4915                                 currentIndex    = 0;                            
4916                         },
4917                         onEnter: function(){
4918                                 currentCombobox.value( currentOption.data.value );
4919                                 //currentCombobox.blur();
4920                                 //OptionControl.hide( currentCombobox );
4921                         },
4922                         update: function( data, _value ){
4923                                 if( currentCombobox !== data.item || currentItem !== data.item ) return;
4924                                 if( currentOption.data.value === _value ) return;
4925                                 updateCurrrentOption( _value, true );
4926                         },
4927                         onWindowResize: function( _w, _h ){
4928                                 currentCombobox && AsyncCall.add( apiuser, updateWrapperPosition );
4929                         }
4930                 };
4931         })();
4932         
4933         var UIGroupPrivateData = function(){};
4934         UIGroupPrivateData.prototype = {
4935                 apiuser  : null,
4936                 node     : null,
4937                 uigroup  : null,
4938                 itemList : null,
4939                 visible  : true,
4940                 enabled  : true,
4941                 init     : function( apiuser, node, uigroup ){
4942                         this.apiuser  = apiuser;
4943                         this.node     = node;
4944                         this.uigroup  = uigroup;
4945                         this.itemList = [];
4946                         UIGroupPrivateData.list.push( this );
4947                 },
4948                 destroy  : function(){
4949                         
4950                 }
4951         };
4952         UIGroupPrivateData.list = [];
4953         UIGroupPrivateData.get  = function( uigroup ){
4954                 var list = UIGroupPrivateData.list,
4955                         i    = list.length;
4956                 for( ; i; ){
4957                         if( list[ --i ].uigroup === uigroup ) return list[ i ];
4958                 };
4959                 return null;
4960         };
4961         
4962         var UIGroupClass = function( apiuser, node ){
4963                 ( new UIGroupPrivateData() ).init( apiuser, node, this );
4964         };
4965         UIGroupClass.prototype = {
4966                 focus : function( _value ){
4967                         var data = UIGroupPrivateData.get( this );
4968                         /*
4969                         if( _value === true ){
4970                                 if( currentItem ){
4971                                         start( apiuser, self, currentItem );
4972                                 } else
4973                                 if( itemList.length > 0 ){
4974                                         start( apiuser, self, itemList[ 0 ] );
4975                                 };
4976                         } else
4977                         if( _value === false ){
4978                                 finish( apiuser, self, currentItem );
4979                         } else
4980                         */
4981                         if( _value && Util.getIndex( data.itemList, _value ) !== -1 ){
4982                                 // currentItem = _value;
4983                                 currentList = data.itemList;
4984                         };
4985                         return currentUi === this; 
4986                 },
4987                 blur : function(){
4988                         var data = UIGroupPrivateData.get( this );
4989                         if( currentList === data.itemList ){
4990                                 currentList = null;
4991                         };
4992                 },
4993                 createInputText : function( elmWrapper, onUpdate, validater ){
4994                         var data     = UIGroupPrivateData.get( this ),
4995                                 elmValue = Util.getElementsByClassName( elmWrapper, 'editable-value' )[ 0 ],
4996                                 ret;
4997                         if( elmValue ){
4998                                 ret = new TextInputClass( data, elmWrapper, elmValue, onUpdate, validater );
4999                                 data.itemList.push( ret );
5000                                 return ret;
5001                         };
5002                         alert( 'error createInputText' );
5003                 },
5004                 createButton : function( elm, onClick ){
5005                         var data = UIGroupPrivateData.get( this ),
5006                                 ret  = new ButtonClass( data, elm, onClick );
5007                         data.itemList.push( ret );
5008                         return ret;
5009                 },
5010                 createFileInput : function( elm, onUpdate, validater, elmFileInputReal ){
5011                         var data     = UIGroupPrivateData.get( this ),
5012                                 elmValue = Util.getElementsByClassName( elm, 'fileinput-value' )[ 0 ],
5013                                 ret;
5014                         if( elmValue ){
5015                                 ret = new FileInputClass( data, elm, onUpdate, validater, elmFileInputReal, elmValue );
5016                                 data.itemList.push( ret );
5017                                 return ret;
5018                         };
5019                         return ret;
5020                 },
5021                 createCombobox : function( elm, onUpdate, optionList ){
5022                         var data = UIGroupPrivateData.get( this ),
5023                                 ret  = new ComboBoxClass( data, elm, onUpdate, optionList );
5024                         data.itemList.push( ret );
5025                         return ret;
5026                 },
5027                 createCheckBox : function(){
5028                         
5029                 },
5030                 createRadio : function(){
5031                         
5032                 },
5033                 createSlider : function(){
5034                         
5035                 },
5036                 visible : function( v ){
5037                         var data = UIGroupPrivateData.get( this );
5038                         if( Type.isBoolean( v ) === true && data.visible !== v ){
5039                                 for( var i = data.itemList.length; i; ){
5040                                         data.itemList[ --i ].visible( v );
5041                                 };
5042                                 data.visible = v;
5043                                 data.node.disabled( !( data.enabled && v ) );
5044                         };
5045                         return data.visible;
5046                 },
5047                 enabled : function( v ){
5048                         var data = UIGroupPrivateData.get( this );
5049                         if( Type.isBoolean( v ) === true && data.enabled !== v ){
5050                                 for( var i = data.itemList.length; i; ){
5051                                         data.itemList[ --i ].enabled( v );
5052                                 };
5053                                 data.enabled = v;
5054                                 data.node.disabled( !( data.visible && v ) );
5055                         };
5056                         return data.enabled;
5057                 },
5058                 destroy : function(){
5059                         var data = UIGroupPrivateData.get( this ),
5060                                 _item;
5061                         if( currentUi === this ){
5062                                 currentItem.blur();
5063                                 // finish( UIItemPrivateData.get( currentItem ) );
5064                         };                      
5065                         while( _item = data.itemList.shift() ){
5066                                 _item.destroy();
5067                         };
5068                         data.destroy();
5069                 }
5070         };
5071         
5072         function start( data ){
5073                 if( currentItem !== data.item ){
5074                         currentUi !== data.groupData.uigroup && currentUi && currentUi.blur();
5075                         
5076                         currentItem !== null && currentItem.blur();
5077                         
5078                         currentUser = data.groupData.apiuser;
5079                         currentUi   = data.groupData.uigroup;
5080                         currentItem = data.item;
5081                         
5082                         currentUi.focus( currentItem );
5083                         
5084                         // if( currentUser !== _apiuser ) {
5085                                 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 );
5086                                 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 );
5087                                 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown,  9 );
5088                                 KeyEvent.updateCurrentListener( SUPER_USER_KEY );
5089                         // };
5090                 };
5091         }
5092         function finish( data ){
5093                 if( currentItem === data.item ){
5094                         currentUi.blur();
5095                         
5096                         currentUser = null;
5097                         currentUi   = null;
5098                         currentItem = null;
5099                         currentList = null;
5100                         
5101                         KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 );
5102                         KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 );
5103                         KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown,  9 );
5104                         KeyEvent.updateCurrentListener( data.groupData.apiuser );
5105                 };
5106         };
5107
5108         function onKeyDown( e ){
5109                 if( currentItem === null ) return true;
5110                 var keyCode = e.keyCode,
5111                         index   = Util.getIndex( currentList, currentItem );
5112                 if( keyCode === 13 || keyCode === 27 || keyCode === 9 || keyCode === 18 || e.altKey === true ){ // 13.return 27.esc 9.tab 18.alt
5113                         keyCode === 9  && tabShift( index, e.shiftKey === true ? -1 : 1 );
5114                         keyCode === 13 && currentItem instanceof ComboBoxClass && OptionControl.onEnter();
5115                         keyCode === 13 && tabShift( index, 1 );                 
5116                         currentItem && currentItem.blur( keyCode );
5117                         return false;
5118                 };
5119         };
5120
5121         function tabShift( index, way ){
5122                 var l = currentList.length,
5123                         i = index + way,
5124                         item;
5125                 if( l < 2 ) return;
5126                 while( i !== index ){
5127                         i = i < 0 ?
5128                                 l - 1 :
5129                                 i < l ? i : 0; // 0 < i < l
5130                         item = currentList[ i ];
5131                         if( item.enabled() === true && item.visible() === true ){
5132                                 AsyncCall.add( currentUser, item.focus, null, item );
5133                                 return;
5134                         };
5135                         i += way;
5136                 };
5137         };
5138         
5139         return {
5140                 createUIGroup: function( apiuser, node ){
5141                         var uid  = apiuser.getUID(),
5142                                 list = UI_LIST[ uid ],
5143                                 ui   = new UIGroupClass( apiuser, node );
5144                         if( Type.isArray( list ) === false ){
5145                                 list = UI_LIST[ uid ] = [];
5146                         };
5147                         list.push( ui );
5148                         return ui;
5149                 },
5150                 onWindowResize: function( w, h ){
5151                         windowW = w;
5152                         windowH = h;
5153                         currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h );
5154                         currentItem instanceof TextInputClass && TextInputManager.onWindowResize( w, h );
5155                         currentItem instanceof FileInputClass && FileInputManager.onWindowResize( w, h );
5156                 },
5157                 onCurrentApplicationChange: function( _apiuser ){
5158                         currentList = UI_LIST[ _apiuser.getUID() ];
5159                 },
5160                 onApplicationShutdown: function( _apiuser ){
5161                         KeyEvent.remove( _apiuser );
5162                 },
5163                 onSystemShutdown: function(){
5164                         
5165                 }
5166         };
5167 })();
5168
5169 var UIForm = ( function(){
5170         var FORM_LIST           = [];
5171         var CLASSNAME_FORM      = 'uiform-invisible';
5172         var CLASSNAME_FILE_WRAP = 'ui-fileinput-wrapper';
5173         var FormItemData = function(){};
5174         FormItemData.prototype = {
5175                 formData : null,
5176                 uiItem   : null,
5177                 init : function( formData, uiItem ){
5178                         this.formData = formData;
5179                         this.uiItem   = uiItem;
5180                 },
5181                 onUpdate : function( v ){
5182                         // var index = Util.getIndex( this.formData.itemList, this );
5183                 }
5184         };
5185         
5186         var FormPrivateData = function(){};
5187         FormPrivateData.prototype = {
5188                 apiuser  : null,
5189                 node     : null,
5190                 form     : null,
5191                 elmForm  : null,
5192                 itemList : null,
5193                 visible  : true,
5194                 enabled  : true,
5195                 init     : function( apiuser, from, node, elm, elmForm ){
5196                         this.apiuser      = apiuser;
5197                         this.form         = form;
5198                         this.ui           = apiuser.createUIGroup( node );
5199                         this.node         = node;
5200                         this.elm          = elm;
5201                         this.elmForm      = elmForm;
5202                         this.itemList     = [];
5203                         elmForm.className = CLASSNAME_FORM;
5204                         FormPrivateData.list.push( this );
5205                         
5206                         var forms = Util.copyArray( elmForm.getElementsByTagName( '*' ) ),
5207                                 l     = forms.length,
5208                                 i     = 0,
5209                                 items = 'input,select,textarea,button',
5210                                 form, data, el, wrap;
5211                         for( ; i<l; ++i ){
5212                                 form = forms[ i ];
5213                                 if( form.nodeType !== 1 ) continue;
5214                                 switch( form.tagName.toLowerCase() ){
5215                                         case 'input':
5216                                                 switch( form.type.toLowerCase() ){
5217                                                         case 'text':
5218                                                                 break;
5219                                                         case 'file':
5220                                                                 el = document.createElement( 'div' );
5221                                                                 el.className = 'uiform-file-container';
5222                                                                 el.appendChild( document.createElement( 'div' ) );
5223                                                                 el.appendChild( document.createElement( 'div' ) );
5224                                                                 el.firstChild.className = 'uiform-label';
5225                                                                 el.lastChild.className  = 'uiform-file fileinput-value';
5226                                                                 // opera9 don't work for opera9;
5227                                                                 //el = Util.pullHtmlAsTemplete( '<div class="uiform-file-container"><div class="uiform-label"></div><div class="uiform-file fileinput-value"></div></div>' );
5228                                                                 elm.appendChild( el );
5229                                                                 data = new FormItemData();
5230                                                                 wrap = document.createElement( 'div' );
5231                                                                 form.parentNode.insertBefore( wrap, form );
5232                                                                 wrap.className = CLASSNAME_FILE_WRAP;
5233                                                                 wrap.appendChild( form );
5234                                                                 data.init( this, this.ui.createFileInput( el, data.onUpdate, null, form ) );
5235                                                                 this.itemList.push( data );
5236                                                                 break;
5237                                                         case 'button':
5238                                                                 break;
5239                                                         default:
5240                                                                 continue;
5241                                                 };
5242                                                 break;
5243                                         case 'select':
5244                                                 break;
5245                                         case 'button':
5246                                                 break;
5247                                         case 'textarea':
5248                                                 break;
5249                                         default:
5250                                                 continue;
5251                                 };
5252                         };
5253                 },
5254                 destroy  : function(){
5255                         
5256                 }
5257         };
5258         FormPrivateData.list = [];
5259         FormPrivateData.get  = function( from ){
5260                 var list = FormPrivateData.list,
5261                         i    = list.length;
5262                 for( ; i; ){
5263                         if( list[ --i ].form === form ) return list[ i ];
5264                 };
5265                 return null;
5266         };
5267         
5268         var FormClass = function( apiuser, node, elm, elmForm ){
5269                 ( new FormPrivateData() ).init( apiuser, this, node, elm, elmForm );
5270         };
5271         FormClass.prototype = {
5272                 createTextInput : function(){
5273                         
5274                 },
5275                 createMultiLineInput : function(){
5276                         
5277                 },
5278                 createFileInput : function(){
5279                         
5280                 },
5281                 createButton : function(){
5282                         
5283                 },
5284                 createComboBox : function(){
5285                         
5286                 },
5287                 submit : function(){
5288                         
5289                 }
5290         };
5291         
5292         return {
5293                 createForm: function( apiuser, nodeOrElm, opt_elmForm ){
5294                         var uid  = apiuser.getUID(),
5295                                 list = FORM_LIST[ uid ],
5296                                 node, elm, form;
5297                         if( PointingDeviceEventTree.isNodeInstance( nodeOrElm ) === true ){
5298                                 node = nodeOrElm;
5299                                 elm  = PointingDeviceEventTree._getNodePrivateData( nodeOrElm ).elm;
5300                         } else {
5301                                 // App が eventTree を持っている?
5302                                 // App が eventTree を持っていない
5303                                 elm  = nodeOrElm;
5304                         };  
5305                         form = new FormClass( apiuser, node, elm, opt_elmForm );
5306                         if( Type.isArray( list ) === false ){
5307                                 list = FORM_LIST[ uid ] = [];
5308                         };
5309                         list.push( form );
5310                         return form;
5311                 },
5312                 onWindowResize: function( w, h ){
5313                         windowW = w;
5314                         windowH = h;
5315                         currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h );
5316                         currentItem instanceof TextInputClass && TextInputManager.onWindowResize( w, h );
5317                         currentItem instanceof FileInputClass && FileInputManager.onWindowResize( w, h );
5318                 },
5319                 onCurrentApplicationChange: function( _apiuser ){
5320                 },
5321                 onApplicationShutdown: function( _apiuser ){
5322                 },
5323                 onSystemShutdown: function(){
5324                         
5325                 }
5326         };
5327 })();
5328
5329 var Finder = ( function(){
5330         var FINDER_LIST              = [],
5331                 ELM_ORIGIN_LOCATION_ITEM = Util.pullHtmlAsTemplete( '<div class="finder-location-item"></div>' ),
5332                 HTML_FINDER_ICON = ( function(){
5333                         return ( UA.isIE === true && UA.ieVersion < 8 ?
5334                         [
5335                                 '<div class="finder-icon fnder-icon-ie7">',
5336                                         '<div class="finder-icon-handle"></div>',
5337                                         '<div class="file-icon"><div></div></div>',
5338                                         '<span class="finder-icon-cell finder-icon-ie-filename">',
5339                                                 '<span class="finder-icon-vertical-middle-outer">',
5340                                                         '<span class="finder-icon-vertical-middle-inner">',
5341                                                                 '<span class="finder-icon-filename break-word">file name</span>',
5342                                                         '</span>',
5343                                                 '</span>',
5344                                         '</span>',
5345                                         '<span class="finder-icon-cell finder-icon-ie-summary">',
5346                                                 '<span class="finder-icon-vertical-middle-outer">',
5347                                                         '<span class="finder-icon-vertical-middle-inner">',
5348                                                                 '<span class="finder-icon-summary break-word">file descriptiion</span>',
5349                                                         '</span>',
5350                                                 '</span>',
5351                                         '</span>',
5352                                         '<div class="finder-icon-down"></div>',
5353                                 '</div>'
5354                         ] :
5355                         [
5356                                 '<div class="finder-icon fnder-icon-modern">',
5357                                         '<div class="finder-icon-handle"></div>',
5358                                         '<div class="file-icon"><div></div></div>',
5359                                         '<div class="finder-icon-filename break-word">file name</div>',
5360                                         '<div class="finder-icon-summary break-word">file descriptiion</div>',
5361                                         '<div class="finder-icon-down">&gt;</div>',
5362                                 '</div>'
5363                         ] ).join( '' );
5364                 })(),
5365                 ELM_ORIGIN_FINDER_ICON = Util.pullHtmlAsTemplete( HTML_FINDER_ICON ),
5366                 ICON_HEIGHT            = Util.getElementSize( ELM_ORIGIN_FINDER_ICON ).height;
5367         
5368         // t : 時間
5369     // b : 開始の値(開始時の座標やスケールなど)
5370     // c : 開始と終了の値の差分
5371     // d : Tween(トゥイーン)の合計時間
5372
5373         function easeOutQuad( t, b, c, d ){
5374                 t /= d;
5375                 return -c * t*( t-2 ) + b;
5376         };
5377         
5378 /**
5379  * FinderIconClass
5380  */
5381         var FinderIconClass = function(){};
5382         FinderIconClass.prototype = {
5383                 finderData       : null,
5384                 file             : null,
5385                 elm              : null,
5386                 node             : null,
5387                 _index           : -1,
5388                 _style           : -1,
5389                 init : function( page, file, w, index, style ){
5390                         if( !this.elm ) this.elm  = ELM_ORIGIN_FINDER_ICON.cloneNode( true );
5391
5392                         if( this.page !== page ){
5393                                 this.page = page;
5394                                 page.elm.appendChild( this.elm );
5395                                 this.node && this.node.remove();
5396                                 this.node = page.node.createNode( this.elm, false, true, 'finder-icon-hover', '' );
5397                         };
5398                         if( this.file !== file ){
5399                                 this.file && this.file.destroy();
5400                                 this.file   = file;
5401                                 this._index = index;
5402                                 this.draw( w );
5403                                 return;
5404                         };
5405                         if( this._index !== index ){
5406                                 this._index = index;
5407                                 this.resize( w );
5408                         };
5409                 },
5410                 index : function( _index ){     
5411                         return this._index;
5412                 },
5413                 style : function( _style ){
5414                         return this._style;
5415                 },
5416                 draw : function( w ){
5417                         var file       = this.file,
5418                                 elm        = this.elm,
5419                                 thumb      = file.getThumbnail(),
5420                                 elmThumb   = Util.getElementsByClassName( elm, 'file-icon' )[ 0 ].firstChild,
5421                                 elmName    = Util.getElementsByClassName( elm, 'finder-icon-filename' )[ 0 ],
5422                                 elmDesc    = Util.getElementsByClassName( elm, 'finder-icon-summary' )[ 0 ];
5423                         if( thumb.image ){
5424                                 elmThumb.className = 'has-thumbnail';
5425                                 elmThumb.style.backgroundImage = [ 'url(', thumb.image, ')' ].join( '' );
5426                         } else {
5427                                 elmThumb.className = thumb.className;
5428                                 elmThumb.style.backgroundImage = '';
5429                         };
5430                         
5431                         elmName.firstChild.data = file.getName();
5432                         elmDesc.firstChild.data = file.getSummary();
5433                         
5434                         this.resize( w );
5435                 },
5436                 resize : function( w ){
5437                         this.node.update( 0, this._index * ICON_HEIGHT, w );
5438                 },
5439                 onEditorClick : function( e ){
5440                         this.onEditorCallback && this.onEditorCallback( this.file, this.file.editorApplicationList()[ 0 ] );
5441                         return false;
5442                 },
5443                 onViwerClick : function( e ){
5444                         this.onViewerCallback && this.onViewerCallback( this.file, this.file.viewerApplicationList()[ 0 ] );
5445                         return false;
5446                 },
5447                 onActionClick : function( e ){
5448                         this.onActionCallback && this.onActionCallback( this.file );
5449                         return false;
5450                 },
5451                 destroy : function(){
5452                         this.elm && this.elm.parentNode.removeChild( this.elm );
5453                         this.file && this.file.destroy();
5454                         this.node && this.node.remove();
5455                         delete this.page;
5456                         delete this.file;
5457                         delete this.node;
5458                         delete this._index;
5459                         delete this._style;
5460                         FinderIconClass.pool.push( this );
5461                 }       
5462         };
5463         FinderIconClass.pool = [];
5464         FinderIconClass.get = function( page, file, w, index, style ){
5465                 var _icon = FinderIconClass.pool.length > 0 ? FinderIconClass.pool.shift() : new FinderIconClass();
5466                 _icon.init( page, file, w, index, style );
5467                 return _icon;
5468         };
5469
5470 /**
5471  * PathClass
5472  */
5473         var PathClass = function(){};
5474         PathClass.prototype = {
5475                 finderData : null,
5476                 elm        : null,
5477                 node       : null,
5478                 file       : null,
5479                 _index     : null,
5480                 w          : 0,
5481                 init : function( finderData, file, index ){
5482                         if( !this.elm ) this.elm  = ELM_ORIGIN_LOCATION_ITEM.cloneNode( true );
5483                         
5484                         if( this.finderData !== finderData ){
5485                                 this.finderData = finderData;
5486                                 finderData.elmPath.appendChild( this.elm );
5487                                 this.node && this.node.remove();
5488                                 delete this.node;
5489                         };
5490                         if( this.file !== file ){
5491                                 this.file = file;
5492                                 this.draw();
5493                         };
5494                         this._index = index;
5495                         if( !this.node ) this.node = finderData.nodePath.createNode( this.elm, false, true, 'finder-path-hover', 'pointer' );
5496                 },
5497                 draw  : function(){
5498                         this.elm.className = 'file-icon-' + this.file.getType();
5499                         this.elm.innerHTML = this.file.getName();                       
5500                 },
5501                 textWidth : function(){
5502                         this.elm.style.width = 'auto';
5503                         var ret = this.elm.offsetWidth;
5504                         this.elm.style.width = '';
5505                         return ret + 15;
5506                 },
5507                 update : function( x, w ){
5508                         this.node.update( x - 15, undefined, w );
5509                 },
5510                 index : function( _index ){
5511                         return this._index;
5512                 },
5513                 destroy : function(){
5514                         this.finderData.elmPath.removeChild( this.elm );
5515                         this.node && this.node.remove();
5516                         
5517                         delete this.finderData;
5518                         delete this.elm;
5519                         delete this.node;
5520                         delete this.file;
5521                         delete this._index;
5522                         PathClass.pool.push( this );
5523                 }
5524         };
5525         PathClass.pool = [];
5526         PathClass.get  = function( finderData, file, index ){
5527                 var _bread = PathClass.pool.length > 0 ? PathClass.pool.shift() : new PathClass();
5528                 _bread.init( finderData, file, index );
5529                 return _bread;
5530         };
5531         
5532         
5533         /**
5534          * Page
5535          */
5536         var PageClass = function(){};
5537         PageClass.prototype = {
5538                 nodeRoot     : null,
5539                 elmRoot      : null,
5540                 elmScroll    : null,
5541                 elm          : null,
5542                 node         : null,
5543                 folder       : null,
5544                 iconList     : null,
5545                 sliding      : false,
5546                 currentX     : 0,
5547                 panTime      : 0,
5548                 startX       : 0,
5549                 offsetX      : 0,
5550                 panTotalTime : 0,
5551                 isPanOut     : false,
5552                 init : function( nodeRoot, elmRoot, elmScroll ){
5553                         this.nodeRoot  = nodeRoot;
5554                         this.elmRoot   = elmRoot;
5555                         this.elmScroll = elmScroll;
5556                         
5557                         if( this.elm === null ){
5558                                 this.elm = document.createElement( 'div' );
5559                         };
5560                         elmScroll.appendChild( this.elm );
5561                         this.elm.style.cssText = 'position:absolute;top:0;';
5562                         // this.elm.style.display = 'none';
5563                         this.node = this.nodeRoot.createNode( this.elm, true, false );
5564                         if( this.iconList === null ){
5565                                 this.iconList = [];
5566                         };
5567                 },
5568                 panInReady : function( way ){
5569                         this.elm.style.display = '';
5570                         var x = this.sliding === true ? this.currentX : way * this.nodeRoot.width();
5571                         this.startX       = this.currentX = x;
5572                         this.targetX      = 0;
5573                         this.offsetX      = -x;
5574                         this.panTime      = 0;
5575                         this.panTotalTime = 20;
5576                         this.sliding      = true;
5577                         this.isPanOut     = false;
5578                         // this.elm.style.left = x + 'px';
5579                         this.node.x( x );
5580                 },
5581                 panOutReady : function( way ){
5582                         var x = -way * this.nodeRoot.width();
5583                         this.startX       = this.currentX || 0;
5584                         this.targetX      = x;
5585                         this.offsetX      = x - this.startX;
5586                         this.panTime      = 0;
5587                         this.panTotalTime = 20;
5588                         this.sliding      = true;
5589                         this.isPanOut     = true;
5590                 },
5591                 pan : function(){
5592                         var page = this,
5593                                 x    = page.currentX = easeOutQuad( page.panTime, page.startX, page.offsetX, page.panTotalTime );
5594                         // page.elm.style.left = x + 'px';
5595                         this.node.x( x );
5596                         if( page.panTotalTime < ++page.panTime ){
5597                                 delete page.panTime;
5598                                 delete page.startX;
5599                                 delete page.offsetX;                                    
5600                                 delete page.panTotalTime;
5601                                 delete page.sliding;
5602                                 if( this.isPanOut === true ) this.elm.style.display = 'none';
5603                         };
5604                 },
5605                 draw : function( folder ){
5606                         _w = this.nodeRoot.width();
5607                         this.folder = folder;
5608                         var data     = this,
5609                                 iconList = data.iconList,
5610                                 i        = 0,
5611                                 j        = 0,
5612                                 l        = folder.getChildFileLength(),
5613                                 m        = iconList.length,
5614                                 scrollY  = -this.nodeRoot.scrollY(),
5615                                 rootH    = scrollY + this.nodeRoot.height(),
5616                                 icon;
5617
5618                         for( ; i < l; ++i ){
5619                                 if( ( i + 1 ) * ICON_HEIGHT < scrollY || rootH < i * ICON_HEIGHT ) continue;
5620                                 if( j < m ){
5621                                         iconList[ j ].init( this, folder.getChildFileAt( i ), _w, i, data.style );
5622                                 } else {
5623                                         iconList.push( FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) );
5624                                 };
5625                                 j++;
5626                         };
5627                         data.elmRoot.className    = folder.getState() === Const.FILE.STATE.LOADING ? 'finder-body loading' : 'finder-body';
5628                         // data.elmRoot.style.height = ( data.h - data.headH ) + 'px';
5629                         
5630                         while( j < iconList.length ) iconList.pop().destroy();
5631                         data.elmScroll.style.height = ( l * ICON_HEIGHT ) + 'px';
5632                 },
5633                 onScroll : function(){
5634                         var _w       = this.nodeRoot.width();
5635                         
5636                         var data     = this,
5637                                 iconList = data.iconList,
5638                                 folder   = this.folder,
5639                                 i        = 0,
5640                                 j        = 0,
5641                                 l        = folder.getChildFileLength(),
5642                                 scrollY  = -this.nodeRoot.scrollY(),
5643                                 rootH    = scrollY + this.nodeRoot.height(),
5644                                 startIndex = 0 < iconList.length ? iconList[ 0 ]._index : 0,
5645                                 icon;
5646                         
5647                         // console.log( ' > ' + scrollY + ' , ' + rootH )
5648                         for( ; i < l; ++i ){
5649                                 if( ( i + 1 ) * ICON_HEIGHT < scrollY || rootH < i * ICON_HEIGHT ){
5650                                         if( iconList.length <= j ) continue;
5651                                         icon = iconList[ j ];
5652                                         if( icon._index !== i ) continue;
5653                                         icon.destroy();
5654                                         iconList.splice( j, 1 );
5655                                         continue;
5656                                 };
5657                                 if( iconList.length <= j || iconList[ j ]._index !== i ){
5658                                         if( i < startIndex ){
5659                                                 iconList.splice( j, 0, FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) );                    
5660                                         } else
5661                                         if( startIndex + iconList.length <= i ){
5662                                                 iconList.push( FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) );                    
5663                                         };                                      
5664                                 };
5665                                 ++j;
5666                         };
5667                         
5668                         //while( j < iconList.length ) iconList.pop().destroy();
5669                 },
5670                 resize : function( w ){
5671                         var list = this.iconList,
5672                                 i    = list.length;
5673                         for( ; i; ) list[ --i ].resize( w );
5674                 },
5675                 destroy : function(){
5676                         var icon;
5677                         while( icon = this.iconList.shift() ) icon.destroy();
5678                         
5679                         this.elm.parentNode.removeChild( this.elm );
5680                 }
5681         };
5682         
5683         var ApplicationButton = function(){};
5684         ApplicationButton.prototype = {
5685                 elm     : null,
5686                 button  : null,
5687                 app     : null,
5688                 file    : null,
5689                 fileUID : -1,
5690                 init    : function( ui, elmParent, app, file ){
5691                         if( this.elm === null ){
5692                                 this.elm = document.createElement( 'div' );
5693                         };
5694                         elmParent.appendChild( this.elm );
5695                         this.elm.className = 'button';
5696                         this.elm.innerHTML = app.getDisplayName();
5697                         
5698                         var that = this;
5699                         this.button = ui.createButton( this.elm, function(){
5700                                 that.onClick();
5701                                 // that = null;
5702                         } );
5703                         
5704                         this.app     = app;
5705                         this.file    = file;
5706                         this.fileUID = file.getUID();
5707                 },
5708                 onClick : function(){
5709                         this.app.boot( this.file );
5710                         return false;
5711                 },
5712                 destroy : function(){
5713                         var elm = this.elm;
5714                         elm.parentNode.removeChild( elm );
5715                         
5716                         this.button.destroy();
5717                         //this.kill()
5718                         //this.elm = elm;
5719                 }
5720         };
5721         
5722         var DetailPageClass = function(){};
5723         DetailPageClass.prototype = Util.extend( new PageClass(), {
5724                 appButtons : null,
5725                 init : function( finderData ){
5726                         this.finderData = finderData;
5727                         this.apiuser    = finderData.apiuser;
5728                         this.nodeRoot   = finderData.nodeRoot;
5729                         this.elmRoot    = finderData.elmRoot;
5730                         this.elmScroll  = finderData.elmScroll;
5731                         
5732                         if( this.elm === null ){
5733                                 this.elm = Util.pullHtmlAsTemplete( [
5734                                         '<div class="finder-detail">',
5735                                                 '<div class="file-icon"><div></div></div>',
5736                                                 '<div class="finder-detail-filename break-word">file name</div>',
5737                                                 '<div class="finder-detail-summary break-word">file descriptiion</div>',
5738                                                 '<div>View this file</div>',
5739                                                 '<div class="viewer-apps"></div>',                                              
5740                                                 '<div>Edit this file</div>',
5741                                                 '<div class="editor-apps"></div>',
5742                                         '</div>'
5743                                 ].join( '' ) );
5744                         };
5745                         this.elm.style.display = 'none';
5746                         this.elmScroll.appendChild( this.elm );
5747                         this.node = this.nodeRoot.createNode( this.elm, true, false );
5748                         
5749                         this.ui = this.apiuser.createUIGroup( this.node );
5750                         this.appButtons = [];
5751                 },
5752                 draw : function( file ){
5753                         var elm        = this.elm,
5754                                 thumb      = file.getThumbnail(),
5755                                 elmThumb   = Util.getElementsByClassName( elm, 'file-icon' )[ 0 ].firstChild,
5756                                 elmName    = Util.getElementsByClassName( elm, 'finder-detail-filename' )[ 0 ],
5757                                 elmDesc    = Util.getElementsByClassName( elm, 'finder-detail-summary' )[ 0 ],
5758                                 tmpButtons = Util.copyArray( this.appButtons ),
5759                                 apps, app, elmContainer;
5760                         if( thumb.image ){
5761                                 elmThumb.className = 'has-thumbnail';
5762                                 elmThumb.style.backgroundImage = [ 'url(', thumb.image, ')' ].join( '' );
5763                         } else {
5764                                 elmThumb.className = thumb.className;
5765                                 elmThumb.style.backgroundImage = '';
5766                         };
5767                         
5768                         elmName.firstChild.data = file.getName();
5769                         elmDesc.firstChild.data = file.getSummary();
5770                         this.node.width( this.nodeRoot.width() );
5771                         this.node.height( this.nodeRoot.height() );
5772                         
5773                         this.appButtons.length = 0;
5774                         
5775                         apps         = file.viewerApplicationList();
5776                         elmContainer = Util.getElementsByClassName( elm, 'viewer-apps' )[ 0 ];
5777                         for( i = 0; i < apps.length; ++i ){
5778                                 button = 0 < tmpButtons.length ? tmpButtons.shift() : new ApplicationButton();
5779                                 button.init( this.ui, elmContainer, apps[ i ], file );
5780                                 this.appButtons.push( button );
5781                         };
5782                         apps         = file.editorApplicationList();
5783                         elmContainer = Util.getElementsByClassName( elm, 'editor-apps' )[ 0 ];
5784                         for( i = 0; i < apps.length; ++i ){
5785                                 button = 0 < tmpButtons.length ? tmpButtons.shift() : new ApplicationButton();
5786                                 button.init( this.ui, elmContainer, apps[ i ], file );
5787                                 this.appButtons.push( button );
5788                         };
5789                         
5790                         while( button = tmpButtons.shift() ) button.destroy();
5791                         
5792                         this.resize();
5793                 },
5794                 pan : function(){
5795                         var page = this,
5796                                 x    = page.currentX = easeOutQuad( page.panTime, page.startX, page.offsetX, page.panTotalTime );
5797                         // page.elm.style.left = x + 'px';
5798                         this.node.x( x );
5799                         if( page.panTotalTime < ++page.panTime ){
5800                                 delete page.panTime;
5801                                 delete page.startX;
5802                                 delete page.offsetX;                                    
5803                                 delete page.panTotalTime;
5804                                 delete page.sliding;
5805                                 if( this.isPanOut === true ) this.elm.style.display = 'none';
5806                         };
5807                 },
5808                 onScroll : function(){
5809                         
5810                 },
5811                 resize : function(){
5812                         this.elmScroll.style.height = this.nodeRoot.height() + 'px';
5813                 },
5814                 destroy : function(){
5815                         var button;
5816                         while( button = this.appButtons.shift() ) button.destroy();
5817                         this.ui.destroy();
5818                         this.node.remove();
5819                 }
5820         });
5821         
5822 /**
5823  * FinderPrivateData
5824  */
5825         var FinderPrivateData = Class.create(
5826                 Class.PRIVATE_DATA, {
5827                 finder       : null,
5828                 apiuser      : null,
5829                 elmRoot      : null,
5830                 nodeRoot     : null,
5831                 elmScroll    : null,
5832                 elmPath      : null,
5833                 nodePath     : null,
5834                 tree         : null,
5835                 onSelect     : null,
5836                 viewerOption : null,
5837                 editorOption : null,
5838                 pathList     : null,
5839                 headH        : 0,
5840                 iconW        : 0,
5841                 iconH        : 0,
5842                 style        : 0,
5843                 pageIcons1   : null,
5844                 pageIcons2   : null,
5845                 panInPage    : null,
5846                 panOutPage   : null,
5847                 pageDetail   : null,
5848                 currentFile  : null,
5849                 Constructor : function( finder, apiuser, elm, tree, onSelect, viewerOption, editorOption ){
5850                         this.finder       = finder;
5851                         this.apiuser      = apiuser;
5852                         if( PointingDeviceEventTree.isNodeInstance( elm ) === true ){
5853                                 this.nodeRoot = elm;
5854                                 this.elmRoot  = PointingDeviceEventTree._getNodePrivateData( elm ).elm;
5855                         } else {
5856                                 // App が eventTree を持っている?
5857                                 // App が eventTree を持っていない
5858                                 this.elmRoot  = elm;
5859                         };
5860                         this.nodeRoot.addEventListener( 'click', this.onIconClick, this );
5861                         this.nodeRoot.addEventListener( 'scroll', this.onScroll, this );
5862                         
5863                         this.elmScroll    = document.createElement( 'div' );
5864                         this.elmRoot.appendChild( this.elmScroll );
5865                         this.elmScroll.className     = 'finder-elm-scroll';
5866                         this.elmScroll.style.cssText = 'width:100%;overflow:hidden;';
5867                         
5868                         this.tree         = tree;
5869                         this.onSelect     = onSelect;
5870                         this.viewerOption = viewerOption;
5871                         this.editorOption = editorOption;
5872                         
5873                         var size          = Util.getElementSize( ELM_ORIGIN_FINDER_ICON );
5874                         this.iconW        = size.width;
5875                         this.iconH        = size.height;
5876                         
5877                         tree.addTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw, this );
5878                         Util.addClass( this.elmRoot, 'finder-body' );
5879                         
5880                         if( this.panInPage === null ){
5881                                 this.pageIcons1 = new PageClass();
5882                                 this.pageIcons2 = new PageClass();
5883                                 this.pageDetail = new DetailPageClass();
5884                         };
5885                         this.pageIcons1.init( this.nodeRoot, this.elmRoot, this.elmScroll );
5886                         this.pageIcons2.init( this.nodeRoot, this.elmRoot, this.elmScroll );
5887                         this.pageDetail.init( this );
5888                 },
5889                 onIconClick : function( e ){
5890                         if( this.panInPage === this.pageDetail ) return;
5891                         
5892                         var target = e.target,
5893                                 list   = this.panInPage.iconList,
5894                                 i, icon,
5895                                 file;
5896                         if( target === this.nodeRoot ) return;
5897                         for( i = list.length; i; ){
5898                                 icon = list[ --i ];
5899                                 if( icon.node === target ){
5900                                         i = icon._index;
5901                                         file = this.currentFile.getChildFileAt( i );
5902                                         if( target.width() - 30 < e.layerX ){
5903                                                 this.tree.down( i );
5904                                                 this.draw( this.w, this.h, 1, true );
5905                                         } else
5906                                         if( file.getChildFileLength() !== -1 || file.getType() === Const.FILE.TYPE.FOLDER ){
5907                                                 this.tree.down( i );
5908                                                 this.draw( this.w, this.h, 1 );
5909                                         } else
5910                                         if( Type.isFunction( this.onSelect ) === true ){ /* && this.onSelect( file ) === true */
5911                                                 this.onSelect( file );
5912                                         } else {
5913                                                 this.tree.down( i );
5914                                                 this.draw( this.w, this.h, 1 );
5915                                         };
5916                                         file.destroy();
5917                                         break;
5918                                 };
5919                         };
5920                 },
5921                 onScroll : function( e ){
5922                         this.panInPage.onScroll( e );
5923                 },
5924                 onPathClick : function( e ){
5925                         var target = e.target,
5926                                 i      = target.nodeIndex();
5927                         if( target === this.nodePath || this.nodePath.numNode() - 1 === i ) return;
5928                         this.tree.up( i );
5929                         this.draw( this.w, this.h, -1 );
5930                 },
5931                 draw : function( w, h, way, showDetail ){
5932                         var data = this, page;
5933                         data.w = w = Type.isFinite( w ) === true ? w : data.w;
5934                         data.h = h = Type.isFinite( h ) === true ? h : data.h;
5935                         
5936                         var file     = this.currentFile = this.tree.getCurrentFile(),
5937                                 isFolder = showDetail !== true && ( file.getChildFileLength() !== -1 || file.getType() === Const.FILE.TYPE.FOLDER );
5938                         
5939                         data.elmPath && data.drawPath( w );
5940                         page = this.panInPage;
5941                         if( Type.isNumber( way ) === true ){
5942                                 if( page.sliding === false ){
5943                                         if( isFolder === true ){
5944                                                 this.panInPage = page === this.pageIcons1 ? this.pageIcons2 : ( page === this.pageIcons2 ? this.pageIcons1 : this.panOutPage );
5945                                         } else {
5946                                                 this.panInPage = this.pageDetail;
5947                                         };
5948                                         this.panOutPage = page;
5949                                 };
5950                                 this.panInPage.panInReady( way );
5951                                 //this.panInPage.elm.className = 'panIN';
5952                                 this.panOutPage.panOutReady( way );
5953                                 //this.panOutPage.elm.className = 'panOut';
5954                                 this.nodeRoot.disabled( true );
5955                                 SystemTimer.add( this.apiuser, this.tick, 16, false, this );
5956                         } else {
5957                                 if( isFolder === true ){
5958                                         this.panInPage = page === null ? this.pageIcons1 : page;
5959                                 } else {
5960                                         this.panInPage = this.pageDetail;
5961                                 };
5962                         };
5963                         this.panInPage.draw( file );
5964                         
5965                         data.nodeRoot.invalidateScrollbar();
5966                 },
5967                 tick : function(){
5968                         if( this.panInPage.sliding === false && this.panOutPage.sliding === false ){
5969                                 SystemTimer.remove( this.apiuser, this.tick );
5970                                 this.nodeRoot.disabled( false );
5971                                 this.nodeRoot.invalidateScrollbar();
5972                                 return;
5973                         };
5974                         this.panInPage.sliding === true && this.panInPage.pan();
5975                         this.panOutPage.sliding  === true && this.panOutPage.pan();
5976                 },
5977                 drawPath : function( w ){
5978                         if( !this.elmPath.parentNode ) return;
5979                         w = this.nodePath.width();
5980                         var data      = this,
5981                                 tree      = data.tree,
5982                                 pathList  = data.pathList,
5983                                 i         = 0,
5984                                 l         = tree.hierarchy() + 1,
5985                                 m         = pathList.length,
5986                                 wList     = [],
5987                                 totalW    = 0,
5988                                 minW      = FinderPrivateData.MIN_PATH_WIDTH,
5989                                 file, path, pathW, offset, remove, pathX = 0, fit = false;
5990                         
5991                         for( ; i < l; ++i ){
5992                                 file = i !== l - 1 ? tree.getParentFileAt( i ) : this.currentFile;
5993                                 if( i < m ){
5994                                         pathList[ i ].init( this, file, i );
5995                                 } else {
5996                                         pathList.push( PathClass.get( this, file, i ) );
5997                                 };
5998                         };
5999                         while( l < pathList.length ) pathList.pop().destroy();
6000                         
6001                         for( i = l; i; ){
6002                                 pathW = pathList[ --i ].textWidth();
6003                                 wList.push( pathW );
6004                                 totalW += pathW;
6005                         };
6006                         
6007                         //if( minW * ( l + 1 ) * 1.2 < w ){
6008                                 console.log( totalW + ' , ' + w )
6009                                 while( true ){
6010                                         if( fit === true ) break;
6011                                         for( i = 0; i < l; ++i ){
6012                                                 offset = totalW - w;
6013                                                 if( offset <= 0 ){
6014                                                         fit = true;
6015                                                         break;
6016                                                 };
6017                                                 remove = l - i;
6018                                                 remove = offset < remove ? offset : remove;
6019                                                 pathW  = wList[ i ];
6020                                                 if( pathW - remove < minW ){
6021                                                         totalW -= ( pathW - minW );
6022                                                         wList[ i ] = minW;
6023                                                 } else {
6024                                                         wList[ i ] = pathW - remove;
6025                                                         totalW -= remove;
6026                                                 };
6027                                         };
6028                                 };
6029                                 for( i = 0; i < l; ++i ){
6030                                         path  = pathList[ i ];
6031                                         pathW = wList[ i ];
6032                                         path.update( pathX, pathW );
6033                                         pathX += pathW;
6034                                 };                      
6035                         //} else {
6036                                 
6037                         //};
6038                 },
6039                 createPath : function( node ){
6040                         if( this.elmPath ) return;
6041                         
6042                         if( PointingDeviceEventTree.isNodeInstance( node ) === true ){
6043                                 this.nodePath = node;
6044                                 this.elmPath  = PointingDeviceEventTree._getNodePrivateData( node ).elm;
6045                                 
6046                                 node.addEventListener( 'click', this.onPathClick, this );
6047                                 Util.addClass( this.elmPath, 'finder-path' );
6048                                 // this.elmPath  = document.createElement( 'div' );
6049                                 // this.elmPath.className = ;
6050                                 this.pathList = [];
6051                                 // this.headH    = 0;
6052                                 AsyncCall.add( this.apiuser, this.draw, null, this );
6053                         };
6054                 },
6055                 onKill : function(){
6056                         this.tree.removeTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw );
6057
6058                         if( this.pathList ){
6059                                 while( this.pathList.length > 0 ) this.pathList.shift().destroy();
6060                         };
6061                         
6062                         this.pageIcons1.destroy();
6063                         this.pageIcons2.destroy();
6064                         this.pageDetail.destroy();
6065                         this.nodeRoot.remove();
6066                         
6067                         FINDER_LIST.splice( Util.getIndex( FINDER_LIST, this.finder ), 1 );
6068                         var data = ApplicationPrivateData.get( this.apiuser ),
6069                                 list = data.finderList,
6070                                 i    = Util.getIndex( list, this.finder );
6071                         i !== -1 && list.splice( i, 1 );
6072                 }
6073         });
6074         FinderPrivateData.MIN_PATH_WIDTH = 25;
6075
6076 /**
6077  * FinderClass
6078  */
6079         var Finder = Class.create(
6080                 FinderPrivateData, {
6081                 Constructor : function( application, elmRoot, tree, onSelect, viewerOption, editorOption ){
6082                         Finder.newPrivateData( this, this, application, elmRoot, tree, onSelect, viewerOption, editorOption );
6083                 },
6084                 MIN_WIDTH  : 200,
6085                 MIN_HEIGHT : 200,
6086                 resize : function( w, h ){
6087                         var data = Finder.getPrivateData( this );
6088                         data.panInPage && data.panInPage.resize( w );
6089                 },
6090                 createPath : function( node ){
6091                         return Finder.getPrivateData( this ).createPath( node );
6092                 },
6093                 destroy : function(){
6094                         this.kill();
6095                 }
6096         });
6097
6098         return {
6099                 init: function(){
6100                         
6101                 },
6102                 create: function( application, elmTarget, tree, onSelect, viewerOption, editorOption ){
6103                         //if( Application.isApplicationInstance( _application ) === false ) return;
6104                         
6105                         var finder = new Finder( application, elmTarget, tree, onSelect, viewerOption, editorOption );
6106                         FINDER_LIST.push( finder );
6107                         return finder;
6108                 },
6109                 registerFinderHead: function(){
6110                         
6111                 },
6112                 registerFinderPane: function( _finderPane ){
6113                         
6114                 },
6115                 isFinderInstance: function( _finder ){
6116                         return _finder instanceof Finder;
6117                 },
6118                 isFinderPaneInstance: function(){
6119                         
6120                 },
6121                 isFinderHeadInstance: function(){
6122                 }
6123         };
6124 })();
6125
6126
6127 /*
6128  * -- len, %
6129  * marginBottom, marginLeft, marginRight, marginTop, margin
6130  * padding, paddingBottom, paddingLeft, paddingRight, paddingTop
6131  * fontSize, textIndent
6132  * height, width
6133  * bottom, left, right, top                     (len, %)
6134  *
6135  * -- len
6136  * borderBottomWidth, borderLeftWidth, borderRightWidth, borderTopWidth, borderWidth,
6137  * letterSpacing
6138  *
6139  * -- color
6140  * backgroundColor
6141  * borderBottomColor, borderLeftColor, borderRightColor, borderTopColor, borderColor
6142  * color
6143  *
6144  * -- special
6145  * clip                 rect(0px, 40px, 40px, 0px);
6146  * backgroundPosition   (len, %)
6147  * opacity
6148  * lineHeight           (len, %, num)
6149  * zIndex                       ( order )
6150  */
6151
6152 var DHTML = ( function(){
6153         
6154         var TICKET_ARRAY = [],
6155                 fpms         = 50,
6156                 round        = Math.round,
6157                 cround       = function( v ){ return round( v * 100 ) / 100 };
6158         
6159         function startAnimation( _elm, _cssObject, _onComplete, _onEnterFrame, _numFrames ){
6160                 var _ticket, i = TICKET_ARRAY.length;
6161                 for( ; i; ){
6162                         _ticket = TICKET_ARRAY[ --i ];
6163                         if( _ticket.elm === _elm ){
6164                                 return;
6165                         };
6166                 };
6167                 
6168                 var _currentValues     = [],
6169                         _offsetValues      = [],
6170                         _endValues         = [],
6171                         _targetProperties  = [],
6172                         _units             = [];
6173                 var target, current,
6174                         inlineStyle    = CSS.getInlineStyle( _elm ),
6175                         currentStyle   = CSS.getWrappedStyle( _elm ),
6176                         targetStyle    = CSS.getWrappedStyle( _elm, _cssObject );
6177                         targetStyle.pxPerEm = currentStyle.get( 'fontSize' )._toPx();
6178                 for( var p in _cssObject ){
6179                         p       = Util.camelize( p );
6180                         target  = targetStyle.get( p );
6181                         current = currentStyle.get( p );
6182
6183                         if( target.isValid() === false || current.isValid() === false || current.equal( target ) !== false ){
6184                                 target.clear();
6185                                 current.clear();
6186                                 continue;
6187                         };
6188                         
6189                         current.convert( target );
6190                         // alert( current.getValue() + ' , ' + target.getValue() )
6191                         _currentValues.push( current.getValue() );
6192                         _offsetValues.push( current.getOffset( target ) );
6193                         _endValues.push( target.getValue() );
6194                         _targetProperties.push( p );
6195                         _units.push( target.getUnit() );
6196
6197                         // IE has trouble with opacity if it does not have layout
6198                         // Force it by setting the zoom level                   
6199                         if( p === 'opacity' && SPECIAL.hasLayout ){
6200                                 if( SPECIAL.hasLayout( _elm ) === false ) inlineStyle.zoom = 1;
6201                                 inlineStyle.filter = current.getValueText();
6202                         } else {
6203                                 inlineStyle[ p ]   = current.getValueText();
6204                         };
6205                         
6206                         target.clear();
6207                         current.clear();
6208                 };
6209                 
6210                 var i, cssTexts = [];
6211                 for( i = 0; i < _numFrames; ++i ){
6212                         if( i < _numFrames - 1 ){
6213                                 tickValue( _currentValues, _offsetValues, _numFrames );
6214                                 cssTexts.push( createCssText( _currentValues, _targetProperties, targetStyle, inlineStyle ) );
6215                         } else {
6216                                 cssTexts.push( createCssText( _endValues, _targetProperties, targetStyle, inlineStyle ) );
6217                         };
6218                 };
6219                 
6220                 TICKET_ARRAY.push( new AnimationTaskClass(
6221                         _elm, cssTexts,
6222                         Type.isFunction( _onComplete ) === true   ? _onComplete   : null,
6223                         Type.isFunction( _onEnterFrame ) === true ? _onEnterFrame : null,
6224                         _numFrames
6225                 ) );
6226                 
6227                 currentStyle.clear();
6228                 targetStyle.clear();            
6229                 SystemTimer.add( SUPER_USER_KEY, onEnterFrame, 1000 / fpms );
6230         };
6231         
6232         function tickValue( current, offset, numFrames ){
6233                 if( Type.isArray( current ) === true ){
6234                         var ret, i = current.length;
6235                         for( ; i; ){
6236                                 --i;
6237                                 ret = tickValue( current[ i ], offset[ i ], numFrames );
6238                                 if( Type.isNumber( ret ) === true ) current[ i ] = ret;
6239                         };
6240                 } else {
6241                         return current + offset / numFrames;
6242                 };
6243         };
6244         function createCssText( update, props, style, inline ){
6245                 var prop;
6246                 for( var i = props.length; i; ){
6247                         prop = style.get( props[ --i ] );
6248                         prop.setValue( update[ i ] );
6249                         inline[ Util.uncamelize( prop.name ) ] = prop.getValueText();
6250                         //if( prop.name === 'backgroundColor' ) alert( prop.getValueText() + '|' + update[ i ].join( ',') )
6251                         prop.clear();
6252                 };
6253                 return CSS.toCssText( inline );
6254         };
6255         
6256         function onEnterFrame(){
6257                 var _ticket, l,
6258                         i = 0;
6259                 while( i < TICKET_ARRAY.length ){
6260                         _ticket = TICKET_ARRAY[ i ];
6261                         l       = _ticket.cssTexts.length;
6262                         _ticket.elm.style.cssText = _ticket.cssTexts.shift();
6263                         if( l === 1 ){
6264                                 _ticket.onComplete && _ticket.onComplete();
6265                                 delete _ticket.elm;
6266                                 delete _ticket.cssTexts;
6267                                 delete _ticket.onComplete;
6268                                 delete _ticket.onEnterFrame;
6269                                 delete _ticket.numFrame;
6270                                 TICKET_ARRAY.splice( i, 1 );
6271                         } else {
6272                                 _ticket.onEnterFrame && _ticket.onEnterFrame( l / _ticket.numFrame );
6273                                 ++i;
6274                         };
6275                 };
6276                 if( TICKET_ARRAY.length === 0 ){
6277                         SystemTimer.remove( SUPER_USER_KEY, onEnterFrame );
6278                 };
6279         };
6280         
6281         var AnimationTaskClass = function( elm, cssTexts, onEnterFrame, onComplete, numFrame ){
6282                 this.elm          = elm;
6283                 this.cssTexts     = cssTexts;
6284                 this.onEnterFrame = onEnterFrame;
6285                 this.onComplete   = onComplete;
6286                 this.numFrame     = numFrame;
6287         };
6288         
6289         var VisualEffectClass = function( elm ){
6290                 this.elm = elm;
6291         };
6292         VisualEffectClass.prototype = {
6293                 anime : function( _cssObject, _onComplete, _onEnterFrame, _time ){
6294                         var _numFrames = Math.floor( _time / fpms );
6295                         startAnimation( this.elm, _cssObject, _onComplete, _onEnterFrame, _numFrames );
6296                 },
6297                 fadeIn : function(){
6298                         
6299                 },
6300                 fadeOut : function(){
6301                         
6302                 },
6303                 update : function( x, y, w, h ){
6304                         var _cssText = this.elm.style.cssText;
6305                 }
6306         };
6307         
6308         return {
6309                 create: function( application, _elm ){
6310                         return new VisualEffectClass( _elm );
6311                 },
6312                 isInstanceOfVisualEffect: function( _instance){
6313                         return _instance instanceof VisualEffectClass;
6314                 }
6315         }
6316 })();
6317
6318
6319 /* --------------------------------------------
6320  * 
6321  */
6322
6323         Application.onCurrentApplicationChange( SUPER_USER_KEY );
6324         
6325         SERVICE_LIST.push( MouseEvent );
6326         
6327         new EventTicketClass( window, 'unload', function(){
6328                 var _service;
6329                 while( SERVICE_LIST.length > 0 ){
6330                         _service = SERVICE_LIST.shift();
6331                         Type.isFunction( _service.onSystemShutdown ) === true && _service.onSystemShutdown();
6332                 }
6333         });
6334         // beforeunload
6335
6336
6337 /* ---------------------------------------------
6338  * broadcast to global
6339  */
6340         window.gOS = {};
6341         
6342         gOS.registerApplication = Application.register;
6343         gOS.registerDriver      = File.registerDriver;
6344         
6345 })( window, document );