OSDN Git Service

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