OSDN Git Service

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