OSDN Git Service

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