OSDN Git Service

version 0.5.47, fix scope leek.
[pettanr/clientJs.git] / 0.5.x / javascripts / system.js
1 /*
2  * pettanR system.js
3  *   version 0.5.47
4  *
5  * gadgetOS
6  *   author:
7  *     itozyun
8  *   licence:
9  *     3-clause BSD
10  */
11
12 ( function( window, document, undefined ){
13         
14         var body           = document.getElementsByTagName( 'body' )[ 0 ]; //( document.compatMode || '' ) !== 'CSS1Compat' ? document.body : document.documentElement;// 
15         var SERVICE_LIST   = [];
16         var SUPER_USER_KEY = { getUID: function(){ return 0; }};
17         var API_USER_LIST  = [ SUPER_USER_KEY ];
18         var numApiUser     = 1;
19         
20         function EMPTY_FUNCTION(){};
21         
22         function isApiUser( _user ){
23                 return _user === SUPER_USER_KEY ||
24                         File.isDriver( _user ) === true ||
25                         Application.isApplicationInstance( _user ) === true;
26         };
27         
28         var Const = {
29                 FILE: {
30                         TYPE: {
31                                 UNKNOWN:        0,
32                                 FOLDER:         1,
33                                 IMAGE:          2,
34                                 TEXT:           3,
35                                 HTML:           4,
36                                 CSV:            5,
37                                 JSON:           6,
38                                 XML:            7
39                         },
40                         STATE: {
41                                 UNKNOWN:        0,
42                                 OK:                     1,
43                                 LOADING:        2,
44                                 ERROR:          3,
45                                 BROKEN:         4
46                         },
47                         UPDATE_POLICY: {
48                                 _____:          parseInt( '00000', 2 ),
49                                 ____C:          parseInt( '00001', 2 ), // hasCreateMenu
50                                 ___W_:          parseInt( '00010', 2 ), // isWritable
51                                 ___WC:          parseInt( '00011', 2 ), // isWritable
52                                 __R__:          parseInt( '00100', 2 ), // isRenamable
53                                 __R_C:          parseInt( '00101', 2 ), // hasCreateMenu
54                                 __RW_:          parseInt( '00110', 2 ), // isWritable
55                                 __RWC:          parseInt( '00111', 2 ), // isWritable
56                                 _S___:          parseInt( '01000', 2 ), // childrenIsSortable
57                                 _S__C:          parseInt( '01001', 2 ),
58                                 _S_W_:          parseInt( '01010', 2 ),
59                                 _S_WC:          parseInt( '01011', 2 ),
60                                 _SR__:          parseInt( '01100', 2 ),
61                                 _SR_C:          parseInt( '01101', 2 ),
62                                 _SRW_:          parseInt( '01110', 2 ),
63                                 _SRWC:          parseInt( '01111', 2 ),
64                                 D____:          parseInt( '10000', 2 ),
65                                 D___C:          parseInt( '10001', 2 ), // hasCreateMenu
66                                 D__W_:          parseInt( '10010', 2 ), // isWritable
67                                 D__WC:          parseInt( '10011', 2 ), // isWritable
68                                 D_R__:          parseInt( '10100', 2 ), // isRenamable
69                                 D_R_C:          parseInt( '10101', 2 ), // hasCreateMenu
70                                 D_RW_:          parseInt( '10110', 2 ), // isWritable
71                                 D_RWC:          parseInt( '10111', 2 ), // isWritable
72                                 DS___:          parseInt( '11000', 2 ), // childrenIsSortable
73                                 DS__C:          parseInt( '11001', 2 ),
74                                 DS_W_:          parseInt( '11010', 2 ),
75                                 DS_WC:          parseInt( '11011', 2 ),
76                                 DSR__:          parseInt( '11100', 2 ),
77                                 DSR_C:          parseInt( '11101', 2 ),
78                                 DSRW_:          parseInt( '11110', 2 ),
79                                 DSRWC:          parseInt( '11111', 2 ),
80                                 CREATE:         1,
81                                 WRAITE:         2,
82                                 RENAME:         4,
83                                 SORT:           8,
84                                 DELETE:         16
85                         },
86                         EVENT: {
87                                 UPDATE_ATTRIVUTE:       'onFileUpdate',
88                                 GET_SEQENTIAL_FILES:'gotSeqentilFiles'
89                         },
90                         DATA_PROPERTY_RESERVED: [
91                                 'children', 'driver', 'state', 'type'
92                         ]                       
93                 },
94                 TREE: {
95                         EVENT: {
96                                 UPDATE:                         'onTreeUpdate'
97                         }
98                 },
99                 KEY: {
100                         EVENT: {
101                                 KEY_DOWN:                       'keydown',
102                                 KEY_UP:                         'keyup',
103                                 KEY_CHANGE:                     'keychange',
104                                 CURSOL:                         'cursol'
105                         }
106                 },
107                 APP: {
108                         TYPE: {
109                                 GENERAL : 0,
110                                 OVERLAY : 1,
111                                 PAGE    : 2
112                         }
113                 }
114         };
115
116 /**
117  * Class を定義し システムの管理下に置く.
118  * 全てのクラスと pool が有効の場合インスタンスへの参照が保持される.
119  *  1. Class.create( def, opt_final, opt_pool, opt_abstract ) でクラスを登録.
120  *  2. コンストラクタ となるメソッドは、Constructor : function( arg ){ ... }, に書く.
121  *  3. 通常通り new で インスタンス生成
122  *  4. kill() でオブジェクトをクリーンして削除、pool が有効の場合は pool される.
123  *  5. pool が有効の場合、new で pool されたインスタンスが返される.
124  *  6. 
125  * 
126  */
127 var Class = ( function(){
128         var CLASS_LIST         = [],
129                 DEF_LIST           = [],
130                 PRIVATE_CLASS_LIST = [],
131                 PRIVATE_DEF_LIST   = [],
132                 CONSTRUCTOR        = 'Constructor',
133                 GET_INDEX          = Util.getIndex,
134                 killPrivateFlag    = false,
135                 dataUser           = null,
136                 traits             = null,
137                 f                  = true,
138                 copyArray          = Util.copyArray;
139         
140         function getClass( instance ){
141                 var cList    = CLASS_LIST,
142                         i        = cList.length,
143                         klass;
144                 for( ; i; ){
145                         klass = cList[ --i ];
146                         if( instance instanceof klass ) return klass;
147                 };
148                 cList = PRIVATE_CLASS_LIST;
149                 i     = cList.length;
150                 for( ; i; ){
151                         klass = cList[ --i ];
152                         if( instance instanceof klass ) return klass;
153                 };
154                 
155                 if( GET_INDEX( cList, instance ) !== -1 ) return instance;
156                 if( GET_INDEX( CLASS_LIST, instance ) !== -1 ) return instance;
157         };
158         
159         function getClassDef( KlassOrInstance ){
160                 var getIndex = GET_INDEX,
161                         i        = getIndex( CLASS_LIST, KlassOrInstance );
162                 if( i === -1 ) i = getIndex( CLASS_LIST, getClass( KlassOrInstance ) );
163                 if( i !== -1 ) return DEF_LIST[ i ];
164                 
165                 i = getIndex( PRIVATE_CLASS_LIST, KlassOrInstance );
166                 if( i === -1 ) i = getIndex( PRIVATE_CLASS_LIST, getClass( KlassOrInstance ) );
167                 if( i !== -1 ) return PRIVATE_DEF_LIST[ i ];
168                 
169                 if( GET_INDEX( DEF_LIST, KlassOrInstance ) !== -1 ) return KlassOrInstance;
170                 if( GET_INDEX( PRIVATE_DEF_LIST, KlassOrInstance ) !== -1 ) return KlassOrInstance;
171         };
172         
173         /* over のプロパティを target にコピーする.ただし target の プロパティが優先, force で解除 */
174         function override( target, over, force ){
175                 for( var p in over ){
176                         if( force === true || typeof target[ p ] === 'undefined' ){
177                                 target[ p ] = over[ p ];
178                         };
179                 };
180                 return target;
181         };
182         
183         /* サブクラスを作るメソッド  
184          * var subClass = superClass.inherits( ... ) 
185          * http://d.hatena.ne.jp/m-hiyama/20051018/1129605002
186          */
187         function inherits( /* displayName, classSetting, opt_PrivateClass, props */ ){
188                 var args        = copyArray( arguments ),
189                         params      = [],
190                         Super       = this,
191                         superDef    = getClassDef( Super ),
192                         displayName = args[ 0 ],
193                         classSetting,
194                         opt_super,
195                         klass;
196                 if( superDef.Final === true ) throw new Error( 'Class is final!' );
197                 
198                 if( Type.isString( displayName ) === true ){
199                         args.shift();
200                 } else {
201                         displayName = 'SubClass of ' + superDef.displayName;
202                 };
203                 params.push( displayName );
204                 
205                 classSetting = args[ 0 ];
206                 if( Type.isNumber( classSetting ) === true ){
207                         if( superDef.isPrivate === true ) classSetting = classSetting | Class.PRIVATE_DATA;
208                         opt_super = !!( classSetting & Class.SUPER_ACCESS );
209                         params.push( classSetting );
210                         args.shift();
211                 };
212                 if( getClass( args[ 0 ] ) ){
213                         params.push( args.shift() );
214                 } else
215                 if( superDef.privateClass ){
216                         params.push( superDef.privateClass );
217                 };
218                 params.push( args[ 0 ] ); /* props */
219                 f      = false;
220                 traits = new Super();
221                 f      = true;
222                 klass  = Class.create.apply( Class, params );
223                 traits = null;
224                 if( opt_super === true ) getClassDef( klass ).Super = Super.prototype;
225                 return klass;
226         };
227         
228         /* Class.create で作られたクラスのインスタンスが共通で備えるメソッド */
229         var CommonProps = {
230                 kill : function(){
231                         var instance = this,
232                                 klass    = getClass( instance ),
233                                 def      = getClassDef( klass ),
234                                 data, p, i;
235                         if( def.isPrivate === true && killPrivateFlag === false ){
236                                 throw new Error( 'PrivateInstance.kill() work in PrivateUser.kill().' );
237                         };
238                         Type.isFunction( instance.onKill ) === true && instance.onKill();
239                         for( p in instance ){
240                                 if( instance.hasOwnProperty && !instance.hasOwnProperty( p ) ) continue;
241                                 delete instance[ p ];
242                         };
243                         if( def.pool ){
244                                 def.live && def.live.splice( GET_INDEX( def.live, instance ), 1 );
245                                 def.pool.push( instance );
246                         };
247                         if( def.privateClass ){
248                                 i = GET_INDEX( def.userList, instance );
249                                 if( i !== -1 ){
250                                         data            = klass.getPrivateData( instance );
251                                         killPrivateFlag = true;
252                                         data.kill();
253                                         killPrivateFlag = false;
254                                         def.dataList.splice( i, 1 );
255                                         def.userList.splice( i, 1 );
256                                 };
257                         };
258                         // myCallback の削除
259                         // myCallback を受け取った API への通知
260                 },
261                 getMyCallback : function( callback ){
262                         var def       = getClassDef( this ),
263                                 iList     = def.callbackInstanceList,
264                                 rList     = def.callbackRegisterList,
265                                 i, cList, myCallback;
266                         if( !iList ){
267                                 iList = def.callbackInstanceList = [];
268                                 rList = def.callbackRegisterList = [];
269                         };
270                         i = GET_INDEX( iList, this );
271                         if( i === -1 ){
272                                 cList = [];
273                                 iList.push( this );
274                                 rList.push( cList );
275                         } else {
276                                 cList = rList[ i ];
277                                 for( i = cList.length; i; ){
278                                         if( cList[ --i ].callback === callback ) return cList[ i ];
279                                 };
280                         };
281                         myCallback = new Callback( this, callback );
282                         cList.push( myCallback );
283                         return myCallback;
284                 },
285                 releaseMyCallback : function( callback ){
286                         var def   = getClassDef( this ),
287                                 iList = def.callbackInstanceList,
288                                 rList = def.callbackRegisterList,
289                                 i, _i, cList;
290                         if( !iList ) return;
291                         i = GET_INDEX( iList, this );
292                         if( i === -1 ) return;
293                         cList = rList[ i ];
294                         _i    = GET_INDEX( cList, callback );
295                         if( _i === -1 ) return;
296                         cList.splice( _i, 1 );
297                         callback.kill();
298                         if( cList.length !== 0 ) return;
299                         iList.splice( i, 1 );
300                         rList.splice( i, 1 );
301                         if( iList.length !== 0 ) return;
302                         delete def.callbackInstanceList;
303                         delete def.callbackRegisterList;
304                 }
305         };
306
307         /* privateDataclass をもつクラスに追加されるメソッド */
308         function newPrivateData( /* instance, args */ ){
309                 var args         = copyArray( arguments ),
310                         user         = args.shift(),
311                         def          = getClassDef( user ),
312                         privateClass = def.privateClass,
313                         privateDef   = getClassDef( privateClass ),
314                         i            = -1,
315                         data;
316                 if( def.userList ){
317                         i = GET_INDEX( def.userList, user );
318                 } else {
319                         def.userList = [];
320                         def.dataList = [];
321                 };
322                 if( i !== -1 ){
323                         throw new Error( 'PrivateData already exist!' );
324                 };
325                 dataUser  = user;
326                 data      = new privateClass( args );
327                 data.User = user;
328                 dataUser  = null;       
329                 return data;
330         };
331         function getPrivateData( instance ){
332                 var def = getClassDef( instance ),
333                         i   = GET_INDEX( def.userList, instance );
334                 if( i !== -1 ) return def.dataList[ i ];
335         };
336         
337         /*
338          * new の実体.コンストラクタの機能は instance.Constructor に書く.
339          * これにより pool された オブジェクト(破棄されたインスタンス) を再利用できる
340          */
341         /* Constructor Real for GeneralClass */
342         function C( args ){
343                 var klass = this,
344                         def   = getClassDef( klass ),   
345                         instance,
346                         userDef;
347                 if( def.Abstract === true ){
348                         throw new Error( 'AbstractClass!' );
349                 };
350                 if( def.isPrivate === true && dataUser === null ){
351                         throw new Error( 'use myClass.newPrivateData( instance, ...args )!' );
352                 };
353                 f = false;
354                 instance = def.pool && def.pool.length > 0 ? def.pool.shift() : instance = new klass();
355                 f = true;
356                 if( def.Super && !instance.Super ) instance.Super = def.Super;
357                 if( def.isPrivate === true ){
358                         userDef = getClassDef( dataUser );
359                         userDef.dataList.push( instance );
360                         userDef.userList.push( dataUser );
361                 } else {
362                         def.live && def.live.push( instance );
363                         args = copyArray( arguments );
364                 };
365                 def[ CONSTRUCTOR ] && def[ CONSTRUCTOR ].apply( instance, args );
366                 return instance;
367         };
368         
369         return {
370                 POOL_OBJECT  : 1,
371                 ABSTRACT     : 2,
372                 FINAL        : 4,
373                 SUPER_ACCESS : 8,
374                 PRIVATE_DATA : 16,
375                 create : function( /* displayName, classSetting, opt_PrivateClass, props */ ){
376                         var args        = copyArray( arguments ),
377                                 displayName = args[ 0 ],
378                                 classSetting,
379                                 opt_pool, opt_abstract, opt_final, opt_private,
380                                 privateDef,
381                                 props,
382                                 klass,
383                                 classDef = {};
384                         if( Type.isString( displayName ) === true ){
385                                 classDef.displayName = displayName;
386                                 args.shift();
387                         };
388                         classSetting = args[ 0 ];
389                         if( Type.isNumber( classSetting ) === true ){
390                                 opt_pool     = !!( classSetting & Class.POOL_OBJECT  );
391                                 opt_abstract = !!( classSetting & Class.ABSTRACT     );
392                                 opt_final    = !!( classSetting & Class.FINAL        );
393                                 opt_private  = !!( classSetting & Class.PRIVATE_DATA );
394                                 if( opt_final === true && opt_abstract === true ){
395                                         throw new Error( 'final & Abstract!' );
396                                 };                              
397                                 args.shift();
398                         };
399                         
400                         if( GET_INDEX( PRIVATE_CLASS_LIST, args[ 0 ] ) !== -1 ){
401                                 privateDef = getClassDef( args[ 0 ] );
402                                 if( privateDef.isPrivate !== true ){
403                                         throw new Error( 'PrivateClass not found! please, Class.create( Class.PRIVATE, {...} ).' );
404                                 } else
405                                 if( privateDef.Abstract === true ){
406                                         throw new Error( 'PrivateClass is Abstract!' );
407                                 };
408                                 classDef.privateClass = args.shift();
409                         };
410                         props = args[ 0 ];
411                         if( props === null || Type.isObject( props ) === false ){
412                                 throw new Error( 'No Class Def!' );
413                         };
414                         
415                         if( Type.isFunction( props[ CONSTRUCTOR ] ) === true ){
416                                 classDef[ CONSTRUCTOR ] = props[ CONSTRUCTOR ];
417                         };
418                         
419                         klass = function(){ var a = arguments; if( f ) return C.apply( a.callee, a )};
420                         klass.prototype = override( override( traits || {}, props, true ), CommonProps, false );
421                         
422                         if( opt_abstract === true ){
423                                 classDef.Abstract = true;
424                         } else
425                         if( opt_pool === true ){
426                                 classDef.pool = [];
427                                 if( opt_private === false )classDef.live = [];
428                         };                      
429                         if( opt_final === true ){
430                                 classDef.Final = true;
431                         } else {
432                                 klass.inherits = inherits;
433                         };                      
434                         if( opt_private === true ){
435                                 if( classDef.privateClass ){
436                                         throw new Error( 'Private Data Class has no PrivateClass!' );
437                                 };
438                                 classDef.isPrivate = true;
439                                 PRIVATE_CLASS_LIST.push( klass );
440                                 PRIVATE_DEF_LIST.push( classDef );
441                         } else {
442                                 if( classDef.privateClass ){
443                                         klass.newPrivateData = newPrivateData;
444                                         klass.getPrivateData = getPrivateData;  
445                                 };
446                                 CLASS_LIST.push( klass );
447                                 DEF_LIST.push( classDef );                              
448                         };
449                         return klass;
450                 },
451                 onShutdown : function(){
452                         
453                 },
454                 getClass : function( instance ){
455                         return getClass( instance );
456                 },
457                 getClassDef : function(){
458                         
459                 }
460         };
461 })();
462
463 /**
464  * Callback 時に thisObject や args を指定したい場合に使用. 
465  */
466 var Callback = Class.create(
467         Class.POOL_OBJECT | Class.FINAL, {
468         Constructor : function( thisObject, callback, opt_args ){
469                 if( Type.isFunction( callback ) === false ){
470                         throw new Error( 'Not function!' );
471                 };
472                 this.callback = callback;
473                 if( thisObject ) this.thisObject = thisObject;
474                 if( Type.isArray( opt_args ) === true ){
475                         this.args = opt_args;
476                 } else
477                 if( opt_args !== undefined ){
478                         this.arg = opt_args;
479                 };
480         },
481         fire : function( /* args */ ){
482                 var thisObject = this.thisObject || window,
483                         args       = Util.copyArray( arguments );
484                 if( 0 < args.length ){
485                         if( this.args !== undefined ){
486                                 args.push.apply( args, this.args );
487                         } else
488                         if( this.arg !== undefined ){
489                                 args.push( this.arg );
490                         };
491                         this.callback.apply( thisObject, args );
492                 } else {
493                         if( this.args !== undefined ){
494                                 this.callback.apply( thisObject, this.args );
495                         } else
496                         if( this.arg !== undefined ){
497                                 this.callback.call( thisObject, this.arg );
498                         } else {
499                                 this.callback.call( thisObject );
500                         };
501                 };
502         },
503         registerUser : function( user ){
504                 if( !this.userList ){
505                         this.userList = [ user ];
506                 } else {
507                         Util.getIndex( this.userList, user ) === -1 && this.userList.push( user );
508                 };
509         },
510         onKill : function(){
511                 var instance = this.thisObject;
512                 this.userList && Class.getClass( instance ) && instance.releaseMyCalllback( this );
513         }
514 });
515
516
517 /* --------------------------------------------------------------
518  * System Timer
519  * 
520  */
521
522 var SystemTimer = ( function(){
523         var setTimeout    = window.setTimeout;
524         var clearTimeout  = window.clearTimeout;
525         var INTERVAL_TIME = 16;
526         var TICKET_LIST   = [];
527         var timerId       = undefined;
528         var next          = 0;
529         
530         function loop(){
531                 var i    = 0,
532                         list = TICKET_LIST;
533             for( i = 0; i < list.length; ){
534                 if( list[ i ].fire( next ) !== false ) ++i;
535             };
536             timerId = undefined;
537             update();
538         };
539         function update(){
540                 var list = TICKET_LIST,
541                         l    = list.length,
542                         n    = 99999999,
543                         c;
544                 if( l === 0 ){
545                         timerId !== undefined && clearTimeout( timerId );
546                         timerId = undefined;
547                         return;
548                 };
549             for( ; l; ){
550                 c = list[ --l ].count;
551                 if( n > c ) n = c;
552             };
553             if( next > n || timerId === undefined ){
554                 timerId !== undefined && clearTimeout( timerId );
555                 timerId = setTimeout( loop, INTERVAL_TIME * n );
556                 next = n;
557             };
558         };
559         
560         var TimerTicket = Class.create(
561                 Class.POOL_OBJECT, {
562                         Constructor : function( apiuser, callback, time, once, opt_thisObject ){
563                                 this.apiuser  = apiuser;
564                                 this.callback = callback;
565                                 this.time     = time;
566                                 this.count    = time;
567                                 if( once ) this.once = once;
568                                 this.thisObj  = opt_thisObject || apiuser;
569                         },
570                         fire : function( c ){
571                                 this.count -= c;
572                                 if( 0 < this.count ) return;
573                                 this.callback.call( this.thisObj );
574                                 if( this.once === true ){
575                                         this.destroy();
576                                         TICKET_LIST.splice( Util.getIndex( TICKET_LIST, this ), 1 );
577                                         return false;
578                                 } else {
579                                         this.count = this.time;
580                                 };
581                         },
582                         destroy : function( apiuser, callback ){
583                                 if( apiuser  && apiuser  !== this.apiuser )  return false;
584                                 if( callback && callback !== this.callback ) return false;
585                                 
586                                 this.kill();
587                                 return true;
588                         }
589                 }
590         );
591         
592         return {
593                 add: function( _apiuser, _handler, _time, _once, opt_thisObject ){
594                         if( Type.isNumber( _time ) === false || _time < INTERVAL_TIME ) _time = INTERVAL_TIME;
595                         
596                     var _ticket = new TimerTicket( _apiuser, _handler, Math.ceil( _time / INTERVAL_TIME ), _once, opt_thisObject );
597                     TICKET_LIST.push( _ticket );
598                     
599                     update();
600                 },
601                 remove: function( _apiuser, _handler ){
602                         var _ticket,
603                                 i = 0;
604                         while( _ticket = TICKET_LIST[ i ] ){
605                                 if( _ticket.destroy( _apiuser, _handler ) === true ){
606                                         TICKET_LIST.splice( i, 1 );
607                                 } else {
608                                         ++i;
609                                 };
610                         };
611                     update();
612                 }
613         };
614 })();
615
616 /* --------------------------------------------------------------
617  * Async Callback
618  * 
619  */
620 var AsyncCall = ( function(){
621         var CALLBACK_LIST = [];
622         
623         var CallbackTicket = Class.create(
624                 Class.POOL_OBJECT, {
625                 Constructor : function( apiuser, callback, args, thisObject ){
626                         this.apiuser  = apiuser;
627                         this.callback = callback;
628                         this.args     = args;
629                         this.thisObj  = thisObject || apiuser;
630                 },
631                 fire : function(){
632                         var f = this.callback,
633                                 a = this.args,
634                                 t = this.thisObj;
635                         this.destroy();
636                         if( Type.isArray( a ) === true ){
637                                 f.apply( t, a );
638                         } else {
639                                 f.call( t, a );
640                         };
641                 },
642                 destroy : function( apiuser, callback ){
643                         if( apiuser  && apiuser  !== this.apiuser ) return false;
644                         if( callback && callback !== this.callback ) return false;
645                         
646                         this.kill();
647                         return true;
648                 }
649         });
650
651         function dispatch(){
652                 var _ticket = CALLBACK_LIST.shift();
653                 if( _ticket ){
654                         _ticket.fire();
655                         CALLBACK_LIST.length !== 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true );
656                 };
657         };
658
659         return {
660                 add: function( _apiuser, _callback, _argments, _thisObject ){
661                         CALLBACK_LIST.length === 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true );
662                         CALLBACK_LIST.push( new CallbackTicket( _apiuser, _callback, _argments, _thisObject ) );
663                 },
664                 remove: function( _apiuser, _callback ){
665                         var _ticket,
666                                 i = 0;
667                         while( _ticket = CALLBACK_LIST[ i ] ){
668                                 if( _ticket.destroy( _apiuser, _callback ) === true ){
669                                         CALLBACK_LIST.splice( i, 1 );
670                                 } else {
671                                         ++i;
672                                 };
673                         };
674                 }
675         };
676 })();
677
678 /* -----------------------------------------------------------
679  * 画像一覧は
680  *      お気に入り画像一覧 > tag:ペン次郎 > ペン次郎:笑う
681  *  最近アップロードされた画像 > images
682  *  最近使われた画像 > images
683  *  キャラクター画像庫 > アニマル系 > tag:ペン次郎 > ペン次郎:笑う
684  *  風景画像庫 >
685  *  効果画像庫 >
686  *  アイテム画像庫 >
687  *  
688  * 画像一覧を読み込むタイミング
689  */
690 var File = ( function(){
691         var DRIVER_LIST             = [];
692         
693         var FILE_TYPE_IS_FOLDER     = Const.FILE.TYPE.FOLDER,
694                 numFileType             = Const.FILE.TYPE.XML,
695                 FILEDATA_RESITER        = [],                   // store all of fileData( json object )
696                 FILEDATA_ACCESS         = [],                   // file operations for Kernel only ! hide from Out of File
697                 FILE_OBJECT_POOL        = [],
698                 EVENT_LISTENER_REGISTER = [],
699                 TREE_ARRAY              = [],
700                 TREE_ACCESS_ARRAY       = [];
701         
702         var REQUEST_CONTROLER = ( function(){
703                 var REQUEST_TICKET_RESISTER = [],
704                         currentTicket           = null,
705                         currentData             = null,
706                         DATA_TYPE_ARRAY         = 'json,xml,html,text'.split( ',' ),
707                         DATA_IS_JSON            = 0,
708                         DATA_IS_XML             = 1,
709                         DATA_IS_HTML            = 2,
710                         DATA_IS_TEXT            = 3,
711                         numError                = 0;
712                 
713                 var RequestTicket = Class.create(
714                         Class.POOL_OBJECT, {
715                         Constructor : function( apiuser, type, data, url, onLoad, onError ){
716                                 this.apiuser = apiuser;
717                                 this.type    = type;
718                                 this.data    = data;
719                                 this.url     = url;
720                                 this.onLoad  = onLoad;
721                                 this.onError = onError;
722                                 this.state   = 0;
723                         },
724                         load : function( data ){
725                                 AsyncCall.add( this.apiuser, this.onLoad, [ this.data, data ] );
726                         },
727                         error : function(){
728                                 AsyncCall.add( this.apiuser, this.onError, this.data );
729                         }
730                 });
731                 
732                 function request(){
733                         if( currentTicket !== null || REQUEST_TICKET_RESISTER.length === 0 ) return;
734                         currentTicket = REQUEST_TICKET_RESISTER.shift();
735                         $.ajax({
736                                 url:            currentTicket.url,
737                                 dataType:       DATA_TYPE_ARRAY[ currentTicket.type ],
738                                 success:        onSuccess,
739                                 error:          onError
740                         });
741                 };
742                 function onSuccess( _data ){
743                         currentTicket.load( _data );
744                         currentTicket.kill();
745                         currentTicket = null;
746                         request();
747                 };
748                 function onError(){
749                         ++numError;
750                         currentTicket.error();
751                         currentTicket.kill(); // retry
752                         currentTicket = null;
753                         request();
754                 };
755
756                 return {
757                         getNumTask: function(){
758                                 return REQUEST_TICKET_RESISTER.length;
759                         },
760                         getNumError: function(){
761                                 return numError;
762                         },
763                         getJson: function( _apiuser, _data, _url, _onLoad, _onError ){
764                                 REQUEST_TICKET_RESISTER.push( new RequestTicket( _apiuser, DATA_IS_JSON, _data, _url, _onLoad, _onError ));
765                                 currentTicket === null && request();
766                         }
767                 };
768         })();
769
770         var FILE_CONTROLER = {
771                 createTree: function( _apiuser, _rootFileData ){
772                         var _tree = new TreeClass( _apiuser, _rootFileData );
773                         TREE_ARRAY.push( _tree );
774                         return _tree;
775                 },
776                 getFileUID: function( FILEDATAorFILE ){
777                         if( FILEDATAorFILE instanceof FileClass ){
778                                 return FILEDATAorFILE.getUID();
779                         };
780                         
781                         var uid = Util.getIndex( FILEDATA_RESITER, FILEDATAorFILE );
782                         if( uid === -1 ){
783                                 uid = FILEDATA_RESITER.length;
784                                 FILEDATA_RESITER.push( FILEDATAorFILE );
785                         };
786                         return uid;
787                 },
788                 getFileDataAccess: function( UIDorFILEorFILEDATA ){
789                         var _uid, _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA ), _access;
790
791                         if( _data === null || typeof _data !== 'object' ) return null;
792                         for( var i=0, l = FILEDATA_ACCESS.length; i<l; ++i ){
793                                 _access = FILEDATA_ACCESS[ i ];
794                                 if( _access.DATA === _data ) return _access;
795                         };
796                         return null;
797                 },      
798                 getFileData: function( UIDorFILEorFILEDATA ){
799                         if( typeof UIDorFILEorFILEDATA === 'number' ){
800                                 return FILEDATA_RESITER[ UIDorFILEorFILEDATA ] || null;
801                         } else
802                         if( UIDorFILEorFILEDATA instanceof FileClass ){
803                                 return FILEDATA_RESITER[ UIDorFILEorFILEDATA.getUID() ] || null;
804                         } else
805                         if( Util.getIndex( FILEDATA_RESITER, UIDorFILEorFILEDATA ) !== -1 ){
806                                 return UIDorFILEorFILEDATA;
807                         };
808                         return null;
809                 },
810                 getChildren: function( UIDorFILEorFILEDATA ){
811                         var _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA );
812                         return _data !== null ? _data.children || null : null;
813                 },
814                 getDriver: function( _file ){
815                         var _data = FILE_CONTROLER.getFileData( _file );
816                         return _data !== null && _data.driver ? _data.driver : BASE_DRIVER;
817                 },
818                 getUpdateFlag: function( _file, _bit ){
819                         var _driver = FILE_CONTROLER.getDriver( _file ),
820                                 _policy;
821                         if( typeof _driver.getUpdatePolicy === 'function' ){
822                                 _policy = _driver.getUpdatePolicy( _file );
823                                 
824                         }
825                         if( typeof _policy !== 'number' ) {
826                                 _policy = BASE_DRIVER.getUpdatePolicy( _file )
827                         }
828                         return _policy % ( _bit * 2 ) >= _bit;
829                 },
830                 move: function( _prentUID, _targetfile, _newFolder, _newIndex, _opt_callback ){
831                         var _parentData = FILE_CONTROLER.getFileDataAccess( _prentUID ),
832                                 _parentType = _parentData.TYPE,
833                                 _targetData = FILE_CONTROLER.getFileDataAccess( _targetfile ),
834                                 _targetType = _targetData.TYPE;
835                 },
836                 replace: function( _uid, _file, _newIndex ){
837                         
838                 },
839                 addEventListener: function( FILEorNULL, _eventType, _callback, opt_thisObject ){
840                         var _uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL;
841                         EVENT_LISTENER_REGISTER.push( new FileEventTicket( _uid, _eventType, _callback, opt_thisObject ));
842                 },
843                 removeEventListener: function( FILEorNULL, eventType, callback ){
844                         var uid  = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL,
845                                 list = EVENT_LISTENER_REGISTER,
846                                 i    = 0,
847                                 ticket;
848                         for( ; i < list.length; ){
849                                 ticket = list[ i ];
850                                 if( ticket.fileUID === uid && ticket.eventType === eventType && ticket.callBack === callback ){
851                                         list.splice( i, 1 );
852                                         ticket.kill();
853                                 } else {
854                                         ++i;
855                                 };
856                         };
857                 },
858                 getTreeAccess: function(){
859                         
860                 },
861                 fileEventRellay: function( _uid, _event ){
862                         var _fileAccess = FILE_CONTROLER.getFileDataAccess( _uid );
863                         if( _fileAccess === null ) return;
864                         var _treeUID    =  _fileAccess.TREE.getUID(),
865                                 _treeAccess = TREE_ACCESS_ARRAY[ _treeUID ],
866                                 _data       = _fileAccess.DATA,
867                                 _tree;
868                         if( !_treeAccess ) return;
869                         _treeAccess.dispatchFileEvent( _event );
870                         for( var i=0, l = TREE_ARRAY.length; i<l; ++i ){
871                                 if( i !== _treeUID ){
872                                         _tree = TREE_ARRAY[ i ];
873                                         if( FILE_CONTROLER.getFileData( _tree.getCurrentFile() ) === _data ){
874                                                 _treeAccess = TREE_ACCESS_ARRAY[ _tree.getUID() ];
875                                                 _treeAccess && _treeAccess.dispatchFileEvent( _event );
876                                         };
877                                 };
878                         };
879                 }
880         };
881         
882         var TreeClass = function( apiuser, rootFileData ){
883                 var PARENT_FILE_RESITER = [],
884                         ACCESS = {
885                                 apiuser          : apiuser,
886                                 dispatchFileEvent: dispatchFileEvent
887                         },
888                         EVENT_LISTENER_ARRAY = [],
889                         instance             = this,
890                         rootFile             = new FileClass( instance, null, rootFileData ),
891                         currentFile          = rootFile;
892                 
893                 currentFile.getSeqentialFiles();
894                 TREE_ACCESS_ARRAY.push( ACCESS );
895                 
896                 function dispatchFileEvent( e ){
897                         var _eventType  = e.eventType,
898                                 _targetFile = e.targetFile,
899                                 _uid        = _targetFile.getUID(),
900                                 _ticket, _type, _callback;
901                         for( var i=0, l = EVENT_LISTENER_REGISTER.length; i<l; ++i ){
902                                 _ticket   = EVENT_LISTENER_REGISTER[ i ];
903                                 _type     = _ticket.eventType;
904                                 _callback = _ticket.callBack;
905                                 if( _eventType === _type && _uid === _ticket.fileUID ){
906                                         AsyncCall.add( apiuser, _callback, [ _eventType, _targetFile, e.key, e.value ], _ticket.thisObject || _targetFile );
907                                 } else
908                                 if( _type === Const.TREE.EVENT.UPDATE && _eventType === Const.FILE.EVENT.GET_SEQENTIAL_FILES ){
909                                         //_callback( _eventType, _targetFile );
910                                         AsyncCall.add( apiuser, _callback, [ _eventType, _targetFile ], _ticket.thisObject || instance );
911                                 };
912                         };
913                 };
914                 
915                 this.getUID = function(){
916                         return Util.getIndex( TREE_ACCESS_ARRAY, ACCESS );
917                 };
918                 this.getRootFile = function(){
919                         return rootFile;
920                 };
921                 this.getCurrentFile = function(){
922                         return currentFile;
923                 };
924                 this.hierarchy = function(){
925                         return PARENT_FILE_RESITER.length;
926                 };
927                 this.getParentFileAt = function( _index ){
928                         var l = PARENT_FILE_RESITER.length;
929                         if( typeof _index !== 'number' || _index < 0 || _index >= l ) return null;
930                         return PARENT_FILE_RESITER[ l -1 -_index ];
931                 };
932                 this.down = function( _index ){
933                         if( typeof _index !== 'number' || _index < 0 || _index >= currentFile.getChildFileLength()) return;
934                         PARENT_FILE_RESITER.unshift( currentFile );
935                         currentFile = currentFile.getChildFileAt( _index );
936                         currentFile.getSeqentialFiles();
937                         return currentFile;
938                 };
939                 this.up = function( _index ){
940                         var l = PARENT_FILE_RESITER.length;
941                         if( l === 0 ) return null;
942                         
943                         if( currentFile ){
944                                 var _currentFile = currentFile;
945                                 currentFile = null;
946                                 _currentFile.destroy();
947                         };
948                         if( typeof _index === 'number' ){
949                                 if( _index >= l ) return null;
950                                 currentFile = this.getParentFileAt( _index );
951                                 PARENT_FILE_RESITER.splice( 0, l -_index);
952                         } else {
953                                 currentFile = PARENT_FILE_RESITER.shift();
954                         };
955                         currentFile.getSeqentialFiles();
956                         return currentFile;     
957                 };
958                 this.addTreeEventListener = function( _eventType, _callback, opt_thisObject ){
959                         FILE_CONTROLER.addEventListener( null, _eventType, _callback, opt_thisObject );
960                 };
961                 this.removeTreeEventListener = function( _eventType, _callback ){
962                         FILE_CONTROLER.removeEventListener( null, _eventType, _callback );
963                 };
964                 this.destroy = function( _apiuser ){
965                         if( _apiuser && apiuser !== _apiuser ) return false;
966                         // removeEvent
967                         var _currentFile = currentFile;
968                         currentFile = rootFile = rootFileData = null;
969                         // currentFile, rootFile を null にしないと .File.destroy() ができない.
970                         _currentFile.destroy();
971                         while( PARENT_FILE_RESITER.length > 0 ){
972                                 _currentFile = PARENT_FILE_RESITER.shift();
973                                 _currentFile.destroy();
974                         };
975                         
976                         AsyncCall.remove( apiuser );
977                         instance = apiuser = null;
978                         return true;
979                 };
980         };
981         
982         var FileEventTicket = Class.create(
983                 Class.POOL_OBJECT, {
984                 Constructor : function( uid, eventType, callback, opt_thisObject ){
985                         this.fileUID    = uid;
986                         this.eventType  = eventType;
987                         this.callBack   = callback;
988                         this.thisObject = opt_thisObject;
989                 }       
990         });
991         
992         var FileEventClass = function( eventType, file, key, value ){
993                 this.eventType        = eventType;
994                 this.targetFile       = file;
995                 this.updatedAttribute = key;
996                 this.updatedValue     = value;
997         };
998
999 /*
1000  * file の data は object で保持している。
1001  * File の外からファイルをみるときは、FileClassを通して操作する。
1002  * fileの変更、それに付随して追加されたイベントは、TreeClassで管理される。
1003  * treeがdestryされると、fileのイベントリスナーも全て削除される。
1004  * 他の tree も data の共通する currentFile に対してのみは、file の変更イベントを受け取って流す.
1005  * 
1006  */
1007         
1008         var FileClass = function( tree, parentData, data ){
1009                 var uid = FILE_CONTROLER.getFileUID( data );
1010                 
1011                 FILEDATA_ACCESS.push( {
1012                         TREE:                           tree,
1013                         parentData:                     parentData,
1014                         DATA:                           data
1015                 } );
1016                 
1017                 tree = parentData = data = null;
1018
1019                 this.getUID = function(){
1020                         return uid;
1021                 };
1022         };
1023         
1024         FileClass.prototype = {
1025                 isChildFile: function( _FILEorFILEDATA ){
1026                         return this.getChildFileIndex( _FILEorFILEDATA) !== -1;
1027                 },
1028                 getSeqentialFiles: function(){
1029                         var _driver = FILE_CONTROLER.getDriver( this );
1030                         if( _driver !== null && typeof _driver.getSeqentialFiles === 'function' ){
1031                                 _driver.getSeqentialFiles( this );
1032                         }
1033                 },
1034                 addEventListener: function( _eventType, _callback ){
1035                         FILE_CONTROLER.addEventListener( this, _eventType, _callback );
1036                 },
1037                 removeEventListener: function( _eventType, _callback ){
1038                         FILE_CONTROLER.removeEventListener( this, _eventType, _callback );
1039                 },
1040                 dispatchEvent: function( e ){
1041                         e instanceof FileEventClass && FILE_CONTROLER.fileEventRellay( this.getUID(), e );
1042                 },
1043                 getChildFileLength: function(){
1044                         var children = FILE_CONTROLER.getChildren( this );
1045                         return Type.isArray( children ) === true ? children.length : -1;
1046                 },
1047                 getChildFileIndex: function( _FILEorFILEDATA ){
1048                         var children = FILE_CONTROLER.getChildren( this );
1049                         if( Type.isArray( children ) === false ) return -1;
1050                         var l = children.length,
1051                                 _fileData = FILE_CONTROLER.getFileData( _FILEorFILEDATA );
1052                         if( _fileData === null ) return -1;
1053                         for( var i=0; i<l; ++i ){
1054                                 if( children[ i ] === _fileData ) return i;
1055                         }
1056                         return -1;
1057                 },
1058                 getChildFileAt: function( _index ){
1059                         var _access = FILE_CONTROLER.getFileDataAccess( this ),
1060                                 _children = FILE_CONTROLER.getChildren( this );
1061                         if( typeof _index !== 'number' || _index < 0 || Type.isArray( _children ) === false || _index >= _children.length ) return null;
1062                         var _file = new FileClass( _access.TREE, _access.DATA, _children[ _index ]);
1063                         // _file.init();
1064                         return _file;
1065                 },
1066                 getName: function(){
1067                         var driver = FILE_CONTROLER.getDriver( this );
1068                         if( typeof driver.getName === 'function'){
1069                                 return driver.getName( this );
1070                         }
1071                         return BASE_DRIVER.getName( this );
1072                 },
1073                 getThumbnail: function(){
1074                         var driver = FILE_CONTROLER.getDriver( this );
1075                         if( typeof driver.getThumbnail === 'function'){
1076                                 return driver.getThumbnail( this );
1077                         }
1078                         return BASE_DRIVER.getThumbnail( this );
1079                 },
1080                 getType: function(){
1081                         var _data = FILE_CONTROLER.getFileData( this );
1082                         return typeof _data.type === 'number' ? _data.type : Const.FILE.TYPE.UNKNOWN;
1083                 },
1084                 getState: function(){
1085                         var _data = FILE_CONTROLER.getFileData( this );
1086                         return typeof _data.state === 'number' ? _data.state : Const.FILE.STATE.OK;
1087                 },
1088                 getSummary: function(){
1089                         var driver = FILE_CONTROLER.getDriver( this );
1090                         if( typeof driver.getSummary === 'function'){
1091                                 return driver.getSummary( this );
1092                         }
1093                         return BASE_DRIVER.getSummary( this );
1094                 },
1095                 isWritable: function(){
1096                         return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.WRITE );
1097                 },
1098                 isSortable: function(){
1099                         return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.SORT );
1100                 },              
1101                 isCreatable: function(){
1102                         return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.CREATE );
1103                 },
1104                 isRenamable: function(){
1105                         return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.RENAME );
1106                 },
1107                 isDeletable: function(){
1108                         return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.DELETE );
1109                 },
1110                 read: function(){
1111                         // simpleDeepCopy
1112                         var driver = FILE_CONTROLER.getDriver( this ),
1113                                 data;
1114                         if( Type.isFunction( driver.read ) === true ){
1115                                  data = driver.read( this );
1116                         };
1117                         return BASE_DRIVER.read( data || this );
1118                 },
1119                 write: function( _newData, _onUpdateFunction ){
1120                         var driver = FILE_CONTROLER.getDriver( this );
1121                         if( typeof driver.write === 'function' ){
1122                                 return driver.write( this, _newData, _onUpdateFunction );
1123                         };
1124                         return BASE_DRIVER.write( this, _newData, _onUpdateFunction );
1125                 },
1126                 viewerApplicationList: function(){
1127                         var driver = FILE_CONTROLER.getDriver( this );
1128                         if( typeof driver.viewerApplicationList === 'function' ){
1129                                 return driver.viewerApplicationList( this );
1130                         };
1131                         return BASE_DRIVER.viewerApplicationList( this );
1132                 },
1133                 editorApplicationList: function(){
1134                         var driver = FILE_CONTROLER.getDriver( this );
1135                         if( typeof driver.editorApplicationList === 'function' ){
1136                                 return driver.editorApplicationList( this );
1137                         };
1138                         return BASE_DRIVER.viwerApps( this );
1139                 },
1140                 create: function(){
1141                         
1142                 },
1143                 sort: function(){
1144                         
1145                 },
1146                 onCopy: function(){
1147                         
1148                 },
1149                 onDelete: function(){
1150                         
1151                 },
1152                 move: function( _newFolder, _newIndex, opt_callback ){
1153                         var _access = FILE_CONTROLER.getFileDataAccess( this );
1154                         _access.TREE.move( _access.parentData, this.getUID(), _newFolder, _newIndex, opt_callback );
1155                 },
1156                 replace: function( _newIndex, opt_callback ){
1157                         var _access = FILE_CONTROLER.getFileDataAccess( this );
1158                         _access.TREE.replace( _access.parentData, this.getUID(), _newIndex, opt_callback);
1159                 },
1160                 /**
1161                  * サーチ
1162                  * 探しているファイルの属性と値を指定.一致する child の index を配列で返す.
1163                  */
1164                 search: function( obj, rule ){
1165                         var _children = FILE_CONTROLER.getChildren( this ),
1166                                 _child,
1167                                 ret = [], k, c;
1168                         for( var i=0, l=_children.length; i<l; ++i ){
1169                                 _child = _children[ i ];
1170                                 c = true;
1171                                 for( k in obj ){
1172                                         if( obj[ k ] !== _child[ k ] ){
1173                                                 c = false;
1174                                                 break;
1175                                         }
1176                                 }
1177                                 c === true && ret.push( i );
1178                         }
1179                         return ret;
1180                 },
1181                 destroy: function(){
1182                         var _access = FILE_CONTROLER.getFileDataAccess( this );
1183                         var _tree = _access.TREE;
1184                         if( _tree.getCurrentFile() === this ) return;
1185                         if( _tree.getRootFile() === this ) return;
1186                         for( var i=0, l = _tree.hierarchy(); i<l; ++i ){
1187                                 if( _tree.getParentFileAt( i ) === this ){
1188                                         return;
1189                                 }
1190                         }
1191                         var _index = Util.getIndex( FILEDATA_ACCESS, _access );
1192                         if( _index === -1 ) return;
1193                         // event の 削除
1194                         FILEDATA_ACCESS.splice( _index, 1 );
1195                         delete _access.DATA;
1196                         delete _access.TREE;
1197                         delete _access.parentData;
1198                 }
1199         };
1200
1201         /*
1202          * FileDriverBase
1203          */
1204         var FileDriverBase = function( driverClass ){
1205                 this.getUID = function(){
1206                         return Util.getIndex( API_USER_LIST, driverClass );
1207                 };
1208                 this.getSeqentialFiles = function( _file ){
1209                 };
1210                 this.getName = function( _file ){
1211                         var _data = FILE_CONTROLER.getFileData( _file );
1212                         return _data.name || 'No Name';
1213                 };
1214                 this.getThumbnail = function( _file ){
1215                         var _data = FILE_CONTROLER.getFileData( _file ),
1216                                 _type = _data.type,
1217                                 _className = '';
1218                         if( _type === Const.FILE.TYPE.FOLDER ){
1219                                 _className = 'folder';
1220                         } else
1221                         if( _type === Const.FILE.TYPE.IMAGE ){
1222                                 
1223                         } else
1224                         if( _type === Const.FILE.TYPE.TEXT ){
1225                                 
1226                         } else
1227                         if( _type === Const.FILE.TYPE.HTML ){
1228                                 
1229                         } else
1230                         if( _type === Const.FILE.TYPE.CSV ){
1231                                 
1232                         } else
1233                         if( _type === Const.FILE.TYPE.JSON ){
1234                                 
1235                         } else
1236                         if( _type === Const.FILE.TYPE.XML ){
1237                                 
1238                         };
1239                         return {
1240                                 image:          null,
1241                                 className:      ' file-type-' + _className
1242                         };
1243                 };
1244                 this.getSummary = function( _file ){
1245                         var _data = FILE_CONTROLER.getFileData( _file ),
1246                                 _type = _data.type;
1247                         if( _type === Const.FILE.TYPE.FOLDER ){
1248                                 return 'folder';
1249                         } else
1250                         if( _type === Const.FILE.TYPE.IMAGE ){
1251                                 return 'image file';
1252                         } else
1253                         if( _type === Const.FILE.TYPE.TEXT ){
1254                                 return 'text file';
1255                         } else
1256                         if( _type === Const.FILE.TYPE.HTML ){
1257                                 return 'html document file';
1258                         } else
1259                         if( _type === Const.FILE.TYPE.CSV ){
1260                                 return 'csv daat file';
1261                         } else
1262                         if( _type === Const.FILE.TYPE.JSON ){
1263                                 return 'json data file';
1264                         } else
1265                         if( _type === Const.FILE.TYPE.XML ){
1266                                 return 'xml data file';
1267                         }
1268                         return '';
1269                 };
1270                 this.getUpdatePolicy = function( _file ){
1271                         // debug用 全てのメニューを許可
1272                         return Const.FILE.UPDATE_POLICY.DSRWC;
1273                 };
1274                 this.read = function( FILEorDATA ){
1275                         var data,
1276                                 protects = Const.FILE.DATA_PROPERTY_RESERVED,
1277                                 objSrc   = [],
1278                                 objCopy  = [],
1279                                 getIndex = Util.getIndex;                       
1280                         if( FILEorDATA instanceof FileClass ){
1281                                 data = FILE_CONTROLER.getFileData( FILEorDATA )
1282                         } else {
1283                                 data = FILEorDATA;
1284                         };
1285                         
1286                         function clone( src ) {
1287                                 var ret, i, key;
1288                                 if( Type.isArray( src ) === true ){
1289                                         i = getIndex( objSrc, src );
1290                                         if( i !== -1 ) return objCopy[ i ];
1291                                         ret = [];
1292                                         objSrc[ objSrc.length ]   = src;
1293                                         objCopy[ objCopy.length ] = ret;
1294                                 } else
1295                                 if( Type.isObject( src ) === true ){
1296                                         i = getIndex( objSrc, src );
1297                                         if( i !== -1 ) return objCopy[ i ];
1298                                         ret = {};
1299                                         objSrc[ objSrc.length ]   = src;
1300                                         objCopy[ objCopy.length ] = ret;
1301                                 } else
1302                                 if( Type.isNumber( src ) === true || Type.isString( src ) === true || Type.isBoolean( src ) === true ){
1303                                         return src;
1304                                 } else {
1305                                         return src;
1306                                 };
1307                                 for( key in src ){
1308                                         if( getIndex( protects, key ) === -1 ){
1309                                                 ret[ key ] = clone( src[ key ]);
1310                                         };
1311                                 };
1312                                 return ret;
1313                         };                              
1314                         return clone( data );
1315                 };
1316                 this.write = function( _file, _newData, _onUpdateFunction ){
1317                         var _data = FILE_CONTROLER.getFileData( _file ),
1318                                 _type = _data.type;
1319                         return false;
1320                 };
1321                 this.viewerApplicationList = function(){
1322                         return [];
1323                 };
1324                 this.editorApplicationList = function(){
1325                         return [];
1326                 };
1327                 this.onCreate = function(){
1328                         
1329                 };
1330                 this.onSort = function(){
1331                         
1332                 };
1333                 this.onCopy = function(){
1334                         
1335                 };
1336                 this.onDelete = function(){
1337                         
1338                 };
1339         };
1340         
1341         var BASE_DRIVER   = new FileDriverBase();
1342         
1343         var ROOT_FILEDATA = {
1344                         name:           'system root',
1345                         type:           FILE_TYPE_IS_FOLDER,
1346                         children:       []
1347                 },
1348                 SYSTEM_TREE = FILE_CONTROLER.createTree( SUPER_USER_KEY, ROOT_FILEDATA ),
1349                 ROOT_FILE   = SYSTEM_TREE.getRootFile();
1350
1351         function createFileTypeID(){
1352                 return ++numFileType;
1353         };
1354         
1355         var FileAPIClass = function( driver ){
1356                 var constObject;
1357                 this.createFolderUnderRoot = function( _fileData ){
1358                         if( _fileData !== null && Type.isObject( _fileData ) === true ){
1359                                 ROOT_FILEDATA.children.push( _fileData );
1360                                 ROOT_FILE.dispatchEvent( new FileEventClass( Const.FILE.EVENT.GET_SEQENTIAL_FILES, ROOT_FILE, 'children', null ));
1361                         }
1362                 };
1363                 this.createFileEvent   = function( _eventType, _file, _key, _value ){
1364                         return new FileEventClass( _eventType, _file, _key, _value );
1365                 };
1366                 this.createFileTypeID  = createFileTypeID;
1367                 this.getFileDataAccess = FILE_CONTROLER.getFileDataAccess;
1368                 this.getFileData       = FILE_CONTROLER.getFileData;
1369                 this.getJson           = function( _data, _url, _onLoad, _onError ){
1370                         REQUEST_CONTROLER.getJson( driver, _data, _url, _onLoad, _onError );
1371                 };
1372                 this.createTree        = function( _rootFile ){
1373                         return FILE_CONTROLER.createTree( driver, _rootFile );
1374                 };
1375                 this.isTreeInstance    = function( _tree ){
1376                         return _tree instanceof TreeClass;
1377                 };
1378                 this.isFileInstance    = function( _file ){
1379                         return _file instanceof FileClass;
1380                 };
1381                 this.isFileEvent       = function( _event ){
1382                         return _event instanceof FileEventClass;
1383                 };
1384                 this.getConst          = function(){
1385                         return Const; // constObject = constObject || clone( Const )
1386                 };
1387         };
1388         
1389         return {
1390                 registerDriver: function( _class ){
1391                         _class.prototype = new FileDriverBase( _class );
1392                         var _driver = new _class();
1393                         
1394                         DRIVER_LIST.push( _driver );
1395                         API_USER_LIST.push( _class );
1396
1397                         return new FileAPIClass( _driver );
1398                 },
1399                 isDriver: function( _driver ){
1400                         return _driver instanceof FileDriverBase;
1401                 },
1402                 isTreeInstance: function( _tree ){
1403                         return _tree instanceof TreeClass;
1404                 },
1405                 isFileInstance: function( _file ){
1406                         return _file instanceof FileClass;
1407                 }
1408         }
1409 })();
1410
1411
1412 /* ----------------------------------------------------
1413  * ApplicationManager
1414  * window resize event, overlayApplication currentAplication に流す
1415  */     
1416
1417 var APPLICATION_LIST = [];
1418
1419 var ApplicationPrivateData = function(){};
1420 ApplicationPrivateData.prototype = {
1421         appClass      : null,
1422         application   : null,
1423         displayName   : null,
1424         isOverlay     : false,
1425         rootElement   : null,
1426         bgColor       : '#C1CACF',
1427         uiList        : null,
1428         formList      : null,
1429         finderList    : null,
1430         styleCursor   : null,
1431         eventRoot     : null,
1432         fetchResource : 0,
1433         bootParams    : null,
1434         phase         : 0,
1435         cursor        : '',
1436         w             : 0,
1437         h             : 0,
1438         init          : function( appClass, displayName, isOverlay ){
1439                 this.appClass    = appClass;
1440                 // this.application = app;
1441                 this.displayName = displayName;
1442                 this.isOverlay   = isOverlay;
1443                 this.rootElement = document.createElement( 'div' );
1444                 this.styleCursor = this.rootElement.style;
1445                 ApplicationPrivateData.list.push( this );
1446         },
1447         detect : function(){
1448                 if( this.rootElement.firstChild && this.fetchResource === 0 ){
1449                         SystemTimer.remove( this.application, this.detect );
1450                         this.onOpen();
1451                 };
1452         },
1453         onOpen : function(){
1454                 this.rootElement.style.display = '';
1455                 
1456                 // this.layer !== null && this.layer.onResize( this.w, this.h );
1457                 
1458                 if( this.application.MIN_WIDTH > this.w || this.application.MIN_HEIGHT > this.h ){
1459                         if( Type.isHTMLElement( this.rootElement ) === true ){
1460                                 // 小さすぎる!、と表示
1461                         };
1462                 };
1463                 if( this.bootParams.length > 2 ){
1464                         this.application.onOpen.apply( this.application, this.bootParams );
1465                 } else {
1466                         this.application.onOpen( this.w, this.h );
1467                 };
1468                 this.phase = 4; 
1469         },
1470         fetchResourceComplete : function(){
1471                 --this.fetchResource;
1472         }
1473 };
1474 ApplicationPrivateData.list = [];
1475 ApplicationPrivateData.get = function( app ){
1476         var list = ApplicationPrivateData.list,
1477                 i    = list.length;
1478         for( ; i; ){
1479                 if( app instanceof list[ --i ].appClass ) return list[ i ];
1480         };
1481         return null;
1482 };
1483
1484 var AbstractApplication = function( appClass, displayName, isOverlay ){
1485         ( new ApplicationPrivateData() ).init( appClass, displayName, isOverlay );
1486 };
1487 AbstractApplication.prototype = {
1488         getUID : function(){
1489                 var data = ApplicationPrivateData.get( this );
1490                 return Util.getIndex( API_USER_LIST, data.appClass );
1491         },
1492         init : function(){
1493                 var data = ApplicationPrivateData.get( this );
1494                 // this.rootElement = data.rootElement;
1495                 // data.application = this;
1496                 data.phase = 1;
1497                 data.appClass === Page.appClass && Page.show();
1498                 this.onInit();
1499                 data.phase = 2;
1500         },
1501         open : function( w, h /*, _option */ ){
1502                 var data = ApplicationPrivateData.get( this );
1503                 data.phase      = 3;
1504                 data.bootParams = Util.copyArray( arguments );
1505                 data.w          = w;
1506                 data.h          = h;
1507                 if( data.rootElement.innerHTML && data.rootElement.innerHTML.length > 0 ){
1508                         SystemTimer.add( this, data.detect, 16, false, data );
1509                 } else {
1510                         data.onOpen();
1511                 };
1512         },
1513         resize : function( w, h ){
1514                 var data = ApplicationPrivateData.get( this );
1515                 if( data.phase !== 4 ) return;
1516                 if( this.MIN_WIDTH > w || this.MIN_HEIGHT > h ){
1517                         if( Type.isHTMLElement( this.rootElement ) === true ){
1518                                 // 小さすぎる!、と表示
1519                         };
1520                         return;
1521                 };
1522                 this.onPaneResize( w, h );
1523         },
1524         close : function(){
1525                 var data = ApplicationPrivateData.get( this );
1526                 data.phase = 5;
1527                 if( this.onClose() === false ){
1528                         return false;
1529                 };
1530                 if( data.uiList ){ 
1531                         while( data.uiList.length > 0 ) data.uiList.shift().destroy();
1532                 };
1533                 if( data.finderList ){
1534                         while( data.finderList.length > 0 ) data.finderList.shift().destroy();
1535                 };              
1536                 
1537                 data.eventRoot && PointingDeviceEventTree.destroyTree( data.eventRoot );
1538                 MouseEvent.remove( this );
1539                 KeyEvent.remove( this );
1540                 SystemTimer.remove( this );
1541                 AsyncCall.remove( this );
1542                 StyleSheet.unload( this );
1543
1544                 var elm = this.rootElement;
1545                 Util.removeAllChildren( elm );
1546                 elm.parentNode.removeChild( elm );
1547                 
1548                 Application.shutdown( this, data.isOverlay );
1549                 
1550                 data.appClass === Page.appClass && Page.hide();
1551
1552                 data.phase = 6;
1553                 
1554                 var list = ApplicationPrivateData.list;
1555                 list.splice( Util.getIndex( list, data ), 1 );
1556         },
1557         createUIGroup : function( node ){
1558                 var data = ApplicationPrivateData.get( this ),
1559                         ui = UI.createUIGroup( this, node );
1560                 if( data.uiList === null ) data.uiList = [];
1561                 data.uiList.push( ui );
1562                 return ui;
1563         },
1564         createUIForm : function( nodeOrElm, opt_elmForm ){
1565                 var data = ApplicationPrivateData.get( this ),
1566                         form = UIForm.createForm( this, nodeOrElm, opt_elmForm );
1567                 if( data.formList === null ) data.formList = [];
1568                 data.formList.push( form );
1569                 return form;
1570         },
1571         createFinder : function( _elmTarget, _tree, _onSelect, _viewerOption, _editorOption ){
1572                 var data   = ApplicationPrivateData.get( this ),
1573                         finder = Finder.create( this, _elmTarget, _tree, _onSelect, _viewerOption, _editorOption );
1574                 if( data.finderList === null ) data.finderList = [];
1575                 data.finderList.push( finder );
1576                 return finder;
1577         },
1578         createDHTML : function( _elm ){
1579                 return DHTML.create( this, _elm );
1580         },
1581         addEventListener : function( element, eventType, handler, opt_thisObject ){
1582                 MouseEvent.add( this, element, eventType, handler, opt_thisObject );
1583         },
1584         removeEventListener : function( element, eventType, handler ){
1585                 MouseEvent.remove( this, element, eventType, handler );
1586         },
1587         getPointingDeviceEventTreeRoot : function(){
1588                 var data = ApplicationPrivateData.get( this );
1589                 if( data.phase === 1 ){
1590                         data.eventRoot   = PointingDeviceEventTree.create( this );
1591                         data.styleCursor = PointingDeviceEventTree._getNodePrivateData( data.eventRoot ).elmMouseCatch.style;
1592                 };              
1593                 return data.eventRoot;
1594         },
1595         updateCoursor : function( _cursor ){
1596                 var data = ApplicationPrivateData.get( this );
1597                 if( data.cursor !== _cursor ){
1598                         data.styleCursor.cursor = data.cursor = _cursor;
1599                 };
1600         },
1601         fetchCSS : function( url, opt_onload, opt_onerror ){
1602                 var data = ApplicationPrivateData.get( this );
1603                 if( data.phase === 1 ){
1604                         ++data.fetchResource;
1605                         StyleSheet.load( this, url, data.fetchResourceComplete, data.fetchResourceComplete, data );
1606                 };
1607         },
1608         onInit : function(){},
1609         onOpen : function(){},
1610         onClose : function(){ return true; },
1611         onPaneResize : function( w, h ){},
1612         addKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){
1613                 KeyEvent.add( this, _eventType, _handler, _keyCode, _shift, _ctrl );
1614         },
1615         removeKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){
1616                 KeyEvent.remove( this, _eventType, _handler, _keyCode, _shift, _ctrl );
1617         },
1618         shiftEnabled : function(){
1619                 return KeyEvent.shiftEnabled;
1620         },
1621         ctrlEnabled : function(){
1622                 return KeyEvent.ctrlEnabled;
1623         },
1624         addTimer : function( handler, time, once ){
1625                 SystemTimer.add( this, handler, time, !!once );
1626         },
1627         removeTimer : function( handler ){
1628                 SystemTimer.remove( this, handler );
1629         },
1630         addAsyncCall : function( _callback, _argments, _thisObject ){
1631                 AsyncCall.add( this, _callback, _argments, _thisObject );
1632         },
1633         removeAsyncCall : function( _callback ){
1634                 AsyncCall.remove( this, _callback );
1635         },
1636         fetchHTMLElement : function( id ){
1637                 var elm = document.getElementById( id );
1638                 if( elm ){
1639                         elm.removeAttribute( 'id' );
1640                         elm.parentNode.removeChild( elm );
1641                         return elm;
1642                 };
1643         }
1644 };
1645
1646 var PointingDeviceEventTree = ( function(){
1647         var ROOT_LIST       = [],
1648                 currentRootData = null,
1649                 targetNodeData  = null,
1650                 forceNodeData   = null,
1651                 hoverList       = [];
1652         
1653         function eventRellay( e ){
1654                 var data = forceNodeData, // || targetNodeData,
1655                         x    = e.clientX,
1656                         y    = e.clientY,
1657                         type = e.type,
1658                         list = hoverList,
1659                         i    = 0,
1660                         ret, systemOnly = false, addClass, removeClass,
1661                         parent;
1662                 if( data && data.dispatchEvent( e, type, true ) === true ) return false;
1663                 if( currentRootData === null ) return;
1664                 targetNodeData = currentRootData;
1665                 currentRootData._capcher( x, y );
1666                 targetNodeData.apiuser.updateCoursor( targetNodeData._cursor );
1667                 data = targetNodeData;
1668                 while( data ){
1669                         ret = data.dispatchEvent( e, type, true, systemOnly );
1670                         if( ret === true || ret === false ) break; // systemOnly = true;
1671                         data = data.parentData;
1672                 };
1673                 
1674                 addClass    = Util.addClass;
1675                 removeClass = Util.removeClass;
1676                 for( ; i < list.length; ){
1677                         parent = data = list[ i ];
1678                         while( parent.parentData && parent === parent.parentData.hitChild ){
1679                                 parent = parent.parentData;
1680                         };
1681                         if( parent !== currentRootData ){
1682                                 data.hover === true && removeClass( data.elm, data.hoverClass );
1683                                 delete data.isHover;
1684                                 data.events && data.events.mouseout && data.fire( e, 'mouseout', false );
1685                                 delete data.hitSelf;
1686                                 list.splice( i, 1 );
1687                                 continue;
1688                         };
1689                         if( data.hover === true && data.isHover === false ){
1690                                 addClass( data.elm, data.hoverClass );
1691                                 data.isHover = true;
1692                         };
1693                         if( data.hitSelf === false ){
1694                                 data.events && data.events.mouseover && data.fire( e, 'mouseover', true );
1695                                 data.hitSelf = true;
1696                         };
1697                         ++i;
1698                 };
1699                 return false;
1700         };      
1701         
1702         var NodeClass = function( apiuser, rootData, /*parentLayer,*/ parentData, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){
1703                 ( new NodePrivateData() ).init( apiuser, rootData, /*parentLayer,*/ parentData, this, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop );
1704         };
1705         NodeClass.prototype = {
1706                 createNode : function( rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ){
1707                         var data = NodePrivateData.get( this ),
1708                                 elm;
1709                         if( Type.isHTMLElement( rangeOrElmData ) === true ){
1710                                 elm = rangeOrElmData;
1711                         } else
1712                         if( Type.isString( rangeOrElmData ) === true ){
1713                                 elm = document.getElementById( rangeOrElmData );
1714                                 if( !elm ){
1715                                         elm = Util.pullHtmlAsTemplete( rangeOrElmData );
1716                                 };
1717                                 if( !elm || Type.isHTMLElement( elm ) === false || elm.nodeType !== 1 ){
1718                                         throw new Error( "invalid HTMLElement." );
1719                                 };
1720                         } else
1721                         if( Type.isObject( rangeOrElmData ) === false || Type.isFinite( rangeOrElmData.x ) === false || Type.isFinite( rangeOrElmData.y ) === false ){
1722                                 throw new Error( "No range" );
1723                         };
1724                         
1725                         if( elm && data.elm === null ){
1726                                 throw new Error( "MetaLayer don't containe HTMLElement-Layer." );
1727                         };
1728                         if( data.elm && data.elm.style.hasLayout === false ){
1729                                 throw new Error( "[ie] OffsetParent is hasLayout === false." );
1730                         };
1731                         
1732                         var newNode = new NodeClass( data.apiuser, data.rootData, data, elm || rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ),
1733                                 newData = NodePrivateData.get( newNode );
1734                         
1735                         if( data.childData === null ) data.childData = [];
1736                         data.childData.push( newData );
1737                         return newNode;
1738                 },
1739                 createNodeAt : function(){
1740                 },
1741                 remove : function(){
1742                         NodePrivateData.get( this ).remove();
1743                 },
1744                 nodeIndex : function( v ){
1745                         return NodePrivateData.get( this ).nodeIndex( v );
1746                 },
1747                 numNode : function(){
1748                         return NodePrivateData.get( this ).numNode();
1749                 },
1750                 disabled : function( v ){
1751                         return NodePrivateData.get( this ).disabled( v );
1752                 },
1753                 childrenDisabled : function( v ){
1754                         return NodePrivateData.get( this ).disabled( v );
1755                 },
1756                 mesure : function(){
1757                         NodePrivateData.get( this ).mesure();
1758                 },
1759                 mesureChildren : function(){
1760                         NodePrivateData.get( this ).mesureChildren();
1761                 },
1762                 update : function( x, y, w, h ){
1763                         NodePrivateData.get( this ).update( x, y, w, h );
1764                 },
1765                 setPosition : function( x, y ){
1766                         NodePrivateData.get( this ).setPosition( x, y );
1767                 },
1768                 setSize : function( w, h ){
1769                         NodePrivateData.get( this ).setSize( w, h );
1770                 },
1771                 cursor : function( v ){
1772                         return NodePrivateData.get( this ).cursor( v );
1773                 },
1774                 x : function( x ){
1775                         return NodePrivateData.get( this ).positionX( x );
1776                 },
1777                 y : function( y ){
1778                         return NodePrivateData.get( this ).positionY( y );
1779                 },
1780                 width : function( w ){
1781                         return NodePrivateData.get( this ).width( w );
1782                 },
1783                 height : function( h ){
1784                         return NodePrivateData.get( this ).height( h );
1785                 },
1786                 getAbsolutePositionX : function(){
1787                         return NodePrivateData.get( this ).getAbsolutePositionX();
1788                 },
1789                 getAbsolutePositionY : function(){
1790                         return NodePrivateData.get( this ).getAbsolutePositionY();
1791                 },
1792                 addEventListener : function( type, handler, opt_thisObject ){
1793                         NodePrivateData.get( this ).addEventListener( type, handler, opt_thisObject );
1794                 },
1795                 removeEventListener : function( type, handler ){
1796                         NodePrivateData.get( this ).removeEventListener( type, handler );
1797                 },
1798                 scrollTo : function( x, y ){
1799                         NodePrivateData.get( this ).scrollTo( x, y );
1800                 },
1801                 scrollX : function( v ){
1802                         return NodePrivateData.get( this ).scrollX( v );
1803                 },
1804                 scrollY : function( v ){
1805                         return NodePrivateData.get( this ).scrollY( v );
1806                 },
1807                 invalidateScrollbar : function(){
1808                         ScrollBarManager.update( NodePrivateData.get( this ) );
1809                 }
1810         };
1811
1812         /**
1813          * clip : true の場合、子ノードの変更によってヒットエリアを変化させない.elm には overflow:hidden としておくのが通常.
1814          */
1815         var NodePrivateData = function(){};
1816         NodePrivateData.prototype = {
1817                 elmMouseCatch : null, // rootData only
1818                 eventCounter  : null, // rootData only
1819                 cursorStyle   : null, // rootData only
1820                 node          : null,
1821                 apiuser       : null,
1822                 rootData      : null,
1823                 elm           : null, // resizeTarget
1824                 elmScroll     : null,
1825                 elmScroller   : null,
1826                 elmScrollbar  : null,
1827                 x             : 0,
1828                 y             : 0,
1829                 w             : 0,
1830                 h             : 0,
1831                 t             : 0, // top
1832                 l             : 0, // left
1833                 b             : 0, // bottom
1834                 r             : 0, // right
1835                 absoluteX     : 0,
1836                 absoluteY     : 0,
1837                 _scrollX      : 0,
1838                 _scrollY      : 0,
1839                 scrollingX    : 0,
1840                 scrollingY    : 0,
1841                 _cursor       : '',
1842                 // parentLayer   : null,
1843                 parentData    : null,
1844                 childData     : null,
1845                 events        : null,
1846                 hitChild      : null,
1847                 hitSelf       : false,
1848                 _disabled     : false,
1849                 _childDisabled: false,
1850                 layoutManager : null,
1851                 through       : false,
1852                 clip          : false,
1853                 hover         : false,
1854                 hoverClass    : null,
1855                 isHover       : false,
1856                 scroll        : false,
1857                 dragdrop      : false,
1858                 tooltip       : null,
1859                 init: function( apiuser, rootData, /*parentLayer,*/ parentData, node, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){
1860                         this.apiuser     = apiuser;
1861                         this.rootData    = rootData || this;
1862                         // this.parentLayer = parentLayer;
1863                         this.parentData  = parentData;
1864                         this.node        = node;
1865                         this.through     = through;
1866                         this.clip        = !!clip;
1867                         if( cursor ) this._cursor = cursor;   
1868
1869                         if( Type.isHTMLElement( rangeOrElm ) === true ){
1870                                 this.elm        = rangeOrElm;
1871                                 this.hover      = !!hover;
1872                                 this.hoverClass = hover;
1873                                 this.scroll     = clip && scroll;                               
1874                                 this.mesure();
1875                                 this.scroll === true && ScrollBarManager.register( this );
1876                         } else {
1877                                 this.update( rangeOrElm.x, rangeOrElm.y, rangeOrElm.w, rangeOrElm.h );
1878                         };
1879                         
1880                         NodePrivateData.dataList.push( this );
1881                 },
1882                 mesure : function(){
1883                         var x, y, w, h, parent, _this, _parent;
1884                         if( this.elm ){
1885                                 w = this.elm.offsetWidth;
1886                                 h = this.elm.offsetHeight;
1887                                 _this   = Position.cumulativeOffset( this.elm );
1888                                 _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ];
1889                                 x  = _this[ 0 ] - _parent[ 0 ];
1890                                 y  = _this[ 1 ] - _parent[ 1 ];                         
1891                                 if( this.x !== x || this.y !== y || this.w !== w || this.h !== h ){
1892                                         this.x = x;
1893                                         this.y = y;
1894                                         this.w = w;
1895                                         this.h = h;
1896                                         parent = this.parentData;
1897                                         parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY );
1898                                         this._updateRectangle();
1899                                 };                      
1900                         } else {
1901                                 this._updateRectangle();
1902                         };
1903                 },
1904                 mesureChildren : function(){
1905                         var nodes, i;
1906                         if( nodes = this.childData ){
1907                                 for( i = nodes.length; i; ){
1908                                         nodes[ --i ].mesure();
1909                                 };
1910                         };
1911                 },
1912                 update : function( x, y, w, h ){
1913                         var updateXY = false,
1914                                 _this, _parent,
1915                                 parent;
1916                         
1917                         if( this.elm ){
1918                                 // width
1919                                 if( Type.isFinite( w ) === true ){
1920                                         this.elm.style.width = w + 'px';
1921                                 } else
1922                                 if( Type.isString( w ) === true ){
1923                                         this.elm.style.width = w;
1924                                         w = this.elm.offsetWidth;
1925                                 };
1926                                 //update = this.w !== w;
1927         
1928                                 // height
1929                                 if( Type.isFinite( h ) === true ){
1930                                         this.elm.style.height = h + 'px';
1931                                 } else
1932                                 if( Type.isString( h ) === true ){
1933                                         this.elm.style.height = w;
1934                                         h = this.elm.offsetHeight;
1935                                 };
1936                                 //update = update || this.h !== h;
1937                                 
1938                                 // x
1939                                 if( Type.isFinite( x ) === true ){
1940                                         this.elm.style.left = x + 'px';
1941                                 } else
1942                                 if( Type.isString( x ) === true ){
1943                                         this.elm.style.left = x;
1944                                         updateXY = true;
1945                                 } else {
1946                                         updateXY = true;
1947                                 };
1948                                 
1949                                 // y
1950                                 if( Type.isFinite( y ) === true ){
1951                                         this.elm.style.top = y + 'px';
1952                                 } else
1953                                 if( Type.isString( y ) === true ){
1954                                         this.elm.style.top = y;
1955                                         updateXY = true;
1956                                 } else {
1957                                         updateXY = true;
1958                                 };
1959                                 if( updateXY === true ){
1960                                         _this   = Position.cumulativeOffset( this.elm );
1961                                         _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ];
1962                                         x       = _this[ 0 ] - _parent[ 0 ];
1963                                         y       = _this[ 1 ] - _parent[ 1 ];
1964                                 };
1965                                 //update = update || this.x !== x;
1966                                 //update = update || this.y !== y;
1967                                 
1968                                 //update === true && this._updateRectangle();
1969                                 // return;
1970                         };
1971                         x = Type.isFinite( x ) === true ? x : this.x;
1972                         y = Type.isFinite( y ) === true ? y : this.y;
1973                         w = Type.isFinite( w ) === true ? w : this.w;
1974                         h = Type.isFinite( h ) === true ? h : this.h;
1975                         if( this.x !== x || this.y !== y ){
1976                                 this.x = x;
1977                                 this.y = y;
1978                                 //console.log( 'xy  ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h + ' absX:' + this.parentData.absoluteX )
1979                                 parent = this.parentData;
1980                                 parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY );
1981                                 this.w === w && this.h === h && this._updateRectangle();
1982                         };
1983                         if( this.w !== w || this.h !== h ){
1984                                 this.w = w;
1985                                 this.h = h;
1986                                 //console.log( 'wh  ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h )
1987                                 this._updateRectangle();
1988                         };
1989                         
1990                         ScrollBarManager.update( this );
1991                 },
1992                 _updateAbsoluteXY : function( x, y, sX, sY ){
1993                         var nodes, i;
1994                         this.absoluteX = x = this.x + x;
1995                         this.absoluteY = y = this.y + y;
1996                         if( nodes = this.childData ){
1997                                 for( i = nodes.length; i; ){
1998                                         nodes[ --i ]._updateAbsoluteXY( x, y, this.scrollingX, this.scrollingY );
1999                                 };
2000                         };
2001                 },
2002                 _updateRectangle : function(){
2003                         var w = this.w,
2004                                 h = this.h,
2005                                 x = this.x,
2006                                 y = this.y,
2007                                 l = x,
2008                                 t = y,
2009                                 r = x + w,
2010                                 b = y + h,
2011                                 nodes = this.childData,
2012                                 i, node;
2013                         // self;
2014                         // childnodes
2015                         if( this.clip === false && nodes ){
2016                                 for( i = nodes.length; i; ){
2017                                         node = nodes[ --i ];
2018                                         if( node.l + x < l ) l = x + node.l;
2019                                         if( node.t + y < t ) t = y + node.t;
2020                                         if( r < node.r + x ) r = x + node.r;
2021                                         if( b < node.b + y ) b = y + node.b;
2022                                 };
2023                         };
2024                         // update
2025                         if( b !== this.b || r !== this.r || t !== this.t || l !== this.l ){
2026                                 this.l = l;
2027                                 this.t = t;
2028                                 this.r = r;
2029                                 this.b = b;
2030                                 // this.w = r - x;
2031                                 // this.h = b - y;
2032                                 this.parentData && this.parentData.clip === false && this.parentData._updateRectangle();
2033                                 return true;
2034                         };
2035                 },
2036                 setPosition : function( x, y ){
2037                         this.update( x, y );
2038                 },
2039                 setSize : function( w, h ){
2040                         this.update( undefined, undefined, w, h );
2041                 },
2042                 positionX : function( x ){
2043                         x !== undefined && this.update( x );
2044                         return this.x;
2045                 },
2046                 positionY : function( y ){
2047                         y !== undefined && this.update( undefined, y );
2048                         return this.y;
2049                 },
2050                 width : function( w ){
2051                         w !== undefined && this.update( undefined, undefined, w );
2052                         return this.w;
2053                 },
2054                 height : function( h ){
2055                         h !== undefined && this.update( undefined, undefined, undefined, h );
2056                         return this.h;
2057                 },
2058                 getAbsolutePositionX : function(){
2059                         return this.absoluteX;
2060                 },
2061                 getAbsolutePositionY : function(){
2062                         return this.absoluteY;
2063                 },
2064                 cursor : function( v ){
2065                         if( Type.isString( v ) === true ){
2066                                 this._cursor = v;
2067                                 this === targetNodeData && this.apiuser.updateCoursor( v );
2068                         };
2069                         return this._cursor;
2070                 },
2071                 addEventListener : function( eventType, handler, opt_thisObject ){
2072                         var node    = this.node,
2073                                 counter = this.rootData.eventCounter,
2074                                 list, i;
2075                         if( this.events === null ) this.events = {};
2076                         list = this.events[ eventType ];
2077                         if( !list ){
2078                                 list = this.events[ eventType ] = [];
2079                         } else {
2080                                 for( i = list.length; i; ){
2081                                         if( list[ --i ].match( eventType, handler ) === true ){
2082                                                 return;
2083                                         };
2084                                 };                              
2085                         };
2086                         list.push( new EventTicketClass( this.node, eventType, handler, opt_thisObject ) );
2087                         if( eventType !== 'mouseout' && eventType !== 'mouseover' ){
2088                                 if( counter[ eventType ] ){
2089                                         ++counter[ eventType ];
2090                                 } else {
2091                                         //console.log( eventType );
2092                                         counter[ eventType ] = 1;
2093                                         MouseEvent.add( this.apiuser, this.rootData.elmMouseCatch, eventType, eventRellay );
2094                                 };                              
2095                         };
2096                 },
2097                 removeEventListener : function( eventType, handler ){
2098                         var events  = this.events,
2099                                 counter = this.rootData.eventCounter,
2100                                 type, list, i = 0;
2101                         if( events === null ) return;
2102                         console.log( ' *** remove ' + eventType );
2103                         for( type in events ){
2104                                 list = events[ type ];
2105                                 if( eventType && eventType !== type ) continue;
2106                                 for( ; i < list.length; ){
2107                                         if( list[ i ].destroy( type, handler ) === true ){
2108                                                 console.log( ' *** removed! ' + type );
2109                                                 list.splice( i, 1 );
2110                                         } else {
2111                                                 ++i;
2112                                         };
2113                                 };
2114                                 if( list.length === 0 ){
2115                                         // delete this[ type ];
2116                                         delete events[ type ];
2117                                 };
2118                                 if( counter[ type ] ){
2119                                         --counter[ type ];
2120                                         if( counter[ type ] === 0 ){
2121                                                 MouseEvent.remove( this.apiuser, this.rootData.elmMouseCatch, type, eventRellay );
2122                                                 delete counter[ type ];
2123                                         };
2124                                 };
2125                         };
2126                 },
2127                 _capcher : function( x, y ){
2128                         var t = this, nodes, child, _x, _y, hit, i;
2129                         if( t._disabled === true ) return false;
2130                         delete t.hitChild;
2131                         x -= t.x;
2132                         y -= t.y;
2133                         if( nodes = t.childData ){
2134                                 _x = x - t.scrollingX;
2135                                 _y = y - t.scrollingY;
2136                                 for( i = nodes.length; i; ){
2137                                         child = nodes[ --i ];
2138                                         if( child._disabled === false && child.l <= _x && _x < child.r && child.t <= _y && _y < child.b && child._capcher( _x, _y ) === true ){
2139                                                 t.hitChild = child;
2140                                                 break;
2141                                         };
2142                                 };
2143                         };
2144                         if( t.through === true ){
2145                                 t.hitChild && t.hitSelf === false && hoverList.push( t );
2146                                 return !!t.hitChild;
2147                         };
2148                         hit = 0 <= x && x < t.w && 0 <= y && y < t.h;
2149                         ( t.hitChild || hit ) && t.hitSelf === false && hoverList.push( t );
2150                         if( hit === true && t.hitChild === null ) targetNodeData = t;
2151                         return hit || !!t.hitChild;
2152                 },
2153                 fire : function( e, eventType, hit ){
2154                         var list = this.events[ eventType ],
2155                                 i    = list.length;
2156                         e = NodePrivateData.createEvent( e, eventType, this, hit );
2157                         for( ; i; ) list[ --i ].fire( e );
2158                         // console.log( eventType + ' x:' + x + ' y:' + y );
2159                 },
2160                 dispatchEvent : function( e, eventType, hit ){
2161                         var ret, list, i, p, child;
2162                         if( !this.events || !( list = this.events[ eventType ] ) ) return;
2163                         
2164                         child = !!this.hitChild;
2165                         e = NodePrivateData.createEvent( e, eventType, this, hit );
2166                         for( i = list.length; i; ){
2167                                 ret = list[ --i ].fire( e );
2168                                 if( ret === true && child === false ){
2169                                         forceNodeData = this;
2170                                         return true;
2171                                 };
2172                                 if( ret === false ) return false;
2173                         };
2174                         forceNodeData  = null;
2175                 },
2176                 scrollTo : function( x, y ){
2177                         this._scrollX = x;
2178                         this._scrollY = y;
2179                         ScrollBarManager.update( this );
2180                 },
2181                 scrollX : function( v ){
2182                         if( Type.isFinite( v ) === true ){
2183                                 this._scrillX = v;
2184                                 ScrollBarManager.update( this );
2185                         };
2186                         return this.scrollingX; // this._scrollX;
2187                 },
2188                 scrollY : function( v ){
2189                         if( Type.isFinite( v ) === true ){
2190                                 this._scrillY = v;
2191                                 ScrollBarManager.update( this );
2192                         };
2193                         return this.scrollingY; // this._scrollY;
2194                 },
2195                 nodeIndex : function( v ){
2196                         var list, i;
2197                         if( !this.parentData ) return 0;
2198                         
2199                         list = this.parentData.childData;
2200                         i    = Util.getIndex( list, this );
2201                         if( Type.isFinite( v ) === false || i === v && v < 0 && list.length <= v ) return i;
2202                         
2203                         list.splice( i, 1 );
2204                         list.length === v ? list.push( this ) : list.splice( v, 0, this );
2205                         this._free();
2206                         return v;
2207                 },
2208                 _free : function(){
2209                         if( this.parentData.hitChild === this ){
2210                                 this.parentData.hitChild = null;
2211                                 this.isHover === true && hoverList.splice( Util.getIndex( hoverList, this ), 1 ) && Util.removeClass( this.elm, this.hoverClass );
2212                                 this.isHover = false;
2213                                 if( forceNodeData === this ) forceNodeData = null;
2214                                 if( targetNodeData  === this ) targetNodeData  = null;
2215                         };                      
2216                 },
2217                 numNode : function(){
2218                         return this.childData ? this.childData.length : 0;
2219                 },
2220                 disabled : function( v ){
2221                         if( Type.isBoolean( v ) === true ){
2222                                 this._disabled = v;
2223                                 if( v === false ){
2224                                         this._free();
2225                                 };
2226                         };
2227                         return this._disabled;
2228                 },
2229                 childrenDisabled : function( v ){
2230                         if( Type.isBoolean( v ) === true ){
2231                                 this._childDisabled = v;
2232                         };
2233                         return this._childDisabled;
2234                 },
2235                 remove : function(){
2236                         if( this === this.rootData ) return;
2237                         var parent = this.parentData,
2238                                 nodes  = parent.childData;
2239                         this._destroy();
2240                         if( parent.hitChild === this ) delete parent.hitChild;
2241                         nodes.splice( Util.getIndex( nodes, this ), 1 );
2242                         if( nodes.length === 0 ) delete parent.childData;       
2243                         parent.clip === false && parent._updateRectangle();
2244                 },
2245                 _destroy : function(){
2246                         var nodes = this.childData,
2247                                 list  = NodePrivateData.dataList,
2248                                 node;
2249                         this.removeEventListener();
2250                         ScrollBarManager.remove( this );
2251                         if( nodes ){
2252                                 while( node = nodes.shift() ) node._destroy();
2253                                 delete this.childData;
2254                         };
2255                         list.splice( Util.getIndex( list, this ), 1 );
2256                 }
2257         };
2258         NodePrivateData.dataList = [];
2259         NodePrivateData.get = function( node ){
2260                 // if( node instanceof NodePrivateData ) return node;
2261                 // return NodePrivateData.dataList[ layer._getUID() ];
2262                 var list = NodePrivateData.dataList;
2263                 for( var i = list.length; i; ){
2264                         if( list[ --i ].node === node ) return list[ i ];
2265                 };
2266                 return null;
2267         };
2268         NodePrivateData.createEvent = function( e, eventType, data, hit ){
2269                 var _e = {
2270                         layerX      : e.clientX - data.absoluteX,
2271                         layerY      : e.clientY - data.absoluteY,
2272                         clientX     : e.clientX,
2273                         clientY     : e.clientY,
2274                         dragOffsetX : e.dragOffsetX,
2275                         dragOffsetY : e.dragOffsetY,
2276                         dragPhase   : e.dragPhase,                                      
2277                         eventType   : eventType,
2278                         hit         : hit,
2279                         node        : data.node,
2280                         wheelDelta  : e.wheelDelta,
2281                         target      : forceNodeData ? forceNodeData.node : targetNodeData ? targetNodeData.node : null
2282                 };
2283                 return _e;
2284         };
2285         
2286         var EventTicketClass = function( node, eventType, handler, opt_thisObject ){
2287                 this.node    = node;
2288                 this.type    = eventType;
2289                 this.handler = handler;
2290                 this.thisObj = opt_thisObject || node;
2291         };
2292         EventTicketClass.prototype = {
2293                 match : function( eventType, handler ){
2294                         if( handler && this.handler !== handler ) return false;
2295                         if( eventType && this.type !== eventType ) return false;
2296                         return true;
2297                 },
2298                 destroy : function( eventType, handler ){
2299                         if( this.match( eventType, handler ) === false ) return false;
2300                         delete this.node;
2301                         delete this.type;
2302                         delete this.handler;
2303                         delete this.thisObj;
2304                         return true;
2305                 },
2306                 fire : ( function(){
2307                         if( Function.prototype.call ){
2308                                 return function( e ){
2309                                         return this.handler.call( this.thisObj, e );
2310                                 };                              
2311                         };
2312                         return function( e ){
2313                                 var ret;
2314                                 this.thisObj._currentHandler = this.handler;
2315                                 ret = this.thisObj._currentHandler( e );
2316                                 delete this.thisObj._currentHandler;
2317                                 return ret;                                     
2318                         };
2319                 })()
2320         };
2321         
2322 /*-------------------------------------
2323  *  StayHelper
2324  */
2325         var StayEventTicketClass = function( node, data, stayhandler, opt_thisObject ){
2326                 node.addEventListener( 'mouseover', this.mouseoverHandler, this );
2327                 this.node       = node;
2328                 this.data       = data;
2329                 this.handler    = stayhandler;
2330                 this.thisObject = opt_thisObject;
2331         };
2332         StayEventTicketClass.prototype = Util.extend( new EventTicketClass( null, 'mousestay' ), {
2333                 // type : 'mousestay',
2334                 e    : null,
2335                 mouseoverHandler : function( e ){
2336                         this.e = NodePrivateData.createEvent( e, this.type, this.data, true );
2337                         this.node.addEventListener( 'mouseout',  this.mousestayHandler, this );
2338                         this.node.addEventListener( 'mousemove', this.mousemoveHandler, this );
2339                         SystemTimer.add( this.data.apiuser, this.timeoutHandler, null, this );
2340                 },
2341                 timeoutHandler : function(){
2342                         this.mouseoutHandler();
2343                         return this.fire( this.e );
2344                 },
2345                 mousemoveHandler : function( e ){
2346                         this.e = NodePrivateData.createEvent( e, this.type, this.data, true );
2347                         SystemTimer.remove( this.data.apiuser, this.timeoutHandler );
2348                         SystemTimer.add( this.data.apiuser, this.timeoutHandler, null, this );
2349                 },
2350                 mouseoutHandler : function( e ){
2351                         this.node.removeEventListener( 'mouseout', this.mousestayHandler );
2352                         this.node.removeEventListener( 'mousemove', this.mousemoveHandler );
2353                         SystemTimer.remove( this.data.apiuser, this.timeoutHandler );
2354                         delete this.e;
2355                 }
2356         });
2357         
2358         var ScrollBarManager = ( function(){
2359                 var elmScroller     = document.createElement( 'div' ),
2360                         elmBar          = document.createElement( 'div' ),
2361                         smoothList      = [],
2362                         dragPhase       = 2,
2363                         dragOut         = false,
2364                         currentNodeData = null,
2365                         dragStartY      = 0,
2366                         currentEvent;
2367                 
2368                 function tick(){
2369                         var list = smoothList,
2370                                 i, data, y;
2371                         for( i = 0; i < list.length; ){
2372                                 data = list[ i ];
2373                                 if( data.scrollingY !== data._scrollY ){
2374                                         y = data.scrollingY += data.smoothY;
2375                                         if( data.smoothY < 0 ){
2376                                                 y = y < data._scrollY ? data._scrollY : y;
2377                                         } else {
2378                                                 y = data._scrollY < y ? data._scrollY : y;
2379                                         };
2380                                         data.scrollingY    = y;
2381                                         data.elm.scrollTop = -y;
2382                                         data.events && data.events.scroll && data.fire( currentEvent, 'scroll', true );
2383                                 };
2384                                 if( data.scrollingY === data._scrollY ){
2385                                         list.splice( i, 1 );
2386                                         // data.events && data.events.scroll && data.fire( currentEvent, 'scroll', true );
2387                                 } else {
2388                                         ++i;
2389                                 };
2390                         };
2391                         list.length === 0 && SystemTimer.remove( SUPER_USER_KEY, tick );
2392                         currentEvent.type = 'updateAfterScroll';
2393                         AsyncCall.add( data.apiuser, eventRellay, currentEvent ); // スクロール後の更新        
2394                 };
2395                 
2396                 function scrollReady( e ){
2397                         var data = this;
2398                         
2399                         dragOut = false;
2400                         if( data === currentNodeData || dragPhase !== 2 ) return; // Drag中の場合は 他にスクロールを作らない
2401                         currentNodeData && scrollRelease();
2402
2403                         dragPhase = 2;
2404                         data.elm.parentNode.appendChild( elmScroller );
2405                         elmScroller.appendChild( data.elm );
2406                         
2407                         elmScroller.style.cssText = 'position:absolute;left:0;top:0;';
2408                         elmScroller.appendChild( elmBar );      
2409                         
2410                         data.elm.scrollTop = -data.scrollingY;
2411                         data.rootData.addEventListener( 'mousewheel', onMouseWheelScroll, data );
2412                         data.rootData.addEventListener( 'mousedrag',  onMouseDragScroll, data );
2413                         data.addEventListener( 'mouseout',   onMouseOut, data );
2414                         currentNodeData = data;
2415                         ScrollBarManager.update( data );
2416                 };
2417                 function scrollRelease(){
2418                         var data   = currentNodeData;
2419                         var parent = elmScroller.parentNode;
2420                         parent.appendChild( currentNodeData.elm );
2421                         parent.removeChild( elmScroller );
2422                         currentNodeData.elm.scrollTop = -data.scrollingY;
2423                         
2424                         data.rootData.removeEventListener( 'mousewheel', onMouseWheelScroll, data );
2425                         data.rootData.removeEventListener( 'mousedrag',  onMouseDragScroll, data );
2426                         data.removeEventListener( 'mouseout',   onMouseOut, data );
2427                         currentNodeData = null;
2428                 };
2429                 function onMouseOut( e ){
2430                         dragOut = true;
2431                         console.log( 'mouseOut ' + dragPhase );
2432                         dragPhase === 2 && scrollRelease(); // Dragしてのアウトの場合, scroll をリリースしない
2433                 };
2434                 function onMouseWheelScroll( e ){
2435                         var data = this;
2436                         this._scrollY += e.wheelDelta;
2437                         ScrollBarManager.update( this );
2438                         currentEvent = e;
2439                         return true;
2440                 };
2441                 function onMouseDragScroll( e ){
2442                         var data = this;
2443                         //e.dragOffsetY;
2444                         currentEvent = e;
2445                         dragPhase = e.dragPhase;
2446                         switch( dragPhase ){
2447                                 case 0:
2448                                         dragStartY = this.scrollingY;
2449                                         data.rootData.removeEventListener( 'mousewheel', onMouseWheelScroll, data );
2450                                 case 1:
2451                                         this._scrollY = dragStartY + e.dragOffsetY;
2452                                         ScrollBarManager.update( this );                                
2453                                         return true;
2454                                 case 2:
2455                                         dragOut === true ? scrollRelease() : data.rootData.addEventListener( 'mousewheel', onMouseWheelScroll, data );
2456                                         return false;
2457                         };
2458                 };
2459                 
2460                 return {
2461                         register : function( data ){
2462                                 data.addEventListener( 'mouseover', scrollReady, data );
2463                         },
2464                         update : function( data ){
2465                                 // if( data !== currentNodeData ) return;
2466                                 var isCurrent = data === currentNodeData;
2467                                 
2468                                 var contentH = data._scrollH = data.elm.scrollHeight,
2469                                         clipH    = data.h,
2470                                         offsetH  = contentH - clipH,
2471                                         scrollY  = data._scrollY = 0 < data._scrollY ? 0 : ( data._scrollY < -offsetH ? -offsetH : data._scrollY ),
2472                                         barH, barY;
2473                                 if( isCurrent === true ){
2474                                         elmScroller.style.width  = data.w + 'px';
2475                                         elmScroller.style.height = clipH + 'px';                                        
2476                                 };
2477                                 
2478                                 if( offsetH < 1 ){
2479                                         data._scrollY = scrollY = 0;
2480                                         if( isCurrent === true ) elmBar.style.display = 'none';
2481                                 } else
2482                                 if( isCurrent === true ){
2483                                         barH     = Math.floor( clipH * ( clipH / contentH ) );
2484                                         barY     = Math.floor( ( clipH - barH ) * - scrollY / offsetH );
2485                                         elmBar.style.cssText = [
2486                                                 'position:absolute;',
2487                                                 'width:10px;',
2488                                                 'background-color:#333;',
2489                                                 'right:2px;',
2490                                                 'font-size:0;line-height:0;',
2491                                                 'height:', barH, 'px;',
2492                                                 'top:', data.y + barY, 'px;'
2493                                         ].join( '' );                                   
2494                                 };
2495                                 data.smoothY = ( scrollY - data.scrollingY ) / 10;
2496                                 if( data.scrollingY !== scrollY && Util.getIndex( smoothList, data ) === -1 ){
2497                                         smoothList.length === 0 && SystemTimer.add( SUPER_USER_KEY, tick, 16 );
2498                                         smoothList.push( data );
2499                                 };
2500                         },
2501                         remove : function( data ){
2502                                 var list = smoothList,
2503                                         i    = Util.getIndex( list, data );
2504                                 data === currentNodeData && scrollRelease();
2505                                 i !== -1 && list.splice( i, 1 );
2506                         }
2507                 };
2508         })();
2509         
2510         return {
2511                 create : function( apiuser ){
2512                         var     elm  = document.createElement( 'div' ),
2513                                 root, data;
2514                         body.appendChild( elm );
2515                         
2516                         root = new NodeClass( apiuser, null, null, elm );
2517                         data = NodePrivateData.get( root );
2518                         
2519                         // elm.style.cssText = 'position:absolute;top:0;left:0;height:100%;';
2520                         elm.className      = 'mouse-operation-catcher';
2521                         elm.unselectable   = 'on';
2522                         data.elmMouseCatch = elm;
2523                         
2524                         data.eventCounter  = {};
2525                         ROOT_LIST.push( data );
2526                         currentRootData    = data;
2527                         targetNodeData     = null;
2528                         forceNodeData      = null;
2529                         
2530                         MouseEvent.add( apiuser, elm, 'mousemove', eventRellay );
2531                         return root;
2532                 },
2533                 onCurrentApplicationChange : function( _application ){
2534                         currentRootData    = null;
2535                         targetNodeData     = null;
2536                         forceNodeData      = null;
2537                         for( var i = ROOT_LIST.length; i; ){
2538                                 if( ROOT_LIST[ --i ].apiuser === _application ){
2539                                         currentRootData = ROOT_LIST[ i ];
2540                                         return;
2541                                 };
2542                         };
2543                 },
2544                 destroyTree : function( root ){
2545                         var data = NodePrivateData.get( root );
2546                         MouseEvent.remove( data.apiuser, data.elmMouseCatch, 'mousemove', eventRellay );
2547                         body.removeChild( data.elmMouseCatch );
2548                         data._destroy();
2549                         ROOT_LIST.splice( Util.getIndex( ROOT_LIST, data ), 1 );
2550                         if( currentRootData === data ){
2551                                 currentRootData    = null;
2552                                 targetNodeData     = null;
2553                                 forceNodeData      = null;      
2554                         };
2555                 },
2556                 onSystemShutdown : function(){
2557                         
2558                 },
2559                 isNodeInstance : function( node ){
2560                         return node instanceof NodeClass;
2561                 },
2562                 _getNodePrivateData : function( node ){ // system only
2563                         return NodePrivateData.get( node );
2564                 }
2565         };
2566 })();
2567
2568 var Application = ( function(){
2569         
2570         var LIVE_APPLICATION_LIST = [];
2571         
2572         var currentApplication    = null,
2573                 coveredApplication    = null,
2574                 winW                  = 0,
2575                 winH                  = 0;
2576         
2577         var ApplicationReference = function( appClass, isOverlay, displayName, id, thumbnailUrl, tailColor ){
2578                 var self          = this;
2579                 var application   = null;
2580                 this.id           = id;
2581                 this.displayName  = displayName;
2582                 this.thumbnailUrl = thumbnailUrl;
2583                 this.tailColor    = tailColor;
2584                 
2585                 function asyncBoot(){
2586                         application = Application.boot( appClass, displayName, self.getUID(), isOverlay, Util.copyArray( arguments ) );
2587                 };
2588                 this.getUID = function(){
2589                         return Util.getIndex( API_USER_LIST, appClass );
2590                 };
2591                 this.getDisplayName = function(){
2592                         return this.displayName;
2593                 };
2594                 this.boot = function( /* _option */ ){
2595                         AsyncCall.add( this, asyncBoot, Util.copyArray( arguments ) );
2596                 };
2597                 this.shutdown = function(){
2598                         if( !application ) return false;
2599                         
2600                         AsyncCall.add( application, ( isOverlay === true ? Overlay.hide : application.close ) );
2601                 };
2602         };
2603         
2604         function asyncBootHome(){
2605                 currentApplication === null && Home.boot();
2606         };
2607         function asyncOpen( /* arguments */ ){
2608                 var _arg = Util.copyArray( arguments );
2609                 _arg.unshift( winW, winH );
2610                 currentApplication.open.apply( currentApplication, _arg );
2611         };
2612         return {
2613                 register: function( _class, _overlay, _tail, _displayName, _id, _thumbnailUrl, _tailColor ){
2614                         APPLICATION_LIST.push( _class );
2615                         API_USER_LIST.push( _class );
2616                         var _ref = new ApplicationReference( _class, _overlay, _displayName, _id, _thumbnailUrl, _tailColor );
2617                         _tail === true && Home.add( _ref );
2618                         return _ref;
2619                 },
2620                 isApplicationInstance: function( app ){
2621                         return ApplicationPrivateData.get( app ) !== null;
2622                 },
2623                 isApplicationReference: function( _reference ){
2624                         return _reference instanceof ApplicationReference;
2625                 },
2626                 isCurrentAppplication: function( app ){
2627                         return app === currentApplication;
2628                 },
2629                 boot: function( appClass, displayName, uid, isOverlay, arg ){
2630                         if( currentApplication ){
2631                                 if( currentApplication.getUID() === uid ) return null;
2632                                 if( isOverlay === false && currentApplication.close() === false ) return null;
2633                         };
2634
2635                         appClass.prototype = new AbstractApplication( appClass, displayName, isOverlay );
2636                         
2637                         var application = new appClass(),
2638                                 data = ApplicationPrivateData.get( application );
2639                         
2640                         application.rootElement = data.rootElement;
2641                         data.application = application;
2642                         
2643                         coveredApplication = isOverlay === true ? currentApplication : null;
2644                         
2645                         Application.onCurrentApplicationChange( application );
2646                         
2647                         if( isOverlay === false ){
2648                                 body.style.backgroundColor = application.bgColor;
2649                                 
2650                                 body.appendChild( data.rootElement );
2651                                 data.rootElement.style.display = 'none';
2652                                 application.init();
2653
2654                                 application.addAsyncCall( asyncOpen, arg );
2655                         } else {
2656                                 Overlay.show( application, arg );
2657                         };
2658                         
2659                         return application;
2660                 },
2661                 shutdown: function( _application, isOverlay ){
2662                         if( isOverlay === false ){
2663                                 currentApplication = null;
2664                                 AsyncCall.add( SUPER_USER_KEY, asyncBootHome );
2665                         } else {
2666                                 Application.onCurrentApplicationChange( coveredApplication );
2667                                 coveredApplication = null;
2668                         };
2669                 },
2670                 onCurrentApplicationChange: function( _application ){
2671                         if( Application.isApplicationInstance( _application ) === false ) return;
2672                         if( currentApplication === _application ) return;
2673                         currentApplication = _application;
2674                         MouseEvent.onCurrentApplicationChange( _application );
2675                         PointingDeviceEventTree.onCurrentApplicationChange( _application );
2676                         KeyEvent.updateCurrentListener( _application );
2677                         // InteractiveLayer.onCurrentApplicationChange( _application );
2678                 },
2679                 onApplicationShutdown: function( _application ){
2680                         LIVE_APPLICATION_LIST.splice( Util.getIndex(  LIVE_APPLICATION_LIST, _application ) );
2681                 },
2682                 onWindowResize: function( w, h ){
2683                         winW = w;
2684                         winH = h;
2685                         currentApplication && currentApplication.resize( w, h );
2686                         Overlay.onWindowResize( w, h );
2687                         UI.onWindowResize( w, h );
2688                 },
2689                 onSystemShutdown: function(){
2690                         
2691                 }
2692         }
2693 })();
2694
2695 /* --------------------------------------------------------------
2696  * Home
2697  * 
2698  */
2699         var Home = ( function(){
2700                 var APP_REF_LIST    = [];
2701                 var ELM_TAIL_ORIGIN = ( function(){
2702                         var ret = document.createElement( 'div' ),
2703                                 h2  = document.createElement( 'h2' );
2704                         ret.className = 'tail-wrapper';
2705                         ret.appendChild( h2 );
2706                         h2.appendChild( document.createTextNode( 'appName' ) );
2707                         return ret;
2708                 })();
2709                 
2710                 var TailClass = function( appRef ){
2711                         this.elm = ELM_TAIL_ORIGIN.cloneNode( true );
2712                         this.destroy = function(){
2713                                 appRef = self = elmName = null;
2714                         };                      
2715                         
2716                         var self    = this,
2717                                 elmName = this.elm.getElementsByTagName( 'h2' )[ 0 ].firstChild;
2718                         
2719                         this.elm.style.backgroundColor = appRef.tailColor;
2720                         elmName.data = appRef.displayName;
2721                 };
2722                 
2723                 var ref = Application.register( function(){
2724                         var self     = this,
2725                                 winW     = 0,
2726                                 winH     = 0,
2727                                 tailList = [],
2728                                 elmContainer, elmHeader;
2729                         
2730                         function draw(){
2731                                 var tail, elm;
2732                                 for( var i=0, l=APP_REF_LIST.length; i<l; ++i ){
2733                                         tail = new TailClass( APP_REF_LIST[ i ] );
2734                                         tailList.push( tail );
2735                                         elm  = tail.elm;
2736                                         elmContainer.appendChild( elm );
2737                                         self.addEventListener( elm, 'click', onTailClick );
2738                                 };
2739                         };
2740                         
2741                         function onTailClick( e ){
2742                                 var _children = elmContainer.getElementsByTagName( 'div' );
2743                                 for( var i=0, l=_children.length; i<l; ++i ){
2744                                         if( this === _children[ i ] ){
2745                                                 APP_REF_LIST[ i ].boot();
2746                                                 break;
2747                                         };
2748                                 };
2749                         };
2750                         
2751                         this.bgColor     = '#0F6D39';
2752                         this.MIN_WIDTH   = 320;
2753                         this.MIN_HEIGHT  = 320;
2754                         this.onInit = function(){
2755                                 self.rootElement.id = 'home-root';
2756                                 
2757                                 elmContainer        = document.createElement( 'div' );
2758                                 self.rootElement.appendChild( elmContainer );
2759                                 elmContainer.id     = 'home-tail-container';
2760                                 
2761                                 elmHeader           = document.createElement( 'div' );
2762                                 self.rootElement.appendChild( elmHeader );
2763                                 elmHeader.id        = 'home-header';
2764                         };
2765                         this.onOpen = function( _w, _h ){
2766                                 winW = _w;
2767                                 winH = _h;
2768                                 draw();
2769                         };
2770                         this.onPaneResize = function( _w, _h ){
2771                                 
2772                         };
2773                         this.onClose = function(){
2774                                 self.removeEventListener();
2775                                 while( tailList.length > 0 ){
2776                                         tailList.shift().destroy();
2777                                 }
2778                                 self = tailList = elmContainer = null;
2779                         };
2780                 }, false, false, 'home', 'home', null );
2781                 
2782                 return {
2783                         add: function( _appRef ){
2784                                 if( Application.isApplicationReference( _appRef ) === false ) return;
2785                                 Util.getIndex( APP_REF_LIST, _appRef ) === -1 && APP_REF_LIST.push( _appRef );
2786                         },
2787                         boot: function(){
2788                                 ref.boot();
2789                         }
2790                 }
2791         })();
2792
2793         var Page = ( function(){
2794                 var pageNodes = [],
2795                         appClass, ref,
2796                         ignoreTagList = [ 'script', 'noscript', 'style' ];
2797                 
2798                 var MemoryClass = function( node ){
2799                         this.node = node;
2800                 };
2801                 MemoryClass.prototype = {
2802                         init: function(){
2803                                 var node      = this.node,
2804                                         _nodeType = node.nodeType;
2805                                 if( _nodeType === 1 && Util.getIndex( ignoreTagList, node.tagName.toLowerCase() ) === -1 ){
2806                                         this.type    = _nodeType;
2807                                         this.display = node.style.display;
2808                                 } else
2809                                 if( _nodeType === 3 ){
2810                                         if( node.data.replace( /\s/g, '' ).length !== 0 ){
2811                                                 this.type    = _nodeType;
2812                                                 this.before  = pageNodes.length === 0 ? null : pageNodes[ pageNodes.length - 1 ].node;
2813                                         } else {
2814                                                 body.removeChild( node );
2815                                                 return false;
2816                                         }
2817                                 } else {
2818                                         // body.removeChild( node );
2819                                         return false;
2820                                 };
2821                         },
2822                         show: function(){
2823                                 if( this.type === 1 ){
2824                                         if( this.display ){
2825                                                 this.node.style.display = this.display;
2826                                         } else {
2827                                                 this.node.style.display = '';
2828                                         }
2829                                 } else {
2830                                         if( this.before ){
2831                                                 body.insertBefore( this.node, this.before );
2832                                         } else {
2833                                                 body.appendChild( this.node );
2834                                         };
2835                                 };
2836                         },
2837                         hide: function(){
2838                                 if( !this.node.parentNode ){
2839                                         return;
2840                                 };
2841                                 if( this.type === 1 ){
2842                                         this.node.style.display = 'none';
2843                                 } else {
2844                                         body.removeChild( this.node );
2845                                 };
2846                         }
2847                 };
2848                 
2849                 return {
2850                         onReady: function(){
2851                                 var _children = Util.copyArray( body.childNodes ),
2852                                         _mem;
2853                                 for( var i = 0, l = _children.length; i<l; ++i ){
2854                                         _mem = new MemoryClass( _children[ i ] );
2855                                         _mem.init() !== false && pageNodes.push( _mem );
2856                                 };
2857                                 if( pageNodes.length !== 0 ){
2858                                         if( Type.isFunction( gOS.PageApplicationClass ) === true ){
2859                                                 Page.appClass = gOS.PageApplicationClass;
2860                                                 Page.appClass.bgColor    = Page.appClass.bgColor;
2861                                                 Page.appClass.MIN_WIDTH  = Page.appClass.MIN_WIDTH  || 240;
2862                                                 Page.appClass.MIN_HEIGHT = Page.appClass.MIN_HEIGHT || 240;
2863                                         } else {
2864                                                 Page.appClass = function(){
2865                                                         var self     = this;
2866                                                         
2867                                                         this.bgColor      = '#ffffff';
2868                                                         this.MIN_WIDTH    = 200;
2869                                                         this.MIN_HEIGHT   = 200;
2870                                                         this.onInit       = function(){};
2871                                                         this.onOpen       = function( _w, _h ){
2872                                                                 KeyEvent.add( self, Const.KEY.EVENT.KEY_DOWN, ref.shutdown, 27 ); // 27.esc
2873                                                         };
2874                                                         this.onPaneResize = function( _w, _h ){};
2875                                                         this.onClose      = function(){};
2876                                                 };
2877                                         };
2878                                         ref = Application.register( Page.appClass, false, true, document.title, 'page', null, Page.appClass.tailColor || '#999999' );
2879                                         if( Type.isFunction( gOS.PageApplicationClass ) === true ){
2880                                                 gOS.PageApplicationRef = ref;
2881                                         }; 
2882                                 };
2883                                 delete Page.onReady;
2884                         },
2885                         show: function(){
2886                                 for( var i = pageNodes.length; i; ){
2887                                         pageNodes[ --i ].show();
2888                                 };
2889                         },
2890                         hide: function(){
2891                                 for( var i = pageNodes.length; i; ){
2892                                         pageNodes[ --i ].hide();
2893                                 };                              
2894                         },
2895                         boot: function(){
2896                                 ref && ref.boot();
2897                         },
2898                         registered: function(){
2899                                 return !!ref;
2900                         },
2901                         appClass: null
2902                 }
2903         })();
2904
2905 /* --------------------------------------------------------------
2906  * Event
2907  * 
2908  *  screenX
2909  *  スクリーン座標は、コンピュータのディスプレイの左上を原点とする座標系である。screenX, screenY属性で取得できる。Javascritpでは、同名のプロパティとして実装されている。
2910  *  しかし、これは、現実的には、何の役に立たない。ブラウザ自体がディスプレイのどの位置にいるのかがわからないので、画面上の位置を知ったところで、何にもならないからだ。 
2911  * 
2912  *  clientX
2913  *  ウインドウ座標とは、現在のブラウザのウインドウの、ドキュメントを表示している部分の左上原点とした座標である。
2914  *  問題は、ウインドウは、必ずしもドキュメント全体を表示するとは限らない。スクロールと呼ばれるUIによって、ドキュメントの一部だけを表示しているかもしれない。
2915  */
2916         var XBrowserEvent = ( function(){
2917                 var wrappedHandlerClass,
2918                         wrappedEventClass,
2919                         tmp;
2920                 
2921                 if( window.addEventListener ){
2922                         wrappedHandlerClass = function( ticket ){
2923                                 this.handler = function( e ){
2924                                         if( ticket.fire( e ) !== false ) return;
2925                                         e.preventDefault();
2926                                         e.stopPropagation();
2927                                         return false;
2928                                 };
2929                                 this.destroy = function(){
2930                                         ticket = null;
2931                                         delete this.handler;
2932                                         delete this.destroy;
2933                                 };
2934                         };
2935                 } else {
2936                         wrappedEventClass = function( e, element ){
2937                                 this._event        = e;
2938                                 this.type          = e.type;
2939                                 this.target        = e.srcElement;
2940                                 this.currentTarget = element;
2941                                 this.relatedTarget = e.formElement ? e.formElement : e.toElement;
2942                                 this.eventPhase    = e.srcElement === element ? 2: 3;
2943                                 
2944                                 this.clientX       = e.clientX;
2945                                 this.clientY       = e.clientY;
2946                                 this.screenX       = e.screenX;
2947                                 this.screenY       = e.screenY;
2948                                 
2949                                 this.keyCode       = e.keyCode;
2950                                 this.altKey        = e.altKey;
2951                                 this.ctrlKey       = e.ctrlKey;
2952                                 this.shiftKey      = e.shiftKey;
2953                                 
2954                                 this.wheelDelta    = e.wheelDelta;
2955                         };
2956                         wrappedEventClass.prototype.stopPropagation = function(){
2957                                 this._event.cancelBubble = true;
2958                         };
2959                         wrappedEventClass.prototype.preventDefault  = function(){
2960                                 this._event.returnValue = false;
2961                         };
2962
2963                         if( document.attachEvent ){
2964                                 wrappedHandlerClass = function( ticket ){
2965                                         this.handler = function(){
2966                                                 if( ticket === null ) alert( window.event.type )
2967                                                 if( ticket.fire( new wrappedEventClass( window.event, ticket.element ) ) !== false ) return;
2968                                                 // e.preventDefault();
2969                                                 // e.stopPropagation();
2970                                                 window.event.cancelBubble = true;
2971                                                 window.event.returnValue  = false;
2972                                                 return false;
2973                                         };
2974                                         this.destroy = function(){
2975                                                 ticket = null;
2976                                                 delete this.handler;
2977                                                 delete this.destroy;
2978                                         };
2979                                 };
2980                         } else {
2981                                 tmp = {
2982                                         list: [],
2983                                         find: function( _ticket ){
2984                                                 for( var i=0, l= tmp.list.length, _item; i<l; ++i ){
2985                                                         _item = tmp.list[ i ];
2986                                                         if( _item.element === _ticket.element && _item.eventType === _ticket.eventType ){
2987                                                                 return _item;
2988                                                         };
2989                                                 };
2990                                                 return null;
2991                                         }
2992                                 };
2993                                 tmp.TicketClass = function( _ticket ){
2994                                         var self = this;
2995                                         this.element   = _ticket.element;
2996                                         this.eventType = _ticket.eventType;
2997                                         this.tickets   = [ _ticket ];
2998                                         this.onDestroy = function(){ self = null; };
2999                                         
3000                                         this.element[ 'on' + this.eventType ] = function( e ){ return self.fire( e );};
3001                                         _ticket = null;
3002                                 };
3003                                 tmp.TicketClass.prototype = {
3004                                         add: function( _ticket ){
3005                                                 Util.getIndex( this.tickets, ticket ) === -1 && this.tickets.push( _ticket );
3006                                         },
3007                                         remove: function( _ticket ){
3008                                                 var i = Util.getIndex( this.tickets, _ticket );
3009                                                 i !== -1 && this.tickets.splice( i, 1 );
3010                                                 this.tickets.length === 0 && this.destroy();
3011                                         },
3012                                         fire: function( e ){
3013                                                 e = e || new wrappedEventClass( window.event, this.element );
3014                                                 var i = this.tickets.length,
3015                                                         cancel;
3016                                                 for( ; i; ){
3017                                                         if( this.tickets[ --i ].fire( e ) === false ) cancel = false;
3018                                                 };
3019                                                 return cancel;
3020                                         },
3021                                         destroy: function(){
3022                                                 this.onDestroy();
3023                                                 this.element[ 'on' + this.eventType ] = '';
3024                                                 tmp.list.splice( Util.getIndex( tmp.list, this ), 1 );
3025                                                 delete this.element;
3026                                                 delete this.eventType;
3027                                                 delete this.tickets;
3028                                                 delete this.onDestroy;
3029                                         }
3030                                 };
3031                         };
3032                 };
3033
3034                 return {
3035                         add: function( _ticket ){
3036                                 if( document.addEventListener ){
3037                                         XBrowserEvent.add = function( _ticket ){
3038                                                 _ticket.wrappedHandler = new wrappedHandlerClass( _ticket );
3039                                                 _ticket.element.addEventListener( _ticket.eventType, _ticket.wrappedHandler.handler, false );
3040                                         };
3041                                 } else
3042                                 if( document.attachEvent ){
3043                                         XBrowserEvent.add = function( _ticket ){
3044                                                 _ticket.wrappedHandler = new wrappedHandlerClass( _ticket );
3045                                                 _ticket.element.attachEvent( 'on' + _ticket.eventType, _ticket.wrappedHandler.handler );
3046                                         };
3047                                 } else {
3048                                         XBrowserEvent.add = function( _ticket ){
3049                                                 var t = tmp.find( _ticket );
3050                                                 if( t !== null ){
3051                                                         t.add( _ticket );
3052                                                 } else {
3053                                                         tmp.list.push( new tmp.TicketClass( _ticket ) );
3054                                                 };
3055                                         };
3056                                 };
3057                                 
3058                                 XBrowserEvent.add( _ticket );
3059                         },
3060                         remove: function( _ticket ){
3061                                 if( document.removeEventListener ){
3062                                         XBrowserEvent.remove = function( _ticket ){
3063                                                 _ticket.element.removeEventListener( _ticket.eventType, _ticket.wrappedHandler.handler, false );
3064                                                 _ticket.wrappedHandler.destroy();
3065                                         };
3066                                 } else
3067                                 if( document.detachEvent ){
3068                                         XBrowserEvent.remove = function( _ticket ){
3069                                                 _ticket.element.detachEvent( 'on' + _ticket.eventType, _ticket.wrappedHandler.handler );
3070                                                 _ticket.wrappedHandler.destroy();
3071                                         };
3072                                 } else {
3073                                         XBrowserEvent.remove = function( _ticket ){
3074                                                 var t = tmp.find( _ticket );
3075                                                 if( t !== null ){
3076                                                         t.remove( _ticket );
3077                                                 };
3078                                         };
3079                                 };
3080                                 
3081                                 XBrowserEvent.remove( _ticket );
3082                         }
3083                 }
3084         })();
3085
3086 /*
3087  * EventTicketClass
3088  */
3089         var EventTicketClass = function( _element, _eventType, _handler, opt_thisObject ){
3090                 this.element        = _element;
3091                 this.eventType      = _eventType;
3092                 this.handler        = _handler;
3093                 this.wrappedHandler = null;
3094                 this.thisObject     = opt_thisObject;
3095                 XBrowserEvent.add( this );
3096         };
3097         EventTicketClass.prototype = {
3098                 fire : ( function(){
3099                         if( Function.prototype.call ){
3100                                 return function( e ){
3101                                         return this.handler.call( this.thisObject || this.element, e );
3102                                 };                              
3103                         };
3104                         return function( e ){
3105                                 var thisObj = this.thisObject || this.element,
3106                                         ret;
3107                                 thisObj._currentHandler = this.handler;
3108                                 ret = thisObj._currentHandler( e );
3109                                 delete thisObj._currentHandler;
3110                                 return ret;                                     
3111                         };
3112                 })(),
3113                 match: function( _element, _eventType, _handler ){
3114                         if( _handler   && _handler   !== this.handler )   return false;
3115                         if( _eventType && _eventType !== this.eventType ) return false;
3116                         if( _element   && _element   !== this.element )   return false;
3117                         
3118                         return true;
3119                 },
3120                 destroy: function( _element, _eventType, _handler ){
3121                         if( this.match( _element, _eventType, _handler ) === false ) return false;
3122                         
3123                         XBrowserEvent.remove( this );
3124                         
3125                         delete this.element;
3126                         delete this.eventType;
3127                         delete this.handler;
3128                         delete this.wrappedHandler;
3129                         delete this.thisObject;
3130                         return true;
3131                 }
3132         };
3133
3134 var ReadyEvent = ( function(){
3135         var ticketReady,
3136                 ticketLoad,
3137         timer;
3138
3139         function webkitDetect(){
3140                 var state = document.readyState;
3141                 if( state === 'loaded' || state === 'complete' ){
3142                         SystemTimer.remove( SUPER_USER_KEY, webkitDetect );
3143                         timer = null;
3144                         onReady();
3145                 };
3146         };
3147         function ieDetect(){
3148                 if( this.readyState === 'complete' ){ // this.readyState === 'loaded' || 
3149                         this.onreadystatechange = new Function();
3150                         this.onreadystatechange = null;
3151                         AsyncCall.remove( SUPER_USER_KEY, ieScroll );
3152                         onReady();
3153                 };
3154         };
3155         function ieScroll(){
3156                 try {
3157                         document.documentElement.doScroll( 'left' );
3158                 } catch( e ){
3159                         AsyncCall.add( SUPER_USER_KEY, ieScroll );
3160                         return;
3161                 };
3162                 // no errors, fire
3163                 document.onreadystatechange = new Function();
3164                 document.onreadystatechange = null;
3165                 onReady();              
3166         };
3167                 
3168         function onReady(){
3169                 ticketReady && ticketReady.destroy();
3170                 ticketLoad  && ticketLoad.destroy();
3171                 ticketReady = ticketLoad = null;
3172                 Page.onReady();
3173                 if( Page.registered() === true ){
3174                         Page.boot();
3175                 } else {
3176                         Home.boot();
3177                 };
3178         };
3179         
3180         // Apple WebKit (Safari, OmniWeb, ...)
3181         if( document.readyState && !!UA.WEBKIT ){
3182                 SystemTimer.add( SUPER_USER_KEY, webkitDetect, 50 );
3183         /* } else
3184                 if( document.readyState && UA.isIE && UA.ieVersion < 9 ){
3185                 ieScroll();
3186                 document.onreadystatechange = ieDetect; */
3187         } else {
3188                 ticketReady = new EventTicketClass( document, 'DOMContentLoaded', onReady );
3189                 ticketLoad  = new EventTicketClass( window, 'load', onReady );
3190         };
3191 })();
3192
3193
3194
3195
3196 /* =====================================================
3197  *  ResizeEvent
3198  * 
3199  */
3200
3201 var ResizeEvent = ( function(){
3202         var _globalLock = 0;
3203         var _resize;
3204         var root = window;
3205         var w = 0, h = 0;
3206         
3207         function getInnerSize(){
3208                 return {
3209                         w : root.innerWidth || root.clientWidth,
3210                         h : root.innerHeight || root.clientHeight
3211                 };
3212         }
3213         function unlock(){
3214                 _globalLock = 0;
3215         }
3216         
3217         if( document.uniqueID ){
3218                 _resize = function(){
3219                         root = (document.compatMode || "") !== "CSS1Compat" ? document.body : document.documentElement;
3220
3221                         // resize agent
3222                         function loop(){
3223                                 if( !_globalLock++ ){
3224                                         var size = getInnerSize();
3225                                         if( w !== size.w || h !== size.h ){// resized
3226                                                 w = size.w;
3227                                                 h = size.h;
3228                                                 // update
3229                                                 Application.onWindowResize( w, h );
3230                                         }
3231                                         window.setTimeout( unlock, 0 );
3232                                         // delay unlock
3233                                 }
3234                                 window.setTimeout( loop, 100 );
3235                         }
3236                         loop();
3237                 };
3238         } else {
3239                 _resize = function(){
3240                         new EventTicketClass( window, 'resize', onResize );
3241                         
3242                         function onResize(){
3243                                 if( !_globalLock++ ) {
3244                                         var size = getInnerSize();
3245                                         if( w !== size.w || h !== size.h ){// resized
3246                                                 w = size.w;
3247                                                 h = size.h;
3248                                                 // update
3249                                                 Application.onWindowResize( w, h );
3250                                         }
3251                                         window.setTimeout( unlock, 0 );
3252                                 }
3253                         }
3254                         onResize();
3255                 };
3256         }
3257         AsyncCall.add( SUPER_USER_KEY, _resize );
3258         
3259         return {
3260                 getSize: getInnerSize,
3261                 onSystemShutdown: function(){
3262                         
3263                 }
3264         }
3265 })();
3266
3267
3268 /* =====================================================
3269  *  MouseEvent
3270  * 
3271  */
3272         var MouseEvent = ( function(){
3273                 var CLICK_OFFSET   = 2 * 2,
3274                         DRAG_OFFSET    = 4 * 4;         
3275                 
3276                 var EVENT_LIST_MAP = [],
3277                         TMP = {},
3278                         currentEventList;
3279         /*-------------------------------------
3280          * ClickHelper
3281          * mousedown, mouseup, の移動距離を調べて clickハンドラ を呼ぶ
3282          */
3283                 var ClickEventTicketClass = function( element, clickhandler, opt_thisObject ){
3284                         this.mousedownTicket = new EventTicketClass( element, 'mousedown', this.mousedownHandler, this );
3285                         this.element         = element;
3286                         this.handler         = clickhandler;
3287                         this.thisObject      = opt_thisObject;
3288                 };
3289                 ClickEventTicketClass.prototype = {
3290                         element          : null,
3291                         handler          : null,
3292                         thisObject       : null,
3293                         startX           : 0,
3294                         startY           : 0,
3295                         mousedownTicket  : null,
3296                         mousemoveTicket  : null,
3297                         mouseupTicket    : null,
3298                         mouseoutTicket   : null,
3299                         eventType        : 'click',
3300                         fire             : EventTicketClass.prototype.fire,
3301                         match            : EventTicketClass.prototype.match,
3302                         mousedownHandler : function( e ){
3303                                 this.startX = e.clientX;
3304                                 this.startY = e.clientY;
3305                                 
3306                                 this.mousemoveTicket = new EventTicketClass( this.element, 'mousemove', this.mousemoveHandler, this );
3307                                 this.mouseupTicket   = new EventTicketClass( this.element, 'mouseup',   this.mouseupHandler,   this );
3308                                 this.mouseoutTicket  = new EventTicketClass( this.element, 'mouseout',  this.mouseoutHandler,  this );
3309                                 return false;                   
3310                         },
3311                         mousemoveHandler : function( e ){
3312                                 var offsetX = e.clientX - this.startX,
3313                                         offsetY = e.clientY - this.startY;                              
3314                                 offsetX * offsetX + offsetY * offsetY >= CLICK_OFFSET && this.mouseoutHandler();
3315                                 return false;
3316                         },
3317                         mouseupHandler : function( e ){
3318                                 this.mouseoutHandler();
3319                                 return this.fire( ClickEventTicketClass.createEvent( e ) );
3320                         },
3321                         mouseoutHandler : function( e ){
3322                                 this.mousemoveTicket && this.mousemoveTicket.destroy();
3323                                 this.mouseupTicket   && this.mouseupTicket.destroy();
3324                                 this.mouseoutTicket  && this.mouseoutTicket.destroy();
3325                                 if( this.mousemoveTicket ) delete this.mousemoveTicket;
3326                                 if( this.mouseupTicket  )  delete this.mouseupTicket;
3327                                 if( this.mouseoutTicket )  delete this.mouseoutTicket;
3328                                 return false;
3329                         },
3330                         destroy : function( _element, _eventType, _handler ){
3331                                 if( this.match( _element, _eventType, _handler ) === false ) return false;
3332                                 
3333                                 this.mouseoutHandler();
3334                                 this.mousedownTicket.destroy();
3335
3336                                 delete this.element;
3337                                 delete this.handler;
3338                                 delete this.thisObject;
3339                                 delete this.mousedownTicket;    
3340                                 return true;
3341                         }
3342                 };
3343                 if( document.createEvent ){
3344                         ClickEventTicketClass.createEvent = function( e ){
3345                                 var _e = document.createEvent( 'MouseEvents' );
3346                                 _e.initMouseEvent(
3347                                         'click' , false, true, e.view, 
3348                                         e.detail, e.screenX, e.screenY, e.clientX, e.clientY, 
3349                                         e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 
3350                                         e.button, e.relatedTarget
3351                                 );
3352                                 return _e;
3353                         };                                      
3354                 } else
3355                 if( document.attachEvent ){
3356                         ClickEventTicketClass.createEvent = function( e ){
3357                                 e.type = 'click';
3358                                 return e;
3359                         };
3360                 } else {
3361                         
3362                 };
3363                 
3364         /*-------------------------------------
3365          *  WheelHelper
3366          */
3367                 var WheelEventTicketClass = ( function(){
3368                         if( UA.GECKO ){
3369                                 return function( element, wheelhandler, opt_thisObject ){
3370                                         this.wheelTicket = new EventTicketClass( element, 'DOMMouseScroll', this.onGeckoWheel, this );
3371                                         this.element     = element;
3372                                         this.handler     = wheelhandler;
3373                                         this.thisObject  = opt_thisObject;
3374                                 };
3375                         } else
3376                         if( true || UA.isIE ){
3377                                 return function( element, wheelhandler, opt_thisObject ){
3378                                         this.wheelTicket = new EventTicketClass( element, this.eventType, wheelhandler );
3379                                         this.element     = element;
3380                                         this.handler     = wheelhandler;
3381                                         this.thisObject  = opt_thisObject;
3382                                 };
3383                         } else {
3384                                 TMP.wheelHandlerList = [];
3385                                 TMP.wheelThisObjList = [];
3386                                 //TMP.wheelLegacy = undefined;
3387                                 TMP.onWheel   = function( e ){
3388                                         e = e || window.event;
3389                                         var cancel = true,
3390                                                 f = TMP.wheelLegacy, i;
3391                                         if( f ) cancel = f.call( this, e );
3392                                         
3393                                         for( i = TMP.wheelHandlerList.length; i; ){
3394                                                 if( TMP.wheelHandlerList[ --i ].call( TMP.wheelThisObjList[ i ] || this, e ) === false ) cancel = false;
3395                                         };
3396                                         return cancel;
3397                                 };
3398                                 return function( element, wheelhandler, opt_thisObject ){
3399                                         this.element     = element;
3400                                         this.handler     = wheelhandler;
3401                                         this.thisObject  = opt_thisObject;
3402                                         
3403                                         if( TMP.wheelHandlerList.length === 0 ){
3404                                                 //TMP.wheelLegacy     = Type.isFunction( window.onmousewheel ) === true ? window.onmousewheel : undefined;
3405                                                 element.onmousewheel = TMP.onWheel;
3406                                         };
3407                                         TMP.wheelHandlerList.push( wheelhandler );
3408                                         TMP.wheelThisObjList.push( opt_thisObject )
3409                                 };
3410                         };
3411                 })();
3412                 WheelEventTicketClass.prototype = {
3413                         eventType : 'mousewheel',
3414                         match     : EventTicketClass.prototype.match,
3415                         destroy   : function( _element, _eventType, _handler ){
3416                                 if( this.match( _element, _eventType, _handler ) === false ) return false;
3417                                 
3418                                 this.wheelTicket && this.wheelTicket.destroy();
3419                                 
3420                                 delete this.wheelTicket;
3421                                 delete this.element;
3422                                 delete this.handler;
3423                                 delete this.thisObject;
3424                                 
3425                                 this.onDestroy && this.onDestroy();
3426                                 return true;
3427                         }
3428                 };
3429                 if( UA.GECKO ){
3430                         WheelEventTicketClass.prototype.onGeckoWheel = function( e ){
3431                                 var _e = document.createEvent( 'MouseEvents' );
3432                                 _e.initMouseEvent(
3433                                         'mousewheel' , false, true, e.view, 
3434                                         e.detail, e.screenX, e.screenY, e.clientX, e.clientY, 
3435                                         e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 
3436                                         e.button, e.relatedTarget
3437                                 );
3438                                 _e.wheelDelta = e.detail * -40;
3439                                 return this.handler.call( this.thisObject || this.element, _e );
3440                         };
3441                 } else
3442                 if( true || UA.isIE ){
3443
3444                 } else {
3445                         WheelEventTicketClass.prototype.onDestroy = function(){
3446                                 TMP.wheelHandlerList.splice( Util.getIndex( TMP.wheelHandlerList, this.handler ), 1 );
3447                                 TMP.wheelThisObjList.splice( Util.getIndex( TMP.wheelThisObjList, this.handler ), 1 );
3448                                 if( TMP.wheelHandlerList.length === 0 ) this.element.onmousewheel = '';
3449                         };                      
3450                 };
3451                 
3452         /*-------------------------------------
3453          *  DragHelper
3454          */
3455                 var DragEventTicketClass = function( element, draghandler, opt_thisObject ){
3456                         this.mousedownTicket = new EventTicketClass( element, 'mousedown', this.mousedownHandler, this );
3457                         this.element         = element;
3458                         this.handler         = draghandler;
3459                         this.thisObject      = opt_thisObject;
3460                 };
3461                 DragEventTicketClass.prototype = {
3462                         element         : null,
3463                         handler         : null,
3464                         thisObject      : null,
3465                         startX          : 0,
3466                         startY          : 0,
3467                         dragging        : false,
3468                         mousedownTicket : null,
3469                         mousemoveTicket : null,
3470                         mouseupTicket   : null,
3471                         mouseoutTicket  : null,
3472                         eventType       : 'mousedrag',
3473                         fire            : EventTicketClass.prototype.fire,
3474                         match           : EventTicketClass.prototype.match,
3475                         mousedownHandler: function( e ){
3476                                 this.startX = e.clientX;
3477                                 this.startY = e.clientY;
3478                                 
3479                                 this.mousemoveTicket = new EventTicketClass( this.element, 'mousemove', this.dragMoveHandler, this );
3480                                 this.mouseupTicket   = new EventTicketClass( this.element, 'mouseup',   this.dragEndHandler,  this );
3481                                 this.mouseoutTicket  = new EventTicketClass( this.element, 'mouseout',  this.dragEndHandler,  this );                                   
3482                         
3483                                 return false;
3484                         },
3485                         dragMoveHandler : function( e ){
3486                                 var offsetX = e.clientX - this.startX,
3487                                         offsetY = e.clientY - this.startY;
3488                                 if( this.dragging === false ){
3489                                         if( offsetX * offsetX + offsetY * offsetY < DRAG_OFFSET ) return;
3490                                         console.log( 'Drag start' );
3491                                         // dragStart
3492                                         this.dragging = true;
3493                                         return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 0 ) );
3494                                 };
3495                                 return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 1 ) );
3496                         },
3497                         dragEndHandler  : function( e ){
3498                                 if( this.dragging === true ){
3499                                         console.log( 'Drag End ' + e.type );
3500                                         this.removeEvents();
3501                                         // dragEnd
3502                                         return this.fire( DragEventTicketClass.createEvent( e, e.clientX - this.startX, e.clientY - this.startY, 2 ) );
3503                                 };
3504                                 this.removeEvents();
3505                                 return false;
3506                         },
3507                         removeEvents : function(){
3508                                 this.dragging = false;
3509                                 if( this.mousemoveTicket ){
3510                                         this.mousemoveTicket.destroy();
3511                                         delete this.mousemoveTicket;
3512                                 };
3513                                 if( this.mouseupTicket ){
3514                                         this.mouseupTicket.destroy();
3515                                         delete this.mouseupTicket;
3516                                 };
3517                                 if( this.mouseoutTicke ){
3518                                         this.mouseoutTicket.destroy();
3519                                         delete this.mouseoutTicket;
3520                                 };                              
3521                         },
3522                         destroy : function( _element, _eventType, _handler ){
3523                                 if( this.match( _element, _eventType, _handler ) === false ) return false;
3524                                 
3525                                 this.removeEvents();
3526                                 this.mousedownTicket.destroy();
3527
3528                                 delete this.element;
3529                                 delete this.handler;
3530                                 delete this.thisObject;
3531                                 delete this.mousedownTicket;    
3532                                 return true;
3533                         }
3534                 };
3535                 if( document.createEvent ){
3536                         DragEventTicketClass.createEvent = function( e, offsetX, offsetY, dragPhase ){
3537                                 var _e = document.createEvent( 'MouseEvents' );
3538                                 _e.initMouseEvent(
3539                                         DragEventTicketClass.prototype.eventType , false, true, e.view, 
3540                                         e.detail, e.screenX, e.screenY, e.clientX, e.clientY, 
3541                                         e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 
3542                                         e.button, e.relatedTarget
3543                                 );
3544                                 _e.dragPhase   = dragPhase;
3545                                 _e.dragOffsetX = offsetX;
3546                                 _e.dragOffsetY = offsetY;
3547                                 return _e;
3548                         };                                      
3549                 } else
3550                 if( document.attachEvent ){
3551                         DragEventTicketClass.createEvent = function( e, offsetX, offsetY, dragPhase ){
3552                                 e.type        = DragEventTicketClass.prototype.eventType;
3553                                 e.dragPhase   = dragPhase;
3554                                 e.dragOffsetX = offsetX;
3555                                 e.dragOffsetY = offsetY;
3556                                 return e;
3557                         };
3558                 } else {
3559                         
3560                 };
3561
3562                 return {
3563                         add: function( _apiuser, _element, _eventType, _handler, opt_thisObject ){
3564                                 if( isApiUser( _apiuser ) === true &&
3565                                         ( Type.isHTMLElement( _element ) === true || _element === window || _element === document ) &&
3566                                         Type.isString( _eventType ) === true &&
3567                                         Type.isFunction( _handler ) === true
3568                                 ){
3569                                         var _uid    = _apiuser.getUID(),
3570                                                 _events = EVENT_LIST_MAP[ _uid ];
3571                                         if( Type.isArray( _events ) === false ){
3572                                                 _events = EVENT_LIST_MAP[ _uid ] = [];
3573                                         } else {
3574                                                 // 2重登録の禁止
3575                                                 for( var i=0, l=_events.length; i<l; ++i ){
3576                                                         if( _events[ i ].match( _element, _eventType, _handler ) === true ) return;
3577                                                 };
3578                                         };
3579                                         switch( _eventType ){
3580                                                 case 'click':
3581                                                         _events.push( new ClickEventTicketClass( _element, _handler, opt_thisObject ) );
3582                                                         break;
3583                                                 case 'mousewheel':
3584                                                         _events.push( new WheelEventTicketClass( _element, _handler, opt_thisObject ) );
3585                                                         break;
3586                                                 case 'mousedrag':
3587                                                         _events.push( new DragEventTicketClass( _element, _handler, opt_thisObject ) );
3588                                                         break;
3589                                                 default:
3590                                                         _events.push( new EventTicketClass( _element, _eventType, _handler, opt_thisObject ) );
3591                                         };
3592                                 };
3593                         },
3594                         remove: function( apiuser, element, eventType, handler ){
3595                                 if( isApiUser( apiuser ) === true ){
3596                                         var uid  = apiuser.getUID(),
3597                                                 list = EVENT_LIST_MAP[ uid ],
3598                                                 i    = 0;
3599                                         if( Type.isArray( list ) === false ) return;
3600                                         for( ;i < list.length; ){
3601                                                 if( list[ i ].destroy( element, eventType, handler ) === true ){
3602                                                         list.splice( i, 1 );
3603                                                 } else {
3604                                                         ++i;
3605                                                 };
3606                                         };
3607                                         if( list.length === 0 ){
3608                                                 EVENT_LIST_MAP[ uid ] = null;
3609                                         };
3610                                 };
3611                         },
3612                         onCurrentApplicationChange: function(){
3613                                 
3614                         },
3615                         onApplicationShutdown: function(){
3616                                 
3617                         },
3618                         onSystemShutdown: function(){
3619                                 
3620                         }
3621                 }
3622         })();
3623
3624 /* ----------------------------------------
3625  * KEY
3626  * 
3627  *  - EDITABLE_TEXT_CONTROL
3628  * 
3629  *    .SHIFT_DOWN_EVENT:        'shiftDown',
3630  *    .SHIFT_UP_EVENT:          'shiftUp',
3631  *    .CTRL_DOWN_EVENT:         'ctrlDown',
3632  *    .CTRL_UP_EVENT:           'ctrlUp',
3633  *    .SPACE_DOWN_EVENT:        'spaceDown',
3634  *    .SPACE_UP_EVENT:          'spaceUp',
3635  *    .init:                            function,
3636  *    .addKeyDownEvent:         function,
3637  *    .keyEventDispatcher:      function,
3638  * 
3639  * ショートカットキーの監視とテキスト入力(input, textarea)、チェックボックスを管理する。
3640  * キー入力はdocumentで受けて、テキスト編集中(input, textarea)はそちらにキーイベント流す。
3641  * 
3642  */
3643 var KeyEvent = ( function(){
3644         var EVENT_LIST_MAP = [],
3645                 LOCK_UP        = [],
3646                 LOCK_DOWN      = [],
3647                 application    = null,
3648                 currentList    = null;
3649
3650         window.focus();
3651         
3652         var focusTicket    = null,
3653                 keydownTicket  = null,
3654                 keyupTicket    = null,
3655                 keyPress       = null,
3656                 keypressTicket = null;
3657         
3658         function unlock( lock, key ){
3659                 lock.splice( Util.getIndex( lock, key ), 1 );
3660         };
3661         
3662         function onKeyChange( e ){
3663                 var cancel         = false,
3664                         type           = e.type,
3665                         key            = e.keyCode, // || e.which,
3666                         shift          = Type.isBoolean( e.shiftKey ) === true ? e.shiftKey : ( e.modifiers & Event.SHIFT_MASK ),
3667                         ctrl           = Type.isBoolean( e.ctrlKey  ) === true ? e.ctrlKey  : ( e.modifiers & Event.CONTROL_MASK ),
3668                         lock           = type === 'keyup' ? LOCK_UP : LOCK_DOWN,
3669                         i, t;
3670                         
3671                 // block chattering
3672                 if( Util.getIndex( lock, key ) !== -1 ) return;
3673                 lock.push( key );
3674                 AsyncCall.add( SUPER_USER_KEY, unlock, [ lock, key ] );
3675                 
3676                 if( key === 16 || shift === true ){
3677                         KeyEvent.shiftEnabled = type !== 'keyup';
3678                 };
3679                 if( key === 17 || ctrl === true ){
3680                         KeyEvent.ctrlEnabled  = type !== 'keyup';
3681                 };
3682                 for( i = currentList.length; i; ){
3683                         t = currentList[ --i ];
3684                         if( Type.isFunction( t[ type ] ) === true && t.keyCode === key && ( t.shift === undefined || t.shift === shift ) && ( t.ctrl === undefined || t.ctrl === ctrl )){
3685                                 if( t[ type ].call( t.apiuser, e ) === false ){
3686                                         cancel = true;
3687                                         break;
3688                                 };
3689                         };
3690                 };
3691                 if( cancel === true || key === 18 || key === 9 || key === 27 || e.altKey === true ){ // 13.enter 18.esc 9.tab 27.esc   || ( key === 13 && overlayEnabled === false)
3692                         return false;
3693                 };
3694         };
3695         
3696         if( UA.isIE === true && UA.ieRenderingVersion < 9 ){
3697                 keyPress = function( e ){
3698                         var key = e.keyCode;
3699                         if( key === 13 || key === 27 ){
3700                                 e.type = 'keydown';
3701                                 return onKeyChange( e );
3702                         };
3703                 };
3704         };
3705         
3706         var KeyEventTicketClass = function( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ){
3707                 this.apiuser = _apiuser;
3708                 this.type    = _type;
3709                 this.keydown = _onKeydown;
3710                 this.keyup   = _onKeyup;                
3711                 this.keyCode = _keyCode;
3712                 this.shift   = _shift;
3713                 this.ctrl    = _ctrl;
3714                 _apiuser = _onKeydown = _onKeyup = null;
3715         }
3716         KeyEventTicketClass.prototype = {
3717                 match: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3718                         if( _apiuser  && _apiuser  !== this.apiuser ) return false;
3719                         if( _type     && _type     !== this.type )    return false;
3720                         if( _handler ){
3721                                 if( this.type === 'keydown' ){
3722                                         if( _handler !== this.keydown ) return false;
3723                                 } else {
3724                                         if( _handler !== this.keyup )   return false;
3725                                 };
3726                         };
3727                         if( _keyCode  && _keyCode  !== this.keyCode ) return false;
3728                         if( _shift    && _shift    !== this.shift )   return false;
3729                         if( _ctrl     && _ctrl     !== this.ctrl )    return false;
3730                         return true;
3731                 },
3732                 destroy: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3733                         if( this.match( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ) === false ) return false;
3734                         
3735                         delete this.apiuser;
3736                         delete this.keydown;
3737                         delete this.keyup;
3738                         
3739                         return true;
3740                 }
3741         };
3742         
3743         function registerEvent( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ){
3744                 var _uid  = _apiuser.getUID(),
3745                         _list = EVENT_LIST_MAP[ _uid ];
3746                 if( Type.isArray( _list ) === false ){
3747                         _list = EVENT_LIST_MAP[ _uid ] = [];
3748                 }
3749                 for( var i=0, l=_list.length; i<l; ++i ){
3750                         if( _list[ i ].match( _apiuser, _type, _onKeydown || _onKeyup, _keyCode, _shift, _ctrl ) === true ) return;
3751                 }
3752                 _list.push( new KeyEventTicketClass( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ));
3753                 
3754                 if( _apiuser === application ) KeyEvent.updateCurrentListener( _apiuser );
3755         };
3756         
3757         return {
3758                 add: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3759                         if( _type === 'keydown' ){
3760                                 registerEvent( _apiuser, _type, _handler, null, _keyCode, _shift, _ctrl );
3761                         } else
3762                         if( _type === 'keyup' ){
3763                                 registerEvent( _apiuser, _type, null, _handler, _keyCode, _shift, _ctrl );
3764                         } else
3765                         if( _type === 'keychange' ){
3766                                 registerEvent( _apiuser, _type, _handler, _handler, _keyCode, _shift, _ctrl );
3767                         } else
3768                         if( _type === 'cursol' ){
3769                                 
3770                         };
3771                 },
3772                 remove: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3773                         var _list = EVENT_LIST_MAP[ _apiuser.getUID() ],
3774                                 i = 0;
3775                         if( Type.isArray( _list ) === true ){
3776                                 while( i < _list.length ){
3777                                         if( _list[ i ].destroy( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ) === true ){
3778                                                 _list.splice( i, 1 );
3779                                         } else {
3780                                                 ++i;
3781                                         }
3782                                 }
3783                         }
3784                         if( _apiuser === application ) KeyEvent.updateCurrentListener( _apiuser );
3785                 },
3786                 shiftEnabled: false,
3787                 ctrlEnabled:  false,
3788                 /*
3789                  * currentListener
3790                  *  currrentApplication ( overlay Application ) or
3791                  *  superuser ( UI )
3792                  */
3793                 updateCurrentListener: function( _apiuser ){
3794                         application = _apiuser;
3795                         var _uid    = _apiuser.getUID();
3796                         currentList = EVENT_LIST_MAP[ _uid ] || ( EVENT_LIST_MAP[ _uid ] = [] );
3797                         
3798                         var _ticket,
3799                                 _down = false,
3800                                 _up   = false;
3801                         for( var i=currentList.length; _ticket = currentList[ --i ]; ){
3802                                 if( _down === false ) _down = !!_ticket.keydown;
3803                                 if( _up   === false ) _up   = !!_ticket.keyup;
3804                                 if( _down && _up ) break;
3805                         }
3806                         if( _down === true ){
3807                                 keydownTicket = new EventTicketClass( document, 'keydown', onKeyChange );
3808                                 keypressTicket = keyPress !== null ? new EventTicketClass( document, 'keypress', keyPress ) : null;
3809                         } else {
3810                                 keydownTicket && keydownTicket.destroy();
3811                                 keypressTicket && keypressTicket.destroy();
3812                                 keydownTicket = keypressTicket = null;
3813                         }
3814                         if( _up === true ){
3815                                 keyupTicket   = new EventTicketClass( document, 'keyup', onKeyChange );
3816                         } else {
3817                                 keyupTicket && keyupTicket.destroy();
3818                                 keyupTicket = null;
3819                         }
3820                         
3821                         if( _down === true || _up === true ){
3822                                 focusTicket   = new EventTicketClass( document, 'mouseenter', window.focus );
3823                         } else {
3824                                 focusTicket && focusTicket.destroy();
3825                                 focusTicket = null;
3826                         }
3827                 },
3828                 onApplicationShutdown: function( _apiuser ){
3829                         KeyEvent.remove( _apiuser );
3830                 },
3831                 onSystemShutdown: function(){
3832                         
3833                 }
3834         }
3835 })();
3836
3837 /**
3838  * 
3839  * http://thudjs.tumblr.com/post/637855087/stylesheet-onload-or-lack-thereof
3840  */
3841
3842 var StyleSheet = ( function(){
3843         var head = document.getElementsByTagName( 'head' )[ 0 ];
3844         
3845         var TICKET_LIST = [];
3846         var STATE_LIST  = 'loaded,complete,uninitialized'.split( ',' );
3847         
3848         var cssRules, sheet;
3849         
3850         var FetchCssTicketClass = function( _apiuser, _url, _elm, _onload, _onerror, opt_thisObject ){
3851                 this.apiusers = [ _apiuser ];
3852                 this.url      = _url;
3853                 this.elm      = _elm;
3854                 this.onload   = [ _onload ];
3855                 this.onerror  = [ _onerror ];
3856                 this.thisObj  = [ opt_thisObject ];
3857                 this.time     = 0;
3858         };
3859         FetchCssTicketClass.prototype = {
3860                 match: function( _apiuser, _url ){
3861                         if( _apiuser  && Util.getIndex( this.apiusers, _apiuser ) === -1 ) return false;
3862                         if( _url      && _url      !== this.url     ) return false;
3863                         return true;
3864                 },
3865                 destroy: function( _apiuser, _url ){
3866                         if( this.match( _apiuser, _url ) === false ) return false;
3867                         
3868                         var i = Util.getIndex( this.apiusers, _apiuser );
3869                         
3870                         this.apiusers.splice( i, 1 );
3871                         this.onload.splice( i, 1 );
3872                         this.onerror.splice( i, 1 );
3873                         this.thisObj.splice( i, 1 );
3874                         
3875                         if( this.apiusers.length !== 0 ) return false;
3876                         
3877                         head.removeChild( this.elm );
3878                         this.elm.onreadystatechange = new Function();
3879                         this.elm.onload = null;
3880                         
3881                         delete this.apiusers;
3882                         delete this.url;
3883                         delete this.elm;
3884                         delete this.onload;
3885                         delete this.onerror;
3886                         delete this.thisObj;
3887                         delete this.time;
3888                         
3889                         return true;
3890                 },
3891                 loaded: function(){
3892                 for( var i = this.onload.length, f; i; ){
3893                         f = this.onload[ --i ];
3894                         Type.isFunction( f ) === true && AsyncCall.add( this.apiusers[ i ], f, this.url, this.thisObj[ i ] || this.apiusers[ i ] );
3895                         this.onload[ i ] = this.onerror[ i ] = null;
3896                 };
3897                 },
3898                 error: function(){
3899                 for( var i = this.onerror.length, f; i; ){
3900                         f = this.onerror[ --i ];
3901                         Type.isFunction( f ) === true && AsyncCall.add( this.apiusers[ i ], f, this.url, this.thisObj[ i ] || this.apiusers[ i ] );
3902                         this.onload[ i ] = this.onerror[ i ] = null;
3903                 };
3904                 },
3905                 check: function(){
3906                         var el = this.elm;
3907                         try {
3908                                 return el[ sheet ] && el[ sheet ][ cssRules ].length > 0;
3909                         } catch( e ){
3910                                 return false;
3911                         };
3912                 },
3913                 done: false
3914         };
3915         
3916         function getTicket( elm ){
3917                 for( var i = TICKET_LIST.length, t; i; ){
3918                         t = TICKET_LIST[ --i ];
3919                         if( t.elm === elm ) return t;
3920                 };
3921         };
3922         
3923         function detect(){
3924                 var t = getTicket( this ), rs = this.readyState, c;
3925                 if( t && t.done === false && ( !rs || Util.getIndex( STATE_LIST, rs ) !== -1 ) ){
3926                         t.done = true;
3927                 t.loaded();
3928                 this.onreadystatechange = new Function();
3929                 this.onload = null;
3930                 };
3931         };
3932         
3933         function checkTimer(){
3934                 var l = TICKET_LIST.length,
3935                         n = 0, t;
3936                 for( var i = 0; i < l; ++i ){
3937                         t = TICKET_LIST[ i ];
3938                         ++t.time;
3939                         if( t.check() === true ){
3940                                 t.loaded();
3941                                 ++n;
3942                         } else
3943                         if( t.time > 99 ){
3944                                 t.error();
3945                         } else {
3946                                 
3947                         };
3948                 };
3949                 l === n && SystemTimer.remove( SUPER_USER_KEY, checkTimer );
3950         };
3951         
3952         return {
3953                 load: function( _apiuser, _url, opt_onload, opt_onerror, opt_thisObject ){
3954                         _url = Util.getAbsolutePath( _url );
3955                         var t;
3956                         for( var i=TICKET_LIST.length; i; ){
3957                                 t = TICKET_LIST[ --i ];
3958                                 if( t.match( null, _url ) === true ){
3959                                         if( t.match( _apiuser, _url ) === false ){
3960                                                 t.apiusers.push( _apiuser );
3961                                                 t.onload.push( opt_onload );
3962                                                 t.onerror.push( opt_onerror );
3963                                                 t.thisObj.push( opt_thisObject );
3964                                         };
3965                                         SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 );
3966                                         return;
3967                                 };
3968                         };
3969                         var elm = document.createElement( 'link' );
3970                         head.appendChild( elm );
3971                         elm.rel  = 'stylesheet';
3972                         elm.type = 'text\/css';
3973                         elm.onreadystatechange = elm.onload = detect;
3974                         elm.href = _url;
3975                         
3976                         if( !sheet ){ // only assign these once
3977                                 cssRules = 'cssRules';
3978                                 sheet    = 'sheet';
3979                                 if ( !( sheet in elm ) ) { // MSIE uses non-standard property names
3980                                         cssRules = 'rules';
3981                                         sheet    = 'styleSheet';
3982                                 };
3983                         };
3984                         
3985                         TICKET_LIST.push( new FetchCssTicketClass( _apiuser, _url, elm, opt_onload, opt_onerror, opt_thisObject ) );
3986                         
3987                         SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 );
3988                 },
3989                 unload: function( _apiuser, _url ){
3990                         _url = _url ? Util.getAbsolutePath( _url ) : null;
3991             var t;
3992                         for( var i = 0; i < TICKET_LIST.length; ){
3993                                 t = TICKET_LIST[ i ];
3994                                 if( t.destroy( _apiuser, _url ) === true ){
3995                                         TICKET_LIST.splice( i, 1 );
3996                                 } else {
3997                                         ++i;
3998                                 }
3999                         };
4000                         if( TICKET_LIST.length === 0 ){
4001                                 SystemTimer.remove( SUPER_USER_KEY, checkTimer );
4002                         }
4003                 }
4004         }
4005 })();
4006
4007 /*
4008  * AssetLoader
4009  * fetchCSS
4010  * fetchJson
4011  * fetchHtml
4012  * fetchImage
4013  * fetchLocalFile
4014  * fetchLocalStorage
4015  */
4016
4017 var Image = ( function(){
4018         var TASK_LIST = [];
4019         /* 
4020          * FetchClass original is
4021          * 
4022          * LICENSE: MIT?
4023          *  URL: http://d.hatena.ne.jp/uupaa/20080413/1208067631
4024          *  AUTHOR: uupaa.js@gmail.com
4025          * 
4026          */
4027         function detect(){
4028                 for( var i=0, t; i < TASK_LIST.length; ){
4029                         t = TASK_LIST[ i ];
4030                         if( t.complete() === true ){
4031                                 TASK_LIST.splice( i, 1 );
4032                         } else {
4033                                 ++i;
4034                         };
4035                 };
4036                 TASK_LIST.length === 0 && SystemTimer.remove( SUPER_USER_KEY, detect );
4037         };
4038         function getTask( img ){
4039                 for( var i = TASK_LIST.length; i; ){
4040                         if( TASK_LIST[ --i ].img === img ) return TASK_LIST[ i ];
4041                 };
4042         };
4043         function onError(){
4044                 var task = getTask( this );
4045                 if( task.finish === true ) return;
4046                 task.finish = true;
4047                 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
4048         };
4049         function onLoad(){
4050                 // if( finish === true ) return; // これがあると firefox3.6 で駄目、、、
4051                 // if( timer ) return; // これがあると safari3.2 で駄目、、、
4052                 var task = getTask( this );
4053                 task.finish = true;
4054                 TASK_LIST.splice( Util.getIndex( TASK_LIST, task ), 1 );
4055                 if( window.opera && !task.img.complete ){
4056                         AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
4057                         return;
4058                 };
4059                 task.size = Util.getImageSize( this );
4060                 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
4061         };
4062
4063
4064         var FetchClass = function( apiuser, abspath, onLoadCallback, onErrorCallback, timeout ){
4065                 this.apiuser         = apiuser;
4066                 this.abspath         = abspath;
4067                 this.onLoadCallback  = onLoadCallback;
4068                 this.onErrorCallback = onErrorCallback;
4069                 this.timeout         = timeout;
4070                 this.tick            = 0;
4071         };
4072         FetchClass.prototype = {
4073                 img: null,
4074                 size: null,
4075                 tick: 0,
4076                 finish: false,
4077                 load: function(){
4078                         var img     = this.img = document.createElement( 'img' ); //var img = new Image(); ではieでimgのsizeが取れない、、、removeChildも失敗し、imgSizeGetterにimgが残る
4079                         img.onabort = img.onerror = onError;
4080                         img.onload  = onLoad;
4081                         img.src     = this.abspath;
4082                 },
4083                 complete: function(){
4084                         if( this.finish === true ) return true;
4085                         if( this.img.complete ){
4086                                 this.finish = true;
4087                                 if( this.img.width ) return true;
4088                                 AsyncCall.add( this.apiuser, this.asyncCallback, null, this );
4089                                 return true;
4090                         };
4091                         if( ( this.tick += 250 ) > this.timeout ){
4092                                 this.finish = true;
4093                                 AsyncCall.add( this.apiuser, this.asyncCallback, null, this );
4094                                 return true;
4095                         };
4096                 },
4097                 asyncCallback: function(){
4098                         this.size ? this.onLoadCallback( this.abspath, this.size.width, this.size.height ) : this.onErrorCallback( this.abspath );
4099                         this.destroy();
4100                 },
4101                 destroy: function(){
4102                         this.finish  = true;
4103                         this.img.src = this.img.onload = this.img.onabort = this.img.onerror = '';
4104                         delete this.img;
4105                         delete this.size;
4106                         delete this.onLoadCallback;
4107                         delete this.onErrorCallback;
4108                 },
4109                 stop: function(){
4110                         timer !== null && window.clearTimeout( timer );
4111                         destroy();
4112                 }
4113         };
4114         
4115         return {
4116                 load: function( URLorELM, onLoad, onError, opt_timeout ){
4117                         var src, fetch;
4118                         if( Type.isString( URLorELM ) === true ){
4119                                 src = URLorELM;
4120                         } else
4121                         if( Type.isHTMLElement( URLorELM ) === true && URLorELM.tagName.toLowerCase() === 'img' ){
4122                                 src = URLorELM.src;
4123                         } else {
4124                                 return;
4125                         };
4126                         
4127                         fetch = new FetchClass(
4128                                 Util.getAbsolutePath( src ),
4129                                 onLoad, onError,
4130                                 Type.isFinite( opt_timeout ) === true ? opt_timeout : undefined
4131                         );
4132                         TASK_LIST.push( fetch );
4133                         
4134                         SystemTimer.add( SUPER_USER_KEY, detect, 250 );
4135                 },
4136                 unload: function(  ){
4137                         
4138                 }
4139         };
4140 })();
4141
4142
4143 /* ----------------------------------------
4144  * 
4145  */
4146
4147 var Overlay = ( function(){
4148         var elmContainer, elmShadow, elmCloseButton,
4149                 bootParams,
4150                 application    = null,
4151                 visible        = false,
4152                 bodyOverflow   = '',
4153                 windowW, windowH;
4154
4155         function onCloseClick( e ){
4156                 Overlay.hide();
4157                 return false;
4158         };
4159         function asyncInit( /* arguments */ ){
4160                 application.init();
4161                 //application.rootElement.style.display = 'none';
4162                 
4163                 elmContainer.style.cssText = "top:" + body.scrollTop + 'px;display:none;';
4164                 $( elmContainer ).stop().fadeIn( onFadeInComplete );            
4165         };
4166         function asyncOpen( /* arguments */ ){
4167
4168                 
4169                 
4170         };
4171         function onFadeInComplete(){
4172                 KeyEvent.add( application, Const.KEY.EVENT.KEY_DOWN, Overlay.hide, 27 ); // 27.esc
4173                 MouseEvent.add( application, elmCloseButton, 'click', onCloseClick );
4174                 
4175                 var _arg = bootParams; //Util.copyArray( arguments );
4176                 _arg.unshift( windowW, windowH );
4177                 application.open.apply( application, _arg );            
4178         };
4179         function onFadeOutComplete(){   
4180                 Util.removeAllChildren( elmContainer );
4181                 body.removeChild( elmContainer );
4182                 elmContainer = elmShadow = elmCloseButton = null;
4183         };
4184         return {
4185                 show: function( _application, _bootParams ){
4186                         if( visible === true && application === _application ) return;
4187                         if( Application.isApplicationInstance( _application ) === false ) return;
4188                         
4189                         elmContainer = document.createElement( 'div' );
4190                         body.appendChild( elmContainer );
4191                         
4192                         elmContainer.id = 'overlay-container';
4193                         
4194                         bodyOverflow        = body.style.overflow;
4195                         body.style.overflow = 'hidden';
4196                         
4197                         elmShadow = document.createElement( 'div' );
4198                         elmContainer.appendChild( elmShadow );
4199                         elmShadow.id = 'overlay-shadow';
4200                         
4201                         elmCloseButton  = document.createElement( 'div' );
4202                         elmContainer.appendChild( elmCloseButton );
4203                         elmCloseButton.id = 'overlay-close-button';
4204                         elmCloseButton.appendChild( document.createTextNode( 'x' ) );
4205                         
4206                         elmContainer.style.display = 'none'; // hide for fadeIn
4207                         
4208                         visible     = true;
4209                         application = _application;
4210                         
4211                         //asyncInit();
4212                         elmContainer.insertBefore( application.rootElement, elmCloseButton );
4213                         _application.addAsyncCall( asyncInit );
4214                         // _application.addAsyncCall( asyncOpen,  );
4215                         
4216                         bootParams = _bootParams;                       
4217                 },
4218                 hide: function(){
4219                         if( visible === false ) return;
4220                         if( application.close() === false ) return false;
4221                         
4222                         body.style.overflow = bodyOverflow;
4223                         
4224                         $( elmContainer ).stop().css( {
4225                                 filter:         '',
4226                                 opacity:        ''
4227                         }).fadeOut( onFadeOutComplete );
4228                         visible = false;
4229                         
4230                         application = null;
4231                 },
4232                 onWindowResize: function( _windowW, _windowH ){
4233                         windowW = _windowW;
4234                         windowH = _windowH;                     
4235                         
4236                         if( application === null ) return;
4237                         
4238                         elmContainer.style.height = _windowH + 'px';
4239                         elmContainer.style.top    = body.scrollTop + 'px';
4240
4241                         elmShadow.style.height = _windowH + 'px';
4242
4243                         AsyncCall.add( application, application.resize, [ _windowW, _windowH ] );
4244                 }
4245         }
4246 })();
4247
4248 /* ----------------------------------------
4249  * UI
4250  * 
4251  * keyEventRellay
4252  *  form -> overlay -> view
4253  * 
4254  */
4255
4256 var UI = ( function(){
4257         var UI_LIST     = [],
4258                 currentUser = null,
4259                 currentList = null,
4260                 currentUi   = null,
4261                 currentItem = null,
4262                 windowW     = 0,
4263                 windowH     = 0;
4264
4265         var CLASSNAME_COMBOBOX_OPTION = 'combobox-option',
4266                 CLASSNAME_COMBOBOX_OPTION_CURRENT = CLASSNAME_COMBOBOX_OPTION + ' combobox-option-current',
4267                 ELM_COMBOBOX = ( function(){
4268                         var ret       = document.createElement( 'a' ),
4269                                 elmToggle = document.createElement( 'span' ),
4270                                 elmValue  = document.createElement( 'span' );
4271                         ret.href = '#';
4272                         ret.appendChild( elmToggle );
4273                         ret.appendChild( elmValue );
4274                         elmToggle.className = 'combobox-toggle';
4275                         elmValue.className  = 'combobox-value';
4276                         
4277                         elmToggle.appendChild( document.createTextNode( '▼' ));
4278                         elmValue.appendChild( document.createTextNode( 'null' ));
4279                         return ret;
4280                 })();
4281         
4282         var UIItemPrivateData = function(){};
4283         UIItemPrivateData.prototype = {
4284                 groupData   : null,
4285                 item        : null,
4286                 elm         : null,
4287                 node        : null,
4288                 focus       : false,
4289                 visible     : true,
4290                 enabled     : true,
4291                 value       : null,
4292                 onUpdate    : null,
4293                 validator   : null,
4294                 elmValue    : null,
4295                 elmBox      : null,
4296                 elmA        : null,
4297                 elmToggle   : null,
4298                 elmValue    : null,
4299                 selectIndex : 0,
4300                 optionList  : null,
4301                 init    : function( groupData, item, elm, value, onUpdate, validator, focus, visible, enabled ){
4302                         this.groupData = groupData;
4303                         this.item      = item;
4304                         this.elm       = elm;
4305                         this.value     = value;
4306                         this.onUpdate  = onUpdate;
4307                         this.validator = validator;                     
4308                         this.focus     = !!focus;
4309                         this.visible   = !!visible;
4310                         this.enabled   = !!enabled;
4311                         UIItemPrivateData.list.push( this );
4312                 },
4313                 destroy : function(){
4314                         var list = UIItemPrivateData.list;
4315                         list.splice( Util.getIndex( list, this ), 1 );
4316                         
4317                         list = this.groupData.itemList;
4318                         var i = Util.getIndex( list, this.item );
4319                         i !== -1 && list.splice( i, 1 );
4320                         
4321                         this.node && this.node.remove();
4322                 }
4323         };
4324         UIItemPrivateData.list = [];
4325         UIItemPrivateData.get = function( item ){
4326                 var list = UIItemPrivateData.list;
4327                 for( i = list.length; i; ){
4328                         if( list[ --i ].item === item ) return list[ i ];
4329                 };
4330                 return null;
4331         };
4332         
4333 /* --------------------------------
4334  * TextInputManager
4335  */
4336         var TextInputManager = ( function(){
4337                 var elmInput = ( function(){
4338                         var ret  = document.createElement( 'input' );
4339                         ret.type = 'text';
4340                         ret.id   = 'ui-textinput';
4341                         return ret;
4342                 })();
4343                 var currentData;
4344                 
4345                 function updateWrapperPosition(){
4346                         var p = Position.cumulativeOffset( currentData.elmValue ),
4347                                 w = currentData.elmValue.offsetWidth - 2,
4348                                 _w;             
4349                         elmInput.style.cssText = [
4350                                 'left:',   p[ 0 ], 'px;',
4351                                 'top:',    p[ 1 ], 'px;',//,
4352                                 'width:',  w, 'px;'//,
4353                                 //'height:', data.elmValue.offsetHeight, 'px;',
4354                                 //'position:absolute;'
4355                         ].join( '' );
4356                         
4357                         //_w = elmInput.offsetWidth;
4358                         //if( w !== _w ) elmInput.style.width = ( w - ( _w - w ) ) + 'px;';     
4359                 };
4360                 
4361                 return {
4362                         show: function( data ){
4363                                 // this.groupData.node.addEventListener( 'mouseout' );
4364                                 currentData = data;
4365
4366                                 body.appendChild( elmInput );
4367                                 elmInput.value = data.value;
4368                                 updateWrapperPosition();
4369                                 
4370                                 elmInput.focus();
4371                                 elmInput.select();
4372                                 
4373                                 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4374                         },
4375                         hide : function( data ){
4376                                 if( currentData !== data ) return;
4377                                 currentData = null;
4378                                 body.removeChild( elmInput );
4379                                 var ret = elmInput.value;
4380                                 elmInput.value = '';
4381                                 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition );
4382                                 return ret;
4383                         },
4384                         update : function( data ){
4385                                 elmInput.value = data.value;
4386                         },
4387                         onWindowResize: function( _w, _h ){
4388                                 AsyncCall.add( currentUser, updateWrapperPosition );
4389                         }
4390                 };
4391         })();
4392         
4393         var TextInputClass = function( groupData, elmWrapper, elmValue, onUpdate, validater ){
4394                 var data = new UIItemPrivateData();
4395                 data.init( groupData, this, elmWrapper, elmValue.innerHTML, onUpdate, validater, false, true, true );
4396                 Util.addClass( elmValue, 'editable-text' );
4397                 data.elmValue = elmValue;
4398                 this.value( data.value );
4399                 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-inpittext-hover', 'pointer' );
4400                 data.node.addEventListener( 'click', this.focus, this );
4401                 //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', instance.focus );
4402         };
4403         TextInputClass.prototype = {
4404                 value : function( value ){
4405                         var data = UIItemPrivateData.get( this );
4406                         if( Type.isString( value ) === true || Type.isNumber( value ) === true ){
4407                                 data.elmValue.innerHTML = data.value = '' + value;
4408                                 data.focus === true && TextInputManager.update( data );
4409                         };
4410                         data.focus === true && this.blur();
4411                         return data.value;
4412                 },
4413                 focus : function( e ){
4414                         var data = UIItemPrivateData.get( this );
4415                         data.focus = true;
4416                         start( data );
4417                         TextInputManager.show( data );
4418                         return false;
4419                 },
4420                 blur : function( keep ){
4421                         var data = UIItemPrivateData.get( this ),
4422                                 newValue;
4423                         if( data.focus === false ) return;
4424                         newValue = TextInputManager.hide( data );
4425                         newValue = keep !== 27 ? ( data.validater ? '' + data.validater( newValue ) : newValue ) : data.value; // 27:ESC
4426
4427                         data.elmValue.innerHTML = newValue;
4428                         
4429                         data.onUpdate && newValue !== data.value && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ newValue, data.value ], this );
4430                         
4431                         data.value = newValue;
4432                         data.focus = false;
4433                         finish( data );
4434                 },
4435                 enabled : function( v ){
4436                         var data = UIItemPrivateData.get( this );
4437                         if( Type.isBoolean( v ) === true && data.enabled !== v ){
4438                                 Util.toggleClass( data.elm, 'ui-textinput-disabled', !v );
4439                                 if( data.focus === true && v === false ) this.blur();
4440                                 data.enabled = v;
4441                                 data.node.disabled( !( data.visible && v ) );
4442                         };
4443                         return data.enabled;
4444                 },
4445                 visible : function( v ){
4446                         var data = UIItemPrivateData.get( this );
4447                         if( Type.isBoolean( v ) === true && data.visible !== v ){
4448                                 data.elm.style.display = v ? '' : 'none';
4449                                 if( data.focus === true && v === false ) this.blur();
4450                                 data.visible = v;
4451                                 data.node.disabled( !( data.enabled && v ) );
4452                         };
4453                         return data.visible;
4454                 },
4455                 destroy : function(){
4456                         var data = UIItemPrivateData.get( this );
4457                         data.focus === true && TextInputManager.hide( data );
4458                         data.destroy();
4459                 }
4460         };
4461
4462 /* --------------------------------
4463  * TextInputManager
4464  */
4465         var FileInputManager = ( function(){
4466                 var currentData,
4467                         elmForm,
4468                         elmFileInput,
4469                         elmWrap,
4470                         evt;
4471                 
4472                 function updateWrapperPosition(){
4473                         var p = Position.cumulativeOffset( currentData.elmValue ),
4474                                 w = currentData.elmValue.offsetWidth,
4475                                 _w;             
4476                         elmWrap.style.cssText = [
4477                                 'left:',   p[ 0 ], 'px;',
4478                                 'top:',    p[ 1 ], 'px;',//,
4479                                 'width:',  w, 'px;'//,
4480                                 //'height:', data.elmValue.offsetHeight, 'px;',
4481                                 //'position:absolute;'
4482                         ].join( '' );
4483                         
4484                         _w = elmWrap.offsetWidth;
4485                         if( w !== _w ) elmWrap.style.width = ( w - ( _w - w ) ) + 'px'; 
4486                 };
4487                 
4488                 function change( e ){
4489                         var data = currentData,
4490                                 file = data.elmFileInputReal.value;
4491                         file = file.split( '\\' );
4492                         file = file[ file.length - 1 ];
4493                         if( data.value !== file ){
4494                                 data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ file, data.value ], this );
4495                                 data.elmValue.innerHTML = data.value = file;
4496                         };
4497                         currentData.item.blur();
4498                 };
4499                 function asyncMouseout(){
4500                         currentData && currentData.item.blur();
4501                 };
4502                 function onClick(){
4503                         MouseEvent.remove( currentUser, elmFileInput, 'mouseout', asyncMouseout );
4504                         MouseEvent.remove( currentUser, elmFileInput, 'click', onClick );       
4505                 };
4506                 return {
4507                         show : function( data ){
4508                                 currentData = data;
4509                                 
4510                                 elmFileInput = data.elmFileInputReal;
4511                                 elmWrap      = elmFileInput.parentNode;
4512                                 // 
4513                                 
4514                                 updateWrapperPosition();
4515                                 elmFileInput.focus();
4516                                 //data.node.addEventListener( 'change', change, data );
4517                                 evt = new EventTicketClass( elmFileInput, 'change', change );
4518                                 MouseEvent.add( currentUser, elmFileInput, 'mouseout', asyncMouseout );
4519                                 MouseEvent.add( currentUser, elmFileInput, 'click', onClick );
4520                                 // currentData.elmFileInputReal.onchange = change;
4521                                 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4522                         },
4523                         hide : function( data ){
4524                                 if( currentData !== data ) return;
4525                                 // data.node.removeEventListener( 'change', change );
4526                                 evt.destroy();
4527                                 // MouseEvent.remove( currentUser, elmFileInput, 'mouseout', asyncMouseout );
4528                                 onClick();
4529                                 //currentData.elmFileInputReal.onchange = null;
4530                                 elmWrap.style.display = 'none';
4531                                 currentData = elmFileInput = null;
4532                                 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition );
4533                         },
4534                         onWindowResize: function( _w, _h ){
4535                                 AsyncCall.add( currentUser, updateWrapperPosition );
4536                         }
4537                 };
4538         })();
4539         
4540         var FileInputClass = function( groupData, elmWrapper, onUpdate, validater, elmFileInputReal, elmValue ){
4541                 var data = new UIItemPrivateData();
4542                 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4543                 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-fileinput-hover', 'pointer' );
4544                 data.elmValue = elmValue;
4545                 data.elmFileInputReal = elmFileInputReal;
4546                 data.node.addEventListener( 'mouseover', this.focus, this );
4547         };
4548         FileInputClass.prototype = {
4549                 value : function(){
4550                         return data.value;
4551                 },
4552                 focus : function(){
4553                         var data = UIItemPrivateData.get( this );
4554                         data.focus = true;
4555                         Util.addClass( data.elm, 'fileinput-has-focus' );
4556                         start( data );
4557                         FileInputManager.show( data );
4558                 },
4559                 blur : function( keyCode ){
4560                         var data = UIItemPrivateData.get( this );
4561                         Util.removeClass( data.elm, 'fileinput-has-focus' );
4562                         data.focus = false;
4563                         FileInputManager.hide( data );
4564                         finish( data );
4565                 },
4566                 enabled : function( v ){
4567                         var data = UIItemPrivateData.get( this );
4568                         if( Type.isBoolean( v ) === true && data.enabled !== v ){
4569                                 if( data.focus === true && v === false ) this.blur();
4570                                 Util.toggleClass( data.elm, 'fileinput-disabled', !v );
4571                                 data.enabled = v;
4572                                 data.node.disabled( !( data.visible && v ) );
4573                         };
4574                         return data.enabled;
4575                 },
4576                 visible : function( v ){
4577                         var data = UIItemPrivateData.get( this );
4578                         if( Type.isBoolean( v ) === true && data.visible !== v ){
4579                                 if( data.focus === true && v === false ) this.blur();
4580                                 data.elm.style.display = v ? '' : 'none';
4581                                 data.visible = v;
4582                                 data.node.disabled( !( data.enabled && v ) );
4583                         };
4584                         return data.visible;
4585                 },
4586                 destroy : function(){
4587                         var data = UIItemPrivateData.get( this );
4588                         data.focus === true && FileInputManager.hide( data );
4589                         data.destroy();
4590                 }
4591         };
4592         
4593         var ButtonClass = function( groupData, elmWrapper, onUpdate ){
4594                 var data = new UIItemPrivateData();
4595                 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4596                 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-button-hover', 'pointer' );
4597                 data.node.addEventListener( 'click', onUpdate );
4598                 //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', onUpdate );
4599         };
4600         ButtonClass.prototype = {
4601                 focus : function(){
4602                         var data = UIItemPrivateData.get( this );
4603                         data.focus = true;
4604                         Util.addClass( data.elm, 'button-has-focus' );
4605                         start( data );
4606                 },
4607                 blur : function( keyCode ){
4608                         var data = UIItemPrivateData.get( this );
4609                         keyCode === 13 && data.onUpdate && data.onUpdate();
4610                         Util.removeClass( data.elm, 'button-has-focus' );
4611                         data.focus = false;
4612                         finish( data );
4613                 },
4614                 enabled : function( v ){
4615                         var data = UIItemPrivateData.get( this );
4616                         if( Type.isBoolean( v ) === true && data.enabled !== v ){
4617                                 Util.toggleClass( data.elm, 'button-disabled', !v );
4618                                 data.enabled = v;
4619                                 data.node.disabled( !( data.visible && v ) );
4620                         };
4621                         return data.enabled;
4622                 },
4623                 visible : function( v ){
4624                         var data = UIItemPrivateData.get( this );
4625                         if( Type.isBoolean( v ) === true && data.visible !== v ){
4626                                 data.elm.style.display = v ? '' : 'none';
4627                                 data.visible = v;
4628                                 data.node.disabled( !( data.enabled && v ) );
4629                         };
4630                         return data.visible;
4631                 },
4632                 destroy : function(){
4633                         var data = UIItemPrivateData.get( this );
4634                         // MouseEvent.remove( data.groupData.apiuser, data.elm );
4635                         data.destroy();
4636                 }
4637         };
4638
4639         var ComboBoxClass = function( groupData, elmWrapper, onUpdate ){
4640                 var elmA   = ELM_COMBOBOX.cloneNode( true ),
4641                         data   = new UIItemPrivateData();
4642                 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4643                 
4644                 data.elmBox      = Util.getElementsByClassName( elmWrapper, 'combobox' )[ 0 ];
4645                 data.elmBox.appendChild( elmA );
4646                 data.elmA        = elmA;
4647                 data.elmToggle   = Util.getElementsByClassName( elmA, 'combobox-toggle' )[ 0 ];
4648                 data.elmValue    = Util.getElementsByClassName( elmA, 'combobox-value' )[ 0 ].firstChild;
4649                 data.selectIndex = 0;
4650                 data.optionList  = [];
4651
4652                 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-combobox-hover', 'pointer' );
4653                 data.node.addEventListener( 'click', this.focus, this );
4654         };
4655         ComboBoxClass.prototype = {
4656                 focus : function( e ){
4657                         var data = UIItemPrivateData.get( this );
4658                         data.node.removeEventListener( 'click', this.focus );
4659                         data.focus = true;
4660                         data.elmA.className = 'combobox-has-focus';
4661                         start( data );
4662                         OptionControl.show( data );
4663                         return false;
4664                 },
4665                 blur : function( keyCode ){
4666                         var data = UIItemPrivateData.get( this );
4667                         OptionControl.hide( this );
4668                         data.focus = false;
4669                         data.elmA.className = '';
4670                         finish( data );
4671                         data.node.addEventListener( 'click', this.focus, this );
4672                 },
4673                 enabled : function( v ){
4674                         var data = UIItemPrivateData.get( this );
4675                         if( Type.isBoolean( v ) === true && data.enabled !== v ){
4676                                 Util.toggleClass( data.elm, 'ui-combobox-disabled', !v );
4677                                 if( data.focus === true && v === false ) this.blur();
4678                                 data.enabled = v;
4679                                 data.node.disabled( !( data.visible && v ) );
4680                         };
4681                         return data.enabled;
4682                 },
4683                 visible : function( v ){
4684                         var data = UIItemPrivateData.get( this );
4685                         if( Type.isBoolean( v ) === true && data.visible !== v ){
4686                                 data.elm.style.display = v ? '' : 'none';
4687                                 if( data.focus === true && v === false ) this.blur();
4688                                 data.visible = v;
4689                                 data.node.disabled( !( data.enabled && v ) );
4690                         };
4691                         return data.visible;
4692                 },
4693                 value : function( _value ){
4694                         var data = UIItemPrivateData.get( this ),
4695                                 i    = 0,
4696                                 list = data.optionList,
4697                                 l    = list.length,
4698                                 _option;
4699                         if( Type.isString( _value ) === true && data.value !== _value ){
4700                                 for( ; i < l; ++i ){
4701                                         _option = list[ i ];
4702                                         if( _value === _option.value ){
4703                                                 data.value = _value;
4704                                                 data.index = i;
4705                                                 data.elmValue.data = _option.displayValue;
4706                                                 if( data.focus === true ){
4707                                                         OptionControl.update( this, _value );
4708                                                 };
4709                                                 data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, _value, this );
4710                                                 break;
4711                                         };
4712                                 };
4713                         };
4714                         return data.value;
4715                 },
4716                 selectIndex : function(){
4717                         var data = UIItemPrivateData.get( this );
4718                         return data.selectIndex;
4719                 },
4720                 createOption : function( _displayValue, _value, _isSelected ){
4721                         var data   = UIItemPrivateData.get( this ),
4722                                 option = null,
4723                                 list   = data.optionList,
4724                                 i      = list.length,
4725                                 _option, i;
4726                         _value      = _value || _displayValue;
4727                         _isSelected = !!_isSelected;
4728                         for( ; i; ){
4729                                 _option = list[ --i ];
4730                                 if( _value === _option.value ){
4731                                         option = _option;
4732                                         break;
4733                                 };
4734                         };
4735                         if( _isSelected === true ){
4736                                 data.selectIndex   = list.length;
4737                                 data.elmValue.data = _displayValue;
4738                         };                      
4739                         option === null && list.push( new OptionDataClass( _displayValue, _value, _isSelected ) );
4740                 },
4741                 destroy : function(){
4742                         var data   = UIItemPrivateData.get( this );
4743                         data.focus === true && OptionControl.hide( this );
4744                         // this.blur();
4745                         // MouseEvent.remove( data.groupData.apiuser, data.elm );
4746                         data.optionList.length = 0;
4747                         data.destroy();
4748                 }
4749         };
4750         var OptionDataClass = function( displayValue, value, isCurrent ){
4751                 this.displayValue = displayValue;
4752                 this.value        = value || displayValue;
4753                 this.current      = isCurrent;
4754                 displayValue = value = null;
4755         };
4756
4757         var OptionControl = ( function(){
4758                 var ELM_OPTION_WRAPPER = ( function(){
4759                                 var ret = document.createElement( 'div' );
4760                                 ret.className = 'option-container';
4761                                 return ret;
4762                         })(),
4763                         ELM_OPTION_ORIGIN = ( function(){
4764                                 var ret = document.createElement( 'a' );
4765                                 ret.appendChild( document.createTextNode( 'option' ) );
4766                                 ret.href = '#';
4767                                 return ret;
4768                         })();
4769
4770                 var OptionClass = function( option ){
4771                         this.elm     = ELM_OPTION_ORIGIN.cloneNode( true );
4772                         this.data    = option;
4773                         this.init();
4774                 };
4775                 OptionClass.prototype = {
4776                         init: function(){
4777                                 ELM_OPTION_WRAPPER.appendChild( this.elm );
4778                                 this.elm.firstChild.data = this.data.displayValue;
4779                                 this.current( this.data.current );
4780                                 MouseEvent.add( SUPER_USER_KEY, this.elm, 'mousedown', onOptionSelect );// onclick では 選択ボックス 隠すように body に設定した onmouseup が先に動いてしまう!
4781                         },
4782                         current: function( _current ){
4783                                 this.elm.className = _current === true ? CLASSNAME_COMBOBOX_OPTION_CURRENT : CLASSNAME_COMBOBOX_OPTION;
4784                                 this.data.current  = _current;
4785                                 currentOption      = _current === true ? this : currentOption;
4786                         },
4787                         destroy: function(){
4788                                 MouseEvent.remove( SUPER_USER_KEY, this.elm );
4789                                 Util.removeAllChildren( this.elm );
4790                                 ELM_OPTION_WRAPPER.removeChild( this.elm );
4791                                 delete this.elm;
4792                                 delete this.data;
4793                         }
4794                 };
4795                 
4796                 function onOptionSelect( e ){
4797                         var i = 0,
4798                                 l = OPTION_LIST.length,
4799                                 _option;
4800                         for( ; i < l; ++i ){
4801                                 _option = OPTION_LIST[ i ];
4802                                 if( this === _option.elm ){
4803                                         updateCurrrentOption( _option.data.value, true );
4804                                         currentCombobox.blur();
4805                                         break;
4806                                 };
4807                         };
4808                         return false;
4809                 };
4810                 
4811                 var OPTION_LIST     = [],
4812                         currentCombobox = null,
4813                         apiuser,
4814                         elm,
4815                         currentOption,
4816                         currentIndex;
4817                 
4818                 function updateCurrrentOption( _value, _updateCombobox ){
4819                         var _option,
4820                                 i = OPTION_LIST.length;
4821                         for( ; i; ){
4822                                 _option = OPTION_LIST[ --i ];
4823                                 if( _value === _option.data.value ){
4824                                         currentOption && currentOption.current( false );
4825                                         _option.current( true );
4826                                         currentOption = _option;
4827                                         currentIndex  = i;
4828                                         _updateCombobox === true && currentCombobox.value( _value );
4829                                         break;
4830                                 };
4831                         };
4832                 };
4833                 function bodyMouseupHandler(){
4834                         currentCombobox.blur();
4835                         OptionControl.hide( currentCombobox );
4836                 };
4837                 function updateWrapperPosition(){
4838                         var position = Util.getAbsolutePosition( elm );
4839
4840                         ELM_OPTION_WRAPPER.style.cssText = [
4841                                 'width:', elm.offsetWidth - 2, 'px;',
4842                                 'left:',  position.x, 'px;',
4843                                 'top:',   position.y + elm.offsetHeight, 'px;'
4844                         ].join( '' );
4845                 };
4846                 function change( e ){
4847                         var l   = OPTION_LIST.length,
4848                                 i   = currentIndex + ( e.keyCode === 40 ? -1 : 1 );
4849                         if( currentCombobox === null || l < 2 ) return;
4850                         i = i < 0 ?
4851                                         l - 1 :
4852                                         i < l ? i : 0;
4853                         updateCurrrentOption( OPTION_LIST[ i ].data.value, true );
4854                         return false;
4855                 };
4856                 return {
4857                         show: function( data ){
4858                                 var combobox = data.item,
4859                                         list     = data.optionList,
4860                                         i        = 0,
4861                                         l        = list.length;
4862                                 if( currentItem !== combobox || currentCombobox === combobox ) return;
4863                                 currentCombobox && currentCombobox.blur();
4864                                 
4865                                 apiuser         = data.groupData.apiuser;
4866                                 currentCombobox = combobox;
4867                                 elm             = data.elmBox;
4868                                 
4869                                 for( ; i < l; ++i ){
4870                                         OPTION_LIST.unshift( new OptionClass( list[ i ] ) );
4871                                 };
4872                                 MouseEvent.add( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler );
4873                                 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 38 );
4874                                 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 40 );
4875                                 //KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter, 13 );
4876                                 //KeyEvent.updateCurrentListener( SUPER_USER_KEY );
4877                                 
4878                                 body.appendChild( ELM_OPTION_WRAPPER );
4879                                 
4880                                 updateCurrrentOption( combobox.value(), false );
4881                                 updateWrapperPosition();
4882                                 
4883                                 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4884                         },
4885                         hide: function( _combobox ){
4886                                 if( currentCombobox !== _combobox || currentCombobox === null ) return;
4887
4888                                 var _option;
4889                                 while( _option = OPTION_LIST.shift() ){
4890                                         _option.destroy();
4891                                 };
4892                                 
4893                                 body.removeChild( ELM_OPTION_WRAPPER );
4894                                 
4895                                 MouseEvent.remove( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler );
4896                                 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change );
4897                                 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change );
4898                                 //KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter );
4899                                 //KeyEvent.updateCurrentListener( apiuser );
4900                                 
4901                                 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition, 500 );
4902                                 
4903                                 apiuser         = null;
4904                                 currentCombobox = null;
4905                                 currentOption   = null;
4906                                 currentIndex    = 0;                            
4907                         },
4908                         onEnter: function(){
4909                                 currentCombobox.value( currentOption.data.value );
4910                                 //currentCombobox.blur();
4911                                 //OptionControl.hide( currentCombobox );
4912                         },
4913                         update: function( data, _value ){
4914                                 if( currentCombobox !== data.item || currentItem !== data.item ) return;
4915                                 if( currentOption.data.value === _value ) return;
4916                                 updateCurrrentOption( _value, true );
4917                         },
4918                         onWindowResize: function( _w, _h ){
4919                                 currentCombobox && AsyncCall.add( apiuser, updateWrapperPosition );
4920                         }
4921                 };
4922         })();
4923         
4924         var UIGroupPrivateData = function(){};
4925         UIGroupPrivateData.prototype = {
4926                 apiuser  : null,
4927                 node     : null,
4928                 uigroup  : null,
4929                 itemList : null,
4930                 visible  : true,
4931                 enabled  : true,
4932                 init     : function( apiuser, node, uigroup ){
4933                         this.apiuser  = apiuser;
4934                         this.node     = node;
4935                         this.uigroup  = uigroup;
4936                         this.itemList = [];
4937                         UIGroupPrivateData.list.push( this );
4938                 },
4939                 destroy  : function(){
4940                         
4941                 }
4942         };
4943         UIGroupPrivateData.list = [];
4944         UIGroupPrivateData.get  = function( uigroup ){
4945                 var list = UIGroupPrivateData.list,
4946                         i    = list.length;
4947                 for( ; i; ){
4948                         if( list[ --i ].uigroup === uigroup ) return list[ i ];
4949                 };
4950                 return null;
4951         };
4952         
4953         var UIGroupClass = function( apiuser, node ){
4954                 ( new UIGroupPrivateData() ).init( apiuser, node, this );
4955         };
4956         UIGroupClass.prototype = {
4957                 focus : function( _value ){
4958                         var data = UIGroupPrivateData.get( this );
4959                         /*
4960                         if( _value === true ){
4961                                 if( currentItem ){
4962                                         start( apiuser, self, currentItem );
4963                                 } else
4964                                 if( itemList.length > 0 ){
4965                                         start( apiuser, self, itemList[ 0 ] );
4966                                 };
4967                         } else
4968                         if( _value === false ){
4969                                 finish( apiuser, self, currentItem );
4970                         } else
4971                         */
4972                         if( _value && Util.getIndex( data.itemList, _value ) !== -1 ){
4973                                 // currentItem = _value;
4974                                 currentList = data.itemList;
4975                         };
4976                         return currentUi === this; 
4977                 },
4978                 blur : function(){
4979                         var data = UIGroupPrivateData.get( this );
4980                         if( currentList === data.itemList ){
4981                                 currentList = null;
4982                         };
4983                 },
4984                 createInputText : function( elmWrapper, onUpdate, validater ){
4985                         var data     = UIGroupPrivateData.get( this ),
4986                                 elmValue = Util.getElementsByClassName( elmWrapper, 'editable-value' )[ 0 ],
4987                                 ret;
4988                         if( elmValue ){
4989                                 ret = new TextInputClass( data, elmWrapper, elmValue, onUpdate, validater );
4990                                 data.itemList.push( ret );
4991                                 return ret;
4992                         };
4993                         alert( 'error createInputText' );
4994                 },
4995                 createButton : function( elm, onClick ){
4996                         var data = UIGroupPrivateData.get( this ),
4997                                 ret  = new ButtonClass( data, elm, onClick );
4998                         data.itemList.push( ret );
4999                         return ret;
5000                 },
5001                 createFileInput : function( elm, onUpdate, validater, elmFileInputReal ){
5002                         var data     = UIGroupPrivateData.get( this ),
5003                                 elmValue = Util.getElementsByClassName( elm, 'fileinput-value' )[ 0 ],
5004                                 ret;
5005                         if( elmValue ){
5006                                 ret = new FileInputClass( data, elm, onUpdate, validater, elmFileInputReal, elmValue );
5007                                 data.itemList.push( ret );
5008                                 return ret;
5009                         };
5010                         return ret;
5011                 },
5012                 createCombobox : function( elm, onUpdate, optionList ){
5013                         var data = UIGroupPrivateData.get( this ),
5014                                 ret  = new ComboBoxClass( data, elm, onUpdate, optionList );
5015                         data.itemList.push( ret );
5016                         return ret;
5017                 },
5018                 createCheckBox : function(){
5019                         
5020                 },
5021                 createRadio : function(){
5022                         
5023                 },
5024                 createSlider : function(){
5025                         
5026                 },
5027                 visible : function( v ){
5028                         var data = UIGroupPrivateData.get( this );
5029                         if( Type.isBoolean( v ) === true && data.visible !== v ){
5030                                 for( var i = data.itemList.length; i; ){
5031                                         data.itemList[ --i ].visible( v );
5032                                 };
5033                                 data.visible = v;
5034                                 data.node.disabled( !( data.enabled && v ) );
5035                         };
5036                         return data.visible;
5037                 },
5038                 enabled : function( v ){
5039                         var data = UIGroupPrivateData.get( this );
5040                         if( Type.isBoolean( v ) === true && data.enabled !== v ){
5041                                 for( var i = data.itemList.length; i; ){
5042                                         data.itemList[ --i ].enabled( v );
5043                                 };
5044                                 data.enabled = v;
5045                                 data.node.disabled( !( data.visible && v ) );
5046                         };
5047                         return data.enabled;
5048                 },
5049                 destroy : function(){
5050                         var data = UIGroupPrivateData.get( this ),
5051                                 _item;
5052                         if( currentUi === this ){
5053                                 currentItem.blur();
5054                                 // finish( UIItemPrivateData.get( currentItem ) );
5055                         };                      
5056                         while( _item = data.itemList.shift() ){
5057                                 _item.destroy();
5058                         };
5059                         data.destroy();
5060                 }
5061         };
5062         
5063         function start( data ){
5064                 if( currentItem !== data.item ){
5065                         currentUi !== data.groupData.uigroup && currentUi && currentUi.blur();
5066                         
5067                         currentItem !== null && currentItem.blur();
5068                         
5069                         currentUser = data.groupData.apiuser;
5070                         currentUi   = data.groupData.uigroup;
5071                         currentItem = data.item;
5072                         
5073                         currentUi.focus( currentItem );
5074                         
5075                         // if( currentUser !== _apiuser ) {
5076                                 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 );
5077                                 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 );
5078                                 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown,  9 );
5079                                 KeyEvent.updateCurrentListener( SUPER_USER_KEY );
5080                         // };
5081                 };
5082         }
5083         function finish( data ){
5084                 if( currentItem === data.item ){
5085                         currentUi.blur();
5086                         
5087                         currentUser = null;
5088                         currentUi   = null;
5089                         currentItem = null;
5090                         currentList = null;
5091                         
5092                         KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 );
5093                         KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 );
5094                         KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown,  9 );
5095                         KeyEvent.updateCurrentListener( data.groupData.apiuser );
5096                 };
5097         };
5098
5099         function onKeyDown( e ){
5100                 if( currentItem === null ) return true;
5101                 var keyCode = e.keyCode,
5102                         index   = Util.getIndex( currentList, currentItem );
5103                 if( keyCode === 13 || keyCode === 27 || keyCode === 9 || keyCode === 18 || e.altKey === true ){ // 13.return 27.esc 9.tab 18.alt
5104                         keyCode === 9  && tabShift( index, e.shiftKey === true ? -1 : 1 );
5105                         keyCode === 13 && currentItem instanceof ComboBoxClass && OptionControl.onEnter();
5106                         keyCode === 13 && tabShift( index, 1 );                 
5107                         currentItem && currentItem.blur( keyCode );
5108                         return false;
5109                 };
5110         };
5111
5112         function tabShift( index, way ){
5113                 var l = currentList.length,
5114                         i = index + way,
5115                         item;
5116                 if( l < 2 ) return;
5117                 while( i !== index ){
5118                         i = i < 0 ?
5119                                 l - 1 :
5120                                 i < l ? i : 0; // 0 < i < l
5121                         item = currentList[ i ];
5122                         if( item.enabled() === true && item.visible() === true ){
5123                                 AsyncCall.add( currentUser, item.focus, null, item );
5124                                 return;
5125                         };
5126                         i += way;
5127                 };
5128         };
5129         
5130         return {
5131                 createUIGroup: function( apiuser, node ){
5132                         var uid  = apiuser.getUID(),
5133                                 list = UI_LIST[ uid ],
5134                                 ui   = new UIGroupClass( apiuser, node );
5135                         if( Type.isArray( list ) === false ){
5136                                 list = UI_LIST[ uid ] = [];
5137                         };
5138                         list.push( ui );
5139                         return ui;
5140                 },
5141                 onWindowResize: function( w, h ){
5142                         windowW = w;
5143                         windowH = h;
5144                         currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h );
5145                         currentItem instanceof TextInputClass && TextInputManager.onWindowResize( w, h );
5146                         currentItem instanceof FileInputClass && FileInputManager.onWindowResize( w, h );
5147                 },
5148                 onCurrentApplicationChange: function( _apiuser ){
5149                         currentList = UI_LIST[ _apiuser.getUID() ];
5150                 },
5151                 onApplicationShutdown: function( _apiuser ){
5152                         KeyEvent.remove( _apiuser );
5153                 },
5154                 onSystemShutdown: function(){
5155                         
5156                 }
5157         };
5158 })();
5159
5160 var UIForm = ( function(){
5161         var FORM_LIST           = [];
5162         var CLASSNAME_FORM      = 'uiform-invisible';
5163         var CLASSNAME_FILE_WRAP = 'ui-fileinput-wrapper';
5164         var FormItemData = function(){};
5165     var windowW, windowH;
5166         FormItemData.prototype = {
5167                 formData : null,
5168                 uiItem   : null,
5169                 init : function( formData, uiItem ){
5170                         this.formData = formData;
5171                         this.uiItem   = uiItem;
5172                 },
5173                 onUpdate : function( v ){
5174                         // var index = Util.getIndex( this.formData.itemList, this );
5175                 }
5176         };
5177         
5178         var FormPrivateData = function(){};
5179         FormPrivateData.prototype = {
5180                 apiuser  : null,
5181                 node     : null,
5182                 form     : null,
5183                 elmForm  : null,
5184                 itemList : null,
5185                 visible  : true,
5186                 enabled  : true,
5187                 init     : function( apiuser, from, node, elm, elmForm ){
5188                         this.apiuser      = apiuser;
5189                         this.form         = form;
5190                         this.ui           = apiuser.createUIGroup( node );
5191                         this.node         = node;
5192                         this.elm          = elm;
5193                         this.elmForm      = elmForm;
5194                         this.itemList     = [];
5195                         elmForm.className = CLASSNAME_FORM;
5196                         FormPrivateData.list.push( this );
5197                         
5198                         var forms = Util.copyArray( elmForm.getElementsByTagName( '*' ) ),
5199                                 l     = forms.length,
5200                                 i     = 0,
5201                                 items = 'input,select,textarea,button',
5202                                 form, data, el, wrap;
5203                         for( ; i<l; ++i ){
5204                                 form = forms[ i ];
5205                                 if( form.nodeType !== 1 ) continue;
5206                                 switch( form.tagName.toLowerCase() ){
5207                                         case 'input':
5208                                                 switch( form.type.toLowerCase() ){
5209                                                         case 'text':
5210                                                                 break;
5211                                                         case 'file':
5212                                                                 el = document.createElement( 'div' );
5213                                                                 el.className = 'uiform-file-container';
5214                                                                 el.appendChild( document.createElement( 'div' ) );
5215                                                                 el.appendChild( document.createElement( 'div' ) );
5216                                                                 el.firstChild.className = 'uiform-label';
5217                                                                 el.lastChild.className  = 'uiform-file fileinput-value';
5218                                                                 // opera9 don't work for opera9;
5219                                                                 //el = Util.pullHtmlAsTemplete( '<div class="uiform-file-container"><div class="uiform-label"></div><div class="uiform-file fileinput-value"></div></div>' );
5220                                                                 elm.appendChild( el );
5221                                                                 data = new FormItemData();
5222                                                                 wrap = document.createElement( 'div' );
5223                                                                 form.parentNode.insertBefore( wrap, form );
5224                                                                 wrap.className = CLASSNAME_FILE_WRAP;
5225                                                                 wrap.appendChild( form );
5226                                                                 data.init( this, this.ui.createFileInput( el, data.onUpdate, null, form ) );
5227                                                                 this.itemList.push( data );
5228                                                                 break;
5229                                                         case 'button':
5230                                                                 break;
5231                                                         default:
5232                                                                 continue;
5233                                                 };
5234                                                 break;
5235                                         case 'select':
5236                                                 break;
5237                                         case 'button':
5238                                                 break;
5239                                         case 'textarea':
5240                                                 break;
5241                                         default:
5242                                                 continue;
5243                                 };
5244                         };
5245                 },
5246                 destroy  : function(){
5247                         
5248                 }
5249         };
5250         FormPrivateData.list = [];
5251         FormPrivateData.get  = function( from ){
5252                 var list = FormPrivateData.list,
5253                         i    = list.length;
5254                 for( ; i; ){
5255                         if( list[ --i ].form === form ) return list[ i ];
5256                 };
5257                 return null;
5258         };
5259         
5260         var FormClass = function( apiuser, node, elm, elmForm ){
5261                 ( new FormPrivateData() ).init( apiuser, this, node, elm, elmForm );
5262         };
5263         FormClass.prototype = {
5264                 createTextInput : function(){
5265                         
5266                 },
5267                 createMultiLineInput : function(){
5268                         
5269                 },
5270                 createFileInput : function(){
5271                         
5272                 },
5273                 createButton : function(){
5274                         
5275                 },
5276                 createComboBox : function(){
5277                         
5278                 },
5279                 submit : function(){
5280                         
5281                 }
5282         };
5283         
5284         return {
5285                 createForm: function( apiuser, nodeOrElm, opt_elmForm ){
5286                         var uid  = apiuser.getUID(),
5287                                 list = FORM_LIST[ uid ],
5288                                 node, elm, form;
5289                         if( PointingDeviceEventTree.isNodeInstance( nodeOrElm ) === true ){
5290                                 node = nodeOrElm;
5291                                 elm  = PointingDeviceEventTree._getNodePrivateData( nodeOrElm ).elm;
5292                         } else {
5293                                 // App が eventTree を持っている?
5294                                 // App が eventTree を持っていない
5295                                 elm  = nodeOrElm;
5296                         };  
5297                         form = new FormClass( apiuser, node, elm, opt_elmForm );
5298                         if( Type.isArray( list ) === false ){
5299                                 list = FORM_LIST[ uid ] = [];
5300                         };
5301                         list.push( form );
5302                         return form;
5303                 },
5304                 onWindowResize: function( w, h ){
5305                         windowW = w;
5306                         windowH = h;
5307                         currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h );
5308                         currentItem instanceof TextInputClass && TextInputManager.onWindowResize( w, h );
5309                         currentItem instanceof FileInputClass && FileInputManager.onWindowResize( w, h );
5310                 },
5311                 onCurrentApplicationChange: function( _apiuser ){
5312                 },
5313                 onApplicationShutdown: function( _apiuser ){
5314                 },
5315                 onSystemShutdown: function(){
5316                         
5317                 }
5318         };
5319 })();
5320
5321 var Finder = ( function(){
5322         var FINDER_LIST              = [],
5323                 ELM_ORIGIN_LOCATION_ITEM = Util.pullHtmlAsTemplete( '<div class="finder-location-item"></div>' ),
5324                 HTML_FINDER_ICON = ( function(){
5325                         return ( UA.isIE === true && UA.ieVersion < 8 ?
5326                         [
5327                                 '<div class="finder-icon fnder-icon-ie7">',
5328                                         '<div class="finder-icon-handle"></div>',
5329                                         '<div class="file-icon"><div></div></div>',
5330                                         '<span class="finder-icon-cell finder-icon-ie-filename">',
5331                                                 '<span class="finder-icon-vertical-middle-outer">',
5332                                                         '<span class="finder-icon-vertical-middle-inner">',
5333                                                                 '<span class="finder-icon-filename break-word">file name</span>',
5334                                                         '</span>',
5335                                                 '</span>',
5336                                         '</span>',
5337                                         '<span class="finder-icon-cell finder-icon-ie-summary">',
5338                                                 '<span class="finder-icon-vertical-middle-outer">',
5339                                                         '<span class="finder-icon-vertical-middle-inner">',
5340                                                                 '<span class="finder-icon-summary break-word">file descriptiion</span>',
5341                                                         '</span>',
5342                                                 '</span>',
5343                                         '</span>',
5344                                         '<div class="finder-icon-down"></div>',
5345                                 '</div>'
5346                         ] :
5347                         [
5348                                 '<div class="finder-icon fnder-icon-modern">',
5349                                         '<div class="finder-icon-handle"></div>',
5350                                         '<div class="file-icon"><div></div></div>',
5351                                         '<div class="finder-icon-filename break-word">file name</div>',
5352                                         '<div class="finder-icon-summary break-word">file descriptiion</div>',
5353                                         '<div class="finder-icon-down">&gt;</div>',
5354                                 '</div>'
5355                         ] ).join( '' );
5356                 })(),
5357                 ELM_ORIGIN_FINDER_ICON = Util.pullHtmlAsTemplete( HTML_FINDER_ICON ),
5358                 ICON_HEIGHT            = Util.getElementSize( ELM_ORIGIN_FINDER_ICON ).height;
5359         
5360         // t : 時間
5361     // b : 開始の値(開始時の座標やスケールなど)
5362     // c : 開始と終了の値の差分
5363     // d : Tween(トゥイーン)の合計時間
5364
5365         function easeOutQuad( t, b, c, d ){
5366                 t /= d;
5367                 return -c * t*( t-2 ) + b;
5368         };
5369         
5370 /**
5371  * FinderIconClass
5372  */
5373         var FinderIconClass = function(){};
5374         FinderIconClass.prototype = {
5375                 finderData       : null,
5376                 file             : null,
5377                 elm              : null,
5378                 node             : null,
5379                 _index           : -1,
5380                 _style           : -1,
5381                 init : function( page, file, w, index, style ){
5382                         if( !this.elm ) this.elm  = ELM_ORIGIN_FINDER_ICON.cloneNode( true );
5383
5384                         if( this.page !== page ){
5385                                 this.page = page;
5386                                 page.elm.appendChild( this.elm );
5387                                 this.node && this.node.remove();
5388                                 this.node = page.node.createNode( this.elm, false, true, 'finder-icon-hover', '' );
5389                         };
5390                         if( this.file !== file ){
5391                                 this.file && this.file.destroy();
5392                                 this.file   = file;
5393                                 this._index = index;
5394                                 this.draw( w );
5395                                 return;
5396                         };
5397                         if( this._index !== index ){
5398                                 this._index = index;
5399                                 this.resize( w );
5400                         };
5401                 },
5402                 index : function( _index ){     
5403                         return this._index;
5404                 },
5405                 style : function( _style ){
5406                         return this._style;
5407                 },
5408                 draw : function( w ){
5409                         var file       = this.file,
5410                                 elm        = this.elm,
5411                                 thumb      = file.getThumbnail(),
5412                                 elmThumb   = Util.getElementsByClassName( elm, 'file-icon' )[ 0 ].firstChild,
5413                                 elmName    = Util.getElementsByClassName( elm, 'finder-icon-filename' )[ 0 ],
5414                                 elmDesc    = Util.getElementsByClassName( elm, 'finder-icon-summary' )[ 0 ];
5415                         if( thumb.image ){
5416                                 elmThumb.className = 'has-thumbnail';
5417                                 elmThumb.style.backgroundImage = [ 'url(', thumb.image, ')' ].join( '' );
5418                         } else {
5419                                 elmThumb.className = thumb.className;
5420                                 elmThumb.style.backgroundImage = '';
5421                         };
5422                         
5423                         elmName.firstChild.data = file.getName();
5424                         elmDesc.firstChild.data = file.getSummary();
5425                         
5426                         this.resize( w );
5427                 },
5428                 resize : function( w ){
5429                         this.node.update( 0, this._index * ICON_HEIGHT, w );
5430                 },
5431                 onEditorClick : function( e ){
5432                         this.onEditorCallback && this.onEditorCallback( this.file, this.file.editorApplicationList()[ 0 ] );
5433                         return false;
5434                 },
5435                 onViwerClick : function( e ){
5436                         this.onViewerCallback && this.onViewerCallback( this.file, this.file.viewerApplicationList()[ 0 ] );
5437                         return false;
5438                 },
5439                 onActionClick : function( e ){
5440                         this.onActionCallback && this.onActionCallback( this.file );
5441                         return false;
5442                 },
5443                 destroy : function(){
5444                         this.elm && this.elm.parentNode.removeChild( this.elm );
5445                         this.file && this.file.destroy();
5446                         this.node && this.node.remove();
5447                         delete this.page;
5448                         delete this.file;
5449                         delete this.node;
5450                         delete this._index;
5451                         delete this._style;
5452                         FinderIconClass.pool.push( this );
5453                 }       
5454         };
5455         FinderIconClass.pool = [];
5456         FinderIconClass.get = function( page, file, w, index, style ){
5457                 var _icon = FinderIconClass.pool.length > 0 ? FinderIconClass.pool.shift() : new FinderIconClass();
5458                 _icon.init( page, file, w, index, style );
5459                 return _icon;
5460         };
5461
5462 /**
5463  * PathClass
5464  */
5465         var PathClass = function(){};
5466         PathClass.prototype = {
5467                 finderData : null,
5468                 elm        : null,
5469                 node       : null,
5470                 file       : null,
5471                 _index     : null,
5472                 w          : 0,
5473                 init : function( finderData, file, index ){
5474                         if( !this.elm ) this.elm  = ELM_ORIGIN_LOCATION_ITEM.cloneNode( true );
5475                         
5476                         if( this.finderData !== finderData ){
5477                                 this.finderData = finderData;
5478                                 finderData.elmPath.appendChild( this.elm );
5479                                 this.node && this.node.remove();
5480                                 delete this.node;
5481                         };
5482                         if( this.file !== file ){
5483                                 this.file = file;
5484                                 this.draw();
5485                         };
5486                         this._index = index;
5487                         if( !this.node ) this.node = finderData.nodePath.createNode( this.elm, false, true, 'finder-path-hover', 'pointer' );
5488                 },
5489                 draw  : function(){
5490                         this.elm.className = 'file-icon-' + this.file.getType();
5491                         this.elm.innerHTML = this.file.getName();                       
5492                 },
5493                 textWidth : function(){
5494                         this.elm.style.width = 'auto';
5495                         var ret = this.elm.offsetWidth;
5496                         this.elm.style.width = '';
5497                         return ret + 15;
5498                 },
5499                 update : function( x, w ){
5500                         this.node.update( x - 15, undefined, w );
5501                 },
5502                 index : function( _index ){
5503                         return this._index;
5504                 },
5505                 destroy : function(){
5506                         this.finderData.elmPath.removeChild( this.elm );
5507                         this.node && this.node.remove();
5508                         
5509                         delete this.finderData;
5510                         delete this.elm;
5511                         delete this.node;
5512                         delete this.file;
5513                         delete this._index;
5514                         PathClass.pool.push( this );
5515                 }
5516         };
5517         PathClass.pool = [];
5518         PathClass.get  = function( finderData, file, index ){
5519                 var _bread = PathClass.pool.length > 0 ? PathClass.pool.shift() : new PathClass();
5520                 _bread.init( finderData, file, index );
5521                 return _bread;
5522         };
5523         
5524         
5525         /**
5526          * Page
5527          */
5528         var PageClass = function(){};
5529         PageClass.prototype = {
5530                 nodeRoot     : null,
5531                 elmRoot      : null,
5532                 elmScroll    : null,
5533                 elm          : null,
5534                 node         : null,
5535                 folder       : null,
5536                 iconList     : null,
5537                 sliding      : false,
5538                 currentX     : 0,
5539                 panTime      : 0,
5540                 startX       : 0,
5541                 offsetX      : 0,
5542                 panTotalTime : 0,
5543                 isPanOut     : false,
5544                 init : function( nodeRoot, elmRoot, elmScroll ){
5545                         this.nodeRoot  = nodeRoot;
5546                         this.elmRoot   = elmRoot;
5547                         this.elmScroll = elmScroll;
5548                         
5549                         if( this.elm === null ){
5550                                 this.elm = document.createElement( 'div' );
5551                         };
5552                         elmScroll.appendChild( this.elm );
5553                         this.elm.style.cssText = 'position:absolute;top:0;';
5554                         // this.elm.style.display = 'none';
5555                         this.node = this.nodeRoot.createNode( this.elm, true, false );
5556                         if( this.iconList === null ){
5557                                 this.iconList = [];
5558                         };
5559                 },
5560                 panInReady : function( way ){
5561                         this.elm.style.display = '';
5562                         var x = this.sliding === true ? this.currentX : way * this.nodeRoot.width();
5563                         this.startX       = this.currentX = x;
5564                         this.targetX      = 0;
5565                         this.offsetX      = -x;
5566                         this.panTime      = 0;
5567                         this.panTotalTime = 20;
5568                         this.sliding      = true;
5569                         this.isPanOut     = false;
5570                         // this.elm.style.left = x + 'px';
5571                         this.node.x( x );
5572                 },
5573                 panOutReady : function( way ){
5574                         var x = -way * this.nodeRoot.width();
5575                         this.startX       = this.currentX || 0;
5576                         this.targetX      = x;
5577                         this.offsetX      = x - this.startX;
5578                         this.panTime      = 0;
5579                         this.panTotalTime = 20;
5580                         this.sliding      = true;
5581                         this.isPanOut     = true;
5582                 },
5583                 pan : function(){
5584                         var page = this,
5585                                 x    = page.currentX = easeOutQuad( page.panTime, page.startX, page.offsetX, page.panTotalTime );
5586                         // page.elm.style.left = x + 'px';
5587                         this.node.x( x );
5588                         if( page.panTotalTime < ++page.panTime ){
5589                                 delete page.panTime;
5590                                 delete page.startX;
5591                                 delete page.offsetX;                                    
5592                                 delete page.panTotalTime;
5593                                 delete page.sliding;
5594                                 if( this.isPanOut === true ) this.elm.style.display = 'none';
5595                         };
5596                 },
5597                 draw : function( folder ){
5598                         var _w = this.nodeRoot.width();
5599                         this.folder = folder;
5600                         var data     = this,
5601                                 iconList = data.iconList,
5602                                 i        = 0,
5603                                 j        = 0,
5604                                 l        = folder.getChildFileLength(),
5605                                 m        = iconList.length,
5606                                 scrollY  = -this.nodeRoot.scrollY(),
5607                                 rootH    = scrollY + this.nodeRoot.height(),
5608                                 icon;
5609
5610                         for( ; i < l; ++i ){
5611                                 if( ( i + 1 ) * ICON_HEIGHT < scrollY || rootH < i * ICON_HEIGHT ) continue;
5612                                 if( j < m ){
5613                                         iconList[ j ].init( this, folder.getChildFileAt( i ), _w, i, data.style );
5614                                 } else {
5615                                         iconList.push( FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) );
5616                                 };
5617                                 j++;
5618                         };
5619                         data.elmRoot.className    = folder.getState() === Const.FILE.STATE.LOADING ? 'finder-body loading' : 'finder-body';
5620                         // data.elmRoot.style.height = ( data.h - data.headH ) + 'px';
5621                         
5622                         while( j < iconList.length ) iconList.pop().destroy();
5623                         data.elmScroll.style.height = ( l * ICON_HEIGHT ) + 'px';
5624                 },
5625                 onScroll : function(){
5626                         var _w       = this.nodeRoot.width();
5627                         
5628                         var data     = this,
5629                                 iconList = data.iconList,
5630                                 folder   = this.folder,
5631                                 i        = 0,
5632                                 j        = 0,
5633                                 l        = folder.getChildFileLength(),
5634                                 scrollY  = -this.nodeRoot.scrollY(),
5635                                 rootH    = scrollY + this.nodeRoot.height(),
5636                                 startIndex = 0 < iconList.length ? iconList[ 0 ]._index : 0,
5637                                 icon;
5638                         
5639                         // console.log( ' > ' + scrollY + ' , ' + rootH )
5640                         for( ; i < l; ++i ){
5641                                 if( ( i + 1 ) * ICON_HEIGHT < scrollY || rootH < i * ICON_HEIGHT ){
5642                                         if( iconList.length <= j ) continue;
5643                                         icon = iconList[ j ];
5644                                         if( icon._index !== i ) continue;
5645                                         icon.destroy();
5646                                         iconList.splice( j, 1 );
5647                                         continue;
5648                                 };
5649                                 if( iconList.length <= j || iconList[ j ]._index !== i ){
5650                                         if( i < startIndex ){
5651                                                 iconList.splice( j, 0, FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) );                    
5652                                         } else
5653                                         if( startIndex + iconList.length <= i ){
5654                                                 iconList.push( FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) );                    
5655                                         };                                      
5656                                 };
5657                                 ++j;
5658                         };
5659                         
5660                         //while( j < iconList.length ) iconList.pop().destroy();
5661                 },
5662                 resize : function( w ){
5663                         var list = this.iconList,
5664                                 i    = list.length;
5665                         for( ; i; ) list[ --i ].resize( w );
5666                 },
5667                 destroy : function(){
5668                         var icon;
5669                         while( icon = this.iconList.shift() ) icon.destroy();
5670                         
5671                         this.elm.parentNode.removeChild( this.elm );
5672                 }
5673         };
5674         
5675         var ApplicationButton = function(){};
5676         ApplicationButton.prototype = {
5677                 elm     : null,
5678                 button  : null,
5679                 app     : null,
5680                 file    : null,
5681                 fileUID : -1,
5682                 init    : function( ui, elmParent, app, file ){
5683                         if( this.elm === null ){
5684                                 this.elm = document.createElement( 'div' );
5685                         };
5686                         elmParent.appendChild( this.elm );
5687                         this.elm.className = 'button';
5688                         this.elm.innerHTML = app.getDisplayName();
5689                         
5690                         var that = this;
5691                         this.button = ui.createButton( this.elm, function(){
5692                                 that.onClick();
5693                                 // that = null;
5694                         } );
5695                         
5696                         this.app     = app;
5697                         this.file    = file;
5698                         this.fileUID = file.getUID();
5699                 },
5700                 onClick : function(){
5701                         this.app.boot( this.file );
5702                         return false;
5703                 },
5704                 destroy : function(){
5705                         var elm = this.elm;
5706                         elm.parentNode.removeChild( elm );
5707                         
5708                         this.button.destroy();
5709                         //this.kill()
5710                         //this.elm = elm;
5711                 }
5712         };
5713         
5714         var DetailPageClass = function(){};
5715         DetailPageClass.prototype = Util.extend( new PageClass(), {
5716                 appButtons : null,
5717                 init : function( finderData ){
5718                         this.finderData = finderData;
5719                         this.apiuser    = finderData.apiuser;
5720                         this.nodeRoot   = finderData.nodeRoot;
5721                         this.elmRoot    = finderData.elmRoot;
5722                         this.elmScroll  = finderData.elmScroll;
5723                         
5724                         if( this.elm === null ){
5725                                 this.elm = Util.pullHtmlAsTemplete( [
5726                                         '<div class="finder-detail">',
5727                                                 '<div class="file-icon"><div></div></div>',
5728                                                 '<div class="finder-detail-filename break-word">file name</div>',
5729                                                 '<div class="finder-detail-summary break-word">file descriptiion</div>',
5730                                                 '<div>View this file</div>',
5731                                                 '<div class="viewer-apps"></div>',                                              
5732                                                 '<div>Edit this file</div>',
5733                                                 '<div class="editor-apps"></div>',
5734                                         '</div>'
5735                                 ].join( '' ) );
5736                         };
5737                         this.elm.style.display = 'none';
5738                         this.elmScroll.appendChild( this.elm );
5739                         this.node = this.nodeRoot.createNode( this.elm, true, false );
5740                         
5741                         this.ui = this.apiuser.createUIGroup( this.node );
5742                         this.appButtons = [];
5743                 },
5744                 draw : function( file ){
5745                         var elm        = this.elm,
5746                                 thumb      = file.getThumbnail(),
5747                                 elmThumb   = Util.getElementsByClassName( elm, 'file-icon' )[ 0 ].firstChild,
5748                                 elmName    = Util.getElementsByClassName( elm, 'finder-detail-filename' )[ 0 ],
5749                                 elmDesc    = Util.getElementsByClassName( elm, 'finder-detail-summary' )[ 0 ],
5750                                 tmpButtons = Util.copyArray( this.appButtons ),
5751                                 apps, app, elmContainer, button;
5752                         if( thumb.image ){
5753                                 elmThumb.className = 'has-thumbnail';
5754                                 elmThumb.style.backgroundImage = [ 'url(', thumb.image, ')' ].join( '' );
5755                         } else {
5756                                 elmThumb.className = thumb.className;
5757                                 elmThumb.style.backgroundImage = '';
5758                         };
5759                         
5760                         elmName.firstChild.data = file.getName();
5761                         elmDesc.firstChild.data = file.getSummary();
5762                         this.node.width( this.nodeRoot.width() );
5763                         this.node.height( this.nodeRoot.height() );
5764                         
5765                         this.appButtons.length = 0;
5766                         
5767                         apps         = file.viewerApplicationList();
5768                         elmContainer = Util.getElementsByClassName( elm, 'viewer-apps' )[ 0 ];
5769                         for( i = 0; i < apps.length; ++i ){
5770                                 button = 0 < tmpButtons.length ? tmpButtons.shift() : new ApplicationButton();
5771                                 button.init( this.ui, elmContainer, apps[ i ], file );
5772                                 this.appButtons.push( button );
5773                         };
5774                         apps         = file.editorApplicationList();
5775                         elmContainer = Util.getElementsByClassName( elm, 'editor-apps' )[ 0 ];
5776                         for( i = 0; i < apps.length; ++i ){
5777                                 button = 0 < tmpButtons.length ? tmpButtons.shift() : new ApplicationButton();
5778                                 button.init( this.ui, elmContainer, apps[ i ], file );
5779                                 this.appButtons.push( button );
5780                         };
5781                         
5782                         while( button = tmpButtons.shift() ) button.destroy();
5783                         
5784                         this.resize();
5785                 },
5786                 pan : function(){
5787                         var page = this,
5788                                 x    = page.currentX = easeOutQuad( page.panTime, page.startX, page.offsetX, page.panTotalTime );
5789                         // page.elm.style.left = x + 'px';
5790                         this.node.x( x );
5791                         if( page.panTotalTime < ++page.panTime ){
5792                                 delete page.panTime;
5793                                 delete page.startX;
5794                                 delete page.offsetX;                                    
5795                                 delete page.panTotalTime;
5796                                 delete page.sliding;
5797                                 if( this.isPanOut === true ) this.elm.style.display = 'none';
5798                         };
5799                 },
5800                 onScroll : function(){
5801                         
5802                 },
5803                 resize : function(){
5804                         this.elmScroll.style.height = this.nodeRoot.height() + 'px';
5805                 },
5806                 destroy : function(){
5807                         var button;
5808                         while( button = this.appButtons.shift() ) button.destroy();
5809                         this.ui.destroy();
5810                         this.node.remove();
5811                 }
5812         });
5813         
5814 /**
5815  * FinderPrivateData
5816  */
5817         var FinderPrivateData = Class.create(
5818                 Class.PRIVATE_DATA, {
5819                 finder       : null,
5820                 apiuser      : null,
5821                 elmRoot      : null,
5822                 nodeRoot     : null,
5823                 elmScroll    : null,
5824                 elmPath      : null,
5825                 nodePath     : null,
5826                 tree         : null,
5827                 onSelect     : null,
5828                 viewerOption : null,
5829                 editorOption : null,
5830                 pathList     : null,
5831                 headH        : 0,
5832                 iconW        : 0,
5833                 iconH        : 0,
5834                 style        : 0,
5835                 pageIcons1   : null,
5836                 pageIcons2   : null,
5837                 panInPage    : null,
5838                 panOutPage   : null,
5839                 pageDetail   : null,
5840                 currentFile  : null,
5841                 Constructor : function( finder, apiuser, elm, tree, onSelect, viewerOption, editorOption ){
5842                         this.finder       = finder;
5843                         this.apiuser      = apiuser;
5844                         if( PointingDeviceEventTree.isNodeInstance( elm ) === true ){
5845                                 this.nodeRoot = elm;
5846                                 this.elmRoot  = PointingDeviceEventTree._getNodePrivateData( elm ).elm;
5847                         } else {
5848                                 // App が eventTree を持っている?
5849                                 // App が eventTree を持っていない
5850                                 this.elmRoot  = elm;
5851                         };
5852                         this.nodeRoot.addEventListener( 'click', this.onIconClick, this );
5853                         this.nodeRoot.addEventListener( 'scroll', this.onScroll, this );
5854                         
5855                         this.elmScroll    = document.createElement( 'div' );
5856                         this.elmRoot.appendChild( this.elmScroll );
5857                         this.elmScroll.className     = 'finder-elm-scroll';
5858                         this.elmScroll.style.cssText = 'width:100%;overflow:hidden;';
5859                         
5860                         this.tree         = tree;
5861                         this.onSelect     = onSelect;
5862                         this.viewerOption = viewerOption;
5863                         this.editorOption = editorOption;
5864                         
5865                         var size          = Util.getElementSize( ELM_ORIGIN_FINDER_ICON );
5866                         this.iconW        = size.width;
5867                         this.iconH        = size.height;
5868                         
5869                         tree.addTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw, this );
5870                         Util.addClass( this.elmRoot, 'finder-body' );
5871                         
5872                         if( this.panInPage === null ){
5873                                 this.pageIcons1 = new PageClass();
5874                                 this.pageIcons2 = new PageClass();
5875                                 this.pageDetail = new DetailPageClass();
5876                         };
5877                         this.pageIcons1.init( this.nodeRoot, this.elmRoot, this.elmScroll );
5878                         this.pageIcons2.init( this.nodeRoot, this.elmRoot, this.elmScroll );
5879                         this.pageDetail.init( this );
5880                 },
5881                 onIconClick : function( e ){
5882                         if( this.panInPage === this.pageDetail ) return;
5883                         
5884                         var target = e.target,
5885                                 list   = this.panInPage.iconList,
5886                                 i, icon,
5887                                 file;
5888                         if( target === this.nodeRoot ) return;
5889                         for( i = list.length; i; ){
5890                                 icon = list[ --i ];
5891                                 if( icon.node === target ){
5892                                         i = icon._index;
5893                                         file = this.currentFile.getChildFileAt( i );
5894                                         if( target.width() - 30 < e.layerX ){
5895                                                 this.tree.down( i );
5896                                                 this.draw( this.w, this.h, 1, true );
5897                                         } else
5898                                         if( file.getChildFileLength() !== -1 || file.getType() === Const.FILE.TYPE.FOLDER ){
5899                                                 this.tree.down( i );
5900                                                 this.draw( this.w, this.h, 1 );
5901                                         } else
5902                                         if( Type.isFunction( this.onSelect ) === true ){ /* && this.onSelect( file ) === true */
5903                                                 this.onSelect( file );
5904                                         } else {
5905                                                 this.tree.down( i );
5906                                                 this.draw( this.w, this.h, 1 );
5907                                         };
5908                                         file.destroy();
5909                                         break;
5910                                 };
5911                         };
5912                 },
5913                 onScroll : function( e ){
5914                         this.panInPage.onScroll( e );
5915                 },
5916                 onPathClick : function( e ){
5917                         var target = e.target,
5918                                 i      = target.nodeIndex();
5919                         if( target === this.nodePath || this.nodePath.numNode() - 1 === i ) return;
5920                         this.tree.up( i );
5921                         this.draw( this.w, this.h, -1 );
5922                 },
5923                 draw : function( w, h, way, showDetail ){
5924                         var data = this, page;
5925                         data.w = w = Type.isFinite( w ) === true ? w : data.w;
5926                         data.h = h = Type.isFinite( h ) === true ? h : data.h;
5927                         
5928                         var file     = this.currentFile = this.tree.getCurrentFile(),
5929                                 isFolder = showDetail !== true && ( file.getChildFileLength() !== -1 || file.getType() === Const.FILE.TYPE.FOLDER );
5930                         
5931                         data.elmPath && data.drawPath( w );
5932                         page = this.panInPage;
5933                         if( Type.isNumber( way ) === true ){
5934                                 if( page.sliding === false ){
5935                                         if( isFolder === true ){
5936                                                 this.panInPage = page === this.pageIcons1 ? this.pageIcons2 : ( page === this.pageIcons2 ? this.pageIcons1 : this.panOutPage );
5937                                         } else {
5938                                                 this.panInPage = this.pageDetail;
5939                                         };
5940                                         this.panOutPage = page;
5941                                 };
5942                                 this.panInPage.panInReady( way );
5943                                 //this.panInPage.elm.className = 'panIN';
5944                                 this.panOutPage.panOutReady( way );
5945                                 //this.panOutPage.elm.className = 'panOut';
5946                                 this.nodeRoot.disabled( true );
5947                                 SystemTimer.add( this.apiuser, this.tick, 16, false, this );
5948                         } else {
5949                                 if( isFolder === true ){
5950                                         this.panInPage = page === null ? this.pageIcons1 : page;
5951                                 } else {
5952                                         this.panInPage = this.pageDetail;
5953                                 };
5954                         };
5955                         this.panInPage.draw( file );
5956                         
5957                         data.nodeRoot.invalidateScrollbar();
5958                 },
5959                 tick : function(){
5960                         if( this.panInPage.sliding === false && this.panOutPage.sliding === false ){
5961                                 SystemTimer.remove( this.apiuser, this.tick );
5962                                 this.nodeRoot.disabled( false );
5963                                 this.nodeRoot.invalidateScrollbar();
5964                                 return;
5965                         };
5966                         this.panInPage.sliding === true && this.panInPage.pan();
5967                         this.panOutPage.sliding  === true && this.panOutPage.pan();
5968                 },
5969                 drawPath : function( w ){
5970                         if( !this.elmPath.parentNode ) return;
5971                         w = this.nodePath.width();
5972                         var data      = this,
5973                                 tree      = data.tree,
5974                                 pathList  = data.pathList,
5975                                 i         = 0,
5976                                 l         = tree.hierarchy() + 1,
5977                                 m         = pathList.length,
5978                                 wList     = [],
5979                                 totalW    = 0,
5980                                 minW      = FinderPrivateData.MIN_PATH_WIDTH,
5981                                 file, path, pathW, offset, remove, pathX = 0, fit = false;
5982                         
5983                         for( ; i < l; ++i ){
5984                                 file = i !== l - 1 ? tree.getParentFileAt( i ) : this.currentFile;
5985                                 if( i < m ){
5986                                         pathList[ i ].init( this, file, i );
5987                                 } else {
5988                                         pathList.push( PathClass.get( this, file, i ) );
5989                                 };
5990                         };
5991                         while( l < pathList.length ) pathList.pop().destroy();
5992                         
5993                         for( i = l; i; ){
5994                                 pathW = pathList[ --i ].textWidth();
5995                                 wList.push( pathW );
5996                                 totalW += pathW;
5997                         };
5998                         
5999                         //if( minW * ( l + 1 ) * 1.2 < w ){
6000                                 console.log( totalW + ' , ' + w )
6001                                 while( true ){
6002                                         if( fit === true ) break;
6003                                         for( i = 0; i < l; ++i ){
6004                                                 offset = totalW - w;
6005                                                 if( offset <= 0 ){
6006                                                         fit = true;
6007                                                         break;
6008                                                 };
6009                                                 remove = l - i;
6010                                                 remove = offset < remove ? offset : remove;
6011                                                 pathW  = wList[ i ];
6012                                                 if( pathW - remove < minW ){
6013                                                         totalW -= ( pathW - minW );
6014                                                         wList[ i ] = minW;
6015                                                 } else {
6016                                                         wList[ i ] = pathW - remove;
6017                                                         totalW -= remove;
6018                                                 };
6019                                         };
6020                                 };
6021                                 for( i = 0; i < l; ++i ){
6022                                         path  = pathList[ i ];
6023                                         pathW = wList[ i ];
6024                                         path.update( pathX, pathW );
6025                                         pathX += pathW;
6026                                 };                      
6027                         //} else {
6028                                 
6029                         //};
6030                 },
6031                 createPath : function( node ){
6032                         if( this.elmPath ) return;
6033                         
6034                         if( PointingDeviceEventTree.isNodeInstance( node ) === true ){
6035                                 this.nodePath = node;
6036                                 this.elmPath  = PointingDeviceEventTree._getNodePrivateData( node ).elm;
6037                                 
6038                                 node.addEventListener( 'click', this.onPathClick, this );
6039                                 Util.addClass( this.elmPath, 'finder-path' );
6040                                 // this.elmPath  = document.createElement( 'div' );
6041                                 // this.elmPath.className = ;
6042                                 this.pathList = [];
6043                                 // this.headH    = 0;
6044                                 AsyncCall.add( this.apiuser, this.draw, null, this );
6045                         };
6046                 },
6047                 onKill : function(){
6048                         this.tree.removeTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw );
6049
6050                         if( this.pathList ){
6051                                 while( this.pathList.length > 0 ) this.pathList.shift().destroy();
6052                         };
6053                         
6054                         this.pageIcons1.destroy();
6055                         this.pageIcons2.destroy();
6056                         this.pageDetail.destroy();
6057                         this.nodeRoot.remove();
6058                         
6059                         FINDER_LIST.splice( Util.getIndex( FINDER_LIST, this.finder ), 1 );
6060                         var data = ApplicationPrivateData.get( this.apiuser ),
6061                                 list = data.finderList,
6062                                 i    = Util.getIndex( list, this.finder );
6063                         i !== -1 && list.splice( i, 1 );
6064                 }
6065         });
6066         FinderPrivateData.MIN_PATH_WIDTH = 25;
6067
6068 /**
6069  * FinderClass
6070  */
6071         var Finder = Class.create(
6072                 FinderPrivateData, {
6073                 Constructor : function( application, elmRoot, tree, onSelect, viewerOption, editorOption ){
6074                         Finder.newPrivateData( this, this, application, elmRoot, tree, onSelect, viewerOption, editorOption );
6075                 },
6076                 MIN_WIDTH  : 200,
6077                 MIN_HEIGHT : 200,
6078                 resize : function( w, h ){
6079                         var data = Finder.getPrivateData( this );
6080                         data.panInPage && data.panInPage.resize( w );
6081                 },
6082                 createPath : function( node ){
6083                         return Finder.getPrivateData( this ).createPath( node );
6084                 },
6085                 destroy : function(){
6086                         this.kill();
6087                 }
6088         });
6089
6090         return {
6091                 init: function(){
6092                         
6093                 },
6094                 create: function( application, elmTarget, tree, onSelect, viewerOption, editorOption ){
6095                         //if( Application.isApplicationInstance( _application ) === false ) return;
6096                         
6097                         var finder = new Finder( application, elmTarget, tree, onSelect, viewerOption, editorOption );
6098                         FINDER_LIST.push( finder );
6099                         return finder;
6100                 },
6101                 registerFinderHead: function(){
6102                         
6103                 },
6104                 registerFinderPane: function( _finderPane ){
6105                         
6106                 },
6107                 isFinderInstance: function( _finder ){
6108                         return _finder instanceof Finder;
6109                 },
6110                 isFinderPaneInstance: function(){
6111                         
6112                 },
6113                 isFinderHeadInstance: function(){
6114                 }
6115         };
6116 })();
6117
6118
6119 /*
6120  * -- len, %
6121  * marginBottom, marginLeft, marginRight, marginTop, margin
6122  * padding, paddingBottom, paddingLeft, paddingRight, paddingTop
6123  * fontSize, textIndent
6124  * height, width
6125  * bottom, left, right, top                     (len, %)
6126  *
6127  * -- len
6128  * borderBottomWidth, borderLeftWidth, borderRightWidth, borderTopWidth, borderWidth,
6129  * letterSpacing
6130  *
6131  * -- color
6132  * backgroundColor
6133  * borderBottomColor, borderLeftColor, borderRightColor, borderTopColor, borderColor
6134  * color
6135  *
6136  * -- special
6137  * clip                 rect(0px, 40px, 40px, 0px);
6138  * backgroundPosition   (len, %)
6139  * opacity
6140  * lineHeight           (len, %, num)
6141  * zIndex                       ( order )
6142  */
6143
6144 var DHTML = ( function(){
6145         
6146         var TICKET_ARRAY = [],
6147                 fpms         = 50,
6148                 round        = Math.round,
6149                 cround       = function( v ){ return round( v * 100 ) / 100 };
6150         
6151         function startAnimation( _elm, _cssObject, _onComplete, _onEnterFrame, _numFrames ){
6152                 var _ticket, i = TICKET_ARRAY.length;
6153                 for( ; i; ){
6154                         _ticket = TICKET_ARRAY[ --i ];
6155                         if( _ticket.elm === _elm ){
6156                                 return;
6157                         };
6158                 };
6159                 
6160                 var _currentValues     = [],
6161                         _offsetValues      = [],
6162                         _endValues         = [],
6163                         _targetProperties  = [],
6164                         _units             = [];
6165                 var target, current,
6166                         inlineStyle    = CSS.getInlineStyle( _elm ),
6167                         currentStyle   = CSS.getWrappedStyle( _elm ),
6168                         targetStyle    = CSS.getWrappedStyle( _elm, _cssObject );
6169                         targetStyle.pxPerEm = currentStyle.get( 'fontSize' )._toPx();
6170                 for( var p in _cssObject ){
6171                         p       = Util.camelize( p );
6172                         target  = targetStyle.get( p );
6173                         current = currentStyle.get( p );
6174
6175                         if( target.isValid() === false || current.isValid() === false || current.equal( target ) !== false ){
6176                                 target.clear();
6177                                 current.clear();
6178                                 continue;
6179                         };
6180                         
6181                         current.convert( target );
6182                         // alert( current.getValue() + ' , ' + target.getValue() )
6183                         _currentValues.push( current.getValue() );
6184                         _offsetValues.push( current.getOffset( target ) );
6185                         _endValues.push( target.getValue() );
6186                         _targetProperties.push( p );
6187                         _units.push( target.getUnit() );
6188
6189                         // IE has trouble with opacity if it does not have layout
6190                         // Force it by setting the zoom level                   
6191                         if( p === 'opacity' && SPECIAL.hasLayout ){
6192                                 if( SPECIAL.hasLayout( _elm ) === false ) inlineStyle.zoom = 1;
6193                                 inlineStyle.filter = current.getValueText();
6194                         } else {
6195                                 inlineStyle[ p ]   = current.getValueText();
6196                         };
6197                         
6198                         target.clear();
6199                         current.clear();
6200                 };
6201                 
6202                 var i, cssTexts = [];
6203                 for( i = 0; i < _numFrames; ++i ){
6204                         if( i < _numFrames - 1 ){
6205                                 tickValue( _currentValues, _offsetValues, _numFrames );
6206                                 cssTexts.push( createCssText( _currentValues, _targetProperties, targetStyle, inlineStyle ) );
6207                         } else {
6208                                 cssTexts.push( createCssText( _endValues, _targetProperties, targetStyle, inlineStyle ) );
6209                         };
6210                 };
6211                 
6212                 TICKET_ARRAY.push( new AnimationTaskClass(
6213                         _elm, cssTexts,
6214                         Type.isFunction( _onComplete ) === true   ? _onComplete   : null,
6215                         Type.isFunction( _onEnterFrame ) === true ? _onEnterFrame : null,
6216                         _numFrames
6217                 ) );
6218                 
6219                 currentStyle.clear();
6220                 targetStyle.clear();            
6221                 SystemTimer.add( SUPER_USER_KEY, onEnterFrame, 1000 / fpms );
6222         };
6223         
6224         function tickValue( current, offset, numFrames ){
6225                 if( Type.isArray( current ) === true ){
6226                         var ret, i = current.length;
6227                         for( ; i; ){
6228                                 --i;
6229                                 ret = tickValue( current[ i ], offset[ i ], numFrames );
6230                                 if( Type.isNumber( ret ) === true ) current[ i ] = ret;
6231                         };
6232                 } else {
6233                         return current + offset / numFrames;
6234                 };
6235         };
6236         function createCssText( update, props, style, inline ){
6237                 var prop;
6238                 for( var i = props.length; i; ){
6239                         prop = style.get( props[ --i ] );
6240                         prop.setValue( update[ i ] );
6241                         inline[ Util.uncamelize( prop.name ) ] = prop.getValueText();
6242                         //if( prop.name === 'backgroundColor' ) alert( prop.getValueText() + '|' + update[ i ].join( ',') )
6243                         prop.clear();
6244                 };
6245                 return CSS.toCssText( inline );
6246         };
6247         
6248         function onEnterFrame(){
6249                 var _ticket, l,
6250                         i = 0;
6251                 while( i < TICKET_ARRAY.length ){
6252                         _ticket = TICKET_ARRAY[ i ];
6253                         l       = _ticket.cssTexts.length;
6254                         _ticket.elm.style.cssText = _ticket.cssTexts.shift();
6255                         if( l === 1 ){
6256                                 _ticket.onComplete && _ticket.onComplete();
6257                                 delete _ticket.elm;
6258                                 delete _ticket.cssTexts;
6259                                 delete _ticket.onComplete;
6260                                 delete _ticket.onEnterFrame;
6261                                 delete _ticket.numFrame;
6262                                 TICKET_ARRAY.splice( i, 1 );
6263                         } else {
6264                                 _ticket.onEnterFrame && _ticket.onEnterFrame( l / _ticket.numFrame );
6265                                 ++i;
6266                         };
6267                 };
6268                 if( TICKET_ARRAY.length === 0 ){
6269                         SystemTimer.remove( SUPER_USER_KEY, onEnterFrame );
6270                 };
6271         };
6272         
6273         var AnimationTaskClass = function( elm, cssTexts, onEnterFrame, onComplete, numFrame ){
6274                 this.elm          = elm;
6275                 this.cssTexts     = cssTexts;
6276                 this.onEnterFrame = onEnterFrame;
6277                 this.onComplete   = onComplete;
6278                 this.numFrame     = numFrame;
6279         };
6280         
6281         var VisualEffectClass = function( elm ){
6282                 this.elm = elm;
6283         };
6284         VisualEffectClass.prototype = {
6285                 anime : function( _cssObject, _onComplete, _onEnterFrame, _time ){
6286                         var _numFrames = Math.floor( _time / fpms );
6287                         startAnimation( this.elm, _cssObject, _onComplete, _onEnterFrame, _numFrames );
6288                 },
6289                 fadeIn : function(){
6290                         
6291                 },
6292                 fadeOut : function(){
6293                         
6294                 },
6295                 update : function( x, y, w, h ){
6296                         var _cssText = this.elm.style.cssText;
6297                 }
6298         };
6299         
6300         return {
6301                 create: function( application, _elm ){
6302                         return new VisualEffectClass( _elm );
6303                 },
6304                 isInstanceOfVisualEffect: function( _instance){
6305                         return _instance instanceof VisualEffectClass;
6306                 }
6307         }
6308 })();
6309
6310
6311 /* --------------------------------------------
6312  * 
6313  */
6314
6315         Application.onCurrentApplicationChange( SUPER_USER_KEY );
6316         
6317         SERVICE_LIST.push( MouseEvent );
6318         
6319         new EventTicketClass( window, 'unload', function(){
6320                 var _service;
6321                 while( SERVICE_LIST.length > 0 ){
6322                         _service = SERVICE_LIST.shift();
6323                         Type.isFunction( _service.onSystemShutdown ) === true && _service.onSystemShutdown();
6324                 }
6325         });
6326         // beforeunload
6327
6328
6329 /* ---------------------------------------------
6330  * broadcast to global
6331  */
6332         window.gOS = {};
6333         
6334         gOS.registerApplication = Application.register;
6335         gOS.registerDriver      = File.registerDriver;
6336         
6337 var BoxModel
6338
6339 var DOM = ( function( window, document ){
6340         var DIV_LIST  = [],
6341                 SPAN_LIST = [],
6342                 TEXT_LIST = [];
6343         
6344         var elmTextSize;
6345         
6346         function correctNodes( node ){
6347                 var child;
6348                 if( node && node.parentNode ){
6349                         while( node.lastChild ) correctNodes( node.lastChild );
6350                         node.parentNode.removeChild( node );
6351                         if( node.nodeType === 1 ){
6352                                 switch( node.tagName ){
6353                                         case 'DIV':
6354                                                 DIV_LIST.push( node );
6355                                                 break;
6356                                         case 'SPAN':
6357                                                 SPAN_LIST.push( node );
6358                                                 break;
6359                                         
6360                                 };
6361                                 node.removeAttribute( 'className' );
6362                                 node.removeAttribute( 'style' );
6363                                 node.removeAttribute( 'id' );
6364                         } else
6365                         if( node.nodeType === 3 ){
6366                                 node.data = '';
6367                                 TEXT_LIST.push( node );
6368                         };
6369                 };
6370         };
6371         
6372         return {
6373                 createDiv : function(){
6374                         return 0 < DIV_LIST.length ? DIV_LIST.shift() : document.createElement( 'div' );
6375                 },
6376                 createSpan : function(){
6377                         
6378                 },
6379                 createText : function(){
6380                         
6381                 },
6382                 getTextSize : function( elm, content ){
6383                         var span = DOM.createSpan(),
6384                                 text = DOM.createText(),
6385                                 w, h;
6386                         elm.appendChild( span );
6387                         span.style.cssText = 'visibility:hidden;position:absolute;';
6388                         span.appendChild( text );
6389                         text.data = content;
6390                         w = span.offsetWidth;
6391                         h = span.offsetHeight;
6392                         DOM.correctNodes( span );
6393                         return [ w, h ];
6394                 },
6395                 correctNodes : function( node ){
6396                         var child;
6397                         if( node && node.parentNode ){
6398                                 while( node.lastChild ) DOM.correctNodes( node.lastChild );
6399                                 node.parentNode.removeChild( node );
6400                                 if( node.nodeType === 1 ){
6401                                         switch( node.tagName ){
6402                                                 case 'DIV':
6403                                                         DIV_LIST.push( node );
6404                                                         break;
6405                                                 case 'SPAN':
6406                                                         SPAN_LIST.push( node );
6407                                                         break;
6408                                                 
6409                                         };
6410                                         node.removeAttribute( 'className' );
6411                                         node.removeAttribute( 'style' );
6412                                         node.removeAttribute( 'id' );
6413                                 } else
6414                                 if( node.nodeType === 3 ){
6415                                         node.data = '';
6416                                         TEXT_LIST.push( node );
6417                                 };
6418                         };
6419                 }
6420         }
6421 })( window, document );
6422
6423 var XBrowserStyle = ( function(){
6424         var     EMPTY          = '',
6425                 CORON          = ':',
6426                 SEMICORON      = ';',
6427                 SPACE          = ' ',
6428                 UNITS          = 'px,cm,mm,in,pt,pc,em,%'.split( ',' ),
6429                 CLIP_SEPARATOR = UA.isIE === true && UA.ieVersion < 8 ? ' ' : ',';
6430
6431         var SPECIAL = ( function(){
6432                 var special = {};
6433                 if( UA.isIE === true && UA.ieVersion < 9 ){
6434                         if( UA.ACTIVEX === true ){
6435                                 // special.opacity    = 'ActiveXOpacity';
6436                                 special.setFilters = function( style ){
6437                                         var filters = ( style.filter || '' ).split( ') ' ),
6438                                                 data    = {},
6439                                                 i       = filters.length,
6440                                                 filter, names, props, prop, j, l, key, v;
6441                                         for( ; i; ){
6442                                                 filter   = filters[ --i ].split( ' ' ).join( '' ).split( '(' );
6443                                                 if( filter.length !== 2 ) continue;
6444                                                 names    = filter[ 0 ].split( '.' ); // progid:DXImageTransform.Microsoft.Shadow(color=#666666,direction=120,strength=9)
6445                                                 props    = filter[ 1 ].split( ',' ); // 
6446                                                 filter   = {};
6447                                                 for( j = 0, l = props.length; j < l; ++j ){
6448                                                         prop = props[ j ].split( '=' );
6449                                                         key  = prop[ 0 ].toLowerCase();
6450                                                         v    = prop[ 1 ];
6451                                                         filter[ key ] = v; //v.charAt( 0 ) === '#' ? v : parseInt( v );
6452                                                 };
6453                                                 data[ names[ names.length - 1 ] ] = filter;
6454                                         };
6455                                         
6456                                         style.filter  = data;
6457                                         style.opacity = data.alpha && data.alpha.opacity ? data.alpha.opacity / 100 : 1;
6458                                 };
6459                                 special.hasLayout = function( elm ){
6460                                         return elm.currentStyle.hasLayout;
6461                                 };
6462                         } else {
6463                                 special.opacity = null;
6464                         };
6465                 } else {
6466                         var style = document.documentElement.style;
6467                         special.opacity = style.opacity           !== undefined ? 'opacity' : 
6468                                                         style.MozOpacity          !== undefined ? 'MozOpacity' :
6469                                                         style.KhtmlOpacity        !== undefined ? 'KhtmlOpacity' :
6470                                                         style[ '-khtml-opacity' ] !== undefined ? 'KhtmlOpacity' : null;
6471
6472                         // if( style.backgroundPositionX === undefined ){
6473                                 special.setBackgroundPositionXY = function( style ){
6474                                         var bgp = ( style.backgroundPosition || '' ).split( ' ' );
6475                                         style.backgroundPositionX = bgp[ 0 ] || 0;
6476                                         style.backgroundPositionY = bgp[ 1 ] || 0;
6477                                 };
6478                         // };
6479                         if( style.clipTop === undefined && style[ 'clip-top' ] === undefined ){
6480                                 special.setClipTopRightBottomLeft = function( style ){
6481                                         var clip = style.clip;
6482                                         if( !cliop || clip.indexOf( 'rect(' ) === -1 ){
6483                                                 style.clipTop    = 0;
6484                                                 style.clipRight  = 0;
6485                                                 style.clipBottom = 0;
6486                                                 style.clipLeft   = 0;
6487                                                 return;
6488                                         };
6489                                         clip = clip.split( '(' )[ 1 ].split( ')' )[ 0 ].split( clip.indexOf( ',' ) !== -1 ? ',' : ' ' );
6490                                         ret.clipTop    = clip[ 0 ];
6491                                         ret.clipRight  = clip[ 1 ];
6492                                         ret.clipBottom = clip[ 2 ];
6493                                         ret.clipLeft   = clip[ 3 ];
6494                                 };
6495                         };
6496                 };
6497                 return special;
6498         })();
6499         
6500         function cssToObject( css ){
6501                 var ret      = {}, i, nv, n, v,
6502                         parse    = Util.parse,
6503                         isNumber = Type.isNumber,
6504                         camelize = Util.camelize;
6505                 if( Type.isString( css ) === true ){
6506                         css = css.split( SEMICORON );
6507                         for( i = css.length; i; ){
6508                                 nv = css[ --i ].split( CORON ); // filter の場合, progid: がくる
6509                                 n  = nv.shift();
6510                                 if( isNumber( parse( n ) ) === true ) continue;
6511                                 v  = nv.join( EMPTY );
6512                                 while( v.charAt( 0 ) === ' ' ) v = v.substr( 1 );
6513                                 ret[ camelize( n ) ] = parse( v );
6514                         };
6515                 } else {
6516                         for( n in css ){
6517                                 if( Type.isNumber( parse( n ) ) === false ) ret[ n ] = parse( css[ n ] );
6518                         };
6519                 };
6520
6521                 if( SPECIAL.setFilters ){
6522                         SPECIAL.setFilters( ret );
6523                 } else {
6524                         ret.opacity = SPECIAL.opacity !== null ? ret[ SPECIAL.opacity ] : 1;
6525                 };
6526                 
6527                 SPECIAL.setBackgroundPositionXY && SPECIAL.setBackgroundPositionXY( ret );
6528                 SPECIAL.setClipTopRightBottomLeft && SPECIAL.setClipTopRightBottomLeft( ret );
6529                 
6530                 return ret;
6531         };
6532
6533         var COLOR = ( function(){
6534                 var ret = {}, v, name,
6535                         list = [
6536                                 '0', 'BLACK',
6537                                 'FF0000', 'RED',
6538                                 '00FF00', 'LIME',
6539                                 '0000FF', 'BLUE',
6540                                 'FFFF00', 'YELLOW',
6541                                 '00FFFF', 'AQUA',
6542                                 '00FFFF', 'CYAN',
6543                                 'FF00FF', 'MAGENTA',
6544                                 'FF00FF', 'FUCHSIA',
6545                                 'FFFFFF', 'WHITE',
6546                                 '008000', 'GREEN',
6547                                 '800080', 'PURPLE',
6548                                 '800000', 'MAROON',
6549                                 '000080', 'NAVY',
6550                                 '808000', 'OLIVE',
6551                                 '008080', 'TEAL',
6552                                 '808080', 'GRAY',
6553                                 'C0C0C0', 'SILVER',
6554                                 '696969', 'DIMGRAY',
6555                                 '708090', 'SLATEGRAY',
6556                                 'A9A9A9', 'DARKGRAY',
6557                                 'DCDCDC', 'GAINSBORO',
6558                                 '191970', 'MIDNIGHTBLUE',
6559                                 '6A5ACD', 'SLATEBLUE',
6560                                 '0000CD', 'MEDIUMBLUE',
6561                                 '4169E1', 'ROYALBLUE',
6562                                 '1E90FF', 'DODGERBLUE',
6563                                 '87CEEB', 'SKYBLUE',
6564                                 '4682B4', 'STEELBLUE',
6565                                 'ADD8E6', 'LIGHTBLUE',
6566                                 'AFEEEE', 'PALETURQUOISE',
6567                                 '40E0D0', 'TURQUOISE',
6568                                 'E0FFFF', 'LIGHTCYAN',
6569                                 '7FFFD4', 'AQUAMARINE',
6570                                 '006400', 'DARKGREEN',
6571                                 '2E8B57', 'SEAGREEN',
6572                                 '90EE90', 'LIGHTGREEN',
6573                                 '7FFF00', 'CHARTREUSE',
6574                                 'ADFF2F', 'GREENYELLOW',
6575                                 '32CD32', 'LIMEGREEN',
6576                                 '9ACD32', 'YELLOWGREEN',
6577                                 '6B8E23', 'OLIVEDRAB',
6578                                 'BCB76B', 'DARKKHAKI',
6579                                 'EEE8AA', 'PALEGOLDENROD',
6580                                 'FFFFE0', 'LIGHTYELLOW',
6581                                 'FFD700', 'GOLD',
6582                                 'DAA520', 'GOLDENROD',
6583                                 'B8860B', 'DARKGOLDENROD',
6584                                 'BC8F8F', 'ROSYBROWN',
6585                                 'CD5C5C', 'INDIANRED',
6586                                 '8B4513', 'SADDLEBROWN',
6587                                 'A0522D', 'SIENNA',
6588                                 'CD853F', 'PERU',
6589                                 'DEB887', 'BURLYWOOD',
6590                                 'F5F5DC', 'BEIGE',
6591                                 'F5DEB3', 'WHEAT',
6592                                 'F4A460', 'SANDYBROWN',
6593                                 'D2B48C', 'TAN',
6594                                 'D2691E', 'CHOCOLATE',
6595                                 'B22222', 'FIREBRICK',
6596                                 'A52A2A', 'BROWN',
6597                                 'FA8072', 'SALMON',
6598                                 'FFA500', 'ORANGE',
6599                                 'FF7F50', 'CORAL',
6600                                 'FF6347', 'TOMATO',
6601                                 'FF69B4', 'HOTPINK',
6602                                 'FFC0CB', 'PINK',
6603                                 'FF1493', 'DEEPPINK',
6604                                 'DB7093', 'PALEVIOLETRED',
6605                                 'EE82EE', 'VIOLET',
6606                                 'DDA0DD', 'PLUM',
6607                                 'DA70D6', 'ORCHILD',
6608                                 '9400D3', 'DARKVIOLET',
6609                                 '8A2BE2', 'BLUEVIOLET',
6610                                 '9370DB', 'MEDIUMPURPLE',
6611                                 'D8BFD8', 'THISTLE',
6612                                 'E6E6FA', 'LAVENDER',
6613                                 'FFE4E1', 'MISTYROSE',
6614                                 'FFFFF0', 'IVORY',
6615                                 'FFFACD', 'LEMONCHIFFON'
6616                         ];
6617                 for( i = list.length; i; ){
6618                         v    = list[ --i ];
6619                         name = list[ --i ];
6620                         ret[ name ] = parseInt( v, 16 );
6621                 };
6622                 return ret;
6623         })();
6624         
6625         var PARAMS = ( function(){
6626                 var ret = {};
6627                 register( ret.percent = {},
6628                         'marginBottom,marginLeft,marginRight,marginTop,paddingBottom,paddingLeft,paddingRight,paddingTop,fontSize,textIndent'
6629                 );
6630                 register( ret.offset = {},
6631                         'height,width,bottom,left,right,top'
6632                 );              
6633                 register( ret.size = {},
6634                         'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth,letterSpacing'
6635                 );
6636                 register( ret.color = {},
6637                         'backgroundColor,borderBottomColor,borderLeftColor,borderRightColor,borderTopColor,color'
6638                 );
6639                 register( ret.region = {},
6640                         'margin,padding,borderWidth,borderColor'
6641                 );              
6642                 register( ret.special = {},
6643                         'clip,backgroundPosition,opacity,lineHeight,zIndex'
6644                 );
6645                 register( ret.unit = {}, 'px,cm,mm,in,pt,pc,em,%' );
6646                 
6647                 register( ret.margin = {}, 'marginBottom,marginLeft,marginRight,marginTop,paddingBottom' );
6648                 register( ret.padding = {}, 'paddingBottom,paddingLeft,paddingRight,paddingTop' );
6649                 register( ret.borderWidth = {}, 'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth' );
6650                 register( ret.borderColor = {}, 'borderBottomColor,borderLeftColor,borderRightColor,borderTopColor' );
6651                 
6652                 function register( obj, params ){
6653                         params = params.split( ',' );
6654                         for( var i=params.length; i; ) obj[ params[ --i ] ] = true;
6655                 };
6656                 return ret;
6657         })();
6658         
6659         /*
6660          * 
6661          */
6662         var Property = Class.create(
6663                 'Property',
6664                 Class.POOL_OBJECT,
6665                 {
6666                         Constructor : function( name, value, unit, pxPerEm ){
6667                                 this.name    = name;
6668                                 this.value   = value;
6669                                 this.unit    = unit;
6670                                 this.pxPerEm = pxPerEm; // XXpx = 1em;
6671                         },
6672                         name    : '',
6673                         value   : 0,
6674                         pxPerEm : 12, // 1em === ??px
6675                         unit    : '',
6676                         equal : function( prop ){
6677                                 if( this.unit === prop.unit ){
6678                                         return this.value === prop.value;
6679                                 };
6680                                 return Math.abs( this.toPx() - prop.toPx() ) < 1;
6681                         },
6682                         convert: function( prop ){
6683                                 var u = prop.unit, v;
6684                                 if( this.unit === u ) return;
6685                                 this.value = v = this.toPx();
6686                                 this.unit  = u;
6687                                 if( u !== px ){
6688                                         this.value = u === 'em' ? v / this.pxPerEm : Util.pxTo( v, u );
6689                                 };
6690                         },
6691                         setValue: function( v ){
6692                                 this.value = v;
6693                         },
6694                         getValue: function(){
6695                                 return this.value;
6696                         },
6697                         getOffset: function( prop ){
6698                                 return prop.value - this.value;
6699                         },
6700                         getUnit: function(){
6701                                 return this.unit;
6702                         },
6703                         getValueText: function(){
6704                                 return this.value === 0 ? '0' : this.value + this.unit;
6705                         },
6706                         toPx: function(){
6707                                 var v = this.value, u = this.unit;
6708                                 if( u === px )   return v;
6709                                 if( u === 'em' ) return v * this.pxPerEm;
6710                                 if( u === '' && this.name === 'lineHeight' ) return v * this.pxPerEm;
6711                                 return Util.toPx( v, u );
6712                         },
6713                         isValid: function( t ){
6714                                 t = t || this;
6715                                 var n = t.name,
6716                                         v = t.value,
6717                                         u = t.unit,
6718                                         z = u !== '' ? true : v === 0;
6719                                 if( PARAMS.percent[ n ] === true ) return z;
6720                                 if( PARAMS.offset[ n ] === true  ) return z;
6721                                 if( PARAMS.size[ n ] === true  )   return z && u !== '%';
6722                                 if( PARAMS.special[ n ] === true  ){
6723                                         if( n === 'lineHeight' ) return true;
6724                                         if( n === 'opacity' )    return 0 <= v && v <= 1 && u === '';
6725                                         if( n === 'zIndex'  )    return u === '';
6726                                 };
6727                                 return false;
6728                         }
6729                 }
6730         );
6731         
6732         /**
6733          * backgroundPosition, clip
6734          */
6735         var PropertyGroup = Class.create(
6736                 'PropertyGroup',
6737                 Class.POOL_OBJECT,
6738                 {
6739                         Constructor : function( name ){
6740                                 this.name  = name;
6741                                 this.props = [];
6742                                 for( var i = 1, l = arguments.length; i<l; ++i ){
6743                                         this.props.push( arguments[ i ] );
6744                                 };
6745                         },
6746                         name  : '',
6747                         equal : function( prop ){
6748                                 var ps = this.props, i = ps.length;
6749                                 for( ; i; ){
6750                                         --i;
6751                                         if( ps[ i ].equal( prop[ i ] ) === false ) return false;
6752                                 };
6753                                 return true;
6754                         },
6755                         convert : function( prop ){
6756                                 var ps = this.props, i = ps.length;
6757                                 for( ; i; ){
6758                                         --i;
6759                                         ps[ i ].convert( prop[ i ] );
6760                                 };
6761                         },
6762                         setValue : function( ary ){
6763                                 var ps = this.props, i = 0, l = ps.length;
6764                                 for( ; i<l; ++i ){
6765                                         ps[ i ].setValue( ary[ i ] );
6766                                 };
6767                         },
6768                         getValue : function(){
6769                                 var ret = [], ps = this.props, i = 0, l = ps.length;
6770                                 for( ; i<l; ++i ){
6771                                         ret.push( ps[ i ].getValue() );
6772                                 };
6773                                 return ret;
6774                         },
6775                         getOffset : function( prop ){
6776                                 var ret = [],
6777                                         ps  = this.props,
6778                                         _ps = prop.props,
6779                                         i   = 0,
6780                                         l = ps.length;
6781                                 for( ; i<l; ++i ){
6782                                         ret.push( ps[ i ].getOffset( _ps[ i ] ) );
6783                                 };
6784                                 return ret;
6785                         },
6786                         getUnit : function(){
6787                                 var ret = [], ps = this.props, i = 0, l = ps.length;
6788                                 for( ; i<l; ++i ){
6789                                         ret.push( ps[ i ].getUnit() );
6790                                 };
6791                                 return ret;
6792                         },
6793                         getValueText : function(){
6794                                 var ret = [], ps = this.props, i = 0, l = ps.length;
6795                                 for( ; i<l; ++i ){
6796                                         ret.push( ps[ i ].getValueText() );
6797                                 };                      
6798                                 if( this.name === 'clip' ){
6799                                         return 'rect(' + ret.join( CLIP_SEPARATOR ) + ')';
6800                                 };
6801                                 return ret.join( ' ' );
6802                         },
6803                         onKill : function(){
6804                                 var ps = this.props, i = ps.length;
6805                                 for( ; i; ){
6806                                         ps[ --i ].kill();
6807                                 };
6808                         },
6809                         isValid : function( t ){
6810                                 t = t || this;
6811                                 var ps = t.props, i = ps.length;
6812                                 for( ; i; ){
6813                                         if( ps[ --i ].isValid() === false ) return false;
6814                                 };
6815                                 return true;
6816                         }
6817                 }
6818         );
6819         
6820         /**
6821          * margin, padding, borderWidth, borderColor
6822          */
6823         var FrexibleProperty = PropertyGroup.inherits(
6824                 'FrexibleProperty',
6825                 Class.POOL_OBJECT, {
6826                         Constructor : function( name ){
6827                                 this.name  = name;
6828                                 this.props = [];
6829                                 for( var i = 1, l = arguments.length; i<l; ++i ){
6830                                         this.props.push( arguments[ i ] );
6831                                 };
6832                                 // top, bottom, left, right, topbottom, leftright, all                          
6833                         }
6834                 }
6835         );
6836
6837         var ColorProperty = Class.create(
6838                 'ColorProperty',
6839                 Class.POOL_OBJECT, {
6840                         Constructor : function( name, r, g, b, pct ){
6841                                 this.name = name;
6842                                 this.r    = r;
6843                                 this.g    = g;
6844                                 this.b    = b;
6845                                 this.pct  = pct;
6846                         },
6847                         name  : '',
6848                         equal : function( prop ){
6849                                 if( this.pct === prop.pct ){
6850                                         return this.r === prop.r && this.g === prop.g && this.b === prop.b;
6851                                 };
6852                                 var rgb  = this._toPct(),
6853                                         _rgb = prop._toPct(),
6854                                         i    = rgb.length;
6855                                 for( ; i; ){
6856                                         --i;
6857                                         if( Math.abs( rgb[ i ] - _rgb[ i ] ) > 1 ) return false;
6858                                 };
6859                                 return true;
6860                         },
6861                         convert : function( prop ){
6862                                 var u = prop.pct, x;
6863                                 if( this.pct === u ) return;
6864                                 x = u === true ? 100 / 255 : 2.55;
6865                                 this.r  *= x;
6866                                 this.g  *= x;
6867                                 this.b  *= x;
6868                                 this.pct = u;
6869                         },
6870                         setValue : function( rgb ){
6871                                 this.r = rgb[ 0 ];
6872                                 this.g = rgb[ 1 ];
6873                                 this.b = rgb[ 2 ];
6874                         },
6875                         getValue : function(){
6876                                 return [ this.r, this.g, this.b ];
6877                         },
6878                         getOffset : function( prop ){
6879                                 return [ prop.r - this.r, prop.g - this.g, prop.b - this.b ];
6880                         },
6881                         getUnit : function(){
6882                                 return this.pct === true ? '%' : '';
6883                         },
6884                         getValueText : function(){
6885                                 if( this.pct === true ){
6886                                         return [ 'rgb(', this.r, '%,', this.g, '%,', this.b, '%)' ].join( '' );
6887                                 };
6888                                 var round = Math.round;
6889                                 //return [ 'rgb(', round( this.r ), ',', round( this.g ), ',', round( this.b ), ')' ].join( '' );
6890                                 
6891                                 var rgb   = '00000' + ( ( round( this.r ) << 16 ) + ( round( this.g ) << 8 ) + round( this.b ) ).toString( 16 );
6892                                 return '#' + rgb.substr( rgb.length - 6 );
6893                         },
6894                         _toPct : function(){
6895                                 if( this.pct === true ) return [ this.r, this.g, this.b ];
6896                                 return [ this.r / 2.55, this.g / 2.55, this.b / 2.55 ];
6897                         },
6898                         isValid : function( t ){
6899                                 var isFinite = window.isFinite;
6900                                 if( !isFinite( this.r ) || !isFinite( this.g ) || !isFinite( this.b ) ) return false;
6901                                 if( 0 > this.r || 0 > this.g || 0 > this.b ) return false;
6902                                 if( this.pct === true ) return this.r <= 100 && this.g <= 100 && this.b <= 100;
6903                                 return this.r <= 255 && this.g <= 255 && this.b <= 255;
6904                         }
6905                 }
6906         );
6907         
6908         var isString       = Type.isString,
6909                 isNumber       = Type.isNumber;
6910         var REG_UINIT      = /.*\d(\w{1,2})?/,
6911                 $1             = '$1',
6912                 px             = 'px',
6913                 REG_XXXXXX     = /^#[\da-fA-F]{6}?/,
6914                 REG_XXX        = /^#[\da-fA-F]{3}?/;
6915         
6916         var WrappedStyle = Class.create(
6917                 'WrappedStyle',
6918                 Class.POOL_OBJECT,
6919                 {
6920                         Constructor : function( style ){
6921                                 this.style   = style;
6922                                 var fontsize = this.get( 'fontSize' );
6923                                 this.pxPerEm = fontsize.toPx();
6924                                 fonstsize.kill();
6925                         },
6926                         get: function( p ){
6927                                 if( PARAMS.special[ p ] === true || PARAMS.region[ p ] === true ){
6928                                         if( p === 'clip' )        return this.getClip();
6929                                         if( p === 'margin' )      return this.getMarginPaddingBorder( p, '' );
6930                                         if( p === 'padding' )     return this.getMarginPaddingBorder( p, '' );
6931                                         if( p === 'borderWidth' ) return this.getMarginPaddingBorder( 'border', 'Width' );
6932                                         if( p === 'borderColor' ) return this.getBorderColor( 'borderColor' );
6933                                         if( p === 'backgroundPosition' ) return this.getBackgroundPosition( p );
6934                                         // opacity, zindex, lineHeight
6935                                         return new Property( p, this.getValue( x ), this.getUnit( x ), this.pxPerEm );
6936                                 };
6937                                 var x = this.style[ p ], e, v, u;
6938                                 if( PARAMS.offset[ p ] === true ){
6939                                         return new Property( p, this.getValue( x ), this.getUnit( x, p ), this.pxPerEm );
6940                                         /*
6941                                         e = this.elm;
6942                                         if( p === 'width'  ) v = e.offsetWidth;
6943                                         if( p === 'height' ) v = e.offsetHeight;
6944                                         if( p === 'top'    ) v = e.offsetTop;
6945                                         if( p === 'bottom' ) v = e.offsetBottom;
6946                                         if( p === 'left'   ) v = e.offsetLeft;
6947                                         if( p === 'right'  ) v = e.offsetRight;
6948                                         u = this.getUnit( x, p );
6949                                         // alert( p + this.pxTo( v, u ) + u )
6950                                         return new Property( p, this.pxTo( v, u ), u, this.pxPerEm ); */
6951                                 };
6952                                 if( p === 'fontSize' ){ // xx-small 等
6953                                         v = Util.absoluteFontSizeToPx( x );
6954                                         if( v !== 0 ){
6955                                                 return new Property( p, v, px, this.pxPerEm );
6956                                         };
6957                                 };                      
6958                                 if( PARAMS.percent[ p ] === true ){
6959                                         // alert( p + ' , ' + x + ' , ' + this.getUnit( x, p ) )
6960                                         return new Property( p, this.getValue( x ), this.getUnit( x, p ), this.pxPerEm );
6961                                 };
6962                                 if( PARAMS.size[ p ] === true ){
6963                                         return new Property( p, this.getValue( x ), this.getUnit( x, p ), this.pxPerEm );
6964                                 };
6965                                 if( PARAMS.color[ p ] === true ){
6966                                         return this.getColor( x, p );
6967                                 };
6968                         },
6969                         pxTo: function( px, unit ){
6970                                 if( unit === 'em' ) return px / this.pxPerEm;
6971                                 return Util.pxTo( px, unit );
6972                         },
6973                         getValue: function( x ){
6974                                 return isString( x ) === true ? parseInt( x ) :
6975                                        isNumber( x ) === true ? x : 0;
6976                         },
6977                         getUnit: function( x, p ){
6978                                 var u;
6979                                 if( isString( x ) === true ){
6980                                         u = x.replace( REG_UINIT, $1 );
6981                                         if( p === 'lineHeight' ) return u;
6982                                         if( PARAMS.unit[ u ] !== true ) return px;
6983                                         return u;
6984                                 };
6985                                 return px;
6986                         },
6987                         getColor: function( x, p ){
6988                                 var rgb = COLOR[ x.toUpperCase() ],
6989                                         pct = false,
6990                                         r   = 0,
6991                                         g   = 0,
6992                                         b   = 0;
6993                                 if( isNumber( rgb ) === true ){
6994                                         r = ( rgb & 0xff0000 ) >> 16;
6995                                         g = ( rgb & 0xff00 ) >> 8;
6996                                         b = ( rgb & 0xff );
6997                                 } else
6998                                 if( x.match( REG_XXXXXX ) ){
6999                                         r = parseInt( x.charAt( 1 ) + x.charAt( 2 ), 16 );
7000                                         g = parseInt( x.charAt( 3 ) + x.charAt( 4 ), 16 );
7001                                         b = parseInt( x.charAt( 5 ) + x.charAt( 6 ), 16 );
7002                                         //alert( x + ' g: ' + g )
7003                                 } else                  
7004                                 if( x.match( REG_XXX ) ){
7005                                         r = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
7006                                         g = parseInt( x.charAt( 2 ) + x.charAt( 2 ), 16 );
7007                                         b = parseInt( x.charAt( 3 ) + x.charAt( 3 ), 16 );
7008                                 } else
7009                                 if( x.indexOf( 'rgb(' ) === 0 ){
7010                                         rgb = x.substr( 4 ).split( ',' );
7011                                         r = parseFloat( rgb[ 0 ] );
7012                                         g = parseFloat( rgb[ 1 ] );
7013                                         b = parseFloat( rgb[ 2 ] );
7014                                         if( x.indexOf( '%' ) !== -1 ) pct = true;
7015                                 } else {
7016                                         r = 255;
7017                                         g = 255;
7018                                         b = 255;
7019                                 };
7020                                 return new ColorProperty( p, r, g, b, pct );
7021                         },
7022                         getClip: function( name ){
7023                                 // rect(...)    クリップします。<top>, <bottom> は上端からの、 <right>, <left> は左端からのオフセットで指定します。Internet Explorer 4~7 では、カンマの代わりにスペースで区切る必要があります。
7024                                 // position:absolute または position:fixed を適用した要素に対してのみ有効です。
7025                                 var top    = this.get( name + 'Top' ),
7026                                         right  = this.get( name + 'Right' ),
7027                                         bottom = this.get( name + 'Bottom' ),
7028                                         left   = this.get( name + 'Left' ),
7029                                         ret    = new PropertyGroup( name, top, right, bottom, left),
7030                     all;
7031                                 if( ret.isValid() === true ) return ret;
7032                                 ret.kill();
7033                                 all    = this.style[ name ].split( '(' )[ 1 ].split( ')' )[ 0 ].split( CLIP_SEPARATOR );
7034                                 return new PropertyGroup( name,
7035                                         new Property( name + 'Top',    all[ 0 ], px, this.pxPerEm ),
7036                                         new Property( name + 'Right',  all[ 1 ], px, this.pxPerEm ),
7037                                         new Property( name + 'Bottom', all[ 2 ], px, this.pxPerEm ),
7038                                         new Property( name + 'Left',   all[ 3 ], px, this.pxPerEm )
7039                                 );
7040                         },
7041                         getBackgroundPosition: function( name ){
7042                                 var x   = this.get( name + 'X' ),
7043                                         y   = this.get( name + 'Y' ),
7044                                         ret = new PropertyGroup( name, x, y ),
7045                                         xy;
7046                                 if( ret.isValid() === true ) return ret;
7047                                 ret.kill();
7048                                 xy  = this.style[ name ].split( ' ' );
7049                                 return new PropertyGroup( name,
7050                                         new Property( name + 'X', this.getValue( xy[ 0 ] ), this.getUnit( xy[ 0 ] ), this.pxPerEm ),
7051                                         new Property( name + 'Y', this.getValue( xy[ 1 ] ), this.getUnit( xy[ 1 ] ), this.pxPerEm )
7052                                 );
7053                         },
7054                         getMarginPaddingBorder: function( name, width ){
7055                                 var props  = [ name + 'Top'    + width,
7056                                                    name + 'Right'  + width,
7057                                                    name + 'Bottom' + width,
7058                                                    name + 'Left'   + width ],
7059                                         top    = this.get( props[ 0 ] ),
7060                                         right  = this.get( props[ 1 ] ),
7061                                         bottom = this.get( props[ 2 ] ),
7062                                         left   = this.get( props[ 3 ] ),
7063                                         ret    = new FrexibleProperty( name, top, right, bottom, left ),
7064                                         klass, pxPerEm, getValue, getUnit,
7065                                         all, _0, _1, _2, _3, v, u;
7066                                 if( ret.isValid() === true ) return ret;
7067                                 ret.kill();
7068                                 klass    = Property;
7069                                 pxPerEm  = this.pxPerEm;
7070                                 getValue = this.getValue;
7071                                 getUnit  = this.getUnit;
7072                                 all = this.style[ name + width ].split( ' ' );
7073                                 _0 = all[ 0 ];
7074                                 _1 = all[ 1 ];
7075                                 _2 = all[ 2 ];
7076                                 _3 = all[ 3 ];
7077                                 v  = getValue( _0 );
7078                                 u  = getUnit( _0 );
7079                                 switch( all.length ){
7080                                         case 1 :
7081                                                 top    = new klass( props[ 0 ], v, u, pxPerEm );
7082                                                 right  = new klass( props[ 1 ], v, u, pxPerEm );
7083                                                 bottom = new klass( props[ 2 ], v, u, pxPerEm );
7084                                                 left   = new klass( props[ 3 ], v, u, pxPerEm );
7085                                                 break;
7086                                         case 2 :
7087                                                 top    = new klass( props[ 0 ], v, u, pxPerEm );
7088                                                 bottom = new klass( props[ 2 ], v, u, pxPerEm );
7089                                                 v  = getValue( _1 );
7090                                                 u  = getUnit( _1 );
7091                                                 right  = new klass( props[ 1 ], v, u, pxPerEm );
7092                                                 left   = new klass( props[ 3 ], v, u, pxPerEm );
7093                                                 break;
7094                                         case 3 :
7095                                                 top    = new klass( props[ 0 ], v, u, pxPerEm );
7096                                                 v  = getValue( _1 );
7097                                                 u  = getUnit( _1 );
7098                                                 right  = new klass( props[ 1 ], v, u, pxPerEm );
7099                                                 left   = new klass( props[ 3 ], v, u, pxPerEm );
7100                                                 bottom = new klass( props[ 2 ], getValue( _2 ), getUnit( _2 ), pxPerEm );
7101                                                 break;
7102                                         case 4 :
7103                                                 top    = new klass( props[ 0 ], v, u, pxPerEm );
7104                                                 right  = new klass( props[ 1 ], getValue( _1 ), getUnit( _1 ), pxPerEm );
7105                                                 bottom = new klass( props[ 2 ], getValue( _2 ), getUnit( _2 ), pxPerEm );
7106                                                 left   = new klass( props[ 3 ], getValue( _3 ), getUnit( _3 ), pxPerEm );
7107                                                 break;
7108                                 };
7109                                 return new FrexibleProperty( name, top, right, bottom, left );
7110                         },
7111                         getBorderColor: function( name ){
7112                                 var props    = 'borderTopColor,borderRightColor,borderBottomColor,borderLeftColor'.split( ',' ),
7113                                         top      = this.get( props[ 0 ] ),
7114                                         right    = this.get( props[ 1 ] ),
7115                                         bottom   = this.get( props[ 2 ] ),
7116                                         left     = this.get( props[ 3 ] ),
7117                                         ret      = new FrexibleProperty( name, top, right, bottom, left ),
7118                                         all, _0, _1, getColor;
7119                                 if( ret.isValid() === true ) return ret;
7120                                 ret.kill();
7121                                 getColor = this.getColor;
7122                                 all = this.style[ name ].split( ' ' );
7123                                 _0  = all[ 0 ];
7124                                 _1  = all[ 1 ];
7125                                 switch( all.length ){
7126                                         case 1 :
7127                                                 top    = getColor( _0, props[ 0 ] );
7128                                                 right  = getColor( _0, props[ 1 ] );
7129                                                 bottom = getColor( _0, props[ 2 ] );
7130                                                 left   = getColor( _0, props[ 3 ] );
7131                                                 break;
7132                                         case 2 :
7133                                                 top    = getColor( _0, props[ 0 ] );
7134                                                 right  = getColor( _1, props[ 1 ] );
7135                                                 bottom = getColor( _0, props[ 2 ] );
7136                                                 left   = getColor( _1, props[ 3 ] );
7137                                                 break;
7138                                         case 3 :
7139                                                 top    = getColor( _0,       props[ 0 ] );
7140                                                 right  = getColor( _1,       props[ 1 ] );
7141                                                 bottom = getColor( all[ 2 ], props[ 2 ] );
7142                                                 left   = getColor( _1,       props[ 3 ] );
7143                                                 break;
7144                                         case 4 :
7145                                                 top    = getColor( _0,       props[ 0 ] );
7146                                                 right  = getColor( _1,       props[ 1 ] );
7147                                                 bottom = getColor( all[ 2 ], props[ 2 ] );
7148                                                 left   = getColor( all[ 3 ], props[ 3 ] );
7149                                                 break;
7150                                 };
7151                                 return new FrexibleProperty( name, top, right, bottom, left );
7152                         }
7153                 }
7154         );
7155         function camelizeHash( obj ){
7156                 var p, _p, came = Util.camelize;
7157                 for( p in obj ){
7158                         _p = came( p );
7159                         if( _p === p ) continue;
7160                         obj[ _p ] = obj[ _p ] || obj[ p ];
7161                         delete obj[ p ];
7162                 };
7163         };      
7164         return {
7165                 create: function( css ){
7166                         return new WrappedStyle( camelizeHash( p ) );
7167                 }
7168         };
7169 })();
7170
7171 var XDocument = ( function( window, document ){
7172         
7173         var getIndex  = Util.getIndex;
7174         var ROOT_LIST = [];
7175         var DEF_ATTRS = {};
7176         var AUTO      = undefined;
7177         var FULL      = DEF_ATTRS; // something unigue value;
7178         var FLOOR     = Math.floor;
7179         
7180         DEF_ATTRS.LENGTH            =  1;
7181         DEF_ATTRS.PERCENT           =  2;
7182         DEF_ATTRS.COLOR             =  4;
7183         DEF_ATTRS.U_DECIMAL         =  8;
7184         DEF_ATTRS.NUMERICAL         = 16;
7185         DEF_ATTRS.BOOLEAN           = 32;
7186         DEF_ATTRS.QUARTET           = 64;
7187         DEF_ATTRS.URL               = 128;
7188         DEF_ATTRS.FONT_NAME         = 256;
7189         DEF_ATTRS.LIST              = 512;
7190         DEF_ATTRS.AUTO              = 1024;
7191         DEF_ATTRS.COMBI             = 2048;
7192         DEF_ATTRS.BORDER_STYLE      = 'none,hidden,dotted,dashed,solid,double,groove,ridge,inset,outset'.split(',');
7193         DEF_ATTRS.POSITION_X        = 'left,center,right'.split(',');
7194         DEF_ATTRS.POSITION_Y        = 'top,center,bottom'.split(',');
7195         DEF_ATTRS.ALIGN             = 'left,center,right,justify'.split(',');
7196         DEF_ATTRS.TEXT_DECORATION   = 'none,underline,overline,line-through,blink'.split(',');
7197         DEF_ATTRS.TEXT_TRANSFORM    = 'none,capitalize,lowercase,uppercase'.split(',');
7198         DEF_ATTRS.WIDTH_HEIGHT      = 'auto'.split(',');
7199         DEF_ATTRS.BOX_SIZING        = 'content-box,padding-box,border-box,margin-box'.split(',');
7200         DEF_ATTRS.PAINT             = 1; // 再描画のみ必要
7201         DEF_ATTRS.REFLOW            = 2; // レイアウトの再計算が必要
7202         
7203         DEF_ATTRS.borderWidth    = [ DEF_ATTRS.REFLOW,  0, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH      ]; // em [ top, right, bottom, left ]
7204         DEF_ATTRS.borderColor    = [ DEF_ATTRS.PAINT,   4, DEF_ATTRS.QUARTET | DEF_ATTRS.DEF_COLOR   ]; // color [ top, right, bottom, left ]
7205         DEF_ATTRS.borderStyle    = [ DEF_ATTRS.REFLOW,  8, DEF_ATTRS.QUARTET | DEF_ATTRS.LIST, DEF_ATTRS.BORDER_STYLE ]; // string [ top, right, bottom, left ]
7206         DEF_ATTRS.cornerRadius   = [ DEF_ATTRS.PAINT,  12, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ]; // em, px [ top, right, bottom, left ]
7207         DEF_ATTRS.bgColor        = [ DEF_ATTRS.PAINT,  16, DEF_ATTRS.COLOR     ]; // color
7208         DEF_ATTRS.bgAlpha        = [ DEF_ATTRS.PAINT,  17, DEF_ATTRS.U_DECIMAL ]; // 0 - 1
7209         DEF_ATTRS.bgImgUrl       = [ DEF_ATTRS.PAINT,  18, DEF_ATTRS.URL       ]; // url
7210         DEF_ATTRS.bgImgRepeatX   = [ DEF_ATTRS.PAINT,  19, DEF_ATTRS.BOOLEAN   ]; // true / false
7211         DEF_ATTRS.bgImgRepeatY   = [ DEF_ATTRS.PAINT,  20, DEF_ATTRS.BOOLEAN   ]; // true / false
7212         DEF_ATTRS.bgImgPositionX = [ DEF_ATTRS.PAINT,  21, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT | DEF_ATTRS.LIST, DEF_ATTRS.POSITION_X ]; // em %, px, string
7213         DEF_ATTRS.bgImgPositionY = [ DEF_ATTRS.PAINT,  22, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT | DEF_ATTRS.LIST, DEF_ATTRS.POSITION_Y ]; // em %, px, string
7214         DEF_ATTRS.shadowColor    = [ DEF_ATTRS.PAINT,  23, DEF_ATTRS.COLOR     ]; // color
7215         DEF_ATTRS.shadowAlpha    = [ DEF_ATTRS.PAINT,  24, DEF_ATTRS.U_DECIMAL ]; // 0 - 1
7216         DEF_ATTRS.shadowOffsetX  = [ DEF_ATTRS.PAINT,  25, DEF_ATTRS.LENGTH    ]; // em
7217         DEF_ATTRS.shadowOffsetY  = [ DEF_ATTRS.PAINT,  26, DEF_ATTRS.LENGTH    ]; // em
7218         DEF_ATTRS.shadowBlur     = [ DEF_ATTRS.PAINT,  27, DEF_ATTRS.LENGTH    ]; // em
7219         DEF_ATTRS.shadowSpread   = [ DEF_ATTRS.PAINT,  28, DEF_ATTRS.LENGTH    ]; // em
7220         DEF_ATTRS.shadowInset    = [ DEF_ATTRS.PAINT,  29, DEF_ATTRS.BOOLEAN   ]; // true / false
7221         
7222         DEF_ATTRS.color          = [ DEF_ATTRS.PAINT,  30, DEF_ATTRS.COLOR     ]; // color
7223         DEF_ATTRS.fontFamily     = [ DEF_ATTRS.REFLOW, 31, DEF_ATTRS.FONT_NAME ]; // string
7224         DEF_ATTRS.fontSize       = [ DEF_ATTRS.REFLOW, 32, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ]; // em, %
7225         DEF_ATTRS.bold           = [ DEF_ATTRS.REFLOW, 33, DEF_ATTRS.BOOLEAN   ]; // true / false
7226         DEF_ATTRS.italic         = [ DEF_ATTRS.REFLOW, 34, DEF_ATTRS.BOOLEAN   ]; // true / false
7227         DEF_ATTRS.lineHeight     = [ DEF_ATTRS.REFLOW, 35, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT | DEF_ATTRS.NUMERICAL ]; // em, %, 
7228         DEF_ATTRS.letterSpacing  = [ DEF_ATTRS.REFLOW, 36, DEF_ATTRS.LENGTH    ]; // em
7229         DEF_ATTRS.wordSpacing    = [ DEF_ATTRS.REFLOW, 37, DEF_ATTRS.LENGTH    ];
7230         DEF_ATTRS.align          = [ DEF_ATTRS.REFLOW, 38, DEF_ATTRS.LIST, DEF_ATTRS.ALIGN           ];
7231         DEF_ATTRS.decoration     = [ DEF_ATTRS.PAINT,  39, DEF_ATTRS.LIST, DEF_ATTRS.TEXT_DECORATION ];
7232         DEF_ATTRS.transform      = [ DEF_ATTRS.REFLOW, 40, DEF_ATTRS.LIST, DEF_ATTRS.TEXT_TRANSFORM  ];
7233         DEF_ATTRS.shadowColor    = [ DEF_ATTRS.PAINT,  41, DEF_ATTRS.COLOR     ];
7234         DEF_ATTRS.shadowOffsetX  = [ DEF_ATTRS.PAINT,  42, DEF_ATTRS.LENGTH    ];
7235         DEF_ATTRS.shadowOffsetY  = [ DEF_ATTRS.PAINT,  43, DEF_ATTRS.LENGTH    ];
7236         DEF_ATTRS.shadowBlur     = [ DEF_ATTRS.PAINT,  44, DEF_ATTRS.LENGTH    ];
7237         
7238         DEF_ATTRS.width              = [ DEF_ATTRS.REFLOW, 45, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT, DEF_ATTRS.WIDTH_HEIGHT ];
7239         DEF_ATTRS.minWidth           = [ DEF_ATTRS.REFLOW, 46, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7240         DEF_ATTRS.maxWidth           = [ DEF_ATTRS.REFLOW, 47, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7241         DEF_ATTRS.height             = [ DEF_ATTRS.REFLOW, 48, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT, DEF_ATTRS.WIDTH_HEIGHT ];
7242         DEF_ATTRS.minHeight          = [ DEF_ATTRS.REFLOW, 49, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7243         DEF_ATTRS.maxHeight          = [ DEF_ATTRS.REFLOW, 50, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7244         DEF_ATTRS.padding            = [ DEF_ATTRS.REFLOW, 51, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7245         DEF_ATTRS.margin             = [ DEF_ATTRS.REFLOW, 55, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7246         DEF_ATTRS.sizing             = [ DEF_ATTRS.REFLOW, 59, DEF_ATTRS.LIST, DEF_ATTRS.BOX_SIZING ];
7247         DEF_ATTRS.pageBox            = [ DEF_ATTRS.REFLOW, 60, DEF_ATTRS.BOOLEAN   ]; // true / false
7248         DEF_ATTRS.x = DEF_ATTRS.left = [ DEF_ATTRS.REFLOW, 61, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7249         DEF_ATTRS.y = DEF_ATTRS.top  = [ DEF_ATTRS.REFLOW, 62, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7250         DEF_ATTRS.bottom             = [ DEF_ATTRS.REFLOW, 63, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7251         DEF_ATTRS.right              = [ DEF_ATTRS.REFLOW, 64, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7252         
7253         /**
7254          * 再計算と再描画
7255          * redraw 再描画はパラメータ変更後に setTimeout で
7256          * reflow 再計算は値が get された場合 invalidate が サイズだったら
7257          * または再描画前に invalidate がサイズなフラグが足っていたら 
7258          */
7259         
7260         var BasicLayoutManager = Class.create(
7261                 'BasicLayoutManager',
7262                 Class.POOL_OBJECT,
7263                 {
7264                         Constructor : function(){
7265                                 
7266                         },
7267                         redraw : function( nodeData ){
7268                                 var root = nodeData.__root;
7269                                 root.dirty === DEF_ATTRS.REFLOW && this.reflow( root );
7270                                 
7271                                 // draw
7272                         },
7273                         reflow : function( nodeData ){
7274                                 var parent   = nodeData.__parent,
7275                                         allowW   = parent.contentWidth,
7276                                         allowH   = parent.contentHeight,
7277                                         autoW    = parent.autoWidth,
7278                                         autoH    = parent.autoHeight,
7279                                         offsetX  = parent.offsetX,
7280                                         offsetY  = parent.offsetY,
7281                                         children = nodeData.children,                                   
7282                                         style    = nodeData.__style,                            
7283                                         x, y, w, minW, maxW, h, minH, maxH,
7284                                         contentW, contentH, boxW, boxH,
7285                                         autoSize, sizing, page,
7286                                         paddingT, paddingR, paddingB, paddingL,
7287                                         borderT, borderR, borderB, borderL,
7288                                         marginT, marginR, marginB, marginL,
7289                                         childW   = 0,
7290                                         childH   = 0,
7291                                         styles, child, calc, i;
7292
7293                                 if( style ){
7294                                         styles   = style.data;
7295                                         calc     = BasicLayoutManager.calcValue;
7296                                         sizing   = styles[ 53 ];
7297                                         page     = styles[ 54 ];                                
7298                                         x        = calc( styles[ 55 ], allowW );
7299                                         y        = calc( styles[ 56 ], page === true ? allowH : allowW );
7300                                         w        = styles[ 45 ];
7301                                         minW     = styles[ 46 ];
7302                                         maxW     = styles[ 47 ];
7303                                         contentW = BasicLayoutManager.finalValue( w, minW, maxW, allowW );
7304                                         h        = styles[ 48 ];
7305                                         minW     = styles[ 49 ];
7306                                         maxW     = styles[ 50 ];
7307                                         contentH = BasicLayoutManager.finalValue( h, minW, maxW, allowH );
7308                                         autoSize = w === AUTO || h === AUTO;
7309                                         paddingT = calc( styles[ 51 ], page === true ? allowH : allowW );// paddingTRBL の % 指定は 最大幅に対して TB でも幅に対して
7310                                         paddingR = calc( styles[ 52 ], allowW );
7311                                         paddingT = calc( styles[ 53 ], page === true ? allowH : allowW );
7312                                         paddingL = calc( styles[ 54 ], allowW, autoW );
7313                                         borderT  = styles[  0 ];
7314                                         borderR  = styles[  1 ];
7315                                         borderB  = styles[  2 ];
7316                                         borderL  = styles[  3 ];
7317                                         marginT  = calc( styles[ 55 ], page === true ? allowH : allowW );// marginTRBL の % 指定は 最大幅に対して TB でも幅に対して
7318                                         marginR  = calc( styles[ 56 ], allowW );
7319                                         marginB  = calc( styles[ 57 ], page === true ? allowH : allowW );
7320                                         marginL  = calc( styles[ 58 ], allowW );
7321                                         boxW     = contentW;
7322                                         boxH     = contentH;
7323                                         switch( sizing ){
7324                                                 case 3 : // margin-box
7325                                                          contentW -= ( marginR + marginL );
7326                                                          contentH -= ( marginT + marginR );
7327                                                          
7328                                                 case 2 : // border-box
7329                                                          contentW -= ( borderR + borderL );
7330                                                          contentH -= ( borderT + borderR );
7331                                                 case 1 : // padding-box
7332                                                          contentW -= ( paddingR + paddingL );
7333                                                          contentH -= ( paddingT + paddingR );
7334                                                 // case 0 : // content-box
7335                                         };              
7336                                 } else {
7337                                         boxW     = contentW = w        = allowW;
7338                                         boxH     = contentH = h        = allowH;
7339                                         minW     = minH     = 0;
7340                                         maxW     = maxH     = Infinity;
7341                                         autoSize = false;
7342                                 };
7343                                 
7344                                 if( nodeData.contentWidth !== contentW || nodeData.contentHeight === contentH ){
7345                                         if( autoSize === false ){
7346                                                 nodeData.updateLayout();
7347                                                 nodeData.contentWidth  = contentW;
7348                                                 nodeData.contentHeight = contentH;
7349                                                 nodeData.boxWidth      = boxW;
7350                                                 nodeData.boxHeight     = boxH;                                          
7351                                         };
7352                                         if( node instanceof LayoutBoxPrivate ){
7353                                                 nodeData.Super.reflow.call( nodeData );
7354                                         } else {
7355                                                 node.reflow();
7356                                         };
7357                                 };
7358
7359                                 if( children ){
7360                                         for( i = children.length; i; ){
7361                                                 child = children[ --i ];
7362                                                 if( child instanceof LayoutBoxPrivate ){
7363                                                         child.layoutManager.reflow( child );
7364                                                 } else {
7365                                                         child.reflow();
7366                                                 };
7367                                                 if( autoSize === false ) continue;
7368                                                 if( childW < child.rectRight  ) childW = child.rectRight;
7369                                                 if( childH < child.rectBottom ) childH = child.rectBottom;                                              
7370                                         };
7371                                         if( autoSize === true ){
7372                                                 if( w === AUTO && childW < contentW ) contentW = childW;
7373                                                 if( h === AUTO && childH < contentH ) contentH = childH;
7374                                                 if( contentW < minW ) contentW = minW;
7375                                                 if( maxW < contentW ){
7376                                                         nodeData.scrollWidth = contentW;
7377                                                         contentW = maxW;
7378                                                 };
7379                                                 if( contentH < minH ) contentH = minH;
7380                                                 if( maxH < contentH ){
7381                                                         nodeData.scrollHeight = contentH;
7382                                                         contentH = maxH;
7383                                                 };
7384                                                 nodeData.contentWidth  = boxW = contentW;
7385                                                 nodeData.contentHeight = boxH = contentH;
7386                                                 switch( sizing ){
7387                                                         case 3 : // margin-box
7388                                                                  boxW += ( marginR + marginL );
7389                                                                  boxH += ( marginT + marginR );
7390                                                         case 2 : // border-box
7391                                                                  boxW += ( borderR + borderL );
7392                                                                  boxH += ( borderT + borderR );
7393                                                         case 1 : // padding-box
7394                                                                  boxW += ( paddingR + paddingL );
7395                                                                  boxH += ( paddingT + paddingR );
7396                                                         // case 0 : // content-box
7397                                                 };
7398                                                 nodeData.boxWidth  = boxW;
7399                                                 nodeData.boxHeight = boxH;
7400                                         };                                      
7401                                 };
7402                                 delete nodeData.dirty;
7403                         }
7404                 }
7405         );
7406         BasicLayoutManager.finalValue = function( styleValue, styleMin, styleMax, srcValue ){
7407                 var calc = BasicLayoutManager.calcValue,
7408                         v    = calc( styleValue, srcValue ),
7409                         min  = calc( styleMin,   srcValue ),
7410                         max  = calc( styleMax,   srcValue );
7411                 if( v < min ) return min;
7412                 if( max < v ) return max;
7413                 return v;
7414         };
7415         BasicLayoutManager.calcValue = function( styleValue, srcValue ){
7416                 if( styleValue === 0 ) return 0;
7417                 // 100%
7418                 if( styleValue === FULL || styleValue === AUTO ) return srcValue;
7419                 if( 1 <= styleValue  ) return styleValue; // legth
7420                 if( -1 < styleValue  ) return FLOOR( srcValue * styleValue ); // %
7421                 return styleValue; // - length
7422         };
7423         
7424         var NodeStylePrivate = Class.create(
7425                 Class.PRIVATE_DATA | Class.POOL_OBJECT,
7426                 {
7427                         colorCssText  : null,
7428                         layoutCssText : null,
7429                         Constructor : function(){
7430                                 this.data  = [];
7431                                 this.dirty = 0;
7432                         },
7433                         register : function( node ){
7434                                 var root  = node.__root,
7435                                         roots = this.rootList,
7436                                         nodes = this.nodeList;
7437                                 if( !roots ){
7438                                         this.rootList = [ root ];
7439                                 } else
7440                                 if( getIndex( roots, root ) === -1 ) roots[ roots.length ] = root;
7441                                 
7442                                 if( !nodes ){
7443                                         this.nodeList = [ node ];
7444                                         return;
7445                                 };
7446                                 if( getIndex( nodes, node ) === -1 ) nodes[ nodes.length ] = node;
7447                         },
7448                         unRegister : function( node ){
7449                                 var nodes = this.nodeList,
7450                                         i     = getIndex( nodes, node ),
7451                                         root  = node._root,
7452                                         roots = this.rootList,
7453                                         j     = getIndex( roots, root );
7454                                 if( i !== -1 && nodes.splice( i, 1 ) && nodes.length === 0 ) delete this.nodeList;
7455                                 if( j !== -1 && roots.splice( j, 1 ) && roots.length === 0 ) delete this.rootList;
7456                         },
7457                         clone : function(){
7458                                 var styleClass = Class.getClass( this.User ),
7459                                         dataClass  = Class.getClass( this );
7460                         },
7461                         attr : function( prop, v ){
7462                                 var update    = prop[ 0 ],
7463                                         propID    = prop[ 1 ],
7464                                         type      = prop[ 2 ],
7465                                         list      = prop[ 3 ],
7466                                         length    = !!( type & DEF_ATTRS.LENGTH    ),
7467                                         percent   = !!( type & DEF_ATTRS.PERCENT   ),
7468                                         color     = !!( type & DEF_ATTRS.COLOR     ),
7469                                         uDecimal  = !!( type & DEF_ATTRS.U_DECIMAL ),
7470                                         numerical = !!( type & DEF_ATTRS.NUMERICAL ),
7471                                         flag      = !!( type & DEF_ATTRS.BOOLEAN   ),
7472                                         quartet   = !!( type & DEF_ATTRS.QUARTET   ),
7473                                         url       = !!( type & DEF_ATTRS.URL       ),
7474                                         fontName  = !!( type & DEF_ATTRS.FONT_NAME ),
7475                                         //list      = !!( type & DEF_ATTRS.LIST      ),
7476                                         combi     = !!( type & DEF_ATTRS.COMBI     ),
7477                                         data      = this.data,
7478                                         _v        = -1,
7479                                         i, l, nodes, root;
7480                                 /*
7481                                  * Setter
7482                                  */
7483                                 if( v !== undefined ){
7484                                         if( Type.isNumber( v ) === true ){
7485                                                 if( numerical === false ){
7486                                                         if( uDecimal === false || v < 0 || 1 < v ) throw new Error( '' );
7487                                                 };
7488                                         } else
7489                                         if( Type.isBoolean( v ) === true ){
7490                                                 if( flag === false ) throw new Error( '' );
7491                                         } else
7492                                         if( Type.isString( v ) === true ){
7493                                                 if( url === false && fontName === false ){
7494                                                         if( v.indexOf( ' ' ) !== -1 ){
7495                                                                 v = v.split( ' ' );
7496                                                         } else {
7497                                                                 if( length === false && percent === false && color === false ) throw new Error( '' );
7498                                                         };
7499                                                 };
7500                                         };                                      
7501                                         if( Type.isArray( v ) === true ){
7502                                                 if( v.length <= 4 && quartet === true ){
7503                                                         type ^= DEF_ATTRS.QUARTET;
7504                                                 } else
7505                                                 if( v.length === 2 && combi === true ){
7506                                                         type ^= DEF_ATTRS.COMBI;
7507                                                 } else {
7508                                                         throw new Error( '' );
7509                                                 };
7510                                                 switch( v.length ){
7511                                                         case 1 :
7512                                                                 this.attr( [ propID  , type, list ], v[ 0 ] );
7513                                                                 this.attr( [ ++propID, type, list ], v[ 0 ] );
7514                                                                 this.attr( [ ++propID, type, list ], v[ 0 ] );
7515                                                                 this.attr( [ ++propID, type, list ], v[ 0 ] );
7516                                                                 break;
7517                                                         case 2 :
7518                                                                 this.attr( [ propID  , type, list ], v[ 0 ] );
7519                                                                 this.attr( [ ++propID, type, list ], v[ 1 ] );
7520                                                                 this.attr( [ ++propID, type, list ], v[ 0 ] );
7521                                                                 this.attr( [ ++propID, type, list ], v[ 1 ] );
7522                                                                 break;
7523                                                         case 3 :
7524                                                                 this.attr( [ propID  , type, list ], v[ 0 ] );
7525                                                                 this.attr( [ ++propID, type, list ], v[ 1 ] );
7526                                                                 this.attr( [ ++propID, type, list ], v[ 2 ] );
7527                                                                 this.attr( [ ++propID, type, list ], v[ 1 ] );
7528                                                                 break;
7529                                                         case 4 :
7530                                                                 this.attr( [ propID  , type, list ], v[ 0 ] );
7531                                                                 this.attr( [ ++propID, type, list ], v[ 1 ] );
7532                                                                 this.attr( [ ++propID, type, list ], v[ 2 ] );
7533                                                                 this.attr( [ ++propID, type, list ], v[ 3 ] );
7534                                                                 break;
7535                                                         default :
7536                                                 };
7537                                                 return this.User;
7538                                         };
7539                                         if( update === DEF_ATTRS.REFLOW ){
7540                                                 delete this.layoutCssText;
7541                                         } else {
7542                                                 delete this.colorCssText;
7543                                         };
7544                                         if( this.dirty < update ){
7545                                                 this.dirty = update;
7546                                                 roots = this.rootList;
7547                                                 for( i = 0, l = roots.length; i < l; ++i ){
7548                                                         root = roots[ i ];
7549                                                         if( root.dirty < update ) root.dirty = update;
7550                                                 };
7551                                         };
7552                                         
7553                                         if( list ) _v = Util.getIndex( list, v );
7554                                         data[ propID ] = _v !== -1 ? _v : v;
7555                                         return this.User;
7556                                 };
7557                                 /*
7558                                  * Getter
7559                                  */
7560                                 if( this.dirty === DEF_ATTRS.REFLOW ){
7561                                         roots = this.rootList;
7562                                         if( roots ){
7563                                                 for( i = 0, l = roots.length; i < l; ++i ){
7564                                                         roots[ i ].reflow();
7565                                                 };
7566                                         };
7567                                 };
7568                                 v = data[ propID ];
7569                                 if( quartet === true ) return [ v, data[ ++propID ], data[ ++propID ], data[ ++propID ] ];
7570                                 if( combi === true ) return [ v, data[ ++propID ] ];
7571                                 if( list && Type.isNumber( v ) === true ) return list[ v ];
7572                                 return v;
7573                         },
7574                         cssText : function(){
7575                                 if( this.colorCssText  === null ) this.colorCssText  = this.createColorCssText();
7576                                 if( this.layoutCssText === null ) this.layoutCssText = this.createLayoutCssText();
7577                                 return this.colorCssText + ';' + this.layoutCssText;
7578                         },
7579                         createColorCssText : function(){
7580                                 
7581                         },
7582                         createLayoutCssText : function(){
7583                                 
7584                         }
7585                 }
7586         );
7587         
7588         var NodeStyle = Class.create(
7589                 'NodeStyle',
7590                 Class.POOL_OBJECT,
7591                 NodeStylePrivate,
7592                 {
7593                         Constructor : function(){
7594                                 NodeStyle.newPrivateData( this );
7595                         },
7596                         borderWidth : function( v ){
7597                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.borderWidth, v );
7598                         },
7599                         borderColor : function(){
7600                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.borderColor, v );
7601                         },
7602                         borderStyle : function(){
7603                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.borderStyle, v );
7604                         },
7605                         cornerRadius : function(){
7606                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.cornerRadius, v );
7607                         },
7608                         bgColor : function(){
7609                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgColor, v );
7610                         },
7611                         bgAlpha : function(){
7612                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgAlpha, v );
7613                         },
7614                         bgImgUrl : function(){
7615                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgImgUrl, v );
7616                         },
7617                         bgImgRepeatX : function(){
7618                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgImgRepeatX, v );
7619                         },
7620                         bgImgRepeatY : function(){
7621                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgImgRepeatY, v );
7622                         },
7623                         bgImgPositionX : function(){
7624                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgImgPositionX, v );
7625                         },
7626                         bgImgPositionY : function(){
7627                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgImgPositionY, v );
7628                         },
7629                         shadowColor : function(){
7630                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowColor, v );
7631                         },
7632                         shadowAlpha : function(){
7633                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowAlpha, v );
7634                         },
7635                         shadowOffsetX : function(){
7636                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowOffsetX, v );
7637                         },
7638                         shadowOffsetY : function(){
7639                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowOffsetY, v );
7640                         },
7641                         shadowBlur : function(){
7642                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowBlur, v );
7643                         },
7644                         shadowSpread : function(){
7645                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowSpread, v );
7646                         },
7647                         shadowInset : function(){
7648                                 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowInset, v );
7649                         },
7650                         color : function( v ){
7651                                 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.color, v );
7652                         },
7653                         fontFamily : function( v ){
7654                                 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.fontFamily, v );
7655                         },
7656                         fontSize : function( v ){
7657                                 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.fontSize, v );
7658                         },
7659                         bold : function( v ){
7660                                 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.bold, v );
7661                         },
7662                         italic : function( v ){
7663                                 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.italic, v );
7664                         },
7665                         lineHeight : function( v ){
7666                                 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.lineHeight, v );
7667                         },
7668                         letterSpacing : function( v ){
7669                                 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.letterSpacing, v );
7670                         },
7671                         wordSpacing : function( v ){
7672                                 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.wordSpacing, v );
7673                         },
7674                         align : function( v ){
7675                                 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.align, v );
7676                         },
7677                         decoration : function( v ){
7678                                 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.decoration, v );
7679                         },
7680                         transform : function( v ){
7681                                 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.transform, v );
7682                         },
7683                         shadowColor : function( v ){
7684                                 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowColor, v );
7685                         },
7686                         shadowOffsetX : function( v ){
7687                                 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowOffsetX, v );
7688                         },
7689                         shadowOffsetY : function( v ){
7690                                 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowOffsetY, v );
7691                         },
7692                         shadowBlur : function( v ){
7693                                 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowBlur, v );
7694                         },
7695                         cssText : function(){
7696                                 return TypoStyle.getPrivateData( this ).cssText();
7697                         }
7698                 }
7699         );
7700
7701         var NodePrivate = Class.create(
7702                 'NodePrivate',
7703                 Class.PRIVATE_DATA | Class.POOL_OBJECT,
7704                 {
7705                         elmWrap       : null,
7706                         textNode      : null,
7707                         autoWidth     : false,
7708                         autoHeight    : false,
7709                         autoSize      : false,
7710                         boxX          : 0,
7711                         boxY          : 0,
7712                         boxWidth      : 0,
7713                         boxHeight     : 0,
7714                         boxRight      : 0,
7715                         boxBottom     : 0,
7716                         contentX      : 0,
7717                         contentY      : 0,                      
7718                         contentWidth  : 0,
7719                         contentHeight : 0,
7720                         Constructor   : function( __root, __parent ){
7721                                 this.__root   = __root;
7722                                 if( __parent ) this.__parent = __parent;
7723                         },
7724                         style : function( v ){
7725                                 if( v instanceof NodeStyle ){
7726                                         this.__style && this.__style.unRegister( this );
7727                                         this._style = v;
7728                                         this.__style = StylePrivate.getPrivateData( v );                                        
7729                                         this.__style.register( this );
7730                                         return this.User;
7731                                 } else
7732                                 if( v === null ){
7733                                         this.__style && this.__style.unRegister( this );
7734                                         delete this._style;
7735                                         delete this.__style;
7736                                         return this.User;
7737                                 };
7738                                 return this._style;
7739                         },
7740                         /**
7741                          * 1. 要素の追加・削除
7742                          * 2. auto 指定時は要素の高さ取得.
7743                          * 3. 親の許す子の最大サイズと自信のスタイル指定から、自身の位置とサイズを計算
7744                          * 4. 描画更新リストに追加
7745                          */
7746                         reflow : function(){
7747                                 var content = this._textContent,
7748                                         style   = this.__style,
7749                                         parent  = this.__parent,
7750                                         size, data, w, h;
7751                                 
7752                                 if( content || ( style && style.hasPaint === true ) ){
7753                                         if( !this.elmWrap ){
7754                                                 this.elmWrap = DOM.createDiv();
7755                                                 parent.addDisplayElement( this );
7756                                         };
7757                                         if( style && style.hasStyle === true ){
7758                                                 this.elmWrap.style.cssText = style.cssText();
7759                                         };                              
7760                                         if( content ){
7761                                                 if( !this.textNode ){
7762                                                         this.textNode = DOM.cerateText();
7763                                                         this.elmWrap.appendChild( this.textNode );
7764                                                 };
7765                                                 if( style && ( style.autoWidth === true || style.autoHeight === true ) ){
7766                                                         size = DOM.getTextSize( this.elmWrap, content );
7767                                                         this.contentWidth  = size[ 0 ];
7768                                                         this.conetntHeight = size[ 1 ];
7769                                                 };
7770                                                 this.textNode.data = content;
7771                                         } else
7772                                         if( this.textNode ){
7773                                                 DOM.correct( this.textNode );
7774                                                 delete this.textNode;
7775                                                 delete this.contentWidth;
7776                                                 delete this.conetntHeight;
7777                                         };
7778                                         this.boxWidth  = this.elmWrap.offsetWidth;
7779                                         this.boxHeight = this.elmWrap.offsetHeight;                                     
7780                                 } else
7781                                 if( this.elmWrap ){
7782                                         parent.removeDisplayElement( this );
7783                                 };
7784                         },
7785                         preSizing : function(){
7786                                 var parent   = nodeData.__parent,
7787                                         allowW   = parent.contentWidth,
7788                                         allowH   = parent.contentHeight,                
7789                                         style    = nodeData.__style,                            
7790                                         x, y, w, minW, maxW, h, minH, maxH,
7791                                         contentW, contentH,
7792                                         page,
7793                                         paddingT, paddingR, paddingB, paddingL,
7794                                         borderT, borderR, borderB, borderL,
7795                                         marginT, marginR, marginB, marginL,
7796                                         styles, calc;
7797
7798                                 if( style ){
7799                                         styles   = style.data;
7800                                         calc     = BasicLayoutManager.calcValue;
7801                                         page     = styles[ 54 ] === true ? allowH : allowW ;
7802                                         w        = styles[ 45 ];
7803                                         minW     = styles[ 46 ];
7804                                         maxW     = styles[ 47 ];
7805                                         contentW = BasicLayoutManager.finalValue( w, minW, maxW, allowW );
7806                                         h        = styles[ 48 ];
7807                                         minW     = styles[ 49 ];
7808                                         maxW     = styles[ 50 ];
7809                                         contentH = BasicLayoutManager.finalValue( h, minW, maxW, allowH );
7810                                         paddingT = calc( styles[ 51 ], page );// paddingTRBL の % 指定は 最大幅に対して TB でも幅に対して
7811                                         paddingR = calc( styles[ 52 ], allowW );
7812                                         paddingB = calc( styles[ 53 ], page );
7813                                         paddingL = calc( styles[ 54 ], allowW );
7814                                         borderT  = styles[  0 ];
7815                                         borderR  = styles[  1 ];
7816                                         borderB  = styles[  2 ];
7817                                         borderL  = styles[  3 ];
7818                                         marginT  = calc( styles[ 55 ], page );// marginTRBL の % 指定は 最大幅に対して TB でも幅に対して
7819                                         marginR  = calc( styles[ 56 ], allowW );
7820                                         marginB  = calc( styles[ 57 ], page );
7821                                         marginL  = calc( styles[ 58 ], allowW );
7822                                         this.boxWidth      = contentW;
7823                                         this.boxHeight     = contentH;
7824                                         switch( styles[ 53 ] ){
7825                                                 case 3 : // margin-box
7826                                                          contentW -= ( marginR + marginL );
7827                                                          contentH -= ( marginT + marginR );
7828                                                          
7829                                                 case 2 : // border-box
7830                                                          contentW -= ( borderR + borderL );
7831                                                          contentH -= ( borderT + borderR );
7832                                                 case 1 : // padding-box
7833                                                          contentW -= ( paddingR + paddingL );
7834                                                          contentH -= ( paddingT + paddingR );
7835                                                 // case 0 : // content-box
7836                                         };
7837                                         this.contentX      = marginL + borderL + paddingL;
7838                                         this.contentY      = marginT + borderT + paddingT;                                      
7839                                         this.contentWidth  = contentW;
7840                                         this.contentHeight = contentH;
7841                                         this.autoHeight    = h === AUTO;
7842                                         this.autoWidth     = w === AUTO;
7843                                         this.autoSize      = this.autoWidth || this.autoHeight;
7844                                 } else {
7845                                         this.boxWidth  = this.contentWidth  = allowW;
7846                                         this.boxHeight = this.contentHeight = allowH;
7847                                         delete this.contentX;
7848                                         delete this.contentY;                                           
7849                                         delete this.autoSize;
7850                                         delete this.autoWidth;
7851                                         delete this.autoHeight;
7852                                 };
7853                         },
7854                         addDisplayElement : function( nodeData ){
7855                                 
7856                         },
7857                         removeDisplayElement : function( nodeData ){
7858                                 DOM.correct( nodeData.elmWrap );
7859                                 delete nodeData.elmWrap;
7860                                 delete nodeData.textNode;
7861                                 delete nodeData.contentWidth;
7862                                 delete nodeData.conetntHeight;
7863                                 delete nodeData.currentWidth;
7864                                 delete nodeData.currentHeight;                  
7865                         }
7866                 }
7867         );
7868         var Node = Class.create(
7869                 'Node',
7870                 Class.POOL_OBJECT,
7871                 NodePrivate,
7872                 {
7873                         Constructor : function( root, parent ){
7874                                 Node.newPrivateData( this,  LayoutBox.getPrivateData( root ), parent ? LayoutBox.getPrivateData( parent ) : undefined, this );
7875                         },
7876                         style : function( v ){
7877                                 return Node.getPrivateData( this ).paint( v );
7878                         },
7879                         remove : function(){
7880                                 Node.getPrivateData( this ).remove();
7881                         },
7882                         nodeIndex : function( v ){
7883                                 return Node.getPrivateData( this ).nodeIndex( v );
7884                         },
7885                         displayIndex : function(){
7886                                 
7887                         },
7888                         disabled : function( v ){
7889                                 return Node.getPrivateData( this ).disabled( v );
7890                         },
7891                         cursor : function( v ){
7892                                 return Node.getPrivateData( this ).cursor( v );
7893                         },
7894                         getAbsolutePositionX : function(){
7895                                 return Node.getPrivateData( this ).getAbsolutePositionX();
7896                         },
7897                         getAbsolutePositionY : function(){
7898                                 return Node.getPrivateData( this ).getAbsolutePositionY();
7899                         },
7900                         addEventListener : function( type, handler, opt_thisObject ){
7901                                 Node.getPrivateData( this ).addEventListener( type, handler, opt_thisObject );
7902                         },
7903                         removeEventListener : function( type, handler ){
7904                                 Node.getPrivateData( this ).removeEventListener( type, handler );
7905                         },
7906                         scrollTo : function( x, y ){
7907                                 Node.getPrivateData( this ).scrollTo( x, y );
7908                         },
7909                         scrollX : function( v ){
7910                                 return Node.getPrivateData( this ).scrollX( v );
7911                         },
7912                         scrollY : function( v ){
7913                                 return Node.getPrivateData( this ).scrollY( v );
7914                         }
7915                 }
7916         );
7917         
7918         var LayoutBoxPrivate = NodePrivate.inherits(
7919                 'LayoutBoxPrivate',
7920                 Class.POOL_OBJECT | Class.SUPER_ACCESS,
7921                 {
7922                         Constructor : function( layoutManager, root, parent ){
7923                                 this.layoutManager = layoutManager;
7924                                 this._root         = _root;
7925                                 if( _parent ) this._parent = _parent;
7926                         },
7927                         reflow : function(){
7928                                 this.layoutManager.reflow( this );
7929                         }
7930                 }
7931         );
7932         
7933         var LayoutBox = Node.inherits(
7934                 'LayoutBox',
7935                 Class.POOL_OBJECT,
7936                 LayoutBoxPrivate,
7937                 {
7938                         Constructor : function( layoutManager, root, parent ){
7939                                 LayoutBox.newPrivateData( this, layoutManager, LayoutBox.getPrivateData( root ), parent ? LayoutBox.getPrivateData( parent ) : undefined );
7940                         },
7941                         layoutManager : function( v ){
7942                                 
7943                         },
7944                         createLayoutBox : function(){
7945                                 
7946                         },
7947                         createContentBox : function(){
7948                                 
7949                         }
7950                 }
7951         );
7952         
7953 })( window, document );
7954         
7955 })( window, document );