12 ( function( window, document, undefined ){
14 var body = document.getElementsByTagName( 'body' )[ 0 ]; //( document.compatMode || '' ) !== 'CSS1Compat' ? document.body : document.documentElement;//
15 var SERVICE_LIST = [];
16 var SUPER_USER_KEY = { getUID: function(){ return 0; }};
17 var API_USER_LIST = [ SUPER_USER_KEY ];
20 function EMPTY_FUNCTION(){};
22 function isApiUser( _user ){
23 return _user === SUPER_USER_KEY ||
24 File.isDriver( _user ) === true ||
25 Application.isApplicationInstance( _user ) === true;
48 _____: parseInt( '00000', 2 ),
49 ____C: parseInt( '00001', 2 ), // hasCreateMenu
50 ___W_: parseInt( '00010', 2 ), // isWritable
51 ___WC: parseInt( '00011', 2 ), // isWritable
52 __R__: parseInt( '00100', 2 ), // isRenamable
53 __R_C: parseInt( '00101', 2 ), // hasCreateMenu
54 __RW_: parseInt( '00110', 2 ), // isWritable
55 __RWC: parseInt( '00111', 2 ), // isWritable
56 _S___: parseInt( '01000', 2 ), // childrenIsSortable
57 _S__C: parseInt( '01001', 2 ),
58 _S_W_: parseInt( '01010', 2 ),
59 _S_WC: parseInt( '01011', 2 ),
60 _SR__: parseInt( '01100', 2 ),
61 _SR_C: parseInt( '01101', 2 ),
62 _SRW_: parseInt( '01110', 2 ),
63 _SRWC: parseInt( '01111', 2 ),
64 D____: parseInt( '10000', 2 ),
65 D___C: parseInt( '10001', 2 ), // hasCreateMenu
66 D__W_: parseInt( '10010', 2 ), // isWritable
67 D__WC: parseInt( '10011', 2 ), // isWritable
68 D_R__: parseInt( '10100', 2 ), // isRenamable
69 D_R_C: parseInt( '10101', 2 ), // hasCreateMenu
70 D_RW_: parseInt( '10110', 2 ), // isWritable
71 D_RWC: parseInt( '10111', 2 ), // isWritable
72 DS___: parseInt( '11000', 2 ), // childrenIsSortable
73 DS__C: parseInt( '11001', 2 ),
74 DS_W_: parseInt( '11010', 2 ),
75 DS_WC: parseInt( '11011', 2 ),
76 DSR__: parseInt( '11100', 2 ),
77 DSR_C: parseInt( '11101', 2 ),
78 DSRW_: parseInt( '11110', 2 ),
79 DSRWC: parseInt( '11111', 2 ),
87 UPDATE_ATTRIVUTE: 'onFileUpdate',
88 GET_SEQENTIAL_FILES:'gotSeqentilFiles'
90 DATA_PROPERTY_RESERVED: [
91 'children', 'driver', 'state', 'type'
96 UPDATE: 'onTreeUpdate'
103 KEY_CHANGE: 'keychange',
117 * Class を定義し システムの管理下に置く.
118 * 全てのクラスと pool が有効の場合インスタンスへの参照が保持される.
119 * 1. Class.create( def, opt_final, opt_pool, opt_abstract ) でクラスを登録.
120 * 2. コンストラクタ となるメソッドは、Constructor : function( arg ){ ... }, に書く.
121 * 3. 通常通り new で インスタンス生成
122 * 4. kill() でオブジェクトをクリーンして削除、pool が有効の場合は pool される.
123 * 5. pool が有効の場合、new で pool されたインスタンスが返される.
127 var Class = ( function(){
130 PRIVATE_CLASS_LIST = [],
131 PRIVATE_DEF_LIST = [],
132 CONSTRUCTOR = 'Constructor',
133 GET_INDEX = Util.getIndex,
134 killPrivateFlag = false,
141 function getClass( instance ){
142 var cList = CLASS_LIST,
146 klass = cList[ --i ];
147 if( instance instanceof klass ) return klass;
149 cList = PRIVATE_CLASS_LIST;
152 klass = cList[ --i ];
153 if( instance instanceof klass ) return klass;
156 if( GET_INDEX( cList, instance ) !== -1 ) return instance;
157 if( GET_INDEX( CLASS_LIST, instance ) !== -1 ) return instance;
160 function getClassDef( KlassOrInstance ){
161 var getIndex = GET_INDEX,
162 i = getIndex( CLASS_LIST, KlassOrInstance );
163 if( i === -1 ) i = getIndex( CLASS_LIST, getClass( KlassOrInstance ) );
164 if( i !== -1 ) return DEF_LIST[ i ];
166 i = getIndex( PRIVATE_CLASS_LIST, KlassOrInstance );
167 if( i === -1 ) i = getIndex( PRIVATE_CLASS_LIST, getClass( KlassOrInstance ) );
168 if( i !== -1 ) return PRIVATE_DEF_LIST[ i ];
170 if( GET_INDEX( DEF_LIST, KlassOrInstance ) !== -1 ) return KlassOrInstance;
171 if( GET_INDEX( PRIVATE_DEF_LIST, KlassOrInstance ) !== -1 ) return KlassOrInstance;
174 /* over のプロパティを target にコピーする.ただし target の プロパティが優先, force で解除 */
175 function override( target, over, force ){
176 for( var p in over ){
177 if( force === true || typeof target[ p ] === 'undefined' ){
178 target[ p ] = over[ p ];
185 * var subClass = superClass.inherits( ... )
186 * http://d.hatena.ne.jp/m-hiyama/20051018/1129605002
188 function inherits( /* displayName, classSetting, opt_PrivateClass, props */ ){
189 var args = c( arguments ),
192 superDef = getClassDef( Super ),
193 displayName = args[ 0 ],
197 if( superDef.Final === true ) throw new Error( 'Class is final!' );
199 if( Type.isString( displayName ) === true ){
202 displayName = 'SubClass of ' + superDef.displayName;
204 params.push( displayName );
206 classSetting = args[ 0 ];
207 if( Type.isNumber( classSetting ) === true ){
208 if( superDef.isPrivate === true ) classSetting = classSetting | Class.PRIVATE_DATA;
209 opt_super = !!( classSetting & Class.SUPER_ACCESS );
210 params.push( classSetting );
213 if( getClass( args[ 0 ] ) ){
214 params.push( args.shift() );
216 if( superDef.privateClass ){
217 params.push( superDef.privateClass );
219 params.push( args[ 0 ] ); /* props */
221 traits = new Super();
223 klass = Class.create.apply( Class, params );
225 if( opt_super === true ) getClassDef( klass ).Super = Super.prototype;
229 /* Class.create で作られたクラスのインスタンスが共通で備えるメソッド */
233 klass = getClass( instance ),
234 def = getClassDef( klass ),
236 if( def.isPrivate === true && killPrivateFlag === false ){
237 throw new Error( 'PrivateInstance.kill() work in PrivateUser.kill().' );
239 Type.isFunction( instance.onKill ) === true && instance.onKill();
240 for( p in instance ){
241 if( instance.hasOwnProperty && !instance.hasOwnProperty( p ) ) continue;
242 delete instance[ p ];
245 def.live && def.live.splice( GET_INDEX( def.live, instance ), 1 );
246 def.pool.push( instance );
248 if( def.privateClass ){
249 i = GET_INDEX( def.userList, instance );
251 data = klass.getPrivateData( instance );
252 killPrivateFlag = true;
254 killPrivateFlag = false;
255 def.dataList.splice( i, 1 );
256 def.userList.splice( i, 1 );
260 // myCallback を受け取った API への通知
262 getMyCallback : function( callback ){
263 var def = getClassDef( this ),
264 iList = def.callbackInstanceList,
265 rList = def.callbackRegisterList,
266 i, cList, myCallback;
268 iList = def.callbackInstanceList = [];
269 rList = def.callbackRegisterList = [];
271 i = GET_INDEX( iList, this );
278 for( i = cList.length; i; ){
279 if( cList[ --i ].callback === callback ) return cList[ i ];
282 myCallback = new Callback( this, callback );
283 cList.push( myCallback );
286 releaseMyCallback : function( callback ){
287 var def = getClassDef( this ),
288 iList = def.callbackInstanceList,
289 rList = def.callbackRegisterList,
292 i = GET_INDEX( iList, this );
293 if( i === -1 ) return;
295 _i = GET_INDEX( cList, callback );
296 if( _i === -1 ) return;
297 cList.splice( _i, 1 );
299 if( cList.length !== 0 ) return;
300 iList.splice( i, 1 );
301 rList.splice( i, 1 );
302 if( iList.length !== 0 ) return;
303 delete def.callbackInstanceList;
304 delete def.callbackRegisterList;
308 /* privateDataclass をもつクラスに追加されるメソッド */
309 function newPrivateData( /* instance, args */ ){
310 var args = c( arguments ),
312 def = getClassDef( user ),
313 privateClass = def.privateClass,
314 privateDef = getClassDef( privateClass ),
318 i = GET_INDEX( def.userList, user );
324 throw new Error( 'PrivateData already exist!' );
327 data = new privateClass( args );
332 function getPrivateData( instance ){
333 var def = getClassDef( instance ),
334 i = GET_INDEX( def.userList, instance );
335 if( i !== -1 ) return def.dataList[ i ];
339 * new の実体.コンストラクタの機能は instance.Constructor に書く.
340 * これにより pool された オブジェクト(破棄されたインスタンス) を再利用できる
342 /* Constructor Real for GeneralClass */
345 def = getClassDef( klass ),
348 if( def.Abstract === true ){
349 throw new Error( 'AbstractClass!' );
351 if( def.isPrivate === true && dataUser === null ){
352 throw new Error( 'use myClass.newPrivateData( instance, ...args )!' );
355 instance = def.pool && def.pool.length > 0 ? def.pool.shift() : instance = new klass();
357 if( def.Super && !instance.Super ) instance.Super = def.Super;
358 if( def.isPrivate === true ){
359 userDef = getClassDef( dataUser );
360 userDef.dataList.push( instance );
361 userDef.userList.push( dataUser );
363 def.live && def.live.push( instance );
364 args = c( arguments );
366 def[ CONSTRUCTOR ] && def[ CONSTRUCTOR ].apply( instance, args );
376 create : function( /* displayName, classSetting, opt_PrivateClass, props */ ){
377 var args = c( arguments ),
378 displayName = args[ 0 ],
380 opt_pool, opt_abstract, opt_final, opt_private,
385 if( Type.isString( displayName ) === true ){
386 classDef.displayName = displayName;
389 classSetting = args[ 0 ];
390 if( Type.isNumber( classSetting ) === true ){
391 opt_pool = !!( classSetting & Class.POOL_OBJECT );
392 opt_abstract = !!( classSetting & Class.ABSTRACT );
393 opt_final = !!( classSetting & Class.FINAL );
394 opt_private = !!( classSetting & Class.PRIVATE_DATA );
395 if( opt_final === true && opt_abstract === true ){
396 throw new Error( 'final & Abstract!' );
401 if( GET_INDEX( PRIVATE_CLASS_LIST, args[ 0 ] ) !== -1 ){
402 privateDef = getClassDef( args[ 0 ] );
403 if( privateDef.isPrivate !== true ){
404 throw new Error( 'PrivateClass not found! please, Class.create( Class.PRIVATE, {...} ).' );
406 if( privateDef.Abstract === true ){
407 throw new Error( 'PrivateClass is Abstract!' );
409 classDef.privateClass = args.shift();
412 if( props === null || Type.isObject( props ) === false ){
413 throw new Error( 'No Class Def!' );
416 if( Type.isFunction( props[ CONSTRUCTOR ] ) === true ){
417 classDef[ CONSTRUCTOR ] = props[ CONSTRUCTOR ];
420 klass = function(){ a = arguments; if( f ) return C.apply( a.callee, c( a ) )};
421 klass.prototype = override( override( traits || {}, props, true ), CommonProps, false );
423 if( opt_abstract === true ){
424 classDef.Abstract = true;
426 if( opt_pool === true ){
428 if( opt_private === false )classDef.live = [];
430 if( opt_final === true ){
431 classDef.Final = true;
433 klass.inherits = inherits;
435 if( opt_private === true ){
436 if( classDef.privateClass ){
437 throw new Error( 'Private Data Class has no PrivateClass!' );
439 classDef.isPrivate = true;
440 PRIVATE_CLASS_LIST.push( klass );
441 PRIVATE_DEF_LIST.push( classDef );
443 if( classDef.privateClass ){
444 klass.newPrivateData = newPrivateData;
445 klass.getPrivateData = getPrivateData;
447 CLASS_LIST.push( klass );
448 DEF_LIST.push( classDef );
452 onShutdown : function(){
455 getClass : function( instance ){
456 return getClass( instance );
458 getClassDef : function(){
465 * Callback 時に thisObject や args を指定したい場合に使用.
467 var Callback = Class.create(
468 Class.POOL_OBJECT | Class.FINAL, {
469 Constructor : function( thisObject, callback, opt_args ){
470 if( Type.isFunction( callback ) === false ){
471 throw new Error( 'Not function!' );
473 this.callback = callback;
474 if( thisObject ) this.thisObject = thisObject;
475 if( Type.isArray( opt_args ) === true ){
476 this.args = opt_args;
478 if( opt_args !== undefined ){
482 fire : function( /* args */ ){
483 var thisObject = this.thisObject || window,
484 args = Util.copyArray( arguments );
485 if( 0 < args.length ){
486 if( this.args !== undefined ){
487 args.push.apply( args, this.args );
489 if( this.arg !== undefined ){
490 args.push( this.arg );
492 this.callback.apply( thisObject, args );
494 if( this.args !== undefined ){
495 this.callback.apply( thisObject, this.args );
497 if( this.arg !== undefined ){
498 this.callback.call( thisObject, this.arg );
500 this.callback.call( thisObject );
504 registerUser : function( user ){
505 if( !this.userList ){
506 this.userList = [ user ];
508 Util.getIndex( this.userList, user ) === -1 && this.userList.push( user );
512 var instance = this.thisObject;
513 this.userList && Class.getClass( instance ) && instance.releaseMyCalllback( this );
518 /* --------------------------------------------------------------
523 var SystemTimer = ( function(){
524 var setTimeout = window.setTimeout;
525 var clearTimeout = window.clearTimeout;
526 var INTERVAL_TIME = 16;
527 var TICKET_LIST = [];
528 var timerId = undefined;
534 for( i = 0; i < list.length; ){
535 if( list[ i ].fire( next ) !== false ) ++i;
541 var list = TICKET_LIST,
546 timerId !== undefined && clearTimeout( timerId );
551 c = list[ --l ].count;
554 if( next > n || timerId === undefined ){
555 timerId !== undefined && clearTimeout( timerId );
556 timerId = setTimeout( loop, INTERVAL_TIME * n );
561 var TimerTicket = Class.create(
563 Constructor : function( apiuser, callback, time, once, opt_thisObject ){
564 this.apiuser = apiuser;
565 this.callback = callback;
568 if( once ) this.once = once;
569 this.thisObj = opt_thisObject || apiuser;
571 fire : function( c ){
573 if( 0 < this.count ) return;
574 this.callback.call( this.thisObj );
575 if( this.once === true ){
577 TICKET_LIST.splice( Util.getIndex( TICKET_LIST, this ), 1 );
580 this.count = this.time;
583 destroy : function( apiuser, callback ){
584 if( apiuser && apiuser !== this.apiuser ) return false;
585 if( callback && callback !== this.callback ) return false;
594 add: function( _apiuser, _handler, _time, _once, opt_thisObject ){
595 if( Type.isNumber( _time ) === false || _time < INTERVAL_TIME ) _time = INTERVAL_TIME;
597 var _ticket = new TimerTicket( _apiuser, _handler, Math.ceil( _time / INTERVAL_TIME ), _once, opt_thisObject );
598 TICKET_LIST.push( _ticket );
602 remove: function( _apiuser, _handler ){
605 while( _ticket = TICKET_LIST[ i ] ){
606 if( _ticket.destroy( _apiuser, _handler ) === true ){
607 TICKET_LIST.splice( i, 1 );
617 /* --------------------------------------------------------------
621 var AsyncCall = ( function(){
622 var CALLBACK_LIST = [];
624 var CallbackTicket = Class.create(
626 Constructor : function( apiuser, callback, args, thisObject ){
627 this.apiuser = apiuser;
628 this.callback = callback;
630 this.thisObj = thisObject || apiuser;
633 var f = this.callback,
637 if( Type.isArray( a ) === true ){
643 destroy : function( apiuser, callback ){
644 if( apiuser && apiuser !== this.apiuser ) return false;
645 if( callback && callback !== this.callback ) return false;
653 var _ticket = CALLBACK_LIST.shift();
656 CALLBACK_LIST.length !== 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true );
661 add: function( _apiuser, _callback, _argments, _thisObject ){
662 CALLBACK_LIST.length === 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true );
663 CALLBACK_LIST.push( new CallbackTicket( _apiuser, _callback, _argments, _thisObject ) );
665 remove: function( _apiuser, _callback ){
668 while( _ticket = CALLBACK_LIST[ i ] ){
669 if( _ticket.destroy( _apiuser, _callback ) === true ){
670 CALLBACK_LIST.splice( i, 1 );
679 /* -----------------------------------------------------------
681 * お気に入り画像一覧 > tag:ペン次郎 > ペン次郎:笑う
682 * 最近アップロードされた画像 > images
684 * キャラクター画像庫 > アニマル系 > tag:ペン次郎 > ペン次郎:笑う
691 var File = ( function(){
692 var DRIVER_LIST = [];
694 var FILE_TYPE_IS_FOLDER = Const.FILE.TYPE.FOLDER,
695 numFileType = Const.FILE.TYPE.XML,
696 FILEDATA_RESITER = [], // store all of fileData( json object )
697 FILEDATA_ACCESS = [], // file operations for Kernel only ! hide from Out of File
698 FILE_OBJECT_POOL = [],
699 EVENT_LISTENER_REGISTER = [],
701 TREE_ACCESS_ARRAY = [];
703 var REQUEST_CONTROLER = ( function(){
704 var REQUEST_TICKET_RESISTER = [],
705 currentTicket = null,
707 DATA_TYPE_ARRAY = 'json,xml,html,text'.split( ',' ),
714 var RequestTicket = Class.create(
716 Constructor : function( apiuser, type, data, url, onLoad, onError ){
717 this.apiuser = apiuser;
721 this.onLoad = onLoad;
722 this.onError = onError;
725 load : function( data ){
726 AsyncCall.add( this.apiuser, this.onLoad, [ this.data, data ] );
729 AsyncCall.add( this.apiuser, this.onError, this.data );
734 if( currentTicket !== null || REQUEST_TICKET_RESISTER.length === 0 ) return;
735 currentTicket = REQUEST_TICKET_RESISTER.shift();
737 url: currentTicket.url,
738 dataType: DATA_TYPE_ARRAY[ currentTicket.type ],
743 function onSuccess( _data ){
744 currentTicket.load( _data );
745 currentTicket.kill();
746 currentTicket = null;
751 currentTicket.error();
752 currentTicket.kill(); // retry
753 currentTicket = null;
758 getNumTask: function(){
759 return REQUEST_TICKET_RESISTER.length;
761 getNumError: function(){
764 getJson: function( _apiuser, _data, _url, _onLoad, _onError ){
765 REQUEST_TICKET_RESISTER.push( new RequestTicket( _apiuser, DATA_IS_JSON, _data, _url, _onLoad, _onError ));
766 currentTicket === null && request();
771 var FILE_CONTROLER = {
772 createTree: function( _apiuser, _rootFileData ){
773 var _tree = new TreeClass( _apiuser, _rootFileData );
774 TREE_ARRAY.push( _tree );
777 getFileUID: function( FILEDATAorFILE ){
778 if( FILEDATAorFILE instanceof FileClass ){
779 return FILEDATAorFILE.getUID();
782 var uid = Util.getIndex( FILEDATA_RESITER, FILEDATAorFILE );
784 uid = FILEDATA_RESITER.length;
785 FILEDATA_RESITER.push( FILEDATAorFILE );
789 getFileDataAccess: function( UIDorFILEorFILEDATA ){
790 var _uid, _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA ), _access;
792 if( _data === null || typeof _data !== 'object' ) return null;
793 for( var i=0, l = FILEDATA_ACCESS.length; i<l; ++i ){
794 _access = FILEDATA_ACCESS[ i ];
795 if( _access.DATA === _data ) return _access;
799 getFileData: function( UIDorFILEorFILEDATA ){
800 if( typeof UIDorFILEorFILEDATA === 'number' ){
801 return FILEDATA_RESITER[ UIDorFILEorFILEDATA ] || null;
803 if( UIDorFILEorFILEDATA instanceof FileClass ){
804 return FILEDATA_RESITER[ UIDorFILEorFILEDATA.getUID() ] || null;
806 if( Util.getIndex( FILEDATA_RESITER, UIDorFILEorFILEDATA ) !== -1 ){
807 return UIDorFILEorFILEDATA;
811 getChildren: function( UIDorFILEorFILEDATA ){
812 var _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA );
813 return _data !== null ? _data.children || null : null;
815 getDriver: function( _file ){
816 var _data = FILE_CONTROLER.getFileData( _file );
817 return _data !== null && _data.driver ? _data.driver : BASE_DRIVER;
819 getUpdateFlag: function( _file, _bit ){
820 var _driver = FILE_CONTROLER.getDriver( _file ),
822 if( typeof _driver.getUpdatePolicy === 'function' ){
823 _policy = _driver.getUpdatePolicy( _file );
826 if( typeof _policy !== 'number' ) {
827 _policy = BASE_DRIVER.getUpdatePolicy( _file )
829 return _policy % ( _bit * 2 ) >= _bit;
831 move: function( _prentUID, _targetfile, _newFolder, _newIndex, _opt_callback ){
832 var _parentData = FILE_CONTROLER.getFileDataAccess( _prentUID ),
833 _parentType = _parentData.TYPE,
834 _targetData = FILE_CONTROLER.getFileDataAccess( _targetfile ),
835 _targetType = _targetData.TYPE;
837 replace: function( _uid, _file, _newIndex ){
840 addEventListener: function( FILEorNULL, _eventType, _callback, opt_thisObject ){
841 var _uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL;
842 EVENT_LISTENER_REGISTER.push( new FileEventTicket( _uid, _eventType, _callback, opt_thisObject ));
844 removeEventListener: function( FILEorNULL, eventType, callback ){
845 var uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL,
846 list = EVENT_LISTENER_REGISTER,
849 for( ; i < list.length; ){
851 if( ticket.fileUID === uid && ticket.eventType === eventType && ticket.callBack === callback ){
859 getTreeAccess: function(){
862 fileEventRellay: function( _uid, _event ){
863 var _fileAccess = FILE_CONTROLER.getFileDataAccess( _uid );
864 if( _fileAccess === null ) return;
865 var _treeUID = _fileAccess.TREE.getUID(),
866 _treeAccess = TREE_ACCESS_ARRAY[ _treeUID ],
867 _data = _fileAccess.DATA,
869 if( !_treeAccess ) return;
870 _treeAccess.dispatchFileEvent( _event );
871 for( var i=0, l = TREE_ARRAY.length; i<l; ++i ){
872 if( i !== _treeUID ){
873 _tree = TREE_ARRAY[ i ];
874 if( FILE_CONTROLER.getFileData( _tree.getCurrentFile() ) === _data ){
875 _treeAccess = TREE_ACCESS_ARRAY[ _tree.getUID() ];
876 _treeAccess && _treeAccess.dispatchFileEvent( _event );
883 var TreeClass = function( apiuser, rootFileData ){
884 var PARENT_FILE_RESITER = [],
887 dispatchFileEvent: dispatchFileEvent
889 EVENT_LISTENER_ARRAY = [],
891 rootFile = new FileClass( instance, null, rootFileData ),
892 currentFile = rootFile;
894 currentFile.getSeqentialFiles();
895 TREE_ACCESS_ARRAY.push( ACCESS );
897 function dispatchFileEvent( e ){
898 var _eventType = e.eventType,
899 _targetFile = e.targetFile,
900 _uid = _targetFile.getUID(),
901 _ticket, _type, _callback;
902 for( var i=0, l = EVENT_LISTENER_REGISTER.length; i<l; ++i ){
903 _ticket = EVENT_LISTENER_REGISTER[ i ];
904 _type = _ticket.eventType;
905 _callback = _ticket.callBack;
906 if( _eventType === _type && _uid === _ticket.fileUID ){
907 AsyncCall.add( apiuser, _callback, [ _eventType, _targetFile, e.key, e.value ], _ticket.thisObject || _targetFile );
909 if( _type === Const.TREE.EVENT.UPDATE && _eventType === Const.FILE.EVENT.GET_SEQENTIAL_FILES ){
910 //_callback( _eventType, _targetFile );
911 AsyncCall.add( apiuser, _callback, [ _eventType, _targetFile ], _ticket.thisObject || instance );
916 this.getUID = function(){
917 return Util.getIndex( TREE_ACCESS_ARRAY, ACCESS );
919 this.getRootFile = function(){
922 this.getCurrentFile = function(){
925 this.hierarchy = function(){
926 return PARENT_FILE_RESITER.length;
928 this.getParentFileAt = function( _index ){
929 var l = PARENT_FILE_RESITER.length;
930 if( typeof _index !== 'number' || _index < 0 || _index >= l ) return null;
931 return PARENT_FILE_RESITER[ l -1 -_index ];
933 this.down = function( _index ){
934 if( typeof _index !== 'number' || _index < 0 || _index >= currentFile.getChildFileLength()) return;
935 PARENT_FILE_RESITER.unshift( currentFile );
936 currentFile = currentFile.getChildFileAt( _index );
937 currentFile.getSeqentialFiles();
940 this.up = function( _index ){
941 var l = PARENT_FILE_RESITER.length;
942 if( l === 0 ) return null;
945 var _currentFile = currentFile;
947 _currentFile.destroy();
949 if( typeof _index === 'number' ){
950 if( _index >= l ) return null;
951 currentFile = this.getParentFileAt( _index );
952 PARENT_FILE_RESITER.splice( 0, l -_index);
954 currentFile = PARENT_FILE_RESITER.shift();
956 currentFile.getSeqentialFiles();
959 this.addTreeEventListener = function( _eventType, _callback, opt_thisObject ){
960 FILE_CONTROLER.addEventListener( null, _eventType, _callback, opt_thisObject );
962 this.removeTreeEventListener = function( _eventType, _callback ){
963 FILE_CONTROLER.removeEventListener( null, _eventType, _callback );
965 this.destroy = function( _apiuser ){
966 if( _apiuser && apiuser !== _apiuser ) return false;
968 var _currentFile = currentFile;
969 currentFile = rootFile = rootFileData = null;
970 // currentFile, rootFile を null にしないと .File.destroy() ができない.
971 _currentFile.destroy();
972 while( PARENT_FILE_RESITER.length > 0 ){
973 _currentFile = PARENT_FILE_RESITER.shift();
974 _currentFile.destroy();
977 AsyncCall.remove( apiuser );
978 instance = apiuser = null;
983 var FileEventTicket = Class.create(
985 Constructor : function( uid, eventType, callback, opt_thisObject ){
987 this.eventType = eventType;
988 this.callBack = callback;
989 this.thisObject = opt_thisObject;
993 var FileEventClass = function( eventType, file, key, value ){
994 this.eventType = eventType;
995 this.targetFile = file;
996 this.updatedAttribute = key;
997 this.updatedValue = value;
1001 * file の data は object で保持している。
1002 * File の外からファイルをみるときは、FileClassを通して操作する。
1003 * fileの変更、それに付随して追加されたイベントは、TreeClassで管理される。
1004 * treeがdestryされると、fileのイベントリスナーも全て削除される。
1005 * 他の tree も data の共通する currentFile に対してのみは、file の変更イベントを受け取って流す.
1009 var FileClass = function( tree, parentData, data ){
1010 var uid = FILE_CONTROLER.getFileUID( data );
1012 FILEDATA_ACCESS.push( {
1014 parentData: parentData,
1018 tree = parentData = data = null;
1020 this.getUID = function(){
1025 FileClass.prototype = {
1026 isChildFile: function( _FILEorFILEDATA ){
1027 return this.getChildFileIndex( _FILEorFILEDATA) !== -1;
1029 getSeqentialFiles: function(){
1030 var _driver = FILE_CONTROLER.getDriver( this );
1031 if( _driver !== null && typeof _driver.getSeqentialFiles === 'function' ){
1032 _driver.getSeqentialFiles( this );
1035 addEventListener: function( _eventType, _callback ){
1036 FILE_CONTROLER.addEventListener( this, _eventType, _callback );
1038 removeEventListener: function( _eventType, _callback ){
1039 FILE_CONTROLER.removeEventListener( this, _eventType, _callback );
1041 dispatchEvent: function( e ){
1042 e instanceof FileEventClass && FILE_CONTROLER.fileEventRellay( this.getUID(), e );
1044 getChildFileLength: function(){
1045 var children = FILE_CONTROLER.getChildren( this );
1046 return Type.isArray( children ) === true ? children.length : -1;
1048 getChildFileIndex: function( _FILEorFILEDATA ){
1049 var children = FILE_CONTROLER.getChildren( this );
1050 if( Type.isArray( children ) === false ) return -1;
1051 var l = children.length,
1052 _fileData = FILE_CONTROLER.getFileData( _FILEorFILEDATA );
1053 if( _fileData === null ) return -1;
1054 for( var i=0; i<l; ++i ){
1055 if( children[ i ] === _fileData ) return i;
1059 getChildFileAt: function( _index ){
1060 var _access = FILE_CONTROLER.getFileDataAccess( this ),
1061 _children = FILE_CONTROLER.getChildren( this );
1062 if( typeof _index !== 'number' || _index < 0 || Type.isArray( _children ) === false || _index >= _children.length ) return null;
1063 var _file = new FileClass( _access.TREE, _access.DATA, _children[ _index ]);
1067 getName: function(){
1068 var driver = FILE_CONTROLER.getDriver( this );
1069 if( typeof driver.getName === 'function'){
1070 return driver.getName( this );
1072 return BASE_DRIVER.getName( this );
1074 getThumbnail: function(){
1075 var driver = FILE_CONTROLER.getDriver( this );
1076 if( typeof driver.getThumbnail === 'function'){
1077 return driver.getThumbnail( this );
1079 return BASE_DRIVER.getThumbnail( this );
1081 getType: function(){
1082 var _data = FILE_CONTROLER.getFileData( this );
1083 return typeof _data.type === 'number' ? _data.type : Const.FILE.TYPE.UNKNOWN;
1085 getState: function(){
1086 var _data = FILE_CONTROLER.getFileData( this );
1087 return typeof _data.state === 'number' ? _data.state : Const.FILE.STATE.OK;
1089 getSummary: function(){
1090 var driver = FILE_CONTROLER.getDriver( this );
1091 if( typeof driver.getSummary === 'function'){
1092 return driver.getSummary( this );
1094 return BASE_DRIVER.getSummary( this );
1096 isWritable: function(){
1097 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.WRITE );
1099 isSortable: function(){
1100 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.SORT );
1102 isCreatable: function(){
1103 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.CREATE );
1105 isRenamable: function(){
1106 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.RENAME );
1108 isDeletable: function(){
1109 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.DELETE );
1113 var driver = FILE_CONTROLER.getDriver( this ),
1115 if( Type.isFunction( driver.read ) === true ){
1116 data = driver.read( this );
1118 return BASE_DRIVER.read( data || this );
1120 write: function( _newData, _onUpdateFunction ){
1121 var driver = FILE_CONTROLER.getDriver( this );
1122 if( typeof driver.write === 'function'){
1123 return driver.write( this, _newData, _onUpdateFunction );
1125 return BASE_DRIVER.write( this, _newData, _onUpdateFunction );
1127 viewerApplicationList: function(){
1128 var driver = FILE_CONTROLER.getDriver( this );
1129 if( typeof driver.viewerApplicationList === 'function'){
1130 return driver.viewerApplicationList( this );
1132 return BASE_DRIVER.viewerApplicationList( this );
1134 editorApplicationList: function(){
1135 var driver = FILE_CONTROLER.getDriver( this );
1136 if( typeof driver.editorApplicationList === 'function'){
1137 return driver.editorApplicationList( this );
1139 return BASE_DRIVER.viwerApps( this );
1150 onDelete: function(){
1153 move: function( _newFolder, _newIndex, opt_callback ){
1154 var _access = FILE_CONTROLER.getFileDataAccess( this );
1155 _access.TREE.move( _access.parentData, this.getUID(), _newFolder, _newIndex, opt_callback );
1157 replace: function( _newIndex, opt_callback ){
1158 var _access = FILE_CONTROLER.getFileDataAccess( this );
1159 _access.TREE.replace( _access.parentData, this.getUID(), _newIndex, opt_callback);
1163 * 探しているファイルの属性と値を指定.一致する child の index を配列で返す.
1165 search: function( obj, rule ){
1166 var _children = FILE_CONTROLER.getChildren( this ),
1169 for( var i=0, l=_children.length; i<l; ++i ){
1170 _child = _children[ i ];
1173 if( obj[ k ] !== _child[ k ] ){
1178 c === true && ret.push( i );
1182 destroy: function(){
1183 var _access = FILE_CONTROLER.getFileDataAccess( this );
1184 var _tree = _access.TREE;
1185 if( _tree.getCurrentFile() === this ) return;
1186 if( _tree.getRootFile() === this ) return;
1187 for( var i=0, l = _tree.hierarchy(); i<l; ++i ){
1188 if( _tree.getParentFileAt( i ) === this ){
1192 var _index = Util.getIndex( FILEDATA_ACCESS, _access );
1193 if( _index === -1 ) return;
1195 FILEDATA_ACCESS.splice( _index, 1 );
1196 delete _access.DATA;
1197 delete _access.TREE;
1198 delete _access.parentData;
1205 var FileDriverBase = function( driverClass ){
1206 this.getUID = function(){
1207 return Util.getIndex( API_USER_LIST, driverClass );
1209 this.getSeqentialFiles = function( _file ){
1211 this.getName = function( _file ){
1212 var _data = FILE_CONTROLER.getFileData( _file );
1213 return _data.name || 'No Name';
1215 this.getThumbnail = function( _file ){
1216 var _data = FILE_CONTROLER.getFileData( _file ),
1219 if( _type === Const.FILE.TYPE.FOLDER ){
1220 _className = 'folder';
1222 if( _type === Const.FILE.TYPE.IMAGE ){
1225 if( _type === Const.FILE.TYPE.TEXT ){
1228 if( _type === Const.FILE.TYPE.HTML ){
1231 if( _type === Const.FILE.TYPE.CSV ){
1234 if( _type === Const.FILE.TYPE.JSON ){
1237 if( _type === Const.FILE.TYPE.XML ){
1242 className: ' file-type-' + _className
1245 this.getSummary = function( _file ){
1246 var _data = FILE_CONTROLER.getFileData( _file ),
1248 if( _type === Const.FILE.TYPE.FOLDER ){
1251 if( _type === Const.FILE.TYPE.IMAGE ){
1252 return 'image file';
1254 if( _type === Const.FILE.TYPE.TEXT ){
1257 if( _type === Const.FILE.TYPE.HTML ){
1258 return 'html document file';
1260 if( _type === Const.FILE.TYPE.CSV ){
1261 return 'csv daat file';
1263 if( _type === Const.FILE.TYPE.JSON ){
1264 return 'json data file';
1266 if( _type === Const.FILE.TYPE.XML ){
1267 return 'xml data file';
1271 this.getUpdatePolicy = function( _file ){
1272 // debug用 全てのメニューを許可
1273 return Const.FILE.UPDATE_POLICY.DSRWC;
1275 this.read = function( FILEorDATA ){
1277 protects = Const.FILE.DATA_PROPERTY_RESERVED,
1280 getIndex = Util.getIndex;
1281 if( FILEorDATA instanceof FileClass ){
1282 data = FILE_CONTROLER.getFileData( FILEorDATA )
1287 function clone( src ) {
1289 if( Type.isArray( src ) === true ){
1290 i = getIndex( objSrc, src );
1291 if( i !== -1 ) return objCopy[ i ];
1293 objSrc[ objSrc.length ] = src;
1294 objCopy[ objCopy.length ] = ret;
1296 if( Type.isObject( src ) === true ){
1297 i = getIndex( objSrc, src );
1298 if( i !== -1 ) return objCopy[ i ];
1300 objSrc[ objSrc.length ] = src;
1301 objCopy[ objCopy.length ] = ret;
1303 if( Type.isNumber( src ) === true || Type.isString( src ) === true || Type.isBoolean( src ) === true ){
1309 if( getIndex( protects, key ) === -1 ){
1310 ret[ key ] = clone( src[ key ]);
1315 return clone( data );
1317 this.write = function( _file, _newData, _onUpdateFunction ){
1318 var _data = FILE_CONTROLER.getFileData( _file ),
1322 this.viewerApplicationList = function(){
1325 this.editorApplicationList = function(){
1328 this.onCreate = function(){
1331 this.onSort = function(){
1334 this.onCopy = function(){
1337 this.onDelete = function(){
1342 var BASE_DRIVER = new FileDriverBase();
1344 var ROOT_FILEDATA = {
1345 name: 'system root',
1346 type: FILE_TYPE_IS_FOLDER,
1349 SYSTEM_TREE = FILE_CONTROLER.createTree( SUPER_USER_KEY, ROOT_FILEDATA ),
1350 ROOT_FILE = SYSTEM_TREE.getRootFile();
1352 function createFileTypeID(){
1353 return ++numFileType;
1356 var FileAPIClass = function( driver ){
1358 this.createFolderUnderRoot = function( _fileData ){
1359 if( _fileData !== null && Type.isObject( _fileData ) === true ){
1360 ROOT_FILEDATA.children.push( _fileData );
1361 ROOT_FILE.dispatchEvent( new FileEventClass( Const.FILE.EVENT.GET_SEQENTIAL_FILES, ROOT_FILE, 'children', null ));
1364 this.createFileEvent = function( _eventType, _file, _key, _value ){
1365 return new FileEventClass( _eventType, _file, _key, _value );
1367 this.createFileTypeID = createFileTypeID;
1368 this.getFileDataAccess = FILE_CONTROLER.getFileDataAccess;
1369 this.getFileData = FILE_CONTROLER.getFileData;
1370 this.getJson = function( _data, _url, _onLoad, _onError ){
1371 REQUEST_CONTROLER.getJson( driver, _data, _url, _onLoad, _onError );
1373 this.createTree = function( _rootFile ){
1374 return FILE_CONTROLER.createTree( driver, _rootFile );
1376 this.isTreeInstance = function( _tree ){
1377 return _tree instanceof TreeClass;
1379 this.isFileInstance = function( _file ){
1380 return _file instanceof FileClass;
1382 this.isFileEvent = function( _event ){
1383 return _event instanceof FileEventClass;
1385 this.getConst = function(){
1386 return Const; // constObject = constObject || clone( Const )
1391 registerDriver: function( _class ){
1392 _class.prototype = new FileDriverBase( _class );
1393 var _driver = new _class();
1395 DRIVER_LIST.push( _driver );
1396 API_USER_LIST.push( _class );
1398 return new FileAPIClass( _driver );
1400 isDriver: function( _driver ){
1401 return _driver instanceof FileDriverBase;
1403 isTreeInstance: function( _tree ){
1404 return _tree instanceof TreeClass;
1406 isFileInstance: function( _file ){
1407 return _file instanceof FileClass;
1413 /* ----------------------------------------------------
1414 * ApplicationManager
1415 * window resize event, overlayApplication currentAplication に流す
1418 var APPLICATION_LIST = [];
1420 var ApplicationPrivateData = function(){};
1421 ApplicationPrivateData.prototype = {
1427 bgColor : '#C1CACF',
1439 init : function( appClass, displayName, isOverlay ){
1440 this.appClass = appClass;
1441 // this.application = app;
1442 this.displayName = displayName;
1443 this.isOverlay = isOverlay;
1444 this.rootElement = document.createElement( 'div' );
1445 this.styleCursor = this.rootElement.style;
1446 ApplicationPrivateData.list.push( this );
1448 detect : function(){
1449 if( this.rootElement.firstChild && this.fetchResource === 0 ){
1450 SystemTimer.remove( this.application, this.detect );
1454 onOpen : function(){
1455 this.rootElement.style.display = '';
1457 // this.layer !== null && this.layer.onResize( this.w, this.h );
1459 if( this.application.MIN_WIDTH > this.w || this.application.MIN_HEIGHT > this.h ){
1460 if( Type.isHTMLElement( this.rootElement ) === true ){
1464 if( this.bootParams.length > 2 ){
1465 this.application.onOpen.apply( this.application, this.bootParams );
1467 this.application.onOpen( this.w, this.h );
1471 fetchResourceComplete : function(){
1472 --this.fetchResource;
1475 ApplicationPrivateData.list = [];
1476 ApplicationPrivateData.get = function( app ){
1477 var list = ApplicationPrivateData.list,
1480 if( app instanceof list[ --i ].appClass ) return list[ i ];
1485 var AbstractApplication = function( appClass, displayName, isOverlay ){
1486 ( new ApplicationPrivateData() ).init( appClass, displayName, isOverlay );
1488 AbstractApplication.prototype = {
1489 getUID : function(){
1490 var data = ApplicationPrivateData.get( this );
1491 return Util.getIndex( API_USER_LIST, data.appClass );
1494 var data = ApplicationPrivateData.get( this );
1495 // this.rootElement = data.rootElement;
1496 // data.application = this;
1498 data.appClass === Page.appClass && Page.show();
1502 open : function( w, h /*, _option */ ){
1503 var data = ApplicationPrivateData.get( this );
1505 data.bootParams = Util.copyArray( arguments );
1508 if( data.rootElement.innerHTML && data.rootElement.innerHTML.length > 0 ){
1509 SystemTimer.add( this, data.detect, 16, false, data );
1514 resize : function( w, h ){
1515 var data = ApplicationPrivateData.get( this );
1516 if( data.phase !== 4 ) return;
1517 if( this.MIN_WIDTH > w || this.MIN_HEIGHT > h ){
1518 if( Type.isHTMLElement( this.rootElement ) === true ){
1523 this.onPaneResize( w, h );
1526 var data = ApplicationPrivateData.get( this );
1528 if( this.onClose() === false ){
1532 while( data.uiList.length > 0 ) data.uiList.shift().destroy();
1534 if( data.finderList ){
1535 while( data.finderList.length > 0 ) data.finderList.shift().destroy();
1538 data.eventRoot && PointingDeviceEventTree.destroyTree( data.eventRoot );
1539 MouseEvent.remove( this );
1540 KeyEvent.remove( this );
1541 SystemTimer.remove( this );
1542 AsyncCall.remove( this );
1543 StyleSheet.unload( this );
1545 var elm = this.rootElement;
1546 Util.removeAllChildren( elm );
1547 elm.parentNode.removeChild( elm );
1549 Application.shutdown( this, data.isOverlay );
1551 data.appClass === Page.appClass && Page.hide();
1555 var list = ApplicationPrivateData.list;
1556 list.splice( Util.getIndex( list, data ), 1 );
1558 createUIGroup : function( node ){
1559 var data = ApplicationPrivateData.get( this ),
1560 ui = UI.createUIGroup( this, node );
1561 if( data.uiList === null ) data.uiList = [];
1562 data.uiList.push( ui );
1565 createUIForm : function( nodeOrElm, opt_elmForm ){
1566 var data = ApplicationPrivateData.get( this ),
1567 form = UIForm.createForm( this, nodeOrElm, opt_elmForm );
1568 if( data.formList === null ) data.formList = [];
1569 data.formList.push( form );
1572 createFinder : function( _elmTarget, _tree, _onSelect, _viewerOption, _editorOption ){
1573 var data = ApplicationPrivateData.get( this ),
1574 finder = Finder.create( this, _elmTarget, _tree, _onSelect, _viewerOption, _editorOption );
1575 if( data.finderList === null ) data.finderList = [];
1576 data.finderList.push( finder );
1579 createDHTML : function( _elm ){
1580 return DHTML.create( this, _elm );
1582 addEventListener : function( element, eventType, handler, opt_thisObject ){
1583 MouseEvent.add( this, element, eventType, handler, opt_thisObject );
1585 removeEventListener : function( element, eventType, handler ){
1586 MouseEvent.remove( this, element, eventType, handler );
1588 getPointingDeviceEventTreeRoot : function(){
1589 var data = ApplicationPrivateData.get( this );
1590 if( data.phase === 1 ){
1591 data.eventRoot = PointingDeviceEventTree.create( this );
1592 data.styleCursor = PointingDeviceEventTree._getNodePrivateData( data.eventRoot ).elmMouseCatch.style;
1594 return data.eventRoot;
1596 updateCoursor : function( _cursor ){
1597 var data = ApplicationPrivateData.get( this );
1598 if( data.cursor !== _cursor ){
1599 data.styleCursor.cursor = data.cursor = _cursor;
1602 fetchCSS : function( url, opt_onload, opt_onerror ){
1603 var data = ApplicationPrivateData.get( this );
1604 if( data.phase === 1 ){
1605 ++data.fetchResource;
1606 StyleSheet.load( this, url, data.fetchResourceComplete, data.fetchResourceComplete, data );
1609 onInit : function(){},
1610 onOpen : function(){},
1611 onClose : function(){ return true; },
1612 onPaneResize : function( w, h ){},
1613 addKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){
1614 KeyEvent.add( this, _eventType, _handler, _keyCode, _shift, _ctrl );
1616 removeKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){
1617 KeyEvent.remove( this, _eventType, _handler, _keyCode, _shift, _ctrl );
1619 shiftEnabled : function(){
1620 return KeyEvent.shiftEnabled;
1622 ctrlEnabled : function(){
1623 return KeyEvent.ctrlEnabled;
1625 addTimer : function( handler, time, once ){
1626 SystemTimer.add( this, handler, time, !!once );
1628 removeTimer : function( handler ){
1629 SystemTimer.remove( this, handler );
1631 addAsyncCall : function( _callback, _argments, _thisObject ){
1632 AsyncCall.add( this, _callback, _argments, _thisObject );
1634 removeAsyncCall : function( _callback ){
1635 AsyncCall.remove( this, _callback );
1637 fetchHTMLElement : function( id ){
1638 var elm = document.getElementById( id );
1640 elm.removeAttribute( 'id' );
1641 elm.parentNode.removeChild( elm );
1647 var PointingDeviceEventTree = ( function(){
1649 currentRootData = null,
1650 targetNodeData = null,
1651 forceNodeData = null,
1654 function eventRellay( e ){
1655 var data = forceNodeData, // || targetNodeData,
1661 ret, systemOnly = false, addClass, removeClass,
1663 if( data && data.dispatchEvent( e, type, true ) === true ) return false;
1664 if( currentRootData === null ) return;
1665 targetNodeData = currentRootData;
1666 currentRootData._capcher( x, y );
1667 targetNodeData.apiuser.updateCoursor( targetNodeData._cursor );
1668 data = targetNodeData;
1670 ret = data.dispatchEvent( e, type, true, systemOnly );
1671 if( ret === true || ret === false ) break; // systemOnly = true;
1672 data = data.parentData;
1675 addClass = Util.addClass;
1676 removeClass = Util.removeClass;
1677 for( ; i < list.length; ){
1678 parent = data = list[ i ];
1679 while( parent.parentData && parent === parent.parentData.hitChild ){
1680 parent = parent.parentData;
1682 if( parent !== currentRootData ){
1683 data.hover === true && removeClass( data.elm, data.hoverClass );
1684 delete data.isHover;
1685 data.events && data.events.mouseout && data.fire( e, 'mouseout', false );
1686 delete data.hitSelf;
1687 list.splice( i, 1 );
1690 if( data.hover === true && data.isHover === false ){
1691 addClass( data.elm, data.hoverClass );
1692 data.isHover = true;
1694 if( data.hitSelf === false ){
1695 data.events && data.events.mouseover && data.fire( e, 'mouseover', true );
1696 data.hitSelf = true;
1703 var NodeClass = function( apiuser, rootData, /*parentLayer,*/ parentData, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){
1704 ( new NodePrivateData() ).init( apiuser, rootData, /*parentLayer,*/ parentData, this, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop );
1706 NodeClass.prototype = {
1707 createNode : function( rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ){
1708 var data = NodePrivateData.get( this ),
1710 if( Type.isHTMLElement( rangeOrElmData ) === true ){
1711 elm = rangeOrElmData;
1713 if( Type.isString( rangeOrElmData ) === true ){
1714 elm = document.getElementById( rangeOrElmData );
1716 elm = Util.pullHtmlAsTemplete( rangeOrElmData );
1718 if( !elm || Type.isHTMLElement( elm ) === false || elm.nodeType !== 1 ){
1719 throw new Error( "invalid HTMLElement." );
1722 if( Type.isObject( rangeOrElmData ) === false || Type.isFinite( rangeOrElmData.x ) === false || Type.isFinite( rangeOrElmData.y ) === false ){
1723 throw new Error( "No range" );
1726 if( elm && data.elm === null ){
1727 throw new Error( "MetaLayer don't containe HTMLElement-Layer." );
1729 if( data.elm && data.elm.style.hasLayout === false ){
1730 throw new Error( "[ie] OffsetParent is hasLayout === false." );
1733 var newNode = new NodeClass( data.apiuser, data.rootData, data, elm || rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ),
1734 newData = NodePrivateData.get( newNode );
1736 if( data.childData === null ) data.childData = [];
1737 data.childData.push( newData );
1740 createNodeAt : function(){
1742 remove : function(){
1743 NodePrivateData.get( this ).remove();
1745 nodeIndex : function( v ){
1746 return NodePrivateData.get( this ).nodeIndex( v );
1748 numNode : function(){
1749 return NodePrivateData.get( this ).numNode();
1751 disabled : function( v ){
1752 return NodePrivateData.get( this ).disabled( v );
1754 childrenDisabled : function( v ){
1755 return NodePrivateData.get( this ).disabled( v );
1757 mesure : function(){
1758 NodePrivateData.get( this ).mesure();
1760 mesureChildren : function(){
1761 NodePrivateData.get( this ).mesureChildren();
1763 update : function( x, y, w, h ){
1764 NodePrivateData.get( this ).update( x, y, w, h );
1766 setPosition : function( x, y ){
1767 NodePrivateData.get( this ).setPosition( x, y );
1769 setSize : function( w, h ){
1770 NodePrivateData.get( this ).setSize( w, h );
1772 cursor : function( v ){
1773 return NodePrivateData.get( this ).cursor( v );
1776 return NodePrivateData.get( this ).positionX( x );
1779 return NodePrivateData.get( this ).positionY( y );
1781 width : function( w ){
1782 return NodePrivateData.get( this ).width( w );
1784 height : function( h ){
1785 return NodePrivateData.get( this ).height( h );
1787 getAbsolutePositionX : function(){
1788 return NodePrivateData.get( this ).getAbsolutePositionX();
1790 getAbsolutePositionY : function(){
1791 return NodePrivateData.get( this ).getAbsolutePositionY();
1793 addEventListener : function( type, handler, opt_thisObject ){
1794 NodePrivateData.get( this ).addEventListener( type, handler, opt_thisObject );
1796 removeEventListener : function( type, handler ){
1797 NodePrivateData.get( this ).removeEventListener( type, handler );
1799 scrollTo : function( x, y ){
1800 NodePrivateData.get( this ).scrollTo( x, y );
1802 scrollX : function( v ){
1803 return NodePrivateData.get( this ).scrollX( v );
1805 scrollY : function( v ){
1806 return NodePrivateData.get( this ).scrollY( v );
1808 invalidateScrollbar : function(){
1809 ScrollBarManager.update( NodePrivateData.get( this ) );
1814 * clip : true の場合、子ノードの変更によってヒットエリアを変化させない.elm には overflow:hidden としておくのが通常.
1816 var NodePrivateData = function(){};
1817 NodePrivateData.prototype = {
1818 elmMouseCatch : null, // rootData only
1819 eventCounter : null, // rootData only
1820 cursorStyle : null, // rootData only
1824 elm : null, // resizeTarget
1827 elmScrollbar : null,
1843 // parentLayer : null,
1850 _childDisabled: false,
1851 layoutManager : null,
1860 init: function( apiuser, rootData, /*parentLayer,*/ parentData, node, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){
1861 this.apiuser = apiuser;
1862 this.rootData = rootData || this;
1863 // this.parentLayer = parentLayer;
1864 this.parentData = parentData;
1866 this.through = through;
1868 if( cursor ) this._cursor = cursor;
1870 if( Type.isHTMLElement( rangeOrElm ) === true ){
1871 this.elm = rangeOrElm;
1872 this.hover = !!hover;
1873 this.hoverClass = hover;
1874 this.scroll = clip && scroll;
1876 this.scroll === true && ScrollBarManager.register( this );
1878 this.update( rangeOrElm.x, rangeOrElm.y, rangeOrElm.w, rangeOrElm.h );
1881 NodePrivateData.dataList.push( this );
1883 mesure : function(){
1884 var x, y, w, h, parent, _this, _parent;
1886 w = this.elm.offsetWidth;
1887 h = this.elm.offsetHeight;
1888 _this = Position.cumulativeOffset( this.elm );
1889 _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ];
1890 x = _this[ 0 ] - _parent[ 0 ];
1891 y = _this[ 1 ] - _parent[ 1 ];
1892 if( this.x !== x || this.y !== y || this.w !== w || this.h !== h ){
1897 parent = this.parentData;
1898 parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY );
1899 this._updateRectangle();
1902 this._updateRectangle();
1905 mesureChildren : function(){
1907 if( nodes = this.childData ){
1908 for( i = nodes.length; i; ){
1909 nodes[ --i ].mesure();
1913 update : function( x, y, w, h ){
1914 var updateXY = false,
1920 if( Type.isFinite( w ) === true ){
1921 this.elm.style.width = w + 'px';
1923 if( Type.isString( w ) === true ){
1924 this.elm.style.width = w;
1925 w = this.elm.offsetWidth;
1927 //update = this.w !== w;
1930 if( Type.isFinite( h ) === true ){
1931 this.elm.style.height = h + 'px';
1933 if( Type.isString( h ) === true ){
1934 this.elm.style.height = w;
1935 h = this.elm.offsetHeight;
1937 //update = update || this.h !== h;
1940 if( Type.isFinite( x ) === true ){
1941 this.elm.style.left = x + 'px';
1943 if( Type.isString( x ) === true ){
1944 this.elm.style.left = x;
1951 if( Type.isFinite( y ) === true ){
1952 this.elm.style.top = y + 'px';
1954 if( Type.isString( y ) === true ){
1955 this.elm.style.top = y;
1960 if( updateXY === true ){
1961 _this = Position.cumulativeOffset( this.elm );
1962 _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ];
1963 x = _this[ 0 ] - _parent[ 0 ];
1964 y = _this[ 1 ] - _parent[ 1 ];
1966 //update = update || this.x !== x;
1967 //update = update || this.y !== y;
1969 //update === true && this._updateRectangle();
1972 x = Type.isFinite( x ) === true ? x : this.x;
1973 y = Type.isFinite( y ) === true ? y : this.y;
1974 w = Type.isFinite( w ) === true ? w : this.w;
1975 h = Type.isFinite( h ) === true ? h : this.h;
1976 if( this.x !== x || this.y !== y ){
1979 //console.log( 'xy ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h + ' absX:' + this.parentData.absoluteX )
1980 parent = this.parentData;
1981 parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY );
1982 this.w === w && this.h === h && this._updateRectangle();
1984 if( this.w !== w || this.h !== h ){
1987 //console.log( 'wh ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h )
1988 this._updateRectangle();
1991 ScrollBarManager.update( this );
1993 _updateAbsoluteXY : function( x, y, sX, sY ){
1995 this.absoluteX = x = this.x + x;
1996 this.absoluteY = y = this.y + y;
1997 if( nodes = this.childData ){
1998 for( i = nodes.length; i; ){
1999 nodes[ --i ]._updateAbsoluteXY( x, y, this.scrollingX, this.scrollingY );
2003 _updateRectangle : function(){
2012 nodes = this.childData,
2016 if( this.clip === false && nodes ){
2017 for( i = nodes.length; i; ){
2018 node = nodes[ --i ];
2019 if( node.l + x < l ) l = x + node.l;
2020 if( node.t + y < t ) t = y + node.t;
2021 if( r < node.r + x ) r = x + node.r;
2022 if( b < node.b + y ) b = y + node.b;
2026 if( b !== this.b || r !== this.r || t !== this.t || l !== this.l ){
2033 this.parentData && this.parentData.clip === false && this.parentData._updateRectangle();
2037 setPosition : function( x, y ){
2038 this.update( x, y );
2040 setSize : function( w, h ){
2041 this.update( undefined, undefined, w, h );
2043 positionX : function( x ){
2044 x !== undefined && this.update( x );
2047 positionY : function( y ){
2048 y !== undefined && this.update( undefined, y );
2051 width : function( w ){
2052 w !== undefined && this.update( undefined, undefined, w );
2055 height : function( h ){
2056 h !== undefined && this.update( undefined, undefined, undefined, h );
2059 getAbsolutePositionX : function(){
2060 return this.absoluteX;
2062 getAbsolutePositionY : function(){
2063 return this.absoluteY;
2065 cursor : function( v ){
2066 if( Type.isString( v ) === true ){
2068 this === targetNodeData && this.apiuser.updateCoursor( v );
2070 return this._cursor;
2072 addEventListener : function( eventType, handler, opt_thisObject ){
2073 var node = this.node,
2074 counter = this.rootData.eventCounter,
2076 if( this.events === null ) this.events = {};
2077 list = this.events[ eventType ];
2079 list = this.events[ eventType ] = [];
2081 for( i = list.length; i; ){
2082 if( list[ --i ].match( eventType, handler ) === true ){
2087 list.push( new EventTicketClass( this.node, eventType, handler, opt_thisObject ) );
2088 if( eventType !== 'mouseout' && eventType !== 'mouseover' ){
2089 if( counter[ eventType ] ){
2090 ++counter[ eventType ];
2092 //console.log( eventType );
2093 counter[ eventType ] = 1;
2094 MouseEvent.add( this.apiuser, this.rootData.elmMouseCatch, eventType, eventRellay );
2098 removeEventListener : function( eventType, handler ){
2099 var events = this.events,
2100 counter = this.rootData.eventCounter,
2102 if( events === null ) return;
2103 console.log( ' *** remove ' + eventType );
2104 for( type in events ){
2105 list = events[ type ];
2106 if( eventType && eventType !== type ) continue;
2107 for( ; i < list.length; ){
2108 if( list[ i ].destroy( type, handler ) === true ){
2109 console.log( ' *** removed! ' + type );
2110 list.splice( i, 1 );
2115 if( list.length === 0 ){
2116 // delete this[ type ];
2117 delete events[ type ];
2119 if( counter[ type ] ){
2121 if( counter[ type ] === 0 ){
2122 MouseEvent.remove( this.apiuser, this.rootData.elmMouseCatch, type, eventRellay );
2123 delete counter[ type ];
2128 _capcher : function( x, y ){
2129 var t = this, nodes, child, _x, _y, hit, i;
2130 if( t._disabled === true ) return false;
2134 if( nodes = t.childData ){
2135 _x = x - t.scrollingX;
2136 _y = y - t.scrollingY;
2137 for( i = nodes.length; i; ){
2138 child = nodes[ --i ];
2139 if( child._disabled === false && child.l <= _x && _x < child.r && child.t <= _y && _y < child.b && child._capcher( _x, _y ) === true ){
2145 if( t.through === true ){
2146 t.hitChild && t.hitSelf === false && hoverList.push( t );
2147 return !!t.hitChild;
2149 hit = 0 <= x && x < t.w && 0 <= y && y < t.h;
2150 ( t.hitChild || hit ) && t.hitSelf === false && hoverList.push( t );
2151 if( hit === true && t.hitChild === null ) targetNodeData = t;
2152 return hit || !!t.hitChild;
2154 fire : function( e, eventType, hit ){
2155 var list = this.events[ eventType ],
2157 e = NodePrivateData.createEvent( e, eventType, this, hit );
2158 for( ; i; ) list[ --i ].fire( e );
2159 // console.log( eventType + ' x:' + x + ' y:' + y );
2161 dispatchEvent : function( e, eventType, hit ){
2162 var ret, list, i, p, child;
2163 if( !this.events || !( list = this.events[ eventType ] ) ) return;
2165 child = !!this.hitChild;
2166 e = NodePrivateData.createEvent( e, eventType, this, hit );
2167 for( i = list.length; i; ){
2168 ret = list[ --i ].fire( e );
2169 if( ret === true && child === false ){
2170 forceNodeData = this;
2173 if( ret === false ) return false;
2175 forceNodeData = null;
2177 scrollTo : function( x, y ){
2180 ScrollBarManager.update( this );
2182 scrollX : function( v ){
2183 if( Type.isFinite( v ) === true ){
2185 ScrollBarManager.update( this );
2187 return this.scrollingX; // this._scrollX;
2189 scrollY : function( v ){
2190 if( Type.isFinite( v ) === true ){
2192 ScrollBarManager.update( this );
2194 return this.scrollingY; // this._scrollY;
2196 nodeIndex : function( v ){
2198 if( !this.parentData ) return 0;
2200 list = this.parentData.childData;
2201 i = Util.getIndex( list, this );
2202 if( Type.isFinite( v ) === false || i === v && v < 0 && list.length <= v ) return i;
2204 list.splice( i, 1 );
2205 list.length === v ? list.push( this ) : list.splice( v, 0, this );
2210 if( this.parentData.hitChild === this ){
2211 this.parentData.hitChild = null;
2212 this.isHover === true && hoverList.splice( Util.getIndex( hoverList, this ), 1 ) && Util.removeClass( this.elm, this.hoverClass );
2213 this.isHover = false;
2214 if( forceNodeData === this ) forceNodeData = null;
2215 if( targetNodeData === this ) targetNodeData = null;
2218 numNode : function(){
2219 return this.childData ? this.childData.length : 0;
2221 disabled : function( v ){
2222 if( Type.isBoolean( v ) === true ){
2228 return this._disabled;
2230 childrenDisabled : function( v ){
2231 if( Type.isBoolean( v ) === true ){
2232 this._childDisabled = v;
2234 return this._childDisabled;
2236 remove : function(){
2237 if( this === this.rootData ) return;
2238 var parent = this.parentData,
2239 nodes = parent.childData;
2241 if( parent.hitChild === this ) delete parent.hitChild;
2242 nodes.splice( Util.getIndex( nodes, this ), 1 );
2243 if( nodes.length === 0 ) delete parent.childData;
2244 parent.clip === false && parent._updateRectangle();
2246 _destroy : function(){
2247 var nodes = this.childData,
2248 list = NodePrivateData.dataList,
2250 this.removeEventListener();
2251 ScrollBarManager.remove( this );
2253 while( node = nodes.shift() ) node._destroy();
2254 delete this.childData;
2256 list.splice( Util.getIndex( list, this ), 1 );
2259 NodePrivateData.dataList = [];
2260 NodePrivateData.get = function( node ){
2261 // if( node instanceof NodePrivateData ) return node;
2262 // return NodePrivateData.dataList[ layer._getUID() ];
2263 var list = NodePrivateData.dataList;
2264 for( var i = list.length; i; ){
2265 if( list[ --i ].node === node ) return list[ i ];
2269 NodePrivateData.createEvent = function( e, eventType, data, hit ){
2271 layerX : e.clientX - data.absoluteX,
2272 layerY : e.clientY - data.absoluteY,
2273 clientX : e.clientX,
2274 clientY : e.clientY,
2275 dragOffsetX : e.dragOffsetX,
2276 dragOffsetY : e.dragOffsetY,
2277 dragPhase : e.dragPhase,
2278 eventType : eventType,
2281 wheelDelta : e.wheelDelta,
2282 target : forceNodeData ? forceNodeData.node : targetNodeData ? targetNodeData.node : null
2287 var EventTicketClass = function( node, eventType, handler, opt_thisObject ){
2289 this.type = eventType;
2290 this.handler = handler;
2291 this.thisObj = opt_thisObject || node;
2293 EventTicketClass.prototype = {
2294 match : function( eventType, handler ){
2295 if( handler && this.handler !== handler ) return false;
2296 if( eventType && this.type !== eventType ) return false;
2299 destroy : function( eventType, handler ){
2300 if( this.match( eventType, handler ) === false ) return false;
2303 delete this.handler;
2304 delete this.thisObj;
2307 fire : ( function(){
2308 if( Function.prototype.call ){
2309 return function( e ){
2310 return this.handler.call( this.thisObj, e );
2313 return function( e ){
2315 this.thisObj._currentHandler = this.handler;
2316 ret = this.thisObj._currentHandler( e );
2317 delete this.thisObj._currentHandler;
2323 /*-------------------------------------
2326 var StayEventTicketClass = function( node, data, stayhandler, opt_thisObject ){
2327 node.addEventListener( 'mouseover', this.mouseoverHandler, this );
2330 this.handler = stayhandler;
2331 this.thisObject = opt_thisObject;
2333 StayEventTicketClass.prototype = Util.extend( new EventTicketClass( null, 'mousestay' ), {
2334 // type : 'mousestay',
2336 mouseoverHandler : function( e ){
2337 this.e = NodePrivateData.createEvent( e, this.type, this.data, true );
2338 this.node.addEventListener( 'mouseout', this.mousestayHandler, this );
2339 this.node.addEventListener( 'mousemove', this.mousemoveHandler, this );
2340 SystemTimer.add( this.data.apiuser, this.timeoutHandler, null, this );
2342 timeoutHandler : function(){
2343 this.mouseoutHandler();
2344 return this.fire( this.e );
2346 mousemoveHandler : function( e ){
2347 this.e = NodePrivateData.createEvent( e, this.type, this.data, true );
2348 SystemTimer.remove( this.data.apiuser, this.timeoutHandler );
2349 SystemTimer.add( this.data.apiuser, this.timeoutHandler, null, this );
2351 mouseoutHandler : function( e ){
2352 this.node.removeEventListener( 'mouseout', this.mousestayHandler );
2353 this.node.removeEventListener( 'mousemove', this.mousemoveHandler );
2354 SystemTimer.remove( this.data.apiuser, this.timeoutHandler );
2359 var ScrollBarManager = ( function(){
2360 var elmScroller = document.createElement( 'div' ),
2361 elmBar = document.createElement( 'div' ),
2365 currentNodeData = null,
2370 var list = smoothList,
2372 for( i = 0; i < list.length; ){
2374 if( data.scrollingY !== data._scrollY ){
2375 y = data.scrollingY += data.smoothY;
2376 if( data.smoothY < 0 ){
2377 y = y < data._scrollY ? data._scrollY : y;
2379 y = data._scrollY < y ? data._scrollY : y;
2381 data.scrollingY = y;
2382 data.elm.scrollTop = -y;
2383 data.events && data.events.scroll && data.fire( currentEvent, 'scroll', true );
2385 if( data.scrollingY === data._scrollY ){
2386 list.splice( i, 1 );
2387 // data.events && data.events.scroll && data.fire( currentEvent, 'scroll', true );
2392 list.length === 0 && SystemTimer.remove( SUPER_USER_KEY, tick );
2393 currentEvent.type = 'updateAfterScroll';
2394 AsyncCall.add( data.apiuser, eventRellay, currentEvent ); // スクロール後の更新
2397 function scrollReady( e ){
2401 if( data === currentNodeData || dragPhase !== 2 ) return; // Drag中の場合は 他にスクロールを作らない
2402 currentNodeData && scrollRelease();
2405 data.elm.parentNode.appendChild( elmScroller );
2406 elmScroller.appendChild( data.elm );
2408 elmScroller.style.cssText = 'position:absolute;left:0;top:0;';
2409 elmScroller.appendChild( elmBar );
2411 data.elm.scrollTop = -data.scrollingY;
2412 data.rootData.addEventListener( 'mousewheel', onMouseWheelScroll, data );
2413 data.rootData.addEventListener( 'mousedrag', onMouseDragScroll, data );
2414 data.addEventListener( 'mouseout', onMouseOut, data );
2415 currentNodeData = data;
2416 ScrollBarManager.update( data );
2418 function scrollRelease(){
2419 var data = currentNodeData;
2420 var parent = elmScroller.parentNode;
2421 parent.appendChild( currentNodeData.elm );
2422 parent.removeChild( elmScroller );
2423 currentNodeData.elm.scrollTop = -data.scrollingY;
2425 data.rootData.removeEventListener( 'mousewheel', onMouseWheelScroll, data );
2426 data.rootData.removeEventListener( 'mousedrag', onMouseDragScroll, data );
2427 data.removeEventListener( 'mouseout', onMouseOut, data );
2428 currentNodeData = null;
2430 function onMouseOut( e ){
2432 console.log( 'mouseOut ' + dragPhase );
2433 dragPhase === 2 && scrollRelease(); // Dragしてのアウトの場合, scroll をリリースしない
2435 function onMouseWheelScroll( e ){
2437 this._scrollY += e.wheelDelta;
2438 ScrollBarManager.update( this );
2442 function onMouseDragScroll( e ){
2446 dragPhase = e.dragPhase;
2447 switch( dragPhase ){
2449 dragStartY = this.scrollingY;
2450 data.rootData.removeEventListener( 'mousewheel', onMouseWheelScroll, data );
2452 this._scrollY = dragStartY + e.dragOffsetY;
2453 ScrollBarManager.update( this );
2456 dragOut === true ? scrollRelease() : data.rootData.addEventListener( 'mousewheel', onMouseWheelScroll, data );
2462 register : function( data ){
2463 data.addEventListener( 'mouseover', scrollReady, data );
2465 update : function( data ){
2466 // if( data !== currentNodeData ) return;
2467 var isCurrent = data === currentNodeData;
2469 var contentH = data._scrollH = data.elm.scrollHeight,
2471 offsetH = contentH - clipH,
2472 scrollY = data._scrollY = 0 < data._scrollY ? 0 : ( data._scrollY < -offsetH ? -offsetH : data._scrollY ),
2474 if( isCurrent === true ){
2475 elmScroller.style.width = data.w + 'px';
2476 elmScroller.style.height = clipH + 'px';
2480 data._scrollY = scrollY = 0;
2481 if( isCurrent === true ) elmBar.style.display = 'none';
2483 if( isCurrent === true ){
2484 barH = Math.floor( clipH * ( clipH / contentH ) );
2485 barY = Math.floor( ( clipH - barH ) * - scrollY / offsetH );
2486 elmBar.style.cssText = [
2487 'position:absolute;',
2489 'background-color:#333;',
2491 'font-size:0;line-height:0;',
2492 'height:', barH, 'px;',
2493 'top:', data.y + barY, 'px;'
2496 data.smoothY = ( scrollY - data.scrollingY ) / 10;
2497 if( data.scrollingY !== scrollY && Util.getIndex( smoothList, data ) === -1 ){
2498 smoothList.length === 0 && SystemTimer.add( SUPER_USER_KEY, tick, 16 );
2499 smoothList.push( data );
2502 remove : function( data ){
2503 var list = smoothList,
2504 i = Util.getIndex( list, data );
2505 data === currentNodeData && scrollRelease();
2506 i !== -1 && list.splice( i, 1 );
2512 create : function( apiuser ){
2513 var elm = document.createElement( 'div' ),
2515 body.appendChild( elm );
2517 root = new NodeClass( apiuser, null, null, elm );
2518 data = NodePrivateData.get( root );
2520 // elm.style.cssText = 'position:absolute;top:0;left:0;height:100%;';
2521 elm.className = 'mouse-operation-catcher';
2522 elm.unselectable = 'on';
2523 data.elmMouseCatch = elm;
2525 data.eventCounter = {};
2526 ROOT_LIST.push( data );
2527 currentRootData = data;
2528 targetNodeData = null;
2529 forceNodeData = null;
2531 MouseEvent.add( apiuser, elm, 'mousemove', eventRellay );
2534 onCurrentApplicationChange : function( _application ){
2535 currentRootData = null;
2536 targetNodeData = null;
2537 forceNodeData = null;
2538 for( var i = ROOT_LIST.length; i; ){
2539 if( ROOT_LIST[ --i ].apiuser === _application ){
2540 currentRootData = ROOT_LIST[ i ];
2545 destroyTree : function( root ){
2546 var data = NodePrivateData.get( root );
2547 MouseEvent.remove( data.apiuser, data.elmMouseCatch, 'mousemove', eventRellay );
2548 body.removeChild( data.elmMouseCatch );
2550 ROOT_LIST.splice( Util.getIndex( ROOT_LIST, data ), 1 );
2551 if( currentRootData === data ){
2552 currentRootData = null;
2553 targetNodeData = null;
2554 forceNodeData = null;
2557 onSystemShutdown : function(){
2560 isNodeInstance : function( node ){
2561 return node instanceof NodeClass;
2563 _getNodePrivateData : function( node ){ // system only
2564 return NodePrivateData.get( node );
2569 var Application = ( function(){
2571 var LIVE_APPLICATION_LIST = [];
2573 var currentApplication = null,
2574 coveredApplication = null,
2578 var ApplicationReference = function( appClass, isOverlay, displayName, id, thumbnailUrl, tailColor ){
2580 var application = null;
2582 this.displayName = displayName;
2583 this.thumbnailUrl = thumbnailUrl;
2584 this.tailColor = tailColor;
2586 function asyncBoot(){
2587 application = Application.boot( appClass, displayName, self.getUID(), isOverlay, Util.copyArray( arguments ) );
2589 this.getUID = function(){
2590 return Util.getIndex( API_USER_LIST, appClass );
2592 this.getDisplayName = function(){
2593 return this.displayName;
2595 this.boot = function( /* _option */ ){
2596 AsyncCall.add( this, asyncBoot, Util.copyArray( arguments ) );
2598 this.shutdown = function(){
2599 if( !application ) return false;
2601 AsyncCall.add( application, ( isOverlay === true ? Overlay.hide : application.close ) );
2605 function asyncBootHome(){
2606 currentApplication === null && Home.boot();
2608 function asyncOpen( /* arguments */ ){
2609 var _arg = Util.copyArray( arguments );
2610 _arg.unshift( winW, winH );
2611 currentApplication.open.apply( currentApplication, _arg );
2614 register: function( _class, _overlay, _tail, _displayName, _id, _thumbnailUrl, _tailColor ){
2615 APPLICATION_LIST.push( _class );
2616 API_USER_LIST.push( _class );
2617 var _ref = new ApplicationReference( _class, _overlay, _displayName, _id, _thumbnailUrl, _tailColor );
2618 _tail === true && Home.add( _ref );
2621 isApplicationInstance: function( app ){
2622 return ApplicationPrivateData.get( app ) !== null;
2624 isApplicationReference: function( _reference ){
2625 return _reference instanceof ApplicationReference;
2627 isCurrentAppplication: function( app ){
2628 return app === currentApplication;
2630 boot: function( appClass, displayName, uid, isOverlay, arg ){
2631 if( currentApplication ){
2632 if( currentApplication.getUID() === uid ) return null;
2633 if( isOverlay === false && currentApplication.close() === false ) return null;
2636 appClass.prototype = new AbstractApplication( appClass, displayName, isOverlay );
2638 var application = new appClass(),
2639 data = ApplicationPrivateData.get( application );
2641 application.rootElement = data.rootElement;
2642 data.application = application;
2644 coveredApplication = isOverlay === true ? currentApplication : null;
2646 Application.onCurrentApplicationChange( application );
2648 if( isOverlay === false ){
2649 body.style.backgroundColor = application.bgColor;
2651 body.appendChild( data.rootElement );
2652 data.rootElement.style.display = 'none';
2655 application.addAsyncCall( asyncOpen, arg );
2657 Overlay.show( application, arg );
2662 shutdown: function( _application, isOverlay ){
2663 if( isOverlay === false ){
2664 currentApplication = null;
2665 AsyncCall.add( SUPER_USER_KEY, asyncBootHome );
2667 Application.onCurrentApplicationChange( coveredApplication );
2668 coveredApplication = null;
2671 onCurrentApplicationChange: function( _application ){
2672 if( Application.isApplicationInstance( _application ) === false ) return;
2673 if( currentApplication === _application ) return;
2674 currentApplication = _application;
2675 MouseEvent.onCurrentApplicationChange( _application );
2676 PointingDeviceEventTree.onCurrentApplicationChange( _application );
2677 KeyEvent.updateCurrentListener( _application );
2678 // InteractiveLayer.onCurrentApplicationChange( _application );
2680 onApplicationShutdown: function( _application ){
2681 LIVE_APPLICATION_LIST.splice( Util.getIndex( LIVE_APPLICATION_LIST, _application ) );
2683 onWindowResize: function( w, h ){
2686 currentApplication && currentApplication.resize( w, h );
2687 Overlay.onWindowResize( w, h );
2688 UI.onWindowResize( w, h );
2690 onSystemShutdown: function(){
2696 /* --------------------------------------------------------------
2700 var Home = ( function(){
2701 var APP_REF_LIST = [];
2702 var ELM_TAIL_ORIGIN = ( function(){
2703 var ret = document.createElement( 'div' ),
2704 h2 = document.createElement( 'h2' );
2705 ret.className = 'tail-wrapper';
2706 ret.appendChild( h2 );
2707 h2.appendChild( document.createTextNode( 'appName' ) );
2711 var TailClass = function( appRef ){
2712 this.elm = ELM_TAIL_ORIGIN.cloneNode( true );
2713 this.destroy = function(){
2714 appRef = self = elmName = null;
2718 elmName = this.elm.getElementsByTagName( 'h2' )[ 0 ].firstChild;
2720 this.elm.style.backgroundColor = appRef.tailColor;
2721 elmName.data = appRef.displayName;
2724 var ref = Application.register( function(){
2729 elmContainer, elmHeader;
2733 for( var i=0, l=APP_REF_LIST.length; i<l; ++i ){
2734 tail = new TailClass( APP_REF_LIST[ i ] );
2735 tailList.push( tail );
2737 elmContainer.appendChild( elm );
2738 self.addEventListener( elm, 'click', onTailClick );
2742 function onTailClick( e ){
2743 var _children = elmContainer.getElementsByTagName( 'div' );
2744 for( var i=0, l=_children.length; i<l; ++i ){
2745 if( this === _children[ i ] ){
2746 APP_REF_LIST[ i ].boot();
2752 this.bgColor = '#0F6D39';
2753 this.MIN_WIDTH = 320;
2754 this.MIN_HEIGHT = 320;
2755 this.onInit = function(){
2756 self.rootElement.id = 'home-root';
2758 elmContainer = document.createElement( 'div' );
2759 self.rootElement.appendChild( elmContainer );
2760 elmContainer.id = 'home-tail-container';
2762 elmHeader = document.createElement( 'div' );
2763 self.rootElement.appendChild( elmHeader );
2764 elmHeader.id = 'home-header';
2766 this.onOpen = function( _w, _h ){
2771 this.onPaneResize = function( _w, _h ){
2774 this.onClose = function(){
2775 self.removeEventListener();
2776 while( tailList.length > 0 ){
2777 tailList.shift().destroy();
2779 self = tailList = elmContainer = null;
2781 }, false, false, 'home', 'home', null );
2784 add: function( _appRef ){
2785 if( Application.isApplicationReference( _appRef ) === false ) return;
2786 Util.getIndex( APP_REF_LIST, _appRef ) === -1 && APP_REF_LIST.push( _appRef );
2794 var Page = ( function(){
2797 ignoreTagList = [ 'script', 'noscript', 'style' ];
2799 var MemoryClass = function( node ){
2802 MemoryClass.prototype = {
2804 var node = this.node,
2805 _nodeType = node.nodeType;
2806 if( _nodeType === 1 && Util.getIndex( ignoreTagList, node.tagName.toLowerCase() ) === -1 ){
2807 this.type = _nodeType;
2808 this.display = node.style.display;
2810 if( _nodeType === 3 ){
2811 if( node.data.replace( /\s/g, '' ).length !== 0 ){
2812 this.type = _nodeType;
2813 this.before = pageNodes.length === 0 ? null : pageNodes[ pageNodes.length - 1 ].node;
2815 body.removeChild( node );
2819 // body.removeChild( node );
2824 if( this.type === 1 ){
2826 this.node.style.display = this.display;
2828 this.node.style.display = '';
2832 body.insertBefore( this.node, this.before );
2834 body.appendChild( this.node );
2839 if( !this.node.parentNode ){
2842 if( this.type === 1 ){
2843 this.node.style.display = 'none';
2845 body.removeChild( this.node );
2851 onReady: function(){
2852 var _children = Util.copyArray( body.childNodes ),
2854 for( var i = 0, l = _children.length; i<l; ++i ){
2855 _mem = new MemoryClass( _children[ i ] );
2856 _mem.init() !== false && pageNodes.push( _mem );
2858 if( pageNodes.length !== 0 ){
2859 if( Type.isFunction( gOS.PageApplicationClass ) === true ){
2860 Page.appClass = gOS.PageApplicationClass;
2861 Page.appClass.bgColor = Page.appClass.bgColor;
2862 Page.appClass.MIN_WIDTH = Page.appClass.MIN_WIDTH || 240;
2863 Page.appClass.MIN_HEIGHT = Page.appClass.MIN_HEIGHT || 240;
2865 Page.appClass = function(){
2868 this.bgColor = '#ffffff';
2869 this.MIN_WIDTH = 200;
2870 this.MIN_HEIGHT = 200;
2871 this.onInit = function(){};
2872 this.onOpen = function( _w, _h ){
2873 KeyEvent.add( self, Const.KEY.EVENT.KEY_DOWN, ref.shutdown, 27 ); // 27.esc
2875 this.onPaneResize = function( _w, _h ){};
2876 this.onClose = function(){};
2879 ref = Application.register( Page.appClass, false, true, document.title, 'page', null, Page.appClass.tailColor || '#999999' );
2880 if( Type.isFunction( gOS.PageApplicationClass ) === true ){
2881 gOS.PageApplicationRef = ref;
2884 delete Page.onReady;
2887 for( var i = pageNodes.length; i; ){
2888 pageNodes[ --i ].show();
2892 for( var i = pageNodes.length; i; ){
2893 pageNodes[ --i ].hide();
2899 registered: function(){
2906 /* --------------------------------------------------------------
2910 * スクリーン座標は、コンピュータのディスプレイの左上を原点とする座標系である。screenX, screenY属性で取得できる。Javascritpでは、同名のプロパティとして実装されている。
2911 * しかし、これは、現実的には、何の役に立たない。ブラウザ自体がディスプレイのどの位置にいるのかがわからないので、画面上の位置を知ったところで、何にもならないからだ。
2914 * ウインドウ座標とは、現在のブラウザのウインドウの、ドキュメントを表示している部分の左上原点とした座標である。
2915 * 問題は、ウインドウは、必ずしもドキュメント全体を表示するとは限らない。スクロールと呼ばれるUIによって、ドキュメントの一部だけを表示しているかもしれない。
2917 var XBrowserEvent = ( function(){
2918 var wrappedHandlerClass,
2922 if( window.addEventListener ){
2923 wrappedHandlerClass = function( ticket ){
2924 this.handler = function( e ){
2925 if( ticket.fire( e ) !== false ) return;
2927 e.stopPropagation();
2930 this.destroy = function(){
2932 delete this.handler;
2933 delete this.destroy;
2937 wrappedEventClass = function( e, element ){
2940 this.target = e.srcElement;
2941 this.currentTarget = element;
2942 this.relatedTarget = e.formElement ? e.formElement : e.toElement;
2943 this.eventPhase = e.srcElement === element ? 2: 3;
2945 this.clientX = e.clientX;
2946 this.clientY = e.clientY;
2947 this.screenX = e.screenX;
2948 this.screenY = e.screenY;
2950 this.keyCode = e.keyCode;
2951 this.altKey = e.altKey;
2952 this.ctrlKey = e.ctrlKey;
2953 this.shiftKey = e.shiftKey;
2955 this.wheelDelta = e.wheelDelta;
2957 wrappedEventClass.prototype.stopPropagation = function(){
2958 this._event.cancelBubble = true;
2960 wrappedEventClass.prototype.preventDefault = function(){
2961 this._event.returnValue = false;
2964 if( document.attachEvent ){
2965 wrappedHandlerClass = function( ticket ){
2966 this.handler = function(){
2967 if( ticket === null ) alert( window.event.type )
2968 if( ticket.fire( new wrappedEventClass( window.event, ticket.element ) ) !== false ) return;
2969 // e.preventDefault();
2970 // e.stopPropagation();
2971 window.event.cancelBubble = true;
2972 window.event.returnValue = false;
2975 this.destroy = function(){
2977 delete this.handler;
2978 delete this.destroy;
2984 find: function( _ticket ){
2985 for( var i=0, l= tmp.list.length, _item; i<l; ++i ){
2986 _item = tmp.list[ i ];
2987 if( _item.element === _ticket.element && _item.eventType === _ticket.eventType ){
2994 tmp.TicketClass = function( _ticket ){
2996 this.element = _ticket.element;
2997 this.eventType = _ticket.eventType;
2998 this.tickets = [ _ticket ];
2999 this.onDestroy = function(){ self = null; };
3001 this.element[ 'on' + this.eventType ] = function( e ){ return self.fire( e );};
3004 tmp.TicketClass.prototype = {
3005 add: function( _ticket ){
3006 Util.getIndex( this.tickets, ticket ) === -1 && this.tickets.push( _ticket );
3008 remove: function( _ticket ){
3009 var i = Util.getIndex( this.tickets, _ticket );
3010 i !== -1 && this.tickets.splice( i, 1 );
3011 this.tickets.length === 0 && this.destroy();
3013 fire: function( e ){
3014 e = e || new wrappedEventClass( window.event, this.element );
3015 var i = this.tickets.length,
3018 if( this.tickets[ --i ].fire( e ) === false ) cancel = false;
3022 destroy: function(){
3024 this.element[ 'on' + this.eventType ] = '';
3025 tmp.list.splice( Util.getIndex( tmp.list, this ), 1 );
3026 delete this.element;
3027 delete this.eventType;
3028 delete this.tickets;
3029 delete this.onDestroy;
3036 add: function( _ticket ){
3037 if( document.addEventListener ){
3038 XBrowserEvent.add = function( _ticket ){
3039 _ticket.wrappedHandler = new wrappedHandlerClass( _ticket );
3040 _ticket.element.addEventListener( _ticket.eventType, _ticket.wrappedHandler.handler, false );
3043 if( document.attachEvent ){
3044 XBrowserEvent.add = function( _ticket ){
3045 _ticket.wrappedHandler = new wrappedHandlerClass( _ticket );
3046 _ticket.element.attachEvent( 'on' + _ticket.eventType, _ticket.wrappedHandler.handler );
3049 XBrowserEvent.add = function( _ticket ){
3050 var t = tmp.find( _ticket );
3054 tmp.list.push( new tmp.TicketClass( _ticket ) );
3059 XBrowserEvent.add( _ticket );
3061 remove: function( _ticket ){
3062 if( document.removeEventListener ){
3063 XBrowserEvent.remove = function( _ticket ){
3064 _ticket.element.removeEventListener( _ticket.eventType, _ticket.wrappedHandler.handler, false );
3065 _ticket.wrappedHandler.destroy();
3068 if( document.detachEvent ){
3069 XBrowserEvent.remove = function( _ticket ){
3070 _ticket.element.detachEvent( 'on' + _ticket.eventType, _ticket.wrappedHandler.handler );
3071 _ticket.wrappedHandler.destroy();
3074 XBrowserEvent.remove = function( _ticket ){
3075 var t = tmp.find( _ticket );
3077 t.remove( _ticket );
3082 XBrowserEvent.remove( _ticket );
3090 var EventTicketClass = function( _element, _eventType, _handler, opt_thisObject ){
3091 this.element = _element;
3092 this.eventType = _eventType;
3093 this.handler = _handler;
3094 this.wrappedHandler = null;
3095 this.thisObject = opt_thisObject;
3096 XBrowserEvent.add( this );
3098 EventTicketClass.prototype = {
3099 fire : ( function(){
3100 if( Function.prototype.call ){
3101 return function( e ){
3102 return this.handler.call( this.thisObject || this.element, e );
3105 return function( e ){
3106 var thisObj = this.thisObject || this.element,
3108 thisObj._currentHandler = this.handler;
3109 ret = thisObj._currentHandler( e );
3110 delete thisObj._currentHandler;
3114 match: function( _element, _eventType, _handler ){
3115 if( _handler && _handler !== this.handler ) return false;
3116 if( _eventType && _eventType !== this.eventType ) return false;
3117 if( _element && _element !== this.element ) return false;
3121 destroy: function( _element, _eventType, _handler ){
3122 if( this.match( _element, _eventType, _handler ) === false ) return false;
3124 XBrowserEvent.remove( this );
3126 delete this.element;
3127 delete this.eventType;
3128 delete this.handler;
3129 delete this.wrappedHandler;
3130 delete this.thisObject;
3135 var ReadyEvent = ( function(){
3139 function webkitDetect(){
3140 var state = document.readyState;
3141 if( state === 'loaded' || state === 'complete' ){
3142 SystemTimer.remove( SUPER_USER_KEY, webkitDetect );
3147 function ieDetect(){
3148 if( this.readyState === 'complete' ){ // this.readyState === 'loaded' ||
3149 this.onreadystatechange = new Function();
3150 this.onreadystatechange = null;
3151 AsyncCall.remove( SUPER_USER_KEY, ieScroll );
3155 function ieScroll(){
3157 document.documentElement.doScroll( 'left' );
3159 AsyncCall.add( SUPER_USER_KEY, ieScroll );
3163 document.onreadystatechange = new Function();
3164 document.onreadystatechange = null;
3169 ticketReady && ticketReady.destroy();
3170 ticketLoad && ticketLoad.destroy();
3171 ticketReady = ticketLoad = null;
3173 if( Page.registered() === true ){
3180 // Apple WebKit (Safari, OmniWeb, ...)
3181 if( document.readyState && !!UA.WEBKIT ){
3182 SystemTimer.add( SUPER_USER_KEY, webkitDetect, 50 );
3184 if( document.readyState && UA.isIE && UA.ieVersion < 9 ){
3186 document.onreadystatechange = ieDetect; */
3188 ticketReady = new EventTicketClass( document, 'DOMContentLoaded', onReady );
3189 ticketLoad = new EventTicketClass( window, 'load', onReady );
3196 /* =====================================================
3201 var ResizeEvent = ( function(){
3202 var _globalLock = 0;
3207 function getInnerSize(){
3209 w : root.innerWidth || root.clientWidth,
3210 h : root.innerHeight || root.clientHeight
3217 if( document.uniqueID ){
3218 _resize = function(){
3219 root = (document.compatMode || "") !== "CSS1Compat" ? document.body : document.documentElement;
3223 if( !_globalLock++ ){
3224 var size = getInnerSize();
3225 if( w !== size.w || h !== size.h ){// resized
3229 Application.onWindowResize( w, h );
3231 window.setTimeout( unlock, 0 );
3234 window.setTimeout( loop, 100 );
3239 _resize = function(){
3240 new EventTicketClass( window, 'resize', onResize );
3242 function onResize(){
3243 if( !_globalLock++ ) {
3244 var size = getInnerSize();
3245 if( w !== size.w || h !== size.h ){// resized
3249 Application.onWindowResize( w, h );
3251 window.setTimeout( unlock, 0 );
3257 AsyncCall.add( SUPER_USER_KEY, _resize );
3260 getSize: getInnerSize,
3261 onSystemShutdown: function(){
3268 /* =====================================================
3272 var MouseEvent = ( function(){
3273 var CLICK_OFFSET = 2 * 2,
3274 DRAG_OFFSET = 4 * 4;
3276 var EVENT_LIST_MAP = [],
3279 /*-------------------------------------
3281 * mousedown, mouseup, の移動距離を調べて clickハンドラ を呼ぶ
3283 var ClickEventTicketClass = function( element, clickhandler, opt_thisObject ){
3284 this.mousedownTicket = new EventTicketClass( element, 'mousedown', this.mousedownHandler, this );
3285 this.element = element;
3286 this.handler = clickhandler;
3287 this.thisObject = opt_thisObject;
3289 ClickEventTicketClass.prototype = {
3295 mousedownTicket : null,
3296 mousemoveTicket : null,
3297 mouseupTicket : null,
3298 mouseoutTicket : null,
3299 eventType : 'click',
3300 fire : EventTicketClass.prototype.fire,
3301 match : EventTicketClass.prototype.match,
3302 mousedownHandler : function( e ){
3303 this.startX = e.clientX;
3304 this.startY = e.clientY;
3306 this.mousemoveTicket = new EventTicketClass( this.element, 'mousemove', this.mousemoveHandler, this );
3307 this.mouseupTicket = new EventTicketClass( this.element, 'mouseup', this.mouseupHandler, this );
3308 this.mouseoutTicket = new EventTicketClass( this.element, 'mouseout', this.mouseoutHandler, this );
3311 mousemoveHandler : function( e ){
3312 var offsetX = e.clientX - this.startX,
3313 offsetY = e.clientY - this.startY;
3314 offsetX * offsetX + offsetY * offsetY >= CLICK_OFFSET && this.mouseoutHandler();
3317 mouseupHandler : function( e ){
3318 this.mouseoutHandler();
3319 return this.fire( ClickEventTicketClass.createEvent( e ) );
3321 mouseoutHandler : function( e ){
3322 this.mousemoveTicket && this.mousemoveTicket.destroy();
3323 this.mouseupTicket && this.mouseupTicket.destroy();
3324 this.mouseoutTicket && this.mouseoutTicket.destroy();
3325 if( this.mousemoveTicket ) delete this.mousemoveTicket;
3326 if( this.mouseupTicket ) delete this.mouseupTicket;
3327 if( this.mouseoutTicket ) delete this.mouseoutTicket;
3330 destroy : function( _element, _eventType, _handler ){
3331 if( this.match( _element, _eventType, _handler ) === false ) return false;
3333 this.mouseoutHandler();
3334 this.mousedownTicket.destroy();
3336 delete this.element;
3337 delete this.handler;
3338 delete this.thisObject;
3339 delete this.mousedownTicket;
3343 if( document.createEvent ){
3344 ClickEventTicketClass.createEvent = function( e ){
3345 var _e = document.createEvent( 'MouseEvents' );
3347 'click' , false, true, e.view,
3348 e.detail, e.screenX, e.screenY, e.clientX, e.clientY,
3349 e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
3350 e.button, e.relatedTarget
3355 if( document.attachEvent ){
3356 ClickEventTicketClass.createEvent = function( e ){
3364 /*-------------------------------------
3367 var WheelEventTicketClass = ( function(){
3369 return function( element, wheelhandler, opt_thisObject ){
3370 this.wheelTicket = new EventTicketClass( element, 'DOMMouseScroll', this.onGeckoWheel, this );
3371 this.element = element;
3372 this.handler = wheelhandler;
3373 this.thisObject = opt_thisObject;
3376 if( true || UA.isIE ){
3377 return function( element, wheelhandler, opt_thisObject ){
3378 this.wheelTicket = new EventTicketClass( element, this.eventType, wheelhandler );
3379 this.element = element;
3380 this.handler = wheelhandler;
3381 this.thisObject = opt_thisObject;
3384 TMP.wheelHandlerList = [];
3385 TMP.wheelThisObjList = [];
3386 //TMP.wheelLegacy = undefined;
3387 TMP.onWheel = function( e ){
3388 e = e || window.event;
3390 f = TMP.wheelLegacy;
3391 if( f ) cancel = f.call( this, e );
3393 for( i = TMP.wheelHandlerList.length; i; ){
3394 if( TMP.wheelHandlerList[ --i ].call( TMP.wheelThisObjList[ i ] || this, e ) === false ) cancel = false;
3398 return function( element, wheelhandler, opt_thisObject ){
3399 this.element = element;
3400 this.handler = wheelhandler;
3401 this.thisObject = opt_thisObject;
3403 if( TMP.wheelHandlerList.length === 0 ){
3404 //TMP.wheelLegacy = Type.isFunction( window.onmousewheel ) === true ? window.onmousewheel : undefined;
3405 element.onmousewheel = TMP.onWheel;
3407 TMP.wheelHandlerList.push( wheelhandler );
3408 TMP.wheelThisObjList.push( opt_thisObject )
3412 WheelEventTicketClass.prototype = {
3413 eventType : 'mousewheel',
3414 match : EventTicketClass.prototype.match,
3415 destroy : function( _element, _eventType, _handler ){
3416 if( this.match( _element, _eventType, _handler ) === false ) return false;
3418 this.wheelTicket && this.wheelTicket.destroy();
3420 delete this.wheelTicket;
3421 delete this.element;
3422 delete this.handler;
3423 delete this.thisObject;
3425 this.onDestroy && this.onDestroy();
3430 WheelEventTicketClass.prototype.onGeckoWheel = function( e ){
3431 var _e = document.createEvent( 'MouseEvents' );
3433 'mousewheel' , false, true, e.view,
3434 e.detail, e.screenX, e.screenY, e.clientX, e.clientY,
3435 e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
3436 e.button, e.relatedTarget
3438 _e.wheelDelta = e.detail * -40;
3439 return this.handler.call( this.thisObject || this.element, _e );
3442 if( true || UA.isIE ){
3445 WheelEventTicketClass.prototype.onDestroy = function(){
3446 TMP.wheelHandlerList.splice( Util.getIndex( TMP.wheelHandlerList, this.handler ), 1 );
3447 TMP.wheelThisObjList.splice( Util.getIndex( TMP.wheelThisObjList, this.handler ), 1 );
3448 if( TMP.wheelHandlerList.length === 0 ) this.element.onmousewheel = '';
3452 /*-------------------------------------
3455 var DragEventTicketClass = function( element, draghandler, opt_thisObject ){
3456 this.mousedownTicket = new EventTicketClass( element, 'mousedown', this.mousedownHandler, this );
3457 this.element = element;
3458 this.handler = draghandler;
3459 this.thisObject = opt_thisObject;
3461 DragEventTicketClass.prototype = {
3468 mousedownTicket : null,
3469 mousemoveTicket : null,
3470 mouseupTicket : null,
3471 mouseoutTicket : null,
3472 eventType : 'mousedrag',
3473 fire : EventTicketClass.prototype.fire,
3474 match : EventTicketClass.prototype.match,
3475 mousedownHandler: function( e ){
3476 this.startX = e.clientX;
3477 this.startY = e.clientY;
3479 this.mousemoveTicket = new EventTicketClass( this.element, 'mousemove', this.dragMoveHandler, this );
3480 this.mouseupTicket = new EventTicketClass( this.element, 'mouseup', this.dragEndHandler, this );
3481 this.mouseoutTicket = new EventTicketClass( this.element, 'mouseout', this.dragEndHandler, this );
3485 dragMoveHandler : function( e ){
3486 var offsetX = e.clientX - this.startX,
3487 offsetY = e.clientY - this.startY;
3488 if( this.dragging === false ){
3489 if( offsetX * offsetX + offsetY * offsetY < DRAG_OFFSET ) return;
3490 console.log( 'Drag start' );
3492 this.dragging = true;
3493 return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 0 ) );
3495 return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 1 ) );
3497 dragEndHandler : function( e ){
3498 if( this.dragging === true ){
3499 console.log( 'Drag End ' + e.type );
3500 this.removeEvents();
3502 return this.fire( DragEventTicketClass.createEvent( e, e.clientX - this.startX, e.clientY - this.startY, 2 ) );
3504 this.removeEvents();
3507 removeEvents : function(){
3508 this.dragging = false;
3509 if( this.mousemoveTicket ){
3510 this.mousemoveTicket.destroy();
3511 delete this.mousemoveTicket;
3513 if( this.mouseupTicket ){
3514 this.mouseupTicket.destroy();
3515 delete this.mouseupTicket;
3517 if( this.mouseoutTicke ){
3518 this.mouseoutTicket.destroy();
3519 delete this.mouseoutTicket;
3522 destroy : function( _element, _eventType, _handler ){
3523 if( this.match( _element, _eventType, _handler ) === false ) return false;
3525 this.removeEvents();
3526 this.mousedownTicket.destroy();
3528 delete this.element;
3529 delete this.handler;
3530 delete this.thisObject;
3531 delete this.mousedownTicket;
3535 if( document.createEvent ){
3536 DragEventTicketClass.createEvent = function( e, offsetX, offsetY, dragPhase ){
3537 var _e = document.createEvent( 'MouseEvents' );
3539 DragEventTicketClass.prototype.eventType , false, true, e.view,
3540 e.detail, e.screenX, e.screenY, e.clientX, e.clientY,
3541 e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
3542 e.button, e.relatedTarget
3544 _e.dragPhase = dragPhase;
3545 _e.dragOffsetX = offsetX;
3546 _e.dragOffsetY = offsetY;
3550 if( document.attachEvent ){
3551 DragEventTicketClass.createEvent = function( e, offsetX, offsetY, dragPhase ){
3552 e.type = DragEventTicketClass.prototype.eventType;
3553 e.dragPhase = dragPhase;
3554 e.dragOffsetX = offsetX;
3555 e.dragOffsetY = offsetY;
3563 add: function( _apiuser, _element, _eventType, _handler, opt_thisObject ){
3564 if( isApiUser( _apiuser ) === true &&
3565 ( Type.isHTMLElement( _element ) === true || _element === window || _element === document ) &&
3566 Type.isString( _eventType ) === true &&
3567 Type.isFunction( _handler ) === true
3569 var _uid = _apiuser.getUID(),
3570 _events = EVENT_LIST_MAP[ _uid ];
3571 if( Type.isArray( _events ) === false ){
3572 _events = EVENT_LIST_MAP[ _uid ] = [];
3575 for( var i=0, l=_events.length; i<l; ++i ){
3576 if( _events[ i ].match( _element, _eventType, _handler ) === true ) return;
3579 switch( _eventType ){
3581 _events.push( new ClickEventTicketClass( _element, _handler, opt_thisObject ) );
3584 _events.push( new WheelEventTicketClass( _element, _handler, opt_thisObject ) );
3587 _events.push( new DragEventTicketClass( _element, _handler, opt_thisObject ) );
3590 _events.push( new EventTicketClass( _element, _eventType, _handler, opt_thisObject ) );
3594 remove: function( apiuser, element, eventType, handler ){
3595 if( isApiUser( apiuser ) === true ){
3596 var uid = apiuser.getUID(),
3597 list = EVENT_LIST_MAP[ uid ],
3599 if( Type.isArray( list ) === false ) return;
3600 for( ;i < list.length; ){
3601 if( list[ i ].destroy( element, eventType, handler ) === true ){
3602 list.splice( i, 1 );
3607 if( list.length === 0 ){
3608 EVENT_LIST_MAP[ uid ] = null;
3612 onCurrentApplicationChange: function(){
3615 onApplicationShutdown: function(){
3618 onSystemShutdown: function(){
3624 /* ----------------------------------------
3627 * - EDITABLE_TEXT_CONTROL
3629 * .SHIFT_DOWN_EVENT: 'shiftDown',
3630 * .SHIFT_UP_EVENT: 'shiftUp',
3631 * .CTRL_DOWN_EVENT: 'ctrlDown',
3632 * .CTRL_UP_EVENT: 'ctrlUp',
3633 * .SPACE_DOWN_EVENT: 'spaceDown',
3634 * .SPACE_UP_EVENT: 'spaceUp',
3636 * .addKeyDownEvent: function,
3637 * .keyEventDispatcher: function,
3639 * ショートカットキーの監視とテキスト入力(input, textarea)、チェックボックスを管理する。
3640 * キー入力はdocumentで受けて、テキスト編集中(input, textarea)はそちらにキーイベント流す。
3643 var KeyEvent = ( function(){
3644 var EVENT_LIST_MAP = [],
3652 var focusTicket = null,
3653 keydownTicket = null,
3656 keypressTicket = null;
3658 function unlock( lock, key ){
3659 lock.splice( Util.getIndex( lock, key ), 1 );
3662 function onKeyChange( e ){
3665 key = e.keyCode, // || e.which,
3666 shift = Type.isBoolean( e.shiftKey ) === true ? e.shiftKey : ( e.modifiers & Event.SHIFT_MASK ),
3667 ctrl = Type.isBoolean( e.ctrlKey ) === true ? e.ctrlKey : ( e.modifiers & Event.CONTROL_MASK ),
3668 lock = type === 'keyup' ? LOCK_UP : LOCK_DOWN,
3672 if( Util.getIndex( lock, key ) !== -1 ) return;
3674 AsyncCall.add( SUPER_USER_KEY, unlock, [ lock, key ] );
3676 if( key === 16 || shift === true ){
3677 KeyEvent.shiftEnabled = type !== 'keyup';
3679 if( key === 17 || ctrl === true ){
3680 KeyEvent.ctrlEnabled = type !== 'keyup';
3682 for( i = currentList.length; i; ){
3683 t = currentList[ --i ];
3684 if( Type.isFunction( t[ type ] ) === true && t.keyCode === key && ( t.shift === undefined || t.shift === shift ) && ( t.ctrl === undefined || t.ctrl === ctrl )){
3685 if( t[ type ].call( t.apiuser, e ) === false ){
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)
3696 if( UA.isIE === true && UA.ieRenderingVersion < 9 ){
3697 keyPress = function( e ){
3698 var key = e.keyCode;
3699 if( key === 13 || key === 27 ){
3701 return onKeyChange( e );
3706 var KeyEventTicketClass = function( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ){
3707 this.apiuser = _apiuser;
3709 this.keydown = _onKeydown;
3710 this.keyup = _onKeyup;
3711 this.keyCode = _keyCode;
3712 this.shift = _shift;
3714 _apiuser = _onKeydown = _onKeyup = null;
3716 KeyEventTicketClass.prototype = {
3717 match: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3718 if( _apiuser && _apiuser !== this.apiuser ) return false;
3719 if( _type && _type !== this.type ) return false;
3721 if( this.type === 'keydown' ){
3722 if( _handler !== this.keydown ) return false;
3724 if( _handler !== this.keyup ) return false;
3727 if( _keyCode && _keyCode !== this.keyCode ) return false;
3728 if( _shift && _shift !== this.shift ) return false;
3729 if( _ctrl && _ctrl !== this.ctrl ) return false;
3732 destroy: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3733 if( this.match( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ) === false ) return false;
3735 delete this.apiuser;
3736 delete this.keydown;
3743 function registerEvent( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ){
3744 var _uid = _apiuser.getUID(),
3745 _list = EVENT_LIST_MAP[ _uid ];
3746 if( Type.isArray( _list ) === false ){
3747 _list = EVENT_LIST_MAP[ _uid ] = [];
3749 for( var i=0, l=_list.length; i<l; ++i ){
3750 if( _list[ i ].match( _apiuser, _type, _onKeydown || _onKeyup, _keyCode, _shift, _ctrl ) === true ) return;
3752 _list.push( new KeyEventTicketClass( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ));
3754 if( _apiuser === application ) KeyEvent.updateCurrentListener( _apiuser );
3758 add: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3759 if( _type === 'keydown' ){
3760 registerEvent( _apiuser, _type, _handler, null, _keyCode, _shift, _ctrl );
3762 if( _type === 'keyup' ){
3763 registerEvent( _apiuser, _type, null, _handler, _keyCode, _shift, _ctrl );
3765 if( _type === 'keychange' ){
3766 registerEvent( _apiuser, _type, _handler, _handler, _keyCode, _shift, _ctrl );
3768 if( _type === 'cursol' ){
3772 remove: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3773 var _list = EVENT_LIST_MAP[ _apiuser.getUID() ],
3775 if( Type.isArray( _list ) === true ){
3776 while( i < _list.length ){
3777 if( _list[ i ].destroy( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ) === true ){
3778 _list.splice( i, 1 );
3784 if( _apiuser === application ) KeyEvent.updateCurrentListener( _apiuser );
3786 shiftEnabled: false,
3790 * currrentApplication ( overlay Application ) or
3793 updateCurrentListener: function( _apiuser ){
3794 application = _apiuser;
3795 var _uid = _apiuser.getUID();
3796 currentList = EVENT_LIST_MAP[ _uid ] || ( EVENT_LIST_MAP[ _uid ] = [] );
3801 for( var i=currentList.length; _ticket = currentList[ --i ]; ){
3802 if( _down === false ) _down = !!_ticket.keydown;
3803 if( _up === false ) _up = !!_ticket.keyup;
3804 if( _down && _up ) break;
3806 if( _down === true ){
3807 keydownTicket = new EventTicketClass( document, 'keydown', onKeyChange );
3808 keypressTicket = keyPress !== null ? new EventTicketClass( document, 'keypress', keyPress ) : null;
3810 keydownTicket && keydownTicket.destroy();
3811 keypressTicket && keypressTicket.destroy();
3812 keydownTicket = keypressTicket = null;
3815 keyupTicket = new EventTicketClass( document, 'keyup', onKeyChange );
3817 keyupTicket && keyupTicket.destroy();
3821 if( _down === true || _up === true ){
3822 focusTicket = new EventTicketClass( document, 'mouseenter', window.focus );
3824 focusTicket && focusTicket.destroy();
3828 onApplicationShutdown: function( _apiuser ){
3829 KeyEvent.remove( _apiuser );
3831 onSystemShutdown: function(){
3839 * http://thudjs.tumblr.com/post/637855087/stylesheet-onload-or-lack-thereof
3842 var StyleSheet = ( function(){
3843 var head = document.getElementsByTagName( 'head' )[ 0 ];
3845 var TICKET_LIST = [];
3846 var STATE_LIST = 'loaded,complete,uninitialized'.split( ',' );
3848 var cssRules, sheet;
3850 var FetchCssTicketClass = function( _apiuser, _url, _elm, _onload, _onerror, opt_thisObject ){
3851 this.apiusers = [ _apiuser ];
3854 this.onload = [ _onload ];
3855 this.onerror = [ _onerror ];
3856 this.thisObj = [ opt_thisObject ];
3859 FetchCssTicketClass.prototype = {
3860 match: function( _apiuser, _url ){
3861 if( _apiuser && Util.getIndex( this.apiusers, _apiuser ) === -1 ) return false;
3862 if( _url && _url !== this.url ) return false;
3865 destroy: function( _apiuser, _url ){
3866 if( this.match( _apiuser, _url ) === false ) return false;
3868 var i = Util.getIndex( this.apiusers, _apiuser );
3870 this.apiusers.splice( i, 1 );
3871 this.onload.splice( i, 1 );
3872 this.onerror.splice( i, 1 );
3873 this.thisObj.splice( i, 1 );
3875 if( this.apiusers.length !== 0 ) return false;
3877 head.removeChild( this.elm );
3878 this.elm.onreadystatechange = new Function();
3879 this.elm.onload = null;
3881 delete this.apiusers;
3885 delete this.onerror;
3886 delete this.thisObj;
3892 for( var i = this.onload.length, f; i; ){
3893 f = this.onload[ --i ];
3894 Type.isFunction( f ) === true && AsyncCall.add( this.apiusers[ i ], f, this.url, this.thisObj[ i ] || this.apiusers[ i ] );
3895 this.onload[ i ] = this.onerror[ i ] = null;
3899 for( var i = this.onerror.length, f; i; ){
3900 f = this.onerror[ --i ];
3901 Type.isFunction( f ) === true && AsyncCall.add( this.apiusers[ i ], f, this.url, this.thisObj[ i ] || this.apiusers[ i ] );
3902 this.onload[ i ] = this.onerror[ i ] = null;
3908 return el[ sheet ] && el[ sheet ][ cssRules ].length > 0;
3916 function getTicket( elm ){
3917 for( var i = TICKET_LIST.length, t; i; ){
3918 t = TICKET_LIST[ --i ];
3919 if( t.elm === elm ) return t;
3924 var t = getTicket( this ), rs = this.readyState, c;
3925 if( t && t.done === false && ( !rs || Util.getIndex( STATE_LIST, rs ) !== -1 ) ){
3928 this.onreadystatechange = new Function();
3933 function checkTimer(){
3934 var l = TICKET_LIST.length,
3936 for( var i = 0; i < l; ++i ){
3937 t = TICKET_LIST[ i ];
3939 if( t.check() === true ){
3949 l === n && SystemTimer.remove( SUPER_USER_KEY, checkTimer );
3953 load: function( _apiuser, _url, opt_onload, opt_onerror, opt_thisObject ){
3954 _url = Util.getAbsolutePath( _url );
3956 for( var i=TICKET_LIST.length; i; ){
3957 t = TICKET_LIST[ --i ];
3958 if( t.match( null, _url ) === true ){
3959 if( t.match( _apiuser, _url ) === false ){
3960 t.apiusers.push( _apiuser );
3961 t.onload.push( opt_onload );
3962 t.onerror.push( opt_onerror );
3963 t.thisObj.push( opt_thisObject );
3965 SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 );
3969 var elm = document.createElement( 'link' );
3970 head.appendChild( elm );
3971 elm.rel = 'stylesheet';
3972 elm.type = 'text\/css';
3973 elm.onreadystatechange = elm.onload = detect;
3976 if( !sheet ){ // only assign these once
3977 cssRules = 'cssRules';
3979 if ( !( sheet in elm ) ) { // MSIE uses non-standard property names
3981 sheet = 'styleSheet';
3985 TICKET_LIST.push( new FetchCssTicketClass( _apiuser, _url, elm, opt_onload, opt_onerror, opt_thisObject ) );
3987 SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 );
3989 unload: function( _apiuser, _url ){
3990 _url = _url ? Util.getAbsolutePath( _url ) : null;
3991 for( var i = 0; i < TICKET_LIST.length; ){
3992 t = TICKET_LIST[ i ];
3993 if( t.destroy( _apiuser, _url ) === true ){
3994 TICKET_LIST.splice( i, 1 );
3999 if( TICKET_LIST.length === 0 ){
4000 SystemTimer.remove( SUPER_USER_KEY, checkTimer );
4016 var Image = ( function(){
4019 * FetchClass original is
4022 * URL: http://d.hatena.ne.jp/uupaa/20080413/1208067631
4023 * AUTHOR: uupaa.js@gmail.com
4027 for( var i=0, t; i < TASK_LIST.length; ){
4029 if( t.complete() === true ){
4030 TASK_LIST.splice( i, 1 );
4035 TASK_LIST.length === 0 && SystemTimer.remove( SUPER_USER_KEY, detect );
4037 function getTask( img ){
4038 for( var i = TASK_LIST.length; i; ){
4039 if( TASK_LIST[ --i ].img === img ) return TASK_LIST[ i ];
4043 var task = getTask( this );
4044 if( task.finish === true ) return;
4046 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
4049 // if( finish === true ) return; // これがあると firefox3.6 で駄目、、、
4050 // if( timer ) return; // これがあると safari3.2 で駄目、、、
4051 var task = getTask( this );
4053 TASK_LIST.splice( Util.getIndex( TASK_LIST, task ), 1 );
4054 if( window.opera && !task.img.complete ){
4055 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
4058 task.size = Util.getImageSize( this );
4059 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
4063 var FetchClass = function( apiuser, abspath, onLoadCallback, onErrorCallback, timeout ){
4064 this.apiuser = apiuser;
4065 this.abspath = abspath;
4066 this.onLoadCallback = onLoadCallback;
4067 this.onErrorCallback = onErrorCallback;
4068 this.timeout = timeout;
4071 FetchClass.prototype = {
4077 var img = this.img = document.createElement( 'img' ); //var img = new Image(); ではieでimgのsizeが取れない、、、removeChildも失敗し、imgSizeGetterにimgが残る
4078 img.onabort = img.onerror = onError;
4079 img.onload = onLoad;
4080 img.src = this.abspath;
4082 complete: function(){
4083 if( this.finish === true ) return true;
4084 if( this.img.complete ){
4086 if( this.img.width ) return true;
4087 AsyncCall.add( this.apiuser, this.asyncCallback, null, this );
4090 if( ( this.tick += 250 ) > this.timeout ){
4092 AsyncCall.add( this.apiuser, this.asyncCallback, null, this );
4096 asyncCallback: function(){
4097 this.size ? this.onLoadCallback( this.abspath, this.size.width, this.size.height ) : this.onErrorCallback( this.abspath );
4100 destroy: function(){
4102 this.img.src = this.img.onload = this.img.onabort = this.img.onerror = '';
4105 delete this.onLoadCallback;
4106 delete this.onErrorCallback;
4109 timer !== null && window.clearTimeout( timer );
4115 load: function( URLorELM, onLoad, onError, opt_timeout ){
4117 if( Type.isString( URLorELM ) === true ){
4120 if( Type.isHTMLElement( URLorELM ) === true && URLorELM.tagName.toLowerCase() === 'img' ){
4126 fetch = new FetchClass(
4127 Util.getAbsolutePath( src ),
4129 Type.isFinite( opt_timeout ) === true ? opt_timeout : undefined
4131 TASK_LIST.push( fetch );
4133 SystemTimer.add( SUPER_USER_KEY, detect, 250 );
4135 unload: function( ){
4142 /* ----------------------------------------
4146 var Overlay = ( function(){
4147 var elmContainer, elmShadow, elmCloseButton,
4154 function onCloseClick( e ){
4158 function asyncInit( /* arguments */ ){
4160 //application.rootElement.style.display = 'none';
4162 elmContainer.style.cssText = "top:" + body.scrollTop + 'px;display:none;';
4163 $( elmContainer ).stop().fadeIn( onFadeInComplete );
4165 function asyncOpen( /* arguments */ ){
4170 function onFadeInComplete(){
4171 KeyEvent.add( application, Const.KEY.EVENT.KEY_DOWN, Overlay.hide, 27 ); // 27.esc
4172 MouseEvent.add( application, elmCloseButton, 'click', onCloseClick );
4174 var _arg = bootParams; //Util.copyArray( arguments );
4175 _arg.unshift( windowW, windowH );
4176 application.open.apply( application, _arg );
4178 function onFadeOutComplete(){
4179 Util.removeAllChildren( elmContainer );
4180 body.removeChild( elmContainer );
4181 elmContainer = elmShadow = elmCloseButton = null;
4184 show: function( _application, _bootParams ){
4185 if( visible === true && application === _application ) return;
4186 if( Application.isApplicationInstance( _application ) === false ) return;
4188 elmContainer = document.createElement( 'div' );
4189 body.appendChild( elmContainer );
4191 elmContainer.id = 'overlay-container';
4193 bodyOverflow = body.style.overflow;
4194 body.style.overflow = 'hidden';
4196 elmShadow = document.createElement( 'div' );
4197 elmContainer.appendChild( elmShadow );
4198 elmShadow.id = 'overlay-shadow';
4200 elmCloseButton = document.createElement( 'div' );
4201 elmContainer.appendChild( elmCloseButton );
4202 elmCloseButton.id = 'overlay-close-button';
4203 elmCloseButton.appendChild( document.createTextNode( 'x' ) );
4205 elmContainer.style.display = 'none'; // hide for fadeIn
4208 application = _application;
4211 elmContainer.insertBefore( application.rootElement, elmCloseButton );
4212 _application.addAsyncCall( asyncInit );
4213 // _application.addAsyncCall( asyncOpen, );
4215 bootParams = _bootParams;
4218 if( visible === false ) return;
4219 if( application.close() === false ) return false;
4221 body.style.overflow = bodyOverflow;
4223 $( elmContainer ).stop().css( {
4226 }).fadeOut( onFadeOutComplete );
4231 onWindowResize: function( _windowW, _windowH ){
4235 if( application === null ) return;
4237 elmContainer.style.height = _windowH + 'px';
4238 elmContainer.style.top = body.scrollTop + 'px';
4240 elmShadow.style.height = _windowH + 'px';
4242 AsyncCall.add( application, application.resize, [ _windowW, _windowH ] );
4247 /* ----------------------------------------
4251 * form -> overlay -> view
4255 var UI = ( function(){
4264 var CLASSNAME_COMBOBOX_OPTION = 'combobox-option',
4265 CLASSNAME_COMBOBOX_OPTION_CURRENT = CLASSNAME_COMBOBOX_OPTION + ' combobox-option-current',
4266 ELM_COMBOBOX = ( function(){
4267 var ret = document.createElement( 'a' ),
4268 elmToggle = document.createElement( 'span' ),
4269 elmValue = document.createElement( 'span' );
4271 ret.appendChild( elmToggle );
4272 ret.appendChild( elmValue );
4273 elmToggle.className = 'combobox-toggle';
4274 elmValue.className = 'combobox-value';
4276 elmToggle.appendChild( document.createTextNode( '▼' ));
4277 elmValue.appendChild( document.createTextNode( 'null' ));
4281 var UIItemPrivateData = function(){};
4282 UIItemPrivateData.prototype = {
4300 init : function( groupData, item, elm, value, onUpdate, validator, focus, visible, enabled ){
4301 this.groupData = groupData;
4305 this.onUpdate = onUpdate;
4306 this.validator = validator;
4307 this.focus = !!focus;
4308 this.visible = !!visible;
4309 this.enabled = !!enabled;
4310 UIItemPrivateData.list.push( this );
4312 destroy : function(){
4313 var list = UIItemPrivateData.list;
4314 list.splice( Util.getIndex( list, this ), 1 );
4316 list = this.groupData.itemList;
4317 var i = Util.getIndex( list, this.item );
4318 i !== -1 && list.splice( i, 1 );
4320 this.node && this.node.remove();
4323 UIItemPrivateData.list = [];
4324 UIItemPrivateData.get = function( item ){
4325 var list = UIItemPrivateData.list;
4326 for( i = list.length; i; ){
4327 if( list[ --i ].item === item ) return list[ i ];
4332 /* --------------------------------
4335 var TextInputManager = ( function(){
4336 var elmInput = ( function(){
4337 var ret = document.createElement( 'input' );
4339 ret.id = 'ui-textinput';
4344 function updateWrapperPosition(){
4345 var p = Position.cumulativeOffset( currentData.elmValue ),
4346 w = currentData.elmValue.offsetWidth - 2,
4348 elmInput.style.cssText = [
4349 'left:', p[ 0 ], 'px;',
4350 'top:', p[ 1 ], 'px;',//,
4351 'width:', w, 'px;'//,
4352 //'height:', data.elmValue.offsetHeight, 'px;',
4353 //'position:absolute;'
4356 //_w = elmInput.offsetWidth;
4357 //if( w !== _w ) elmInput.style.width = ( w - ( _w - w ) ) + 'px;';
4361 show: function( data ){
4362 // this.groupData.node.addEventListener( 'mouseout' );
4365 body.appendChild( elmInput );
4366 elmInput.value = data.value;
4367 updateWrapperPosition();
4372 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4374 hide : function( data ){
4375 if( currentData !== data ) return;
4377 body.removeChild( elmInput );
4378 var ret = elmInput.value;
4379 elmInput.value = '';
4380 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition );
4383 update : function( data ){
4384 elmInput.value = data.value;
4386 onWindowResize: function( _w, _h ){
4387 AsyncCall.add( currentUser, updateWrapperPosition );
4392 var TextInputClass = function( groupData, elmWrapper, elmValue, onUpdate, validater ){
4393 var data = new UIItemPrivateData();
4394 data.init( groupData, this, elmWrapper, elmValue.innerHTML, onUpdate, validater, false, true, true );
4395 Util.addClass( elmValue, 'editable-text' );
4396 data.elmValue = elmValue;
4397 this.value( data.value );
4398 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-inpittext-hover', 'pointer' );
4399 data.node.addEventListener( 'click', this.focus, this );
4400 //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', instance.focus );
4402 TextInputClass.prototype = {
4403 value : function( value ){
4404 var data = UIItemPrivateData.get( this );
4405 if( Type.isString( value ) === true || Type.isNumber( value ) === true ){
4406 data.elmValue.innerHTML = data.value = '' + value;
4407 data.focus === true && TextInputManager.update( data );
4409 data.focus === true && this.blur();
4412 focus : function( e ){
4413 var data = UIItemPrivateData.get( this );
4416 TextInputManager.show( data );
4419 blur : function( keep ){
4420 var data = UIItemPrivateData.get( this ),
4422 if( data.focus === false ) return;
4423 newValue = TextInputManager.hide( data );
4424 newValue = keep !== 27 ? ( data.validater ? '' + data.validater( newValue ) : newValue ) : data.value; // 27:ESC
4426 data.elmValue.innerHTML = newValue;
4428 data.onUpdate && newValue !== data.value && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ newValue, data.value ], this );
4430 data.value = newValue;
4434 enabled : function( v ){
4435 var data = UIItemPrivateData.get( this );
4436 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4437 Util.toggleClass( data.elm, 'ui-textinput-disabled', !v );
4438 if( data.focus === true && v === false ) this.blur();
4440 data.node.disabled( !( data.visible && v ) );
4442 return data.enabled;
4444 visible : function( v ){
4445 var data = UIItemPrivateData.get( this );
4446 if( Type.isBoolean( v ) === true && data.visible !== v ){
4447 data.elm.style.display = v ? '' : 'none';
4448 if( data.focus === true && v === false ) this.blur();
4450 data.node.disabled( !( data.enabled && v ) );
4452 return data.visible;
4454 destroy : function(){
4455 var data = UIItemPrivateData.get( this );
4456 data.focus === true && TextInputManager.hide( data );
4461 /* --------------------------------
4464 var FileInputManager = ( function(){
4471 function updateWrapperPosition(){
4472 var p = Position.cumulativeOffset( currentData.elmValue ),
4473 w = currentData.elmValue.offsetWidth,
4475 elmWrap.style.cssText = [
4476 'left:', p[ 0 ], 'px;',
4477 'top:', p[ 1 ], 'px;',//,
4478 'width:', w, 'px;'//,
4479 //'height:', data.elmValue.offsetHeight, 'px;',
4480 //'position:absolute;'
4483 _w = elmWrap.offsetWidth;
4484 if( w !== _w ) elmWrap.style.width = ( w - ( _w - w ) ) + 'px';
4487 function change( e ){
4488 var data = currentData,
4489 file = data.elmFileInputReal.value;
4490 file = file.split( '\\' );
4491 file = file[ file.length - 1 ];
4492 if( data.value !== file ){
4493 data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ file, data.value ], this );
4494 data.elmValue.innerHTML = data.value = file;
4496 currentData.item.blur();
4498 function asyncMouseout(){
4499 currentData && currentData.item.blur();
4502 MouseEvent.remove( currentUser, elmFileInput, 'mouseout', asyncMouseout );
4503 MouseEvent.remove( currentUser, elmFileInput, 'click', onClick );
4506 show : function( data ){
4509 elmFileInput = data.elmFileInputReal;
4510 elmWrap = elmFileInput.parentNode;
4513 updateWrapperPosition();
4514 elmFileInput.focus();
4515 //data.node.addEventListener( 'change', change, data );
4516 evt = new EventTicketClass( elmFileInput, 'change', change );
4517 MouseEvent.add( currentUser, elmFileInput, 'mouseout', asyncMouseout );
4518 MouseEvent.add( currentUser, elmFileInput, 'click', onClick );
4519 // currentData.elmFileInputReal.onchange = change;
4520 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4522 hide : function( data ){
4523 if( currentData !== data ) return;
4524 // data.node.removeEventListener( 'change', change );
4526 // MouseEvent.remove( currentUser, elmFileInput, 'mouseout', asyncMouseout );
4528 //currentData.elmFileInputReal.onchange = null;
4529 elmWrap.style.display = 'none';
4530 currentData = elmFileInput = null;
4531 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition );
4533 onWindowResize: function( _w, _h ){
4534 AsyncCall.add( currentUser, updateWrapperPosition );
4539 var FileInputClass = function( groupData, elmWrapper, onUpdate, validater, elmFileInputReal, elmValue ){
4540 var data = new UIItemPrivateData();
4541 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4542 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-fileinput-hover', 'pointer' );
4543 data.elmValue = elmValue;
4544 data.elmFileInputReal = elmFileInputReal;
4545 data.node.addEventListener( 'mouseover', this.focus, this );
4547 FileInputClass.prototype = {
4552 var data = UIItemPrivateData.get( this );
4554 Util.addClass( data.elm, 'fileinput-has-focus' );
4556 FileInputManager.show( data );
4558 blur : function( keyCode ){
4559 var data = UIItemPrivateData.get( this );
4560 Util.removeClass( data.elm, 'fileinput-has-focus' );
4562 FileInputManager.hide( data );
4565 enabled : function( v ){
4566 var data = UIItemPrivateData.get( this );
4567 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4568 if( data.focus === true && v === false ) this.blur();
4569 Util.toggleClass( data.elm, 'fileinput-disabled', !v );
4571 data.node.disabled( !( data.visible && v ) );
4573 return data.enabled;
4575 visible : function( v ){
4576 var data = UIItemPrivateData.get( this );
4577 if( Type.isBoolean( v ) === true && data.visible !== v ){
4578 if( data.focus === true && v === false ) this.blur();
4579 data.elm.style.display = v ? '' : 'none';
4581 data.node.disabled( !( data.enabled && v ) );
4583 return data.visible;
4585 destroy : function(){
4586 var data = UIItemPrivateData.get( this );
4587 data.focus === true && FileInputManager.hide( data );
4592 var ButtonClass = function( groupData, elmWrapper, onUpdate ){
4593 var data = new UIItemPrivateData();
4594 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4595 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-button-hover', 'pointer' );
4596 data.node.addEventListener( 'click', onUpdate );
4597 //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', onUpdate );
4599 ButtonClass.prototype = {
4601 var data = UIItemPrivateData.get( this );
4603 Util.addClass( data.elm, 'button-has-focus' );
4606 blur : function( keyCode ){
4607 var data = UIItemPrivateData.get( this );
4608 keyCode === 13 && data.onUpdate && data.onUpdate();
4609 Util.removeClass( data.elm, 'button-has-focus' );
4613 enabled : function( v ){
4614 var data = UIItemPrivateData.get( this );
4615 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4616 Util.toggleClass( data.elm, 'button-disabled', !v );
4618 data.node.disabled( !( data.visible && v ) );
4620 return data.enabled;
4622 visible : function( v ){
4623 var data = UIItemPrivateData.get( this );
4624 if( Type.isBoolean( v ) === true && data.visible !== v ){
4625 data.elm.style.display = v ? '' : 'none';
4627 data.node.disabled( !( data.enabled && v ) );
4629 return data.visible;
4631 destroy : function(){
4632 var data = UIItemPrivateData.get( this );
4633 // MouseEvent.remove( data.groupData.apiuser, data.elm );
4638 var ComboBoxClass = function( groupData, elmWrapper, onUpdate ){
4639 var elmA = ELM_COMBOBOX.cloneNode( true ),
4640 data = new UIItemPrivateData();
4641 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4643 data.elmBox = Util.getElementsByClassName( elmWrapper, 'combobox' )[ 0 ];
4644 data.elmBox.appendChild( elmA );
4646 data.elmToggle = Util.getElementsByClassName( elmA, 'combobox-toggle' )[ 0 ];
4647 data.elmValue = Util.getElementsByClassName( elmA, 'combobox-value' )[ 0 ].firstChild;
4648 data.selectIndex = 0;
4649 data.optionList = [];
4651 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-combobox-hover', 'pointer' );
4652 data.node.addEventListener( 'click', this.focus, this );
4654 ComboBoxClass.prototype = {
4655 focus : function( e ){
4656 var data = UIItemPrivateData.get( this );
4657 data.node.removeEventListener( 'click', this.focus );
4659 data.elmA.className = 'combobox-has-focus';
4661 OptionControl.show( data );
4664 blur : function( keyCode ){
4665 var data = UIItemPrivateData.get( this );
4666 OptionControl.hide( this );
4668 data.elmA.className = '';
4670 data.node.addEventListener( 'click', this.focus, this );
4672 enabled : function( v ){
4673 var data = UIItemPrivateData.get( this );
4674 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4675 Util.toggleClass( data.elm, 'ui-combobox-disabled', !v );
4676 if( data.focus === true && v === false ) this.blur();
4678 data.node.disabled( !( data.visible && v ) );
4680 return data.enabled;
4682 visible : function( v ){
4683 var data = UIItemPrivateData.get( this );
4684 if( Type.isBoolean( v ) === true && data.visible !== v ){
4685 data.elm.style.display = v ? '' : 'none';
4686 if( data.focus === true && v === false ) this.blur();
4688 data.node.disabled( !( data.enabled && v ) );
4690 return data.visible;
4692 value : function( _value ){
4693 var data = UIItemPrivateData.get( this ),
4695 list = data.optionList,
4698 if( Type.isString( _value ) === true && data.value !== _value ){
4699 for( ; i < l; ++i ){
4700 _option = list[ i ];
4701 if( _value === _option.value ){
4702 data.value = _value;
4704 data.elmValue.data = _option.displayValue;
4705 if( data.focus === true ){
4706 OptionControl.update( this, _value );
4708 data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, _value, this );
4715 selectIndex : function(){
4716 var data = UIItemPrivateData.get( this );
4717 return data.selectIndex;
4719 createOption : function( _displayValue, _value, _isSelected ){
4720 var data = UIItemPrivateData.get( this ),
4722 list = data.optionList,
4725 _value = _value || _displayValue;
4726 _isSelected = !!_isSelected;
4728 _option = list[ --i ];
4729 if( _value === _option.value ){
4734 if( _isSelected === true ){
4735 data.selectIndex = list.length;
4736 data.elmValue.data = _displayValue;
4738 option === null && list.push( new OptionDataClass( _displayValue, _value, _isSelected ) );
4740 destroy : function(){
4741 var data = UIItemPrivateData.get( this );
4742 data.focus === true && OptionControl.hide( this );
4744 // MouseEvent.remove( data.groupData.apiuser, data.elm );
4745 data.optionList.length = 0;
4749 var OptionDataClass = function( displayValue, value, isCurrent ){
4750 this.displayValue = displayValue;
4751 this.value = value || displayValue;
4752 this.current = isCurrent;
4753 displayValue = value = null;
4756 var OptionControl = ( function(){
4757 var ELM_OPTION_WRAPPER = ( function(){
4758 var ret = document.createElement( 'div' );
4759 ret.className = 'option-container';
4762 ELM_OPTION_ORIGIN = ( function(){
4763 var ret = document.createElement( 'a' );
4764 ret.appendChild( document.createTextNode( 'option' ) );
4769 var OptionClass = function( option ){
4770 this.elm = ELM_OPTION_ORIGIN.cloneNode( true );
4774 OptionClass.prototype = {
4776 ELM_OPTION_WRAPPER.appendChild( this.elm );
4777 this.elm.firstChild.data = this.data.displayValue;
4778 this.current( this.data.current );
4779 MouseEvent.add( SUPER_USER_KEY, this.elm, 'mousedown', onOptionSelect );// onclick では 選択ボックス 隠すように body に設定した onmouseup が先に動いてしまう!
4781 current: function( _current ){
4782 this.elm.className = _current === true ? CLASSNAME_COMBOBOX_OPTION_CURRENT : CLASSNAME_COMBOBOX_OPTION;
4783 this.data.current = _current;
4784 currentOption = _current === true ? this : currentOption;
4786 destroy: function(){
4787 MouseEvent.remove( SUPER_USER_KEY, this.elm );
4788 Util.removeAllChildren( this.elm );
4789 ELM_OPTION_WRAPPER.removeChild( this.elm );
4795 function onOptionSelect( e ){
4797 l = OPTION_LIST.length,
4799 for( ; i < l; ++i ){
4800 _option = OPTION_LIST[ i ];
4801 if( this === _option.elm ){
4802 updateCurrrentOption( _option.data.value, true );
4803 currentCombobox.blur();
4810 var OPTION_LIST = [],
4811 currentCombobox = null,
4817 function updateCurrrentOption( _value, _updateCombobox ){
4819 i = OPTION_LIST.length;
4821 _option = OPTION_LIST[ --i ];
4822 if( _value === _option.data.value ){
4823 currentOption && currentOption.current( false );
4824 _option.current( true );
4825 currentOption = _option;
4827 _updateCombobox === true && currentCombobox.value( _value );
4832 function bodyMouseupHandler(){
4833 currentCombobox.blur();
4834 OptionControl.hide( currentCombobox );
4836 function updateWrapperPosition(){
4837 var position = Util.getAbsolutePosition( elm );
4839 ELM_OPTION_WRAPPER.style.cssText = [
4840 'width:', elm.offsetWidth - 2, 'px;',
4841 'left:', position.x, 'px;',
4842 'top:', position.y + elm.offsetHeight, 'px;'
4845 function change( e ){
4846 var l = OPTION_LIST.length,
4847 i = currentIndex + ( e.keyCode === 40 ? -1 : 1 );
4848 if( currentCombobox === null || l < 2 ) return;
4852 updateCurrrentOption( OPTION_LIST[ i ].data.value, true );
4856 show: function( data ){
4857 var combobox = data.item,
4858 list = data.optionList,
4861 if( currentItem !== combobox || currentCombobox === combobox ) return;
4862 currentCombobox && currentCombobox.blur();
4864 apiuser = data.groupData.apiuser;
4865 currentCombobox = combobox;
4868 for( ; i < l; ++i ){
4869 OPTION_LIST.unshift( new OptionClass( list[ i ] ) );
4871 MouseEvent.add( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler );
4872 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 38 );
4873 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 40 );
4874 //KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter, 13 );
4875 //KeyEvent.updateCurrentListener( SUPER_USER_KEY );
4877 body.appendChild( ELM_OPTION_WRAPPER );
4879 updateCurrrentOption( combobox.value(), false );
4880 updateWrapperPosition();
4882 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4884 hide: function( _combobox ){
4885 if( currentCombobox !== _combobox || currentCombobox === null ) return;
4888 while( _option = OPTION_LIST.shift() ){
4892 body.removeChild( ELM_OPTION_WRAPPER );
4894 MouseEvent.remove( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler );
4895 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change );
4896 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change );
4897 //KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter );
4898 //KeyEvent.updateCurrentListener( apiuser );
4900 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition, 500 );
4903 currentCombobox = null;
4904 currentOption = null;
4907 onEnter: function(){
4908 currentCombobox.value( currentOption.data.value );
4909 //currentCombobox.blur();
4910 //OptionControl.hide( currentCombobox );
4912 update: function( data, _value ){
4913 if( currentCombobox !== data.item || currentItem !== data.item ) return;
4914 if( currentOption.data.value === _value ) return;
4915 updateCurrrentOption( _value, true );
4917 onWindowResize: function( _w, _h ){
4918 currentCombobox && AsyncCall.add( apiuser, updateWrapperPosition );
4923 var UIGroupPrivateData = function(){};
4924 UIGroupPrivateData.prototype = {
4931 init : function( apiuser, node, uigroup ){
4932 this.apiuser = apiuser;
4934 this.uigroup = uigroup;
4936 UIGroupPrivateData.list.push( this );
4938 destroy : function(){
4942 UIGroupPrivateData.list = [];
4943 UIGroupPrivateData.get = function( uigroup ){
4944 var list = UIGroupPrivateData.list,
4947 if( list[ --i ].uigroup === uigroup ) return list[ i ];
4952 var UIGroupClass = function( apiuser, node ){
4953 ( new UIGroupPrivateData() ).init( apiuser, node, this );
4955 UIGroupClass.prototype = {
4956 focus : function( _value ){
4957 var data = UIGroupPrivateData.get( this );
4959 if( _value === true ){
4961 start( apiuser, self, currentItem );
4963 if( itemList.length > 0 ){
4964 start( apiuser, self, itemList[ 0 ] );
4967 if( _value === false ){
4968 finish( apiuser, self, currentItem );
4971 if( _value && Util.getIndex( data.itemList, _value ) !== -1 ){
4972 // currentItem = _value;
4973 currentList = data.itemList;
4975 return currentUi === this;
4978 var data = UIGroupPrivateData.get( this );
4979 if( currentList === data.itemList ){
4983 createInputText : function( elmWrapper, onUpdate, validater ){
4984 var data = UIGroupPrivateData.get( this ),
4985 elmValue = Util.getElementsByClassName( elmWrapper, 'editable-value' )[ 0 ],
4988 ret = new TextInputClass( data, elmWrapper, elmValue, onUpdate, validater );
4989 data.itemList.push( ret );
4992 alert( 'error createInputText' );
4994 createButton : function( elm, onClick ){
4995 var data = UIGroupPrivateData.get( this ),
4996 ret = new ButtonClass( data, elm, onClick );
4997 data.itemList.push( ret );
5000 createFileInput : function( elm, onUpdate, validater, elmFileInputReal ){
5001 var data = UIGroupPrivateData.get( this ),
5002 elmValue = Util.getElementsByClassName( elm, 'fileinput-value' )[ 0 ],
5005 ret = new FileInputClass( data, elm, onUpdate, validater, elmFileInputReal, elmValue );
5006 data.itemList.push( ret );
5011 createCombobox : function( elm, onUpdate, optionList ){
5012 var data = UIGroupPrivateData.get( this ),
5013 ret = new ComboBoxClass( data, elm, onUpdate, optionList );
5014 data.itemList.push( ret );
5017 createCheckBox : function(){
5020 createRadio : function(){
5023 createSlider : function(){
5026 visible : function( v ){
5027 var data = UIGroupPrivateData.get( this );
5028 if( Type.isBoolean( v ) === true && data.visible !== v ){
5029 for( var i = data.itemList.length; i; ){
5030 data.itemList[ --i ].visible( v );
5033 data.node.disabled( !( data.enabled && v ) );
5035 return data.visible;
5037 enabled : function( v ){
5038 var data = UIGroupPrivateData.get( this );
5039 if( Type.isBoolean( v ) === true && data.enabled !== v ){
5040 for( var i = data.itemList.length; i; ){
5041 data.itemList[ --i ].enabled( v );
5044 data.node.disabled( !( data.visible && v ) );
5046 return data.enabled;
5048 destroy : function(){
5049 var data = UIGroupPrivateData.get( this ),
5051 if( currentUi === this ){
5053 // finish( UIItemPrivateData.get( currentItem ) );
5055 while( _item = data.itemList.shift() ){
5062 function start( data ){
5063 if( currentItem !== data.item ){
5064 currentUi !== data.groupData.uigroup && currentUi && currentUi.blur();
5066 currentItem !== null && currentItem.blur();
5068 currentUser = data.groupData.apiuser;
5069 currentUi = data.groupData.uigroup;
5070 currentItem = data.item;
5072 currentUi.focus( currentItem );
5074 // if( currentUser !== _apiuser ) {
5075 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 );
5076 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 );
5077 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 9 );
5078 KeyEvent.updateCurrentListener( SUPER_USER_KEY );
5082 function finish( data ){
5083 if( currentItem === data.item ){
5091 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 );
5092 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 );
5093 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 9 );
5094 KeyEvent.updateCurrentListener( data.groupData.apiuser );
5098 function onKeyDown( e ){
5099 if( currentItem === null ) return true;
5100 var keyCode = e.keyCode,
5101 index = Util.getIndex( currentList, currentItem );
5102 if( keyCode === 13 || keyCode === 27 || keyCode === 9 || keyCode === 18 || e.altKey === true ){ // 13.return 27.esc 9.tab 18.alt
5103 keyCode === 9 && tabShift( index, e.shiftKey === true ? -1 : 1 );
5104 keyCode === 13 && currentItem instanceof ComboBoxClass && OptionControl.onEnter();
5105 keyCode === 13 && tabShift( index, 1 );
5106 currentItem && currentItem.blur( keyCode );
5111 function tabShift( index, way ){
5112 var l = currentList.length,
5116 while( i !== index ){
5119 i < l ? i : 0; // 0 < i < l
5120 item = currentList[ i ];
5121 if( item.enabled() === true && item.visible() === true ){
5122 AsyncCall.add( currentUser, item.focus, null, item );
5130 createUIGroup: function( apiuser, node ){
5131 var uid = apiuser.getUID(),
5132 list = UI_LIST[ uid ],
5133 ui = new UIGroupClass( apiuser, node );
5134 if( Type.isArray( list ) === false ){
5135 list = UI_LIST[ uid ] = [];
5140 onWindowResize: function( w, h ){
5143 currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h );
5144 currentItem instanceof TextInputClass && TextInputManager.onWindowResize( w, h );
5145 currentItem instanceof FileInputClass && FileInputManager.onWindowResize( w, h );
5147 onCurrentApplicationChange: function( _apiuser ){
5148 currentList = UI_LIST[ _apiuser.getUID() ];
5150 onApplicationShutdown: function( _apiuser ){
5151 KeyEvent.remove( _apiuser );
5153 onSystemShutdown: function(){
5159 var UIForm = ( function(){
5161 var CLASSNAME_FORM = 'uiform-invisible';
5162 var CLASSNAME_FILE_WRAP = 'ui-fileinput-wrapper';
5163 var FormItemData = function(){};
5164 FormItemData.prototype = {
5167 init : function( formData, uiItem ){
5168 this.formData = formData;
5169 this.uiItem = uiItem;
5171 onUpdate : function( v ){
5172 // var index = Util.getIndex( this.formData.itemList, this );
5176 var FormPrivateData = function(){};
5177 FormPrivateData.prototype = {
5185 init : function( apiuser, from, node, elm, elmForm ){
5186 this.apiuser = apiuser;
5188 this.ui = apiuser.createUIGroup( node );
5191 this.elmForm = elmForm;
5193 elmForm.className = CLASSNAME_FORM;
5194 FormPrivateData.list.push( this );
5196 var forms = Util.copyArray( elmForm.getElementsByTagName( '*' ) ),
5199 items = 'input,select,textarea,button',
5200 form, data, el, wrap;
5203 if( form.nodeType !== 1 ) continue;
5204 switch( form.tagName.toLowerCase() ){
5206 switch( form.type.toLowerCase() ){
5210 el = document.createElement( 'div' );
5211 el.className = 'uiform-file-container';
5212 el.appendChild( document.createElement( 'div' ) );
5213 el.appendChild( document.createElement( 'div' ) );
5214 el.firstChild.className = 'uiform-label';
5215 el.lastChild.className = 'uiform-file fileinput-value';
5216 // opera9 don't work for opera9;
5217 //el = Util.pullHtmlAsTemplete( '<div class="uiform-file-container"><div class="uiform-label"></div><div class="uiform-file fileinput-value"></div></div>' );
5218 elm.appendChild( el );
5219 data = new FormItemData();
5220 wrap = document.createElement( 'div' );
5221 form.parentNode.insertBefore( wrap, form );
5222 wrap.className = CLASSNAME_FILE_WRAP;
5223 wrap.appendChild( form );
5224 data.init( this, this.ui.createFileInput( el, data.onUpdate, null, form ) );
5225 this.itemList.push( data );
5244 destroy : function(){
5248 FormPrivateData.list = [];
5249 FormPrivateData.get = function( from ){
5250 var list = FormPrivateData.list,
5253 if( list[ --i ].form === form ) return list[ i ];
5258 var FormClass = function( apiuser, node, elm, elmForm ){
5259 ( new FormPrivateData() ).init( apiuser, this, node, elm, elmForm );
5261 FormClass.prototype = {
5262 createTextInput : function(){
5265 createMultiLineInput : function(){
5268 createFileInput : function(){
5271 createButton : function(){
5274 createComboBox : function(){
5277 submit : function(){
5283 createForm: function( apiuser, nodeOrElm, opt_elmForm ){
5284 var uid = apiuser.getUID(),
5285 list = FORM_LIST[ uid ],
5287 if( PointingDeviceEventTree.isNodeInstance( nodeOrElm ) === true ){
5289 elm = PointingDeviceEventTree._getNodePrivateData( nodeOrElm ).elm;
5291 // App が eventTree を持っている?
5292 // App が eventTree を持っていない
5295 form = new FormClass( apiuser, node, elm, opt_elmForm );
5296 if( Type.isArray( list ) === false ){
5297 list = FORM_LIST[ uid ] = [];
5302 onWindowResize: function( w, h ){
5305 currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h );
5306 currentItem instanceof TextInputClass && TextInputManager.onWindowResize( w, h );
5307 currentItem instanceof FileInputClass && FileInputManager.onWindowResize( w, h );
5309 onCurrentApplicationChange: function( _apiuser ){
5311 onApplicationShutdown: function( _apiuser ){
5313 onSystemShutdown: function(){
5319 var Finder = ( function(){
5320 var FINDER_LIST = [],
5321 ELM_ORIGIN_LOCATION_ITEM = Util.pullHtmlAsTemplete( '<div class="finder-location-item"></div>' ),
5322 HTML_FINDER_ICON = ( function(){
5323 return ( UA.isIE === true && UA.ieVersion < 8 ?
5325 '<div class="finder-icon fnder-icon-ie7">',
5326 '<div class="finder-icon-handle"></div>',
5327 '<div class="file-icon"><div></div></div>',
5328 '<span class="finder-icon-cell finder-icon-ie-filename">',
5329 '<span class="finder-icon-vertical-middle-outer">',
5330 '<span class="finder-icon-vertical-middle-inner">',
5331 '<span class="finder-icon-filename break-word">file name</span>',
5335 '<span class="finder-icon-cell finder-icon-ie-summary">',
5336 '<span class="finder-icon-vertical-middle-outer">',
5337 '<span class="finder-icon-vertical-middle-inner">',
5338 '<span class="finder-icon-summary break-word">file descriptiion</span>',
5342 '<div class="finder-icon-down"></div>',
5346 '<div class="finder-icon fnder-icon-modern">',
5347 '<div class="finder-icon-handle"></div>',
5348 '<div class="file-icon"><div></div></div>',
5349 '<div class="finder-icon-filename break-word">file name</div>',
5350 '<div class="finder-icon-summary break-word">file descriptiion</div>',
5351 '<div class="finder-icon-down">></div>',
5355 ELM_ORIGIN_FINDER_ICON = Util.pullHtmlAsTemplete( HTML_FINDER_ICON ),
5356 ICON_HEIGHT = Util.getElementSize( ELM_ORIGIN_FINDER_ICON ).height;
5359 // b : 開始の値(開始時の座標やスケールなど)
5361 // d : Tween(トゥイーン)の合計時間
5363 function easeOutQuad( t, b, c, d ){
5365 return -c * t*( t-2 ) + b;
5371 var FinderIconClass = function(){};
5372 FinderIconClass.prototype = {
5379 init : function( page, file, w, index, style ){
5380 if( !this.elm ) this.elm = ELM_ORIGIN_FINDER_ICON.cloneNode( true );
5382 if( this.page !== page ){
5384 page.elm.appendChild( this.elm );
5385 this.node && this.node.remove();
5386 this.node = page.node.createNode( this.elm, false, true, 'finder-icon-hover', '' );
5388 if( this.file !== file ){
5389 this.file && this.file.destroy();
5391 this._index = index;
5395 if( this._index !== index ){
5396 this._index = index;
5400 index : function( _index ){
5403 style : function( _style ){
5406 draw : function( w ){
5407 var file = this.file,
5409 thumb = file.getThumbnail(),
5410 elmThumb = Util.getElementsByClassName( elm, 'file-icon' )[ 0 ].firstChild,
5411 elmName = Util.getElementsByClassName( elm, 'finder-icon-filename' )[ 0 ],
5412 elmDesc = Util.getElementsByClassName( elm, 'finder-icon-summary' )[ 0 ];
5414 elmThumb.className = 'has-thumbnail';
5415 elmThumb.style.backgroundImage = [ 'url(', thumb.image, ')' ].join( '' );
5417 elmThumb.className = thumb.className;
5418 elmThumb.style.backgroundImage = '';
5421 elmName.firstChild.data = file.getName();
5422 elmDesc.firstChild.data = file.getSummary();
5426 resize : function( w ){
5427 this.node.update( 0, this._index * ICON_HEIGHT, w );
5429 onEditorClick : function( e ){
5430 this.onEditorCallback && this.onEditorCallback( this.file, this.file.editorApplicationList()[ 0 ] );
5433 onViwerClick : function( e ){
5434 this.onViewerCallback && this.onViewerCallback( this.file, this.file.viewerApplicationList()[ 0 ] );
5437 onActionClick : function( e ){
5438 this.onActionCallback && this.onActionCallback( this.file );
5441 destroy : function(){
5442 this.elm && this.elm.parentNode.removeChild( this.elm );
5443 this.file && this.file.destroy();
5444 this.node && this.node.remove();
5450 FinderIconClass.pool.push( this );
5453 FinderIconClass.pool = [];
5454 FinderIconClass.get = function( page, file, w, index, style ){
5455 var _icon = FinderIconClass.pool.length > 0 ? FinderIconClass.pool.shift() : new FinderIconClass();
5456 _icon.init( page, file, w, index, style );
5463 var PathClass = function(){};
5464 PathClass.prototype = {
5471 init : function( finderData, file, index ){
5472 if( !this.elm ) this.elm = ELM_ORIGIN_LOCATION_ITEM.cloneNode( true );
5474 if( this.finderData !== finderData ){
5475 this.finderData = finderData;
5476 finderData.elmPath.appendChild( this.elm );
5477 this.node && this.node.remove();
5480 if( this.file !== file ){
5484 this._index = index;
5485 if( !this.node ) this.node = finderData.nodePath.createNode( this.elm, false, true, 'finder-path-hover', 'pointer' );
5488 this.elm.className = 'file-icon-' + this.file.getType();
5489 this.elm.innerHTML = this.file.getName();
5491 textWidth : function(){
5492 this.elm.style.width = 'auto';
5493 var ret = this.elm.offsetWidth;
5494 this.elm.style.width = '';
5497 update : function( x, w ){
5498 this.node.update( x - 15, undefined, w );
5500 index : function( _index ){
5503 destroy : function(){
5504 this.finderData.elmPath.removeChild( this.elm );
5505 this.node && this.node.remove();
5507 delete this.finderData;
5512 PathClass.pool.push( this );
5515 PathClass.pool = [];
5516 PathClass.get = function( finderData, file, index ){
5517 var _bread = PathClass.pool.length > 0 ? PathClass.pool.shift() : new PathClass();
5518 _bread.init( finderData, file, index );
5526 var PageClass = function(){};
5527 PageClass.prototype = {
5542 init : function( nodeRoot, elmRoot, elmScroll ){
5543 this.nodeRoot = nodeRoot;
5544 this.elmRoot = elmRoot;
5545 this.elmScroll = elmScroll;
5547 if( this.elm === null ){
5548 this.elm = document.createElement( 'div' );
5550 elmScroll.appendChild( this.elm );
5551 this.elm.style.cssText = 'position:absolute;top:0;';
5552 // this.elm.style.display = 'none';
5553 this.node = this.nodeRoot.createNode( this.elm, true, false );
5554 if( this.iconList === null ){
5558 panInReady : function( way ){
5559 this.elm.style.display = '';
5560 var x = this.sliding === true ? this.currentX : way * this.nodeRoot.width();
5561 this.startX = this.currentX = x;
5565 this.panTotalTime = 20;
5566 this.sliding = true;
5567 this.isPanOut = false;
5568 // this.elm.style.left = x + 'px';
5571 panOutReady : function( way ){
5572 var x = -way * this.nodeRoot.width();
5573 this.startX = this.currentX || 0;
5575 this.offsetX = x - this.startX;
5577 this.panTotalTime = 20;
5578 this.sliding = true;
5579 this.isPanOut = true;
5583 x = page.currentX = easeOutQuad( page.panTime, page.startX, page.offsetX, page.panTotalTime );
5584 // page.elm.style.left = x + 'px';
5586 if( page.panTotalTime < ++page.panTime ){
5587 delete page.panTime;
5589 delete page.offsetX;
5590 delete page.panTotalTime;
5591 delete page.sliding;
5592 if( this.isPanOut === true ) this.elm.style.display = 'none';
5595 draw : function( folder ){
5596 _w = this.nodeRoot.width();
5597 this.folder = folder;
5599 iconList = data.iconList,
5602 l = folder.getChildFileLength(),
5603 m = iconList.length,
5604 scrollY = -this.nodeRoot.scrollY(),
5605 rootH = scrollY + this.nodeRoot.height(),
5608 for( ; i < l; ++i ){
5609 if( ( i + 1 ) * ICON_HEIGHT < scrollY || rootH < i * ICON_HEIGHT ) continue;
5611 iconList[ j ].init( this, folder.getChildFileAt( i ), _w, i, data.style );
5613 iconList.push( FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) );
5617 data.elmRoot.className = folder.getState() === Const.FILE.STATE.LOADING ? 'finder-body loading' : 'finder-body';
5618 // data.elmRoot.style.height = ( data.h - data.headH ) + 'px';
5620 while( j < iconList.length ) iconList.pop().destroy();
5621 data.elmScroll.style.height = ( l * ICON_HEIGHT ) + 'px';
5623 onScroll : function(){
5624 var _w = this.nodeRoot.width();
5627 iconList = data.iconList,
5628 folder = this.folder,
5631 l = folder.getChildFileLength(),
5632 scrollY = -this.nodeRoot.scrollY(),
5633 rootH = scrollY + this.nodeRoot.height(),
5634 startIndex = 0 < iconList.length ? iconList[ 0 ]._index : 0,
5637 // console.log( ' > ' + scrollY + ' , ' + rootH )
5638 for( ; i < l; ++i ){
5639 if( ( i + 1 ) * ICON_HEIGHT < scrollY || rootH < i * ICON_HEIGHT ){
5640 if( iconList.length <= j ) continue;
5641 icon = iconList[ j ];
5642 if( icon._index !== i ) continue;
5644 iconList.splice( j, 1 );
5647 if( iconList.length <= j || iconList[ j ]._index !== i ){
5648 if( i < startIndex ){
5649 iconList.splice( j, 0, FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) );
5651 if( startIndex + iconList.length <= i ){
5652 iconList.push( FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) );
5658 //while( j < iconList.length ) iconList.pop().destroy();
5660 resize : function( w ){
5661 var list = this.iconList,
5663 for( ; i; ) list[ --i ].resize( w );
5665 destroy : function(){
5667 while( icon = this.iconList.shift() ) icon.destroy();
5669 this.elm.parentNode.removeChild( this.elm );
5673 var ApplicationButton = function(){};
5674 ApplicationButton.prototype = {
5680 init : function( ui, elmParent, app, file ){
5681 if( this.elm === null ){
5682 this.elm = document.createElement( 'div' );
5684 elmParent.appendChild( this.elm );
5685 this.elm.className = 'button';
5686 this.elm.innerHTML = app.getDisplayName();
5689 this.button = ui.createButton( this.elm, function(){
5696 this.fileUID = file.getUID();
5698 onClick : function(){
5699 this.app.boot( this.file );
5702 destroy : function(){
5704 elm.parentNode.removeChild( elm );
5706 this.button.destroy();
5712 var DetailPageClass = function(){};
5713 DetailPageClass.prototype = Util.extend( new PageClass(), {
5715 init : function( finderData ){
5716 this.finderData = finderData;
5717 this.apiuser = finderData.apiuser;
5718 this.nodeRoot = finderData.nodeRoot;
5719 this.elmRoot = finderData.elmRoot;
5720 this.elmScroll = finderData.elmScroll;
5722 if( this.elm === null ){
5723 this.elm = Util.pullHtmlAsTemplete( [
5724 '<div class="finder-detail">',
5725 '<div class="file-icon"><div></div></div>',
5726 '<div class="finder-detail-filename break-word">file name</div>',
5727 '<div class="finder-detail-summary break-word">file descriptiion</div>',
5728 '<div>View this file</div>',
5729 '<div class="viewer-apps"></div>',
5730 '<div>Edit this file</div>',
5731 '<div class="editor-apps"></div>',
5735 this.elm.style.display = 'none';
5736 this.elmScroll.appendChild( this.elm );
5737 this.node = this.nodeRoot.createNode( this.elm, true, false );
5739 this.ui = this.apiuser.createUIGroup( this.node );
5740 this.appButtons = [];
5742 draw : function( file ){
5744 thumb = file.getThumbnail(),
5745 elmThumb = Util.getElementsByClassName( elm, 'file-icon' )[ 0 ].firstChild,
5746 elmName = Util.getElementsByClassName( elm, 'finder-detail-filename' )[ 0 ],
5747 elmDesc = Util.getElementsByClassName( elm, 'finder-detail-summary' )[ 0 ],
5748 tmpButtons = Util.copyArray( this.appButtons ),
5749 apps, app, elmContainer;
5751 elmThumb.className = 'has-thumbnail';
5752 elmThumb.style.backgroundImage = [ 'url(', thumb.image, ')' ].join( '' );
5754 elmThumb.className = thumb.className;
5755 elmThumb.style.backgroundImage = '';
5758 elmName.firstChild.data = file.getName();
5759 elmDesc.firstChild.data = file.getSummary();
5760 this.node.width( this.nodeRoot.width() );
5761 this.node.height( this.nodeRoot.height() );
5763 this.appButtons.length = 0;
5765 apps = file.viewerApplicationList();
5766 elmContainer = Util.getElementsByClassName( elm, 'viewer-apps' )[ 0 ];
5767 for( i = 0; i < apps.length; ++i ){
5768 button = 0 < tmpButtons.length ? tmpButtons.shift() : new ApplicationButton();
5769 button.init( this.ui, elmContainer, apps[ i ], file );
5770 this.appButtons.push( button );
5772 apps = file.editorApplicationList();
5773 elmContainer = Util.getElementsByClassName( elm, 'editor-apps' )[ 0 ];
5774 for( i = 0; i < apps.length; ++i ){
5775 button = 0 < tmpButtons.length ? tmpButtons.shift() : new ApplicationButton();
5776 button.init( this.ui, elmContainer, apps[ i ], file );
5777 this.appButtons.push( button );
5780 while( button = tmpButtons.shift() ) button.destroy();
5786 x = page.currentX = easeOutQuad( page.panTime, page.startX, page.offsetX, page.panTotalTime );
5787 // page.elm.style.left = x + 'px';
5789 if( page.panTotalTime < ++page.panTime ){
5790 delete page.panTime;
5792 delete page.offsetX;
5793 delete page.panTotalTime;
5794 delete page.sliding;
5795 if( this.isPanOut === true ) this.elm.style.display = 'none';
5798 onScroll : function(){
5801 resize : function(){
5802 this.elmScroll.style.height = this.nodeRoot.height() + 'px';
5804 destroy : function(){
5806 while( button = this.appButtons.shift() ) button.destroy();
5815 var FinderPrivateData = Class.create(
5816 Class.PRIVATE_DATA, {
5826 viewerOption : null,
5827 editorOption : null,
5839 Constructor : function( finder, apiuser, elm, tree, onSelect, viewerOption, editorOption ){
5840 this.finder = finder;
5841 this.apiuser = apiuser;
5842 if( PointingDeviceEventTree.isNodeInstance( elm ) === true ){
5843 this.nodeRoot = elm;
5844 this.elmRoot = PointingDeviceEventTree._getNodePrivateData( elm ).elm;
5846 // App が eventTree を持っている?
5847 // App が eventTree を持っていない
5850 this.nodeRoot.addEventListener( 'click', this.onIconClick, this );
5851 this.nodeRoot.addEventListener( 'scroll', this.onScroll, this );
5853 this.elmScroll = document.createElement( 'div' );
5854 this.elmRoot.appendChild( this.elmScroll );
5855 this.elmScroll.className = 'finder-elm-scroll';
5856 this.elmScroll.style.cssText = 'width:100%;overflow:hidden;';
5859 this.onSelect = onSelect;
5860 this.viewerOption = viewerOption;
5861 this.editorOption = editorOption;
5863 var size = Util.getElementSize( ELM_ORIGIN_FINDER_ICON );
5864 this.iconW = size.width;
5865 this.iconH = size.height;
5867 tree.addTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw, this );
5868 Util.addClass( this.elmRoot, 'finder-body' );
5870 if( this.panInPage === null ){
5871 this.pageIcons1 = new PageClass();
5872 this.pageIcons2 = new PageClass();
5873 this.pageDetail = new DetailPageClass();
5875 this.pageIcons1.init( this.nodeRoot, this.elmRoot, this.elmScroll );
5876 this.pageIcons2.init( this.nodeRoot, this.elmRoot, this.elmScroll );
5877 this.pageDetail.init( this );
5879 onIconClick : function( e ){
5880 if( this.panInPage === this.pageDetail ) return;
5882 var target = e.target,
5883 list = this.panInPage.iconList,
5886 if( target === this.nodeRoot ) return;
5887 for( i = list.length; i; ){
5889 if( icon.node === target ){
5891 file = this.currentFile.getChildFileAt( i );
5892 if( target.width() - 30 < e.layerX ){
5893 this.tree.down( i );
5894 this.draw( this.w, this.h, 1, true );
5896 if( file.getChildFileLength() !== -1 || file.getType() === Const.FILE.TYPE.FOLDER ){
5897 this.tree.down( i );
5898 this.draw( this.w, this.h, 1 );
5900 if( Type.isFunction( this.onSelect ) === true ){ /* && this.onSelect( file ) === true */
5901 this.onSelect( file );
5903 this.tree.down( i );
5904 this.draw( this.w, this.h, 1 );
5911 onScroll : function( e ){
5912 this.panInPage.onScroll( e );
5914 onPathClick : function( e ){
5915 var target = e.target,
5916 i = target.nodeIndex();
5917 if( target === this.nodePath || this.nodePath.numNode() - 1 === i ) return;
5919 this.draw( this.w, this.h, -1 );
5921 draw : function( w, h, way, showDetail ){
5922 var data = this, page;
5923 data.w = w = Type.isFinite( w ) === true ? w : data.w;
5924 data.h = h = Type.isFinite( h ) === true ? h : data.h;
5926 var file = this.currentFile = this.tree.getCurrentFile(),
5927 isFolder = showDetail !== true && ( file.getChildFileLength() !== -1 || file.getType() === Const.FILE.TYPE.FOLDER );
5929 data.elmPath && data.drawPath( w );
5930 page = this.panInPage;
5931 if( Type.isNumber( way ) === true ){
5932 if( page.sliding === false ){
5933 if( isFolder === true ){
5934 this.panInPage = page === this.pageIcons1 ? this.pageIcons2 : ( page === this.pageIcons2 ? this.pageIcons1 : this.panOutPage );
5936 this.panInPage = this.pageDetail;
5938 this.panOutPage = page;
5940 this.panInPage.panInReady( way );
5941 //this.panInPage.elm.className = 'panIN';
5942 this.panOutPage.panOutReady( way );
5943 //this.panOutPage.elm.className = 'panOut';
5944 this.nodeRoot.disabled( true );
5945 SystemTimer.add( this.apiuser, this.tick, 16, false, this );
5947 if( isFolder === true ){
5948 this.panInPage = page === null ? this.pageIcons1 : page;
5950 this.panInPage = this.pageDetail;
5953 this.panInPage.draw( file );
5955 data.nodeRoot.invalidateScrollbar();
5958 if( this.panInPage.sliding === false && this.panOutPage.sliding === false ){
5959 SystemTimer.remove( this.apiuser, this.tick );
5960 this.nodeRoot.disabled( false );
5961 this.nodeRoot.invalidateScrollbar();
5964 this.panInPage.sliding === true && this.panInPage.pan();
5965 this.panOutPage.sliding === true && this.panOutPage.pan();
5967 drawPath : function( w ){
5968 if( !this.elmPath.parentNode ) return;
5969 w = this.nodePath.width();
5972 pathList = data.pathList,
5974 l = tree.hierarchy() + 1,
5975 m = pathList.length,
5978 minW = FinderPrivateData.MIN_PATH_WIDTH,
5979 file, path, pathW, offset, remove, pathX = 0, fit = false;
5981 for( ; i < l; ++i ){
5982 file = i !== l - 1 ? tree.getParentFileAt( i ) : this.currentFile;
5984 pathList[ i ].init( this, file, i );
5986 pathList.push( PathClass.get( this, file, i ) );
5989 while( l < pathList.length ) pathList.pop().destroy();
5992 pathW = pathList[ --i ].textWidth();
5993 wList.push( pathW );
5997 //if( minW * ( l + 1 ) * 1.2 < w ){
5998 console.log( totalW + ' , ' + w )
6000 if( fit === true ) break;
6001 for( i = 0; i < l; ++i ){
6002 offset = totalW - w;
6008 remove = offset < remove ? offset : remove;
6010 if( pathW - remove < minW ){
6011 totalW -= ( pathW - minW );
6014 wList[ i ] = pathW - remove;
6019 for( i = 0; i < l; ++i ){
6020 path = pathList[ i ];
6022 path.update( pathX, pathW );
6029 createPath : function( node ){
6030 if( this.elmPath ) return;
6032 if( PointingDeviceEventTree.isNodeInstance( node ) === true ){
6033 this.nodePath = node;
6034 this.elmPath = PointingDeviceEventTree._getNodePrivateData( node ).elm;
6036 node.addEventListener( 'click', this.onPathClick, this );
6037 Util.addClass( this.elmPath, 'finder-path' );
6038 // this.elmPath = document.createElement( 'div' );
6039 // this.elmPath.className = ;
6042 AsyncCall.add( this.apiuser, this.draw, null, this );
6045 onKill : function(){
6046 this.tree.removeTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw );
6048 if( this.pathList ){
6049 while( this.pathList.length > 0 ) this.pathList.shift().destroy();
6052 this.pageIcons1.destroy();
6053 this.pageIcons2.destroy();
6054 this.pageDetail.destroy();
6055 this.nodeRoot.remove();
6057 FINDER_LIST.splice( Util.getIndex( FINDER_LIST, this.finder ), 1 );
6058 var data = ApplicationPrivateData.get( this.apiuser ),
6059 list = data.finderList,
6060 i = Util.getIndex( list, this.finder );
6061 i !== -1 && list.splice( i, 1 );
6064 FinderPrivateData.MIN_PATH_WIDTH = 25;
6069 var Finder = Class.create(
6070 FinderPrivateData, {
6071 Constructor : function( application, elmRoot, tree, onSelect, viewerOption, editorOption ){
6072 Finder.newPrivateData( this, this, application, elmRoot, tree, onSelect, viewerOption, editorOption );
6076 resize : function( w, h ){
6077 var data = Finder.getPrivateData( this );
6078 data.panInPage && data.panInPage.resize( w );
6080 createPath : function( node ){
6081 return Finder.getPrivateData( this ).createPath( node );
6083 destroy : function(){
6092 create: function( application, elmTarget, tree, onSelect, viewerOption, editorOption ){
6093 //if( Application.isApplicationInstance( _application ) === false ) return;
6095 var finder = new Finder( application, elmTarget, tree, onSelect, viewerOption, editorOption );
6096 FINDER_LIST.push( finder );
6099 registerFinderHead: function(){
6102 registerFinderPane: function( _finderPane ){
6105 isFinderInstance: function( _finder ){
6106 return _finder instanceof Finder;
6108 isFinderPaneInstance: function(){
6111 isFinderHeadInstance: function(){
6119 * marginBottom, marginLeft, marginRight, marginTop, margin
6120 * padding, paddingBottom, paddingLeft, paddingRight, paddingTop
6121 * fontSize, textIndent
6123 * bottom, left, right, top (len, %)
6126 * borderBottomWidth, borderLeftWidth, borderRightWidth, borderTopWidth, borderWidth,
6131 * borderBottomColor, borderLeftColor, borderRightColor, borderTopColor, borderColor
6135 * clip rect(0px, 40px, 40px, 0px);
6136 * backgroundPosition (len, %)
6138 * lineHeight (len, %, num)
6142 var DHTML = ( function(){
6144 var TICKET_ARRAY = [],
6147 cround = function( v ){ return round( v * 100 ) / 100 };
6149 function startAnimation( _elm, _cssObject, _onComplete, _onEnterFrame, _numFrames ){
6150 var _ticket, i = TICKET_ARRAY.length;
6152 _ticket = TICKET_ARRAY[ --i ];
6153 if( _ticket.elm === _elm ){
6158 var _currentValues = [],
6161 _targetProperties = [],
6163 var target, current,
6164 inlineStyle = CSS.getInlineStyle( _elm ),
6165 currentStyle = CSS.getWrappedStyle( _elm ),
6166 targetStyle = CSS.getWrappedStyle( _elm, _cssObject );
6167 targetStyle.pxPerEm = currentStyle.get( 'fontSize' )._toPx();
6168 for( var p in _cssObject ){
6169 p = Util.camelize( p );
6170 target = targetStyle.get( p );
6171 current = currentStyle.get( p );
6173 if( target.isValid() === false || current.isValid() === false || current.equal( target ) !== false ){
6179 current.convert( target );
6180 // alert( current.getValue() + ' , ' + target.getValue() )
6181 _currentValues.push( current.getValue() );
6182 _offsetValues.push( current.getOffset( target ) );
6183 _endValues.push( target.getValue() );
6184 _targetProperties.push( p );
6185 _units.push( target.getUnit() );
6187 // IE has trouble with opacity if it does not have layout
6188 // Force it by setting the zoom level
6189 if( p === 'opacity' && SPECIAL.hasLayout ){
6190 if( SPECIAL.hasLayout( _elm ) === false ) inlineStyle.zoom = 1;
6191 inlineStyle.filter = current.getValueText();
6193 inlineStyle[ p ] = current.getValueText();
6200 var i, cssTexts = [];
6201 for( i = 0; i < _numFrames; ++i ){
6202 if( i < _numFrames - 1 ){
6203 tickValue( _currentValues, _offsetValues, _numFrames );
6204 cssTexts.push( createCssText( _currentValues, _targetProperties, targetStyle, inlineStyle ) );
6206 cssTexts.push( createCssText( _endValues, _targetProperties, targetStyle, inlineStyle ) );
6210 TICKET_ARRAY.push( new AnimationTaskClass(
6212 Type.isFunction( _onComplete ) === true ? _onComplete : null,
6213 Type.isFunction( _onEnterFrame ) === true ? _onEnterFrame : null,
6217 currentStyle.clear();
6218 targetStyle.clear();
6219 SystemTimer.add( SUPER_USER_KEY, onEnterFrame, 1000 / fpms );
6222 function tickValue( current, offset, numFrames ){
6223 if( Type.isArray( current ) === true ){
6224 var ret, i = current.length;
6227 ret = tickValue( current[ i ], offset[ i ], numFrames );
6228 if( Type.isNumber( ret ) === true ) current[ i ] = ret;
6231 return current + offset / numFrames;
6234 function createCssText( update, props, style, inline ){
6236 for( var i = props.length; i; ){
6237 prop = style.get( props[ --i ] );
6238 prop.setValue( update[ i ] );
6239 inline[ Util.uncamelize( prop.name ) ] = prop.getValueText();
6240 //if( prop.name === 'backgroundColor' ) alert( prop.getValueText() + '|' + update[ i ].join( ',') )
6243 return CSS.toCssText( inline );
6246 function onEnterFrame(){
6249 while( i < TICKET_ARRAY.length ){
6250 _ticket = TICKET_ARRAY[ i ];
6251 l = _ticket.cssTexts.length;
6252 _ticket.elm.style.cssText = _ticket.cssTexts.shift();
6254 _ticket.onComplete && _ticket.onComplete();
6256 delete _ticket.cssTexts;
6257 delete _ticket.onComplete;
6258 delete _ticket.onEnterFrame;
6259 delete _ticket.numFrame;
6260 TICKET_ARRAY.splice( i, 1 );
6262 _ticket.onEnterFrame && _ticket.onEnterFrame( l / _ticket.numFrame );
6266 if( TICKET_ARRAY.length === 0 ){
6267 SystemTimer.remove( SUPER_USER_KEY, onEnterFrame );
6271 var AnimationTaskClass = function( elm, cssTexts, onEnterFrame, onComplete, numFrame ){
6273 this.cssTexts = cssTexts;
6274 this.onEnterFrame = onEnterFrame;
6275 this.onComplete = onComplete;
6276 this.numFrame = numFrame;
6279 var VisualEffectClass = function( elm ){
6282 VisualEffectClass.prototype = {
6283 anime : function( _cssObject, _onComplete, _onEnterFrame, _time ){
6284 var _numFrames = Math.floor( _time / fpms );
6285 startAnimation( this.elm, _cssObject, _onComplete, _onEnterFrame, _numFrames );
6287 fadeIn : function(){
6290 fadeOut : function(){
6293 update : function( x, y, w, h ){
6294 var _cssText = this.elm.style.cssText;
6299 create: function( application, _elm ){
6300 return new VisualEffectClass( _elm );
6302 isInstanceOfVisualEffect: function( _instance){
6303 return _instance instanceof VisualEffectClass;
6309 /* --------------------------------------------
6313 Application.onCurrentApplicationChange( SUPER_USER_KEY );
6315 SERVICE_LIST.push( MouseEvent );
6317 new EventTicketClass( window, 'unload', function(){
6319 while( SERVICE_LIST.length > 0 ){
6320 _service = SERVICE_LIST.shift();
6321 Type.isFunction( _service.onSystemShutdown ) === true && _service.onSystemShutdown();
6327 /* ---------------------------------------------
6328 * broadcast to global
6332 gOS.registerApplication = Application.register;
6333 gOS.registerDriver = File.registerDriver;
6337 var DOM = ( function( window, document ){
6344 function correctNodes( node ){
6346 if( node && node.parentNode ){
6347 while( node.lastChild ) correctNodes( node.lastChild );
6348 node.parentNode.removeChild( node );
6349 if( node.nodeType === 1 ){
6350 switch( node.tagName ){
6352 DIV_LIST.push( node );
6355 SPAN_LIST.push( node );
6359 node.removeAttribute( 'className' );
6360 node.removeAttribute( 'style' );
6361 node.removeAttribute( 'id' );
6363 if( node.nodeType === 3 ){
6365 TEXT_LIST.push( node );
6371 createDiv : function(){
6372 return 0 < DIV_LIST.length ? DIV_LIST.shift() : document.createElement( 'div' );
6374 createSpan : function(){
6377 createText : function(){
6380 getTextSize : function( elm, content ){
6381 var span = DOM.createSpan(),
6382 text = DOM.createText(),
6384 elm.appendChild( span );
6385 span.style.cssText = 'visibility:hidden;position:absolute;';
6386 span.appendChild( text );
6387 text.data = content;
6388 w = span.offsetWidth;
6389 h = span.offsetHeight;
6390 DOM.correctNodes( span );
6393 correctNodes : function( node ){
6395 if( node && node.parentNode ){
6396 while( node.lastChild ) DOM.correctNodes( node.lastChild );
6397 node.parentNode.removeChild( node );
6398 if( node.nodeType === 1 ){
6399 switch( node.tagName ){
6401 DIV_LIST.push( node );
6404 SPAN_LIST.push( node );
6408 node.removeAttribute( 'className' );
6409 node.removeAttribute( 'style' );
6410 node.removeAttribute( 'id' );
6412 if( node.nodeType === 3 ){
6414 TEXT_LIST.push( node );
6419 })( window, document );
6421 var XBrowserStyle = ( function(){
6426 UNITS = 'px,cm,mm,in,pt,pc,em,%'.split( ',' ),
6427 CLIP_SEPARATOR = UA.isIE === true && UA.ieVersion < 8 ? ' ' : ',';
6429 var SPECIAL = ( function(){
6431 if( UA.isIE === true && UA.ieVersion < 9 ){
6432 if( UA.ACTIVEX === true ){
6433 // special.opacity = 'ActiveXOpacity';
6434 special.setFilters = function( style ){
6435 var filters = ( style.filter || '' ).split( ') ' ),
6438 filter, names, props, prop, j, l, key, v;
6440 filter = filters[ --i ].split( ' ' ).join( '' ).split( '(' );
6441 if( filter.length !== 2 ) continue;
6442 names = filter[ 0 ].split( '.' ); // progid:DXImageTransform.Microsoft.Shadow(color=#666666,direction=120,strength=9)
6443 props = filter[ 1 ].split( ',' ); //
6445 for( j = 0, l = props.length; j < l; ++j ){
6446 prop = props[ j ].split( '=' );
6447 key = prop[ 0 ].toLowerCase();
6449 filter[ key ] = v; //v.charAt( 0 ) === '#' ? v : parseInt( v );
6451 data[ names[ names.length - 1 ] ] = filter;
6454 style.filter = data;
6455 style.opacity = data.alpha && data.alpha.opacity ? data.alpha.opacity / 100 : 1;
6457 special.hasLayout = function( elm ){
6458 return elm.currentStyle.hasLayout;
6461 special.opacity = null;
6464 var style = document.documentElement.style;
6465 special.opacity = style.opacity !== undefined ? 'opacity' :
6466 style.MozOpacity !== undefined ? 'MozOpacity' :
6467 style.KhtmlOpacity !== undefined ? 'KhtmlOpacity' :
6468 style[ '-khtml-opacity' ] !== undefined ? 'KhtmlOpacity' : null;
6470 // if( style.backgroundPositionX === undefined ){
6471 special.setBackgroundPositionXY = function( style ){
6472 var bgp = ( style.backgroundPosition || '' ).split( ' ' );
6473 style.backgroundPositionX = bgp[ 0 ] || 0;
6474 style.backgroundPositionY = bgp[ 1 ] || 0;
6477 if( style.clipTop === undefined && style[ 'clip-top' ] === undefined ){
6478 special.setClipTopRightBottomLeft = function( style ){
6479 var clip = style.clip;
6480 if( !cliop || clip.indexOf( 'rect(' ) === -1 ){
6482 style.clipRight = 0;
6483 style.clipBottom = 0;
6487 clip = clip.split( '(' )[ 1 ].split( ')' )[ 0 ].split( clip.indexOf( ',' ) !== -1 ? ',' : ' ' );
6488 ret.clipTop = clip[ 0 ];
6489 ret.clipRight = clip[ 1 ];
6490 ret.clipBottom = clip[ 2 ];
6491 ret.clipLeft = clip[ 3 ];
6498 function cssToObject( css ){
6499 var ret = {}, i, nv, n, v,
6501 isNumber = Type.isNumber,
6502 camelize = Util.camelize;
6503 if( Type.isString( css ) === true ){
6504 css = css.split( SEMICORON );
6505 for( i = css.length; i; ){
6506 nv = css[ --i ].split( CORON ); // filter の場合, progid: がくる
6508 if( isNumber( parse( n ) ) === true ) continue;
6509 v = nv.join( EMPTY );
6510 while( v.charAt( 0 ) === ' ' ) v = v.substr( 1 );
6511 ret[ camelize( n ) ] = parse( v );
6515 if( Type.isNumber( parse( n ) ) === false ) ret[ n ] = parse( css[ n ] );
6519 if( SPECIAL.setFilters ){
6520 SPECIAL.setFilters( ret );
6522 ret.opacity = SPECIAL.opacity !== null ? ret[ SPECIAL.opacity ] : 1;
6525 SPECIAL.setBackgroundPositionXY && SPECIAL.setBackgroundPositionXY( ret );
6526 SPECIAL.setClipTopRightBottomLeft && SPECIAL.setClipTopRightBottomLeft( ret );
6531 var COLOR = ( function(){
6532 var ret = {}, v, name,
6541 'FF00FF', 'MAGENTA',
6542 'FF00FF', 'FUCHSIA',
6552 '696969', 'DIMGRAY',
6553 '708090', 'SLATEGRAY',
6554 'A9A9A9', 'DARKGRAY',
6555 'DCDCDC', 'GAINSBORO',
6556 '191970', 'MIDNIGHTBLUE',
6557 '6A5ACD', 'SLATEBLUE',
6558 '0000CD', 'MEDIUMBLUE',
6559 '4169E1', 'ROYALBLUE',
6560 '1E90FF', 'DODGERBLUE',
6561 '87CEEB', 'SKYBLUE',
6562 '4682B4', 'STEELBLUE',
6563 'ADD8E6', 'LIGHTBLUE',
6564 'AFEEEE', 'PALETURQUOISE',
6565 '40E0D0', 'TURQUOISE',
6566 'E0FFFF', 'LIGHTCYAN',
6567 '7FFFD4', 'AQUAMARINE',
6568 '006400', 'DARKGREEN',
6569 '2E8B57', 'SEAGREEN',
6570 '90EE90', 'LIGHTGREEN',
6571 '7FFF00', 'CHARTREUSE',
6572 'ADFF2F', 'GREENYELLOW',
6573 '32CD32', 'LIMEGREEN',
6574 '9ACD32', 'YELLOWGREEN',
6575 '6B8E23', 'OLIVEDRAB',
6576 'BCB76B', 'DARKKHAKI',
6577 'EEE8AA', 'PALEGOLDENROD',
6578 'FFFFE0', 'LIGHTYELLOW',
6580 'DAA520', 'GOLDENROD',
6581 'B8860B', 'DARKGOLDENROD',
6582 'BC8F8F', 'ROSYBROWN',
6583 'CD5C5C', 'INDIANRED',
6584 '8B4513', 'SADDLEBROWN',
6587 'DEB887', 'BURLYWOOD',
6590 'F4A460', 'SANDYBROWN',
6592 'D2691E', 'CHOCOLATE',
6593 'B22222', 'FIREBRICK',
6599 'FF69B4', 'HOTPINK',
6601 'FF1493', 'DEEPPINK',
6602 'DB7093', 'PALEVIOLETRED',
6605 'DA70D6', 'ORCHILD',
6606 '9400D3', 'DARKVIOLET',
6607 '8A2BE2', 'BLUEVIOLET',
6608 '9370DB', 'MEDIUMPURPLE',
6609 'D8BFD8', 'THISTLE',
6610 'E6E6FA', 'LAVENDER',
6611 'FFE4E1', 'MISTYROSE',
6613 'FFFACD', 'LEMONCHIFFON'
6615 for( i = list.length; i; ){
6618 ret[ name ] = parseInt( v, 16 );
6623 var PARAMS = ( function(){
6625 register( ret.percent = {},
6626 'marginBottom,marginLeft,marginRight,marginTop,paddingBottom,paddingLeft,paddingRight,paddingTop,fontSize,textIndent'
6628 register( ret.offset = {},
6629 'height,width,bottom,left,right,top'
6631 register( ret.size = {},
6632 'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth,letterSpacing'
6634 register( ret.color = {},
6635 'backgroundColor,borderBottomColor,borderLeftColor,borderRightColor,borderTopColor,color'
6637 register( ret.region = {},
6638 'margin,padding,borderWidth,borderColor'
6640 register( ret.special = {},
6641 'clip,backgroundPosition,opacity,lineHeight,zIndex'
6643 register( ret.unit = {}, 'px,cm,mm,in,pt,pc,em,%' );
6645 register( ret.margin = {}, 'marginBottom,marginLeft,marginRight,marginTop,paddingBottom' );
6646 register( ret.padding = {}, 'paddingBottom,paddingLeft,paddingRight,paddingTop' );
6647 register( ret.borderWidth = {}, 'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth' );
6648 register( ret.borderColor = {}, 'borderBottomColor,borderLeftColor,borderRightColor,borderTopColor' );
6650 function register( obj, params ){
6651 params = params.split( ',' );
6652 for( var i=params.length; i; ) obj[ params[ --i ] ] = true;
6660 var Property = Class.create(
6664 Constructor : function( name, value, unit, pxPerEm ){
6668 this.pxPerEm = pxPerEm; // XXpx = 1em;
6672 pxPerEm : 12, // 1em === ??px
6674 equal : function( prop ){
6675 if( this.unit === prop.unit ){
6676 return this.value === prop.value;
6678 return Math.abs( this.toPx() - prop.toPx() ) < 1;
6680 convert: function( prop ){
6681 var u = prop.unit, v;
6682 if( this.unit === u ) return;
6683 this.value = v = this.toPx();
6686 this.value = u === 'em' ? v / this.pxPerEm : Util.pxTo( v, u );
6689 setValue: function( v ){
6692 getValue: function(){
6695 getOffset: function( prop ){
6696 return prop.value - this.value;
6698 getUnit: function(){
6701 getValueText: function(){
6702 return this.value === 0 ? '0' : this.value + this.unit;
6705 var v = this.value, u = this.unit;
6706 if( u === px ) return v;
6707 if( u === 'em' ) return v * this.pxPerEm;
6708 if( u === '' && this.name === 'lineHeight' ) return v * this.pxPerEm;
6709 return Util.toPx( v, u );
6711 isValid: function( t ){
6716 z = u !== '' ? true : v === 0;
6717 if( PARAMS.percent[ n ] === true ) return z;
6718 if( PARAMS.offset[ n ] === true ) return z;
6719 if( PARAMS.size[ n ] === true ) return z && u !== '%';
6720 if( PARAMS.special[ n ] === true ){
6721 if( n === 'lineHeight' ) return true;
6722 if( n === 'opacity' ) return 0 <= v && v <= 1 && u === '';
6723 if( n === 'zIndex' ) return u === '';
6731 * backgroundPosition, clip
6733 var PropertyGroup = Class.create(
6737 Constructor : function( name ){
6740 for( var i = 1, l = arguments.length; i<l; ++i ){
6741 this.props.push( arguments[ i ] );
6745 equal : function( prop ){
6746 var ps = this.props, i = ps.length;
6749 if( ps[ i ].equal( prop[ i ] ) === false ) return false;
6753 convert : function( prop ){
6754 var ps = this.props, i = ps.length;
6757 ps[ i ].convert( prop[ i ] );
6760 setValue : function( ary ){
6761 var ps = this.props, i = 0, l = ps.length;
6763 ps[ i ].setValue( ary[ i ] );
6766 getValue : function(){
6767 var ret = [], ps = this.props, i = 0, l = ps.length;
6769 ret.push( ps[ i ].getValue() );
6773 getOffset : function( prop ){
6780 ret.push( ps[ i ].getOffset( _ps[ i ] ) );
6784 getUnit : function(){
6785 var ret = [], ps = this.props, i = 0, l = ps.length;
6787 ret.push( ps[ i ].getUnit() );
6791 getValueText : function(){
6792 var ret = [], ps = this.props, i = 0, l = ps.length;
6794 ret.push( ps[ i ].getValueText() );
6796 if( this.name === 'clip' ){
6797 return 'rect(' + ret.join( CLIP_SEPARATOR ) + ')';
6799 return ret.join( ' ' );
6801 onKill : function(){
6802 var ps = this.props, i = ps.length;
6807 isValid : function( t ){
6809 var ps = t.props, i = ps.length;
6811 if( ps[ --i ].isValid() === false ) return false;
6819 * margin, padding, borderWidth, borderColor
6821 var FrexibleProperty = PropertyGroup.inherits(
6823 Class.POOL_OBJECT, {
6824 Constructor : function( name ){
6827 for( var i = 1, l = arguments.length; i<l; ++i ){
6828 this.props.push( arguments[ i ] );
6830 // top, bottom, left, right, topbottom, leftright, all
6835 var ColorProperty = Class.create(
6837 Class.POOL_OBJECT, {
6838 Constructor : function( name, r, g, b, pct ){
6846 equal : function( prop ){
6847 if( this.pct === prop.pct ){
6848 return this.r === prop.r && this.g === prop.g && this.b === prop.b;
6850 var rgb = this._toPct(),
6851 _rgb = prop._toPct(),
6855 if( Math.abs( rgb[ i ] - _rgb[ i ] ) > 1 ) return false;
6859 convert : function( prop ){
6860 var u = prop.pct, x;
6861 if( this.pct === u ) return;
6862 x = u === true ? 100 / 255 : 2.55;
6868 setValue : function( rgb ){
6873 getValue : function(){
6874 return [ this.r, this.g, this.b ];
6876 getOffset : function( prop ){
6877 return [ prop.r - this.r, prop.g - this.g, prop.b - this.b ];
6879 getUnit : function(){
6880 return this.pct === true ? '%' : '';
6882 getValueText : function(){
6883 if( this.pct === true ){
6884 return [ 'rgb(', this.r, '%,', this.g, '%,', this.b, '%)' ].join( '' );
6886 var round = Math.round;
6887 //return [ 'rgb(', round( this.r ), ',', round( this.g ), ',', round( this.b ), ')' ].join( '' );
6889 var rgb = '00000' + ( ( round( this.r ) << 16 ) + ( round( this.g ) << 8 ) + round( this.b ) ).toString( 16 );
6890 return '#' + rgb.substr( rgb.length - 6 );
6892 _toPct : function(){
6893 if( this.pct === true ) return [ this.r, this.g, this.b ];
6894 return [ this.r / 2.55, this.g / 2.55, this.b / 2.55 ];
6896 isValid : function( t ){
6897 var isFinite = window.isFinite;
6898 if( !isFinite( this.r ) || !isFinite( this.g ) || !isFinite( this.b ) ) return false;
6899 if( 0 > this.r || 0 > this.g || 0 > this.b ) return false;
6900 if( this.pct === true ) return this.r <= 100 && this.g <= 100 && this.b <= 100;
6901 return this.r <= 255 && this.g <= 255 && this.b <= 255;
6906 var isString = Type.isString,
6907 isNumber = Type.isNumber;
6908 var REG_UINIT = /.*\d(\w{1,2})?/,
6911 REG_XXXXXX = /^#[\da-fA-F]{6}?/,
6912 REG_XXX = /^#[\da-fA-F]{3}?/;
6914 var WrappedStyle = Class.create(
6918 Constructor : function( style ){
6920 var fontsize = this.get( 'fontSize' );
6921 this.pxPerEm = fontsize.toPx();
6925 if( PARAMS.special[ p ] === true || PARAMS.region[ p ] === true ){
6926 if( p === 'clip' ) return this.getClip();
6927 if( p === 'margin' ) return this.getMarginPaddingBorder( p, '' );
6928 if( p === 'padding' ) return this.getMarginPaddingBorder( p, '' );
6929 if( p === 'borderWidth' ) return this.getMarginPaddingBorder( 'border', 'Width' );
6930 if( p === 'borderColor' ) return this.getBorderColor( 'borderColor' );
6931 if( p === 'backgroundPosition' ) return this.getBackgroundPosition( p );
6932 // opacity, zindex, lineHeight
6933 return new Property( p, this.getValue( x ), this.getUnit( x ), this.pxPerEm );
6935 var x = this.style[ p ], e, v, u;
6936 if( PARAMS.offset[ p ] === true ){
6937 return new Property( p, this.getValue( x ), this.getUnit( x, p ), this.pxPerEm );
6940 if( p === 'width' ) v = e.offsetWidth;
6941 if( p === 'height' ) v = e.offsetHeight;
6942 if( p === 'top' ) v = e.offsetTop;
6943 if( p === 'bottom' ) v = e.offsetBottom;
6944 if( p === 'left' ) v = e.offsetLeft;
6945 if( p === 'right' ) v = e.offsetRight;
6946 u = this.getUnit( x, p );
6947 // alert( p + this.pxTo( v, u ) + u )
6948 return new Property( p, this.pxTo( v, u ), u, this.pxPerEm ); */
6950 if( p === 'fontSize' ){ // xx-small 等
6951 v = Util.absoluteFontSizeToPx( x );
6953 return new Property( p, v, px, this.pxPerEm );
6956 if( PARAMS.percent[ p ] === true ){
6957 // alert( p + ' , ' + x + ' , ' + this.getUnit( x, p ) )
6958 return new Property( p, this.getValue( x ), this.getUnit( x, p ), this.pxPerEm );
6960 if( PARAMS.size[ p ] === true ){
6961 return new Property( p, this.getValue( x ), this.getUnit( x, p ), this.pxPerEm );
6963 if( PARAMS.color[ p ] === true ){
6964 return this.getColor( x, p );
6967 pxTo: function( px, unit ){
6968 if( unit === 'em' ) return px / this.pxPerEm;
6969 return Util.pxTo( px, unit );
6971 getValue: function( x ){
6972 return isString( x ) === true ? parseInt( x ) :
6973 isNumber( x ) === true ? x : 0;
6975 getUnit: function( x, p ){
6977 if( isString( x ) === true ){
6978 u = x.replace( REG_UINIT, $1 );
6979 if( p === 'lineHeight' ) return u;
6980 if( PARAMS.unit[ u ] !== true ) return px;
6985 getColor: function( x, p ){
6986 var rgb = COLOR[ x.toUpperCase() ],
6991 if( isNumber( rgb ) === true ){
6992 r = ( rgb & 0xff0000 ) >> 16;
6993 g = ( rgb & 0xff00 ) >> 8;
6996 if( x.match( REG_XXXXXX ) ){
6997 r = parseInt( x.charAt( 1 ) + x.charAt( 2 ), 16 );
6998 g = parseInt( x.charAt( 3 ) + x.charAt( 4 ), 16 );
6999 b = parseInt( x.charAt( 5 ) + x.charAt( 6 ), 16 );
7000 //alert( x + ' g: ' + g )
7002 if( x.match( REG_XXX ) ){
7003 r = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
7004 g = parseInt( x.charAt( 2 ) + x.charAt( 2 ), 16 );
7005 b = parseInt( x.charAt( 3 ) + x.charAt( 3 ), 16 );
7007 if( x.indexOf( 'rgb(' ) === 0 ){
7008 rgb = x.substr( 4 ).split( ',' );
7009 r = parseFloat( rgb[ 0 ] );
7010 g = parseFloat( rgb[ 1 ] );
7011 b = parseFloat( rgb[ 2 ] );
7012 if( x.indexOf( '%' ) !== -1 ) pct = true;
7018 return new ColorProperty( p, r, g, b, pct );
7020 getClip: function( name ){
7021 // rect(...) クリップします。<top>, <bottom> は上端からの、 <right>, <left> は左端からのオフセットで指定します。Internet Explorer 4~7 では、カンマの代わりにスペースで区切る必要があります。
7022 // position:absolute または position:fixed を適用した要素に対してのみ有効です。
7023 var top = this.get( name + 'Top' ),
7024 right = this.get( name + 'Right' ),
7025 bottom = this.get( name + 'Bottom' ),
7026 left = this.get( name + 'Left' ),
7027 ret = new PropertyGroup( name, top, right, bottom, left );
7028 if( ret.isValid() === true ) return ret;
7030 all = this.style[ name ].split( '(' )[ 1 ].split( ')' )[ 0 ].split( CLIP_SEPARATOR );
7031 return new PropertyGroup( name,
7032 new Property( name + 'Top', all[ 0 ], px, this.pxPerEm ),
7033 new Property( name + 'Right', all[ 1 ], px, this.pxPerEm ),
7034 new Property( name + 'Bottom', all[ 2 ], px, this.pxPerEm ),
7035 new Property( name + 'Left', all[ 3 ], px, this.pxPerEm )
7038 getBackgroundPosition: function( name ){
7039 var x = this.get( name + 'X' ),
7040 y = this.get( name + 'Y' ),
7041 ret = new PropertyGroup( name, x, y ),
7043 if( ret.isValid() === true ) return ret;
7045 xy = this.style[ name ].split( ' ' );
7046 return new PropertyGroup( name,
7047 new Property( name + 'X', this.getValue( xy[ 0 ] ), this.getUnit( xy[ 0 ] ), this.pxPerEm ),
7048 new Property( name + 'Y', this.getValue( xy[ 1 ] ), this.getUnit( xy[ 1 ] ), this.pxPerEm )
7051 getMarginPaddingBorder: function( name, width ){
7052 var props = [ name + 'Top' + width,
7053 name + 'Right' + width,
7054 name + 'Bottom' + width,
7055 name + 'Left' + width ],
7056 top = this.get( props[ 0 ] ),
7057 right = this.get( props[ 1 ] ),
7058 bottom = this.get( props[ 2 ] ),
7059 left = this.get( props[ 3 ] ),
7060 ret = new FrexibleProperty( name, top, right, bottom, left ),
7061 klass, pxPerEm, getValue, getUnit,
7062 all, _0, _1, _2, _3, v, u;
7063 if( ret.isValid() === true ) return ret;
7066 pxPerEm = this.pxPerEm;
7067 getValue = this.getValue;
7068 getUnit = this.getUnit;
7069 all = this.style[ name + width ].split( ' ' );
7076 switch( all.length ){
7078 top = new klass( props[ 0 ], v, u, pxPerEm );
7079 right = new klass( props[ 1 ], v, u, pxPerEm );
7080 bottom = new klass( props[ 2 ], v, u, pxPerEm );
7081 left = new klass( props[ 3 ], v, u, pxPerEm );
7084 top = new klass( props[ 0 ], v, u, pxPerEm );
7085 bottom = new klass( props[ 2 ], v, u, pxPerEm );
7088 right = new klass( props[ 1 ], v, u, pxPerEm );
7089 left = new klass( props[ 3 ], v, u, pxPerEm );
7092 top = new klass( props[ 0 ], v, u, pxPerEm );
7095 right = new klass( props[ 1 ], v, u, pxPerEm );
7096 left = new klass( props[ 3 ], v, u, pxPerEm );
7097 bottom = new klass( props[ 2 ], getValue( _2 ), getUnit( _2 ), pxPerEm );
7100 top = new klass( props[ 0 ], v, u, pxPerEm );
7101 right = new klass( props[ 1 ], getValue( _1 ), getUnit( _1 ), pxPerEm );
7102 bottom = new klass( props[ 2 ], getValue( _2 ), getUnit( _2 ), pxPerEm );
7103 left = new klass( props[ 3 ], getValue( _3 ), getUnit( _3 ), pxPerEm );
7106 return new FrexibleProperty( name, top, right, bottom, left );
7108 getBorderColor: function( name ){
7109 var props = 'borderTopColor,borderRightColor,borderBottomColor,borderLeftColor'.split( ',' ),
7110 top = this.get( props[ 0 ] ),
7111 right = this.get( props[ 1 ] ),
7112 bottom = this.get( props[ 2 ] ),
7113 left = this.get( props[ 3 ] ),
7114 ret = new FrexibleProperty( name, top, right, bottom, left ),
7115 all, _0, _1, getColor;
7116 if( ret.isValid() === true ) return ret;
7118 getColor = this.getColor;
7119 all = this.style[ name ].split( ' ' );
7122 switch( all.length ){
7124 top = getColor( _0, props[ 0 ] );
7125 right = getColor( _0, props[ 1 ] );
7126 bottom = getColor( _0, props[ 2 ] );
7127 left = getColor( _0, props[ 3 ] );
7130 top = getColor( _0, props[ 0 ] );
7131 right = getColor( _1, props[ 1 ] );
7132 bottom = getColor( _0, props[ 2 ] );
7133 left = getColor( _1, props[ 3 ] );
7136 top = getColor( _0, props[ 0 ] );
7137 right = getColor( _1, props[ 1 ] );
7138 bottom = getColor( all[ 2 ], props[ 2 ] );
7139 left = getColor( _1, props[ 3 ] );
7142 top = getColor( _0, props[ 0 ] );
7143 right = getColor( _1, props[ 1 ] );
7144 bottom = getColor( all[ 2 ], props[ 2 ] );
7145 left = getColor( all[ 3 ], props[ 3 ] );
7148 return new FrexibleProperty( name, top, right, bottom, left );
7152 function camelizeHash( obj ){
7153 var p, _p, came = Util.camelize;
7156 if( _p === p ) continue;
7157 obj[ _p ] = obj[ _p ] || obj[ p ];
7162 create: function( css ){
7163 return new WrappedStyle( camelizeHash( p ) );
7168 var XDocument = ( function( window, document ){
7170 var getIndex = Util.getIndex;
7174 var AbstractLayoutManager = Class.create(
7175 'AbstractLayoutManager',
7177 reflow : function(){}
7181 var BasicLayoutManager = AbstractLayoutManager.inherits(
7182 'BasicLayoutManager',
7184 Constructor : function(){
7190 var AbstractStylePrivate = Class.create(
7191 Class.ABSTRACT | Class.PRIVATE_DATA,
7193 register : function( node ){
7194 var list = this.nodeList;
7196 this.nodeList = [ node ];
7199 if( getIndex( list, node ) === -1 ) list[ list.length ] = node;
7201 unRegister : function( node ){
7202 var list = this.nodeList,
7203 i = getIndex( list, node );
7204 if( i !== -1 && list.splice( i, 1 ) && list.length === 0 ) delete this.nodeList;
7207 var styleClass = Class.getClass( this.User ),
7208 dataClass = Class.getClass( this );
7210 attr : function( prop, v ){
7211 var update = prop[ 0 ],
7215 length = !!( type & DEF_ATTRS.LENGTH ),
7216 percent = !!( type & DEF_ATTRS.PERCENT ),
7217 color = !!( type & DEF_ATTRS.COLOR ),
7218 uDecimal = !!( type & DEF_ATTRS.U_DECIMAL ),
7219 numerical = !!( type & DEF_ATTRS.NUMERICAL ),
7220 flag = !!( type & DEF_ATTRS.BOOLEAN ),
7221 quartet = !!( type & DEF_ATTRS.QUARTET ),
7222 url = !!( type & DEF_ATTRS.URL ),
7223 fontName = !!( type & DEF_ATTRS.FONT_NAME ),
7224 list = !!( type & DEF_ATTRS.LIST ),
7225 combi = !!( type & DEF_ATTRS.COMBI ),
7230 if( v !== undefined ){
7231 if( Type.isNumber( v ) === true ){
7232 if( numerical === false ){
7233 if( uDecimal === false || v < 0 || 1 < v ) throw new Error( '' );
7236 if( Type.isBoolean( v ) === true ){
7237 if( flag === false ) throw new Error( '' );
7239 if( Type.isString( v ) === true ){
7240 if( url === false && fontName === false ){
7241 if( v.indexOf( ' ' ) !== -1 ){
7244 if( length === false && percent === false && color === false ) throw new Error( '' );
7248 if( Type.isArray( v ) === true ){
7249 if( v.length <= 4 && quartet === true ){
7250 _type = type ^ DEF_ATTRS.QUARTET;
7252 if( v.length === 2 && combi === true ){
7253 _type = type ^ DEF_ATTRS.COMBI;
7255 throw new Error( '' );
7259 this.attr( [ propID , _type, list ], v[ 0 ] );
7260 this.attr( [ ++propID, _type, list ], v[ 0 ] );
7261 this.attr( [ ++propID, _type, list ], v[ 0 ] );
7262 this.attr( [ ++propID, _type, list ], v[ 0 ] );
7265 this.attr( [ propID , _type, list ], v[ 0 ] );
7266 this.attr( [ ++propID, _type, list ], v[ 1 ] );
7267 this.attr( [ ++propID, _type, list ], v[ 0 ] );
7268 this.attr( [ ++propID, _type, list ], v[ 1 ] );
7271 this.attr( [ propID , _type, list ], v[ 0 ] );
7272 this.attr( [ ++propID, _type, list ], v[ 1 ] );
7273 this.attr( [ ++propID, _type, list ], v[ 2 ] );
7274 this.attr( [ ++propID, _type, list ], v[ 1 ] );
7277 this.attr( [ propID , _type, list ], v[ 0 ] );
7278 this.attr( [ ++propID, _type, list ], v[ 1 ] );
7279 this.attr( [ ++propID, _type, list ], v[ 2 ] );
7280 this.attr( [ ++propID, _type, list ], v[ 3 ] );
7286 if( this.invalidateLayout < update ) this.invalidate = update;
7288 if( list ) _v = Util.getIndex( list, v );
7289 data[ propID ] = _v !== -1 ? _v : v;
7292 if( this.invalidate === DEF_ATTRS.REFLOW ){
7293 nodes = this.nodeList;
7295 for( i = 0, l = nodes.length; i < l; ++i ){
7296 nodes[ i ].reflow();
7301 if( quartet === true ) return [ v, data[ ++propID ], data[ ++propID ], data[ ++propID ] ];
7302 if( combi === true ) return [ v, data[ ++propID ] ];
7303 if( list && Type.isNumber( v ) === true ) return list[ v ];
7309 var PaintPrivate = AbstractStylePrivate.inherits(
7311 Class.PRIVATE_DATA | Class.POOL_OBJECT,
7313 Constructor : function(){
7315 this.invalidate = 0;
7317 cssText : function(){
7320 cssObject : function(){
7323 paint : function( node ){
7329 var PaintStyle = Class.create(
7334 Constructor : function(){
7335 PaintStyle.newPrivateData( this );
7337 borderWidth : function( v ){
7338 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.borderWidth, v );
7340 borderColor : function(){
7341 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.borderColor, v );
7343 borderStyle : function(){
7344 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.borderStyle, v );
7346 cornerRadius : function(){
7347 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.cornerRadius, v );
7349 bgColor : function(){
7350 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.bgColor, v );
7352 bgAlpha : function(){
7353 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.bgAlpha, v );
7355 bgImgUrl : function(){
7356 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.bgImgUrl, v );
7358 bgImgRepeatX : function(){
7359 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.bgImgRepeatX, v );
7361 bgImgRepeatY : function(){
7362 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.bgImgRepeatY, v );
7364 bgImgPositionX : function(){
7365 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.bgImgPositionX, v );
7367 bgImgPositionY : function(){
7368 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.bgImgPositionY, v );
7370 shadowColor : function(){
7371 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.shadowColor, v );
7373 shadowAlpha : function(){
7374 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.shadowAlpha, v );
7376 shadowOffsetX : function(){
7377 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.shadowOffsetX, v );
7379 shadowOffsetY : function(){
7380 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.shadowOffsetY, v );
7382 shadowBlur : function(){
7383 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.shadowBlur, v );
7385 shadowSpread : function(){
7386 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.shadowSpread, v );
7388 shadowInset : function(){
7389 return PaintStyle.getPrivateData( this ).attr( PaintPrivate.shadowInset, v );
7394 var TypoPrivate = AbstractStylePrivate.inherits(
7396 Class.PRIVATE_DATA | Class.POOL_OBJECT,
7398 Constructor : function(){
7400 this.invalidate = 0;
7402 cssText : function(){
7405 cssObject : function(){
7411 var TypoStyle = Class.create(
7416 Constructor : function( v ){
7417 TypoStyle.newPrivateData( this );
7419 color : function( v ){
7420 return TypoStyle.getPrivateData( this ).attr( TypoPrivate.color, v );
7422 fontFamily : function( v ){
7423 return TypoStyle.getPrivateData( this ).attr( TypoPrivate.fontFamily, v );
7425 fontSize : function( v ){
7426 return TypoStyle.getPrivateData( this ).attr( TypoPrivate.fontSize, v );
7428 bold : function( v ){
7429 return TypoStyle.getPrivateData( this ).attr( TypoPrivate.bold, v );
7431 italic : function( v ){
7432 return TypoStyle.getPrivateData( this ).attr( TypoPrivate.italic, v );
7434 lineHeight : function( v ){
7435 return TypoStyle.getPrivateData( this ).attr( TypoPrivate.lineHeight, v );
7437 letterSpacing : function( v ){
7438 return TypoStyle.getPrivateData( this ).attr( TypoPrivate.letterSpacing, v );
7440 wordSpacing : function( v ){
7441 return TypoStyle.getPrivateData( this ).attr( TypoPrivate.wordSpacing, v );
7443 align : function( v ){
7444 return TypoStyle.getPrivateData( this ).attr( TypoPrivate.align, v );
7446 decoration : function( v ){
7447 return TypoStyle.getPrivateData( this ).attr( TypoPrivate.decoration, v );
7449 transform : function( v ){
7450 return TypoStyle.getPrivateData( this ).attr( TypoPrivate.transform, v );
7452 shadowColor : function( v ){
7453 return TypoStyle.getPrivateData( this ).attr( TypoPrivate.shadowColor, v );
7455 shadowOffsetX : function( v ){
7456 return TypoStyle.getPrivateData( this ).attr( TypoPrivate.shadowOffsetX, v );
7458 shadowOffsetY : function( v ){
7459 return TypoStyle.getPrivateData( this ).attr( TypoPrivate.shadowOffsetY, v );
7461 shadowBlur : function( v ){
7462 return TypoStyle.getPrivateData( this ).attr( TypoPrivate.shadowBlur, v );
7467 var LayoutPrivate = AbstractStylePrivate.inherits(
7469 Class.PRIVATE_DATA | Class.POOL_OBJECT,
7471 Constructor : function(){
7473 this.invalidate = 0;
7475 cssText : function(){
7478 cssObject : function(){
7484 DEF_ATTRS.LENGTH = 1;
7485 DEF_ATTRS.PERCENT = 2;
7486 DEF_ATTRS.COLOR = 4;
7487 DEF_ATTRS.U_DECIMAL = 8;
7488 DEF_ATTRS.NUMERICAL = 16;
7489 DEF_ATTRS.BOOLEAN = 32;
7490 DEF_ATTRS.QUARTET = 64;
7491 DEF_ATTRS.URL = 128;
7492 DEF_ATTRS.FONT_NAME = 256;
7493 DEF_ATTRS.LIST = 512;
7494 DEF_ATTRS.AUTO = 1024;
7495 DEF_ATTRS.COMBI = 2048;
7496 DEF_ATTRS.BORDER_STYLE = 'none,hidden,dotted,dashed,solid,double,groove,ridge,inset,outset'.split(',');
7497 DEF_ATTRS.POSITION_X = 'left,center,right'.split(',');
7498 DEF_ATTRS.POSITION_Y = 'top,center,bottom'.split(',');
7499 DEF_ATTRS.ALIGN = 'left,center,right,justify'.split(',');
7500 DEF_ATTRS.TEXT_DECORATION = 'none,underline,overline,line-through,blink'.split(',');
7501 DEF_ATTRS.TEXT_TRANSFORM = 'none,capitalize,lowercase,uppercase'.split(',');
7502 DEF_ATTRS.WIDTH_HEIGHT = 'auto'.split(',');
7503 DEF_ATTRS.PAINT = 1; // 再描画のみ必要
7504 DEF_ATTRS.REFLOW = 2; // レイアウトの再計算が必要
7506 PaintPrivate.borderWidth = [ DEF_ATTRS.REFLOW, 0, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH ]; // em [ top, right, bottom, left ]
7507 PaintPrivate.borderColor = [ DEF_ATTRS.PAINT, 4, DEF_ATTRS.QUARTET | DEF_ATTRS.DEF_COLOR ]; // color [ top, right, bottom, left ]
7508 PaintPrivate.borderStyle = [ DEF_ATTRS.REFLOW, 8, DEF_ATTRS.QUARTET | DEF_ATTRS.LIST, DEF_ATTRS.BORDER_STYLE ]; // string [ top, right, bottom, left ]
7509 PaintPrivate.cornerRadius = [ DEF_ATTRS.PAINT, 12, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ]; // em, px [ top, right, bottom, left ]
7510 PaintPrivate.bgColor = [ DEF_ATTRS.PAINT, 16, DEF_ATTRS.COLOR ]; // color
7511 PaintPrivate.bgAlpha = [ DEF_ATTRS.PAINT, 17, DEF_ATTRS.U_DECIMAL ]; // 0 - 1
7512 PaintPrivate.bgImgUrl = [ DEF_ATTRS.PAINT, 18, DEF_ATTRS.URL ]; // url
7513 PaintPrivate.bgImgRepeatX = [ DEF_ATTRS.PAINT, 19, DEF_ATTRS.BOOLEAN ]; // true / false
7514 PaintPrivate.bgImgRepeatY = [ DEF_ATTRS.PAINT, 20, DEF_ATTRS.BOOLEAN ]; // true / false
7515 PaintPrivate.bgImgPositionX = [ DEF_ATTRS.PAINT, 21, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT | DEF_ATTRS.LIST, DEF_ATTRS.POSITION_X ]; // em %, px, string
7516 PaintPrivate.bgImgPositionY = [ DEF_ATTRS.PAINT, 22, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT | DEF_ATTRS.LIST, DEF_ATTRS.POSITION_Y ]; // em %, px, string
7517 PaintPrivate.shadowColor = [ DEF_ATTRS.PAINT, 23, DEF_ATTRS.COLOR ]; // color
7518 PaintPrivate.shadowAlpha = [ DEF_ATTRS.PAINT, 24, DEF_ATTRS.U_DECIMAL ]; // 0 - 1
7519 PaintPrivate.shadowOffsetX = [ DEF_ATTRS.PAINT, 25, DEF_ATTRS.LENGTH ]; // em
7520 PaintPrivate.shadowOffsetY = [ DEF_ATTRS.PAINT, 26, DEF_ATTRS.LENGTH ]; // em
7521 PaintPrivate.shadowBlur = [ DEF_ATTRS.PAINT, 27, DEF_ATTRS.LENGTH ]; // em
7522 PaintPrivate.shadowSpread = [ DEF_ATTRS.PAINT, 28, DEF_ATTRS.LENGTH ]; // em
7523 PaintPrivate.shadowInset = [ DEF_ATTRS.PAINT, 29, DEF_ATTRS.BOOLEAN ]; // true / false
7525 TypoPrivate.color = [ DEF_ATTRS.PAINT, 0, DEF_ATTRS.COLOR ]; // color
7526 TypoPrivate.fontFamily = [ DEF_ATTRS.REFLOW, 1, DEF_ATTRS.FONT_NAME ]; // string
7527 TypoPrivate.fontSize = [ DEF_ATTRS.REFLOW, 2, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ]; // em, %
7528 TypoPrivate.bold = [ DEF_ATTRS.REFLOW, 3, DEF_ATTRS.BOOLEAN ]; // true / false
7529 TypoPrivate.italic = [ DEF_ATTRS.REFLOW, 4, DEF_ATTRS.BOOLEAN ]; // true / false
7530 TypoPrivate.lineHeight = [ DEF_ATTRS.REFLOW, 5, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT | DEF_ATTRS.NUMERICAL ]; // em, %,
7531 TypoPrivate.letterSpacing = [ DEF_ATTRS.REFLOW, 6, DEF_ATTRS.LENGTH ]; // em
7532 TypoPrivate.wordSpacing = [ DEF_ATTRS.REFLOW, 7, DEF_ATTRS.LENGTH ];
7533 TypoPrivate.align = [ DEF_ATTRS.REFLOW, 8, DEF_ATTRS.LIST, DEF_ATTRS.ALIGN ];
7534 TypoPrivate.decoration = [ DEF_ATTRS.PAINT, 9, DEF_ATTRS.LIST, DEF_ATTRS.TEXT_DECORATION ];
7535 TypoPrivate.transform = [ DEF_ATTRS.REFLOW, 10, DEF_ATTRS.LIST, DEF_ATTRS.TEXT_TRANSFORM ];
7536 TypoPrivate.shadowColor = [ DEF_ATTRS.PAINT, 11, DEF_ATTRS.COLOR ];
7537 TypoPrivate.shadowOffsetX = [ DEF_ATTRS.PAINT, 12, DEF_ATTRS.LENGTH ];
7538 TypoPrivate.shadowOffsetY = [ DEF_ATTRS.PAINT, 13, DEF_ATTRS.LENGTH ];
7539 TypoPrivate.shadowBlur = [ DEF_ATTRS.PAINT, 14, DEF_ATTRS.LENGTH ];
7541 LayoutPrivate.width = [ DEF_ATTRS.REFLOW, 0, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT, DEF_ATTRS.WIDTH_HEIGHT ];
7542 LayoutPrivate.minWidth = [ DEF_ATTRS.REFLOW, 1, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7543 LayoutPrivate.maxWidth = [ DEF_ATTRS.REFLOW, 2, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7544 LayoutPrivate.height = [ DEF_ATTRS.REFLOW, 3, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT, DEF_ATTRS.WIDTH_HEIGHT ];
7545 LayoutPrivate.minHeight = [ DEF_ATTRS.REFLOW, 4, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7546 LayoutPrivate.maxHeight = [ DEF_ATTRS.REFLOW, 5, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7547 LayoutPrivate.padding = [ DEF_ATTRS.REFLOW, 6, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7548 LayoutPrivate.margin = [ DEF_ATTRS.REFLOW, 10, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7551 var NodePrivate = Class.create(
7553 Class.PRIVATE_DATA | Class.POOL_OBJECT,
7559 Constructor : function( __root, __parent ){
7560 this.__root = __root;
7561 if( __parent ) this.__parent = __parent;
7563 paint : function( v ){
7564 if( v instanceof PaintStyle ){
7565 this.__paint && this.__paint.unRegister( this );
7567 this.__paint = PaintStyle.getPrivateData( v );
7568 this.__paint.register( this );
7572 this.__paint && this.__paint.unRegister( this );
7574 delete this.__paint;
7579 typo : function( v ){
7580 if( v instanceof TypoStyle ){
7581 this.__typo && this.__typo.unRegister( this );
7583 this.__typo = TypoStyle.getPrivateData( v );
7584 this.__typo.register( this );
7588 this.__typo && this.__typo.unRegister( this );
7597 * 2. auto 指定時は要素の高さ取得.
7598 * 3. 親の許す子の最大サイズと自信のスタイル指定から、自身の位置とサイズを計算
7601 reflow : function(){
7602 var content = this._textContent,
7603 layout = this.__layout,
7604 targetW = this.__parent.childWidth,
7605 targetH = this.__parent.childHeight,
7608 if( content || ( this.__paint && this.__paint.hasStyle === true ) || ( this.__typo && this.__typo.hasStyle === true ) ){
7609 if( !this.elmWrap ) this.elmWrap = DOM.createDiv();
7610 this.__parent.addDiv( this );
7612 if( !this.textNode ){
7613 this.textNode = DOM.cerateText();
7614 this.elmWrap.appendChild( this.textNode );
7616 if( layout && ( layout.autoWidth === true || layout.autoHeight === true ) ){
7617 size = DOM.getTextSize( this.elmWrap, content );
7618 this.contentWidth = size[ 0 ];
7619 this.conetntHeight = size[ 1 ];
7621 this.textNode.data = content;
7623 if( this.textNode ){
7624 DOM.correct( this.textNode );
7625 delete this.textNode;
7626 delete this.contentWidth;
7627 delete this.conetntHeight;
7629 this.currentWidth = this.elmWrap.offsetWidth;
7630 this.currentHeight = this.elmWrap.offsetHeight;
7633 DOM.correct( this.elmWrap );
7634 delete this.elmWrap;
7635 delete this.textNode;
7636 delete this.contentWidth;
7637 delete this.conetntHeight;
7638 delete this.currentWidth;
7639 delete this.currentHeight
7642 // this.__parent.layoutManager.reflow();
7644 addDiv : function( nodeData ){
7649 var Node = Class.create(
7654 Constructor : function( root, parent ){
7655 Node.newPrivateData( this, LayoutBox.getPrivateData( root ), parent ? LayoutBox.getPrivateData( parent ) : undefined, this );
7657 paint : function( v ){
7658 return Node.getPrivateData( this ).paint( v );
7660 typo : function( v ){
7661 return Node.getPrivateData( this ).typo( v );
7663 remove : function(){
7664 Node.getPrivateData( this ).remove();
7666 nodeIndex : function( v ){
7667 return Node.getPrivateData( this ).nodeIndex( v );
7669 displayIndex : function(){
7672 disabled : function( v ){
7673 return Node.getPrivateData( this ).disabled( v );
7675 cursor : function( v ){
7676 return Node.getPrivateData( this ).cursor( v );
7678 getAbsolutePositionX : function(){
7679 return Node.getPrivateData( this ).getAbsolutePositionX();
7681 getAbsolutePositionY : function(){
7682 return Node.getPrivateData( this ).getAbsolutePositionY();
7684 addEventListener : function( type, handler, opt_thisObject ){
7685 Node.getPrivateData( this ).addEventListener( type, handler, opt_thisObject );
7687 removeEventListener : function( type, handler ){
7688 Node.getPrivateData( this ).removeEventListener( type, handler );
7690 scrollTo : function( x, y ){
7691 Node.getPrivateData( this ).scrollTo( x, y );
7693 scrollX : function( v ){
7694 return Node.getPrivateData( this ).scrollX( v );
7696 scrollY : function( v ){
7697 return Node.getPrivateData( this ).scrollY( v );
7702 var LayoutBoxPrivate = NodePrivate.inherits(
7706 Constructor : function( layoutManager, root, parent ){
7707 this.layoutManager = layoutManager;
7709 if( _parent ) this._parent = _parent;
7711 reflow : function(){
7712 this.manager.reflow( this );
7714 repaint : function(){
7715 this.manager.repaint( this );
7720 var LayoutBox = Node.inherits(
7725 Constructor : function( layoutManager, root, parent ){
7726 LayoutBox.newPrivateData( this, layoutManager, LayoutBox.getPrivateData( root ), parent ? LayoutBox.getPrivateData( parent ) : undefined );
7728 layoutManager : function( v ){
7731 createLayoutBox : function(){
7734 createContentBox : function(){
7740 })( window, document );
7742 })( window, document );