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,
138 copyArray = Util.copyArray;
140 function getClass( instance ){
141 var cList = CLASS_LIST,
145 klass = cList[ --i ];
146 if( instance instanceof klass ) return klass;
148 cList = PRIVATE_CLASS_LIST;
151 klass = cList[ --i ];
152 if( instance instanceof klass ) return klass;
155 if( GET_INDEX( cList, instance ) !== -1 ) return instance;
156 if( GET_INDEX( CLASS_LIST, instance ) !== -1 ) return instance;
159 function getClassDef( KlassOrInstance ){
160 var getIndex = GET_INDEX,
161 i = getIndex( CLASS_LIST, KlassOrInstance );
162 if( i === -1 ) i = getIndex( CLASS_LIST, getClass( KlassOrInstance ) );
163 if( i !== -1 ) return DEF_LIST[ i ];
165 i = getIndex( PRIVATE_CLASS_LIST, KlassOrInstance );
166 if( i === -1 ) i = getIndex( PRIVATE_CLASS_LIST, getClass( KlassOrInstance ) );
167 if( i !== -1 ) return PRIVATE_DEF_LIST[ i ];
169 if( GET_INDEX( DEF_LIST, KlassOrInstance ) !== -1 ) return KlassOrInstance;
170 if( GET_INDEX( PRIVATE_DEF_LIST, KlassOrInstance ) !== -1 ) return KlassOrInstance;
173 /* over のプロパティを target にコピーする.ただし target の プロパティが優先, force で解除 */
174 function override( target, over, force ){
175 for( var p in over ){
176 if( force === true || typeof target[ p ] === 'undefined' ){
177 target[ p ] = over[ p ];
184 * var subClass = superClass.inherits( ... )
185 * http://d.hatena.ne.jp/m-hiyama/20051018/1129605002
187 function inherits( /* displayName, classSetting, opt_PrivateClass, props */ ){
188 var args = copyArray( arguments ),
191 superDef = getClassDef( Super ),
192 displayName = args[ 0 ],
196 if( superDef.Final === true ) throw new Error( 'Class is final!' );
198 if( Type.isString( displayName ) === true ){
201 displayName = 'SubClass of ' + superDef.displayName;
203 params.push( displayName );
205 classSetting = args[ 0 ];
206 if( Type.isNumber( classSetting ) === true ){
207 if( superDef.isPrivate === true ) classSetting = classSetting | Class.PRIVATE_DATA;
208 opt_super = !!( classSetting & Class.SUPER_ACCESS );
209 params.push( classSetting );
212 if( getClass( args[ 0 ] ) ){
213 params.push( args.shift() );
215 if( superDef.privateClass ){
216 params.push( superDef.privateClass );
218 params.push( args[ 0 ] ); /* props */
220 traits = new Super();
222 klass = Class.create.apply( Class, params );
224 if( opt_super === true ) getClassDef( klass ).Super = Super.prototype;
228 /* Class.create で作られたクラスのインスタンスが共通で備えるメソッド */
232 klass = getClass( instance ),
233 def = getClassDef( klass ),
235 if( def.isPrivate === true && killPrivateFlag === false ){
236 throw new Error( 'PrivateInstance.kill() work in PrivateUser.kill().' );
238 Type.isFunction( instance.onKill ) === true && instance.onKill();
239 for( p in instance ){
240 if( instance.hasOwnProperty && !instance.hasOwnProperty( p ) ) continue;
241 delete instance[ p ];
244 def.live && def.live.splice( GET_INDEX( def.live, instance ), 1 );
245 def.pool.push( instance );
247 if( def.privateClass ){
248 i = GET_INDEX( def.userList, instance );
250 data = klass.getPrivateData( instance );
251 killPrivateFlag = true;
253 killPrivateFlag = false;
254 def.dataList.splice( i, 1 );
255 def.userList.splice( i, 1 );
259 // myCallback を受け取った API への通知
261 getMyCallback : function( callback ){
262 var def = getClassDef( this ),
263 iList = def.callbackInstanceList,
264 rList = def.callbackRegisterList,
265 i, cList, myCallback;
267 iList = def.callbackInstanceList = [];
268 rList = def.callbackRegisterList = [];
270 i = GET_INDEX( iList, this );
277 for( i = cList.length; i; ){
278 if( cList[ --i ].callback === callback ) return cList[ i ];
281 myCallback = new Callback( this, callback );
282 cList.push( myCallback );
285 releaseMyCallback : function( callback ){
286 var def = getClassDef( this ),
287 iList = def.callbackInstanceList,
288 rList = def.callbackRegisterList,
291 i = GET_INDEX( iList, this );
292 if( i === -1 ) return;
294 _i = GET_INDEX( cList, callback );
295 if( _i === -1 ) return;
296 cList.splice( _i, 1 );
298 if( cList.length !== 0 ) return;
299 iList.splice( i, 1 );
300 rList.splice( i, 1 );
301 if( iList.length !== 0 ) return;
302 delete def.callbackInstanceList;
303 delete def.callbackRegisterList;
307 /* privateDataclass をもつクラスに追加されるメソッド */
308 function newPrivateData( /* instance, args */ ){
309 var args = copyArray( arguments ),
311 def = getClassDef( user ),
312 privateClass = def.privateClass,
313 privateDef = getClassDef( privateClass ),
317 i = GET_INDEX( def.userList, user );
323 throw new Error( 'PrivateData already exist!' );
326 data = new privateClass( args );
331 function getPrivateData( instance ){
332 var def = getClassDef( instance ),
333 i = GET_INDEX( def.userList, instance );
334 if( i !== -1 ) return def.dataList[ i ];
338 * new の実体.コンストラクタの機能は instance.Constructor に書く.
339 * これにより pool された オブジェクト(破棄されたインスタンス) を再利用できる
341 /* Constructor Real for GeneralClass */
344 def = getClassDef( klass ),
347 if( def.Abstract === true ){
348 throw new Error( 'AbstractClass!' );
350 if( def.isPrivate === true && dataUser === null ){
351 throw new Error( 'use myClass.newPrivateData( instance, ...args )!' );
354 instance = def.pool && def.pool.length > 0 ? def.pool.shift() : instance = new klass();
356 if( def.Super && !instance.Super ) instance.Super = def.Super;
357 if( def.isPrivate === true ){
358 userDef = getClassDef( dataUser );
359 userDef.dataList.push( instance );
360 userDef.userList.push( dataUser );
362 def.live && def.live.push( instance );
363 args = copyArray( arguments );
365 def[ CONSTRUCTOR ] && def[ CONSTRUCTOR ].apply( instance, args );
375 create : function( /* displayName, classSetting, opt_PrivateClass, props */ ){
376 var args = copyArray( arguments ),
377 displayName = args[ 0 ],
379 opt_pool, opt_abstract, opt_final, opt_private,
384 if( Type.isString( displayName ) === true ){
385 classDef.displayName = displayName;
388 classSetting = args[ 0 ];
389 if( Type.isNumber( classSetting ) === true ){
390 opt_pool = !!( classSetting & Class.POOL_OBJECT );
391 opt_abstract = !!( classSetting & Class.ABSTRACT );
392 opt_final = !!( classSetting & Class.FINAL );
393 opt_private = !!( classSetting & Class.PRIVATE_DATA );
394 if( opt_final === true && opt_abstract === true ){
395 throw new Error( 'final & Abstract!' );
400 if( GET_INDEX( PRIVATE_CLASS_LIST, args[ 0 ] ) !== -1 ){
401 privateDef = getClassDef( args[ 0 ] );
402 if( privateDef.isPrivate !== true ){
403 throw new Error( 'PrivateClass not found! please, Class.create( Class.PRIVATE, {...} ).' );
405 if( privateDef.Abstract === true ){
406 throw new Error( 'PrivateClass is Abstract!' );
408 classDef.privateClass = args.shift();
411 if( props === null || Type.isObject( props ) === false ){
412 throw new Error( 'No Class Def!' );
415 if( Type.isFunction( props[ CONSTRUCTOR ] ) === true ){
416 classDef[ CONSTRUCTOR ] = props[ CONSTRUCTOR ];
419 klass = function(){ var a = arguments; if( f ) return C.apply( a.callee, a )};
420 klass.prototype = override( override( traits || {}, props, true ), CommonProps, false );
422 if( opt_abstract === true ){
423 classDef.Abstract = true;
425 if( opt_pool === true ){
427 if( opt_private === false )classDef.live = [];
429 if( opt_final === true ){
430 classDef.Final = true;
432 klass.inherits = inherits;
434 if( opt_private === true ){
435 if( classDef.privateClass ){
436 throw new Error( 'Private Data Class has no PrivateClass!' );
438 classDef.isPrivate = true;
439 PRIVATE_CLASS_LIST.push( klass );
440 PRIVATE_DEF_LIST.push( classDef );
442 if( classDef.privateClass ){
443 klass.newPrivateData = newPrivateData;
444 klass.getPrivateData = getPrivateData;
446 CLASS_LIST.push( klass );
447 DEF_LIST.push( classDef );
451 onShutdown : function(){
454 getClass : function( instance ){
455 return getClass( instance );
457 getClassDef : function(){
464 * Callback 時に thisObject や args を指定したい場合に使用.
466 var Callback = Class.create(
467 Class.POOL_OBJECT | Class.FINAL, {
468 Constructor : function( thisObject, callback, opt_args ){
469 if( Type.isFunction( callback ) === false ){
470 throw new Error( 'Not function!' );
472 this.callback = callback;
473 if( thisObject ) this.thisObject = thisObject;
474 if( Type.isArray( opt_args ) === true ){
475 this.args = opt_args;
477 if( opt_args !== undefined ){
481 fire : function( /* args */ ){
482 var thisObject = this.thisObject || window,
483 args = Util.copyArray( arguments );
484 if( 0 < args.length ){
485 if( this.args !== undefined ){
486 args.push.apply( args, this.args );
488 if( this.arg !== undefined ){
489 args.push( this.arg );
491 this.callback.apply( thisObject, args );
493 if( this.args !== undefined ){
494 this.callback.apply( thisObject, this.args );
496 if( this.arg !== undefined ){
497 this.callback.call( thisObject, this.arg );
499 this.callback.call( thisObject );
503 registerUser : function( user ){
504 if( !this.userList ){
505 this.userList = [ user ];
507 Util.getIndex( this.userList, user ) === -1 && this.userList.push( user );
511 var instance = this.thisObject;
512 this.userList && Class.getClass( instance ) && instance.releaseMyCalllback( this );
517 /* --------------------------------------------------------------
522 var SystemTimer = ( function(){
523 var setTimeout = window.setTimeout;
524 var clearTimeout = window.clearTimeout;
525 var INTERVAL_TIME = 16;
526 var TICKET_LIST = [];
527 var timerId = undefined;
533 for( i = 0; i < list.length; ){
534 if( list[ i ].fire( next ) !== false ) ++i;
540 var list = TICKET_LIST,
545 timerId !== undefined && clearTimeout( timerId );
550 c = list[ --l ].count;
553 if( next > n || timerId === undefined ){
554 timerId !== undefined && clearTimeout( timerId );
555 timerId = setTimeout( loop, INTERVAL_TIME * n );
560 var TimerTicket = Class.create(
562 Constructor : function( apiuser, callback, time, once, opt_thisObject ){
563 this.apiuser = apiuser;
564 this.callback = callback;
567 if( once ) this.once = once;
568 this.thisObj = opt_thisObject || apiuser;
570 fire : function( c ){
572 if( 0 < this.count ) return;
573 this.callback.call( this.thisObj );
574 if( this.once === true ){
576 TICKET_LIST.splice( Util.getIndex( TICKET_LIST, this ), 1 );
579 this.count = this.time;
582 destroy : function( apiuser, callback ){
583 if( apiuser && apiuser !== this.apiuser ) return false;
584 if( callback && callback !== this.callback ) return false;
593 add: function( _apiuser, _handler, _time, _once, opt_thisObject ){
594 if( Type.isNumber( _time ) === false || _time < INTERVAL_TIME ) _time = INTERVAL_TIME;
596 var _ticket = new TimerTicket( _apiuser, _handler, Math.ceil( _time / INTERVAL_TIME ), _once, opt_thisObject );
597 TICKET_LIST.push( _ticket );
601 remove: function( _apiuser, _handler ){
604 while( _ticket = TICKET_LIST[ i ] ){
605 if( _ticket.destroy( _apiuser, _handler ) === true ){
606 TICKET_LIST.splice( i, 1 );
616 /* --------------------------------------------------------------
620 var AsyncCall = ( function(){
621 var CALLBACK_LIST = [];
623 var CallbackTicket = Class.create(
625 Constructor : function( apiuser, callback, args, thisObject ){
626 this.apiuser = apiuser;
627 this.callback = callback;
629 this.thisObj = thisObject || apiuser;
632 var f = this.callback,
636 if( Type.isArray( a ) === true ){
642 destroy : function( apiuser, callback ){
643 if( apiuser && apiuser !== this.apiuser ) return false;
644 if( callback && callback !== this.callback ) return false;
652 var _ticket = CALLBACK_LIST.shift();
655 CALLBACK_LIST.length !== 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true );
660 add: function( _apiuser, _callback, _argments, _thisObject ){
661 CALLBACK_LIST.length === 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true );
662 CALLBACK_LIST.push( new CallbackTicket( _apiuser, _callback, _argments, _thisObject ) );
664 remove: function( _apiuser, _callback ){
667 while( _ticket = CALLBACK_LIST[ i ] ){
668 if( _ticket.destroy( _apiuser, _callback ) === true ){
669 CALLBACK_LIST.splice( i, 1 );
678 /* -----------------------------------------------------------
680 * お気に入り画像一覧 > tag:ペン次郎 > ペン次郎:笑う
681 * 最近アップロードされた画像 > images
683 * キャラクター画像庫 > アニマル系 > tag:ペン次郎 > ペン次郎:笑う
690 var File = ( function(){
691 var DRIVER_LIST = [];
693 var FILE_TYPE_IS_FOLDER = Const.FILE.TYPE.FOLDER,
694 numFileType = Const.FILE.TYPE.XML,
695 FILEDATA_RESITER = [], // store all of fileData( json object )
696 FILEDATA_ACCESS = [], // file operations for Kernel only ! hide from Out of File
697 FILE_OBJECT_POOL = [],
698 EVENT_LISTENER_REGISTER = [],
700 TREE_ACCESS_ARRAY = [];
702 var REQUEST_CONTROLER = ( function(){
703 var REQUEST_TICKET_RESISTER = [],
704 currentTicket = null,
706 DATA_TYPE_ARRAY = 'json,xml,html,text'.split( ',' ),
713 var RequestTicket = Class.create(
715 Constructor : function( apiuser, type, data, url, onLoad, onError ){
716 this.apiuser = apiuser;
720 this.onLoad = onLoad;
721 this.onError = onError;
724 load : function( data ){
725 AsyncCall.add( this.apiuser, this.onLoad, [ this.data, data ] );
728 AsyncCall.add( this.apiuser, this.onError, this.data );
733 if( currentTicket !== null || REQUEST_TICKET_RESISTER.length === 0 ) return;
734 currentTicket = REQUEST_TICKET_RESISTER.shift();
736 url: currentTicket.url,
737 dataType: DATA_TYPE_ARRAY[ currentTicket.type ],
742 function onSuccess( _data ){
743 currentTicket.load( _data );
744 currentTicket.kill();
745 currentTicket = null;
750 currentTicket.error();
751 currentTicket.kill(); // retry
752 currentTicket = null;
757 getNumTask: function(){
758 return REQUEST_TICKET_RESISTER.length;
760 getNumError: function(){
763 getJson: function( _apiuser, _data, _url, _onLoad, _onError ){
764 REQUEST_TICKET_RESISTER.push( new RequestTicket( _apiuser, DATA_IS_JSON, _data, _url, _onLoad, _onError ));
765 currentTicket === null && request();
770 var FILE_CONTROLER = {
771 createTree: function( _apiuser, _rootFileData ){
772 var _tree = new TreeClass( _apiuser, _rootFileData );
773 TREE_ARRAY.push( _tree );
776 getFileUID: function( FILEDATAorFILE ){
777 if( FILEDATAorFILE instanceof FileClass ){
778 return FILEDATAorFILE.getUID();
781 var uid = Util.getIndex( FILEDATA_RESITER, FILEDATAorFILE );
783 uid = FILEDATA_RESITER.length;
784 FILEDATA_RESITER.push( FILEDATAorFILE );
788 getFileDataAccess: function( UIDorFILEorFILEDATA ){
789 var _uid, _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA ), _access;
791 if( _data === null || typeof _data !== 'object' ) return null;
792 for( var i=0, l = FILEDATA_ACCESS.length; i<l; ++i ){
793 _access = FILEDATA_ACCESS[ i ];
794 if( _access.DATA === _data ) return _access;
798 getFileData: function( UIDorFILEorFILEDATA ){
799 if( typeof UIDorFILEorFILEDATA === 'number' ){
800 return FILEDATA_RESITER[ UIDorFILEorFILEDATA ] || null;
802 if( UIDorFILEorFILEDATA instanceof FileClass ){
803 return FILEDATA_RESITER[ UIDorFILEorFILEDATA.getUID() ] || null;
805 if( Util.getIndex( FILEDATA_RESITER, UIDorFILEorFILEDATA ) !== -1 ){
806 return UIDorFILEorFILEDATA;
810 getChildren: function( UIDorFILEorFILEDATA ){
811 var _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA );
812 return _data !== null ? _data.children || null : null;
814 getDriver: function( _file ){
815 var _data = FILE_CONTROLER.getFileData( _file );
816 return _data !== null && _data.driver ? _data.driver : BASE_DRIVER;
818 getUpdateFlag: function( _file, _bit ){
819 var _driver = FILE_CONTROLER.getDriver( _file ),
821 if( typeof _driver.getUpdatePolicy === 'function' ){
822 _policy = _driver.getUpdatePolicy( _file );
825 if( typeof _policy !== 'number' ) {
826 _policy = BASE_DRIVER.getUpdatePolicy( _file )
828 return _policy % ( _bit * 2 ) >= _bit;
830 move: function( _prentUID, _targetfile, _newFolder, _newIndex, _opt_callback ){
831 var _parentData = FILE_CONTROLER.getFileDataAccess( _prentUID ),
832 _parentType = _parentData.TYPE,
833 _targetData = FILE_CONTROLER.getFileDataAccess( _targetfile ),
834 _targetType = _targetData.TYPE;
836 replace: function( _uid, _file, _newIndex ){
839 addEventListener: function( FILEorNULL, _eventType, _callback, opt_thisObject ){
840 var _uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL;
841 EVENT_LISTENER_REGISTER.push( new FileEventTicket( _uid, _eventType, _callback, opt_thisObject ));
843 removeEventListener: function( FILEorNULL, eventType, callback ){
844 var uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL,
845 list = EVENT_LISTENER_REGISTER,
848 for( ; i < list.length; ){
850 if( ticket.fileUID === uid && ticket.eventType === eventType && ticket.callBack === callback ){
858 getTreeAccess: function(){
861 fileEventRellay: function( _uid, _event ){
862 var _fileAccess = FILE_CONTROLER.getFileDataAccess( _uid );
863 if( _fileAccess === null ) return;
864 var _treeUID = _fileAccess.TREE.getUID(),
865 _treeAccess = TREE_ACCESS_ARRAY[ _treeUID ],
866 _data = _fileAccess.DATA,
868 if( !_treeAccess ) return;
869 _treeAccess.dispatchFileEvent( _event );
870 for( var i=0, l = TREE_ARRAY.length; i<l; ++i ){
871 if( i !== _treeUID ){
872 _tree = TREE_ARRAY[ i ];
873 if( FILE_CONTROLER.getFileData( _tree.getCurrentFile() ) === _data ){
874 _treeAccess = TREE_ACCESS_ARRAY[ _tree.getUID() ];
875 _treeAccess && _treeAccess.dispatchFileEvent( _event );
882 var TreeClass = function( apiuser, rootFileData ){
883 var PARENT_FILE_RESITER = [],
886 dispatchFileEvent: dispatchFileEvent
888 EVENT_LISTENER_ARRAY = [],
890 rootFile = new FileClass( instance, null, rootFileData ),
891 currentFile = rootFile;
893 currentFile.getSeqentialFiles();
894 TREE_ACCESS_ARRAY.push( ACCESS );
896 function dispatchFileEvent( e ){
897 var _eventType = e.eventType,
898 _targetFile = e.targetFile,
899 _uid = _targetFile.getUID(),
900 _ticket, _type, _callback;
901 for( var i=0, l = EVENT_LISTENER_REGISTER.length; i<l; ++i ){
902 _ticket = EVENT_LISTENER_REGISTER[ i ];
903 _type = _ticket.eventType;
904 _callback = _ticket.callBack;
905 if( _eventType === _type && _uid === _ticket.fileUID ){
906 AsyncCall.add( apiuser, _callback, [ _eventType, _targetFile, e.key, e.value ], _ticket.thisObject || _targetFile );
908 if( _type === Const.TREE.EVENT.UPDATE && _eventType === Const.FILE.EVENT.GET_SEQENTIAL_FILES ){
909 //_callback( _eventType, _targetFile );
910 AsyncCall.add( apiuser, _callback, [ _eventType, _targetFile ], _ticket.thisObject || instance );
915 this.getUID = function(){
916 return Util.getIndex( TREE_ACCESS_ARRAY, ACCESS );
918 this.getRootFile = function(){
921 this.getCurrentFile = function(){
924 this.hierarchy = function(){
925 return PARENT_FILE_RESITER.length;
927 this.getParentFileAt = function( _index ){
928 var l = PARENT_FILE_RESITER.length;
929 if( typeof _index !== 'number' || _index < 0 || _index >= l ) return null;
930 return PARENT_FILE_RESITER[ l -1 -_index ];
932 this.down = function( _index ){
933 if( typeof _index !== 'number' || _index < 0 || _index >= currentFile.getChildFileLength()) return;
934 PARENT_FILE_RESITER.unshift( currentFile );
935 currentFile = currentFile.getChildFileAt( _index );
936 currentFile.getSeqentialFiles();
939 this.up = function( _index ){
940 var l = PARENT_FILE_RESITER.length;
941 if( l === 0 ) return null;
944 var _currentFile = currentFile;
946 _currentFile.destroy();
948 if( typeof _index === 'number' ){
949 if( _index >= l ) return null;
950 currentFile = this.getParentFileAt( _index );
951 PARENT_FILE_RESITER.splice( 0, l -_index);
953 currentFile = PARENT_FILE_RESITER.shift();
955 currentFile.getSeqentialFiles();
958 this.addTreeEventListener = function( _eventType, _callback, opt_thisObject ){
959 FILE_CONTROLER.addEventListener( null, _eventType, _callback, opt_thisObject );
961 this.removeTreeEventListener = function( _eventType, _callback ){
962 FILE_CONTROLER.removeEventListener( null, _eventType, _callback );
964 this.destroy = function( _apiuser ){
965 if( _apiuser && apiuser !== _apiuser ) return false;
967 var _currentFile = currentFile;
968 currentFile = rootFile = rootFileData = null;
969 // currentFile, rootFile を null にしないと .File.destroy() ができない.
970 _currentFile.destroy();
971 while( PARENT_FILE_RESITER.length > 0 ){
972 _currentFile = PARENT_FILE_RESITER.shift();
973 _currentFile.destroy();
976 AsyncCall.remove( apiuser );
977 instance = apiuser = null;
982 var FileEventTicket = Class.create(
984 Constructor : function( uid, eventType, callback, opt_thisObject ){
986 this.eventType = eventType;
987 this.callBack = callback;
988 this.thisObject = opt_thisObject;
992 var FileEventClass = function( eventType, file, key, value ){
993 this.eventType = eventType;
994 this.targetFile = file;
995 this.updatedAttribute = key;
996 this.updatedValue = value;
1000 * file の data は object で保持している。
1001 * File の外からファイルをみるときは、FileClassを通して操作する。
1002 * fileの変更、それに付随して追加されたイベントは、TreeClassで管理される。
1003 * treeがdestryされると、fileのイベントリスナーも全て削除される。
1004 * 他の tree も data の共通する currentFile に対してのみは、file の変更イベントを受け取って流す.
1008 var FileClass = function( tree, parentData, data ){
1009 var uid = FILE_CONTROLER.getFileUID( data );
1011 FILEDATA_ACCESS.push( {
1013 parentData: parentData,
1017 tree = parentData = data = null;
1019 this.getUID = function(){
1024 FileClass.prototype = {
1025 isChildFile: function( _FILEorFILEDATA ){
1026 return this.getChildFileIndex( _FILEorFILEDATA) !== -1;
1028 getSeqentialFiles: function(){
1029 var _driver = FILE_CONTROLER.getDriver( this );
1030 if( _driver !== null && typeof _driver.getSeqentialFiles === 'function' ){
1031 _driver.getSeqentialFiles( this );
1034 addEventListener: function( _eventType, _callback ){
1035 FILE_CONTROLER.addEventListener( this, _eventType, _callback );
1037 removeEventListener: function( _eventType, _callback ){
1038 FILE_CONTROLER.removeEventListener( this, _eventType, _callback );
1040 dispatchEvent: function( e ){
1041 e instanceof FileEventClass && FILE_CONTROLER.fileEventRellay( this.getUID(), e );
1043 getChildFileLength: function(){
1044 var children = FILE_CONTROLER.getChildren( this );
1045 return Type.isArray( children ) === true ? children.length : -1;
1047 getChildFileIndex: function( _FILEorFILEDATA ){
1048 var children = FILE_CONTROLER.getChildren( this );
1049 if( Type.isArray( children ) === false ) return -1;
1050 var l = children.length,
1051 _fileData = FILE_CONTROLER.getFileData( _FILEorFILEDATA );
1052 if( _fileData === null ) return -1;
1053 for( var i=0; i<l; ++i ){
1054 if( children[ i ] === _fileData ) return i;
1058 getChildFileAt: function( _index ){
1059 var _access = FILE_CONTROLER.getFileDataAccess( this ),
1060 _children = FILE_CONTROLER.getChildren( this );
1061 if( typeof _index !== 'number' || _index < 0 || Type.isArray( _children ) === false || _index >= _children.length ) return null;
1062 var _file = new FileClass( _access.TREE, _access.DATA, _children[ _index ]);
1066 getName: function(){
1067 var driver = FILE_CONTROLER.getDriver( this );
1068 if( typeof driver.getName === 'function'){
1069 return driver.getName( this );
1071 return BASE_DRIVER.getName( this );
1073 getThumbnail: function(){
1074 var driver = FILE_CONTROLER.getDriver( this );
1075 if( typeof driver.getThumbnail === 'function'){
1076 return driver.getThumbnail( this );
1078 return BASE_DRIVER.getThumbnail( this );
1080 getType: function(){
1081 var _data = FILE_CONTROLER.getFileData( this );
1082 return typeof _data.type === 'number' ? _data.type : Const.FILE.TYPE.UNKNOWN;
1084 getState: function(){
1085 var _data = FILE_CONTROLER.getFileData( this );
1086 return typeof _data.state === 'number' ? _data.state : Const.FILE.STATE.OK;
1088 getSummary: function(){
1089 var driver = FILE_CONTROLER.getDriver( this );
1090 if( typeof driver.getSummary === 'function'){
1091 return driver.getSummary( this );
1093 return BASE_DRIVER.getSummary( this );
1095 isWritable: function(){
1096 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.WRITE );
1098 isSortable: function(){
1099 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.SORT );
1101 isCreatable: function(){
1102 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.CREATE );
1104 isRenamable: function(){
1105 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.RENAME );
1107 isDeletable: function(){
1108 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.DELETE );
1112 var driver = FILE_CONTROLER.getDriver( this ),
1114 if( Type.isFunction( driver.read ) === true ){
1115 data = driver.read( this );
1117 return BASE_DRIVER.read( data || this );
1119 write: function( _newData, _onUpdateFunction ){
1120 var driver = FILE_CONTROLER.getDriver( this );
1121 if( typeof driver.write === 'function' ){
1122 return driver.write( this, _newData, _onUpdateFunction );
1124 return BASE_DRIVER.write( this, _newData, _onUpdateFunction );
1126 viewerApplicationList: function(){
1127 var driver = FILE_CONTROLER.getDriver( this );
1128 if( typeof driver.viewerApplicationList === 'function' ){
1129 return driver.viewerApplicationList( this );
1131 return BASE_DRIVER.viewerApplicationList( this );
1133 editorApplicationList: function(){
1134 var driver = FILE_CONTROLER.getDriver( this );
1135 if( typeof driver.editorApplicationList === 'function' ){
1136 return driver.editorApplicationList( this );
1138 return BASE_DRIVER.viwerApps( this );
1149 onDelete: function(){
1152 move: function( _newFolder, _newIndex, opt_callback ){
1153 var _access = FILE_CONTROLER.getFileDataAccess( this );
1154 _access.TREE.move( _access.parentData, this.getUID(), _newFolder, _newIndex, opt_callback );
1156 replace: function( _newIndex, opt_callback ){
1157 var _access = FILE_CONTROLER.getFileDataAccess( this );
1158 _access.TREE.replace( _access.parentData, this.getUID(), _newIndex, opt_callback);
1162 * 探しているファイルの属性と値を指定.一致する child の index を配列で返す.
1164 search: function( obj, rule ){
1165 var _children = FILE_CONTROLER.getChildren( this ),
1168 for( var i=0, l=_children.length; i<l; ++i ){
1169 _child = _children[ i ];
1172 if( obj[ k ] !== _child[ k ] ){
1177 c === true && ret.push( i );
1181 destroy: function(){
1182 var _access = FILE_CONTROLER.getFileDataAccess( this );
1183 var _tree = _access.TREE;
1184 if( _tree.getCurrentFile() === this ) return;
1185 if( _tree.getRootFile() === this ) return;
1186 for( var i=0, l = _tree.hierarchy(); i<l; ++i ){
1187 if( _tree.getParentFileAt( i ) === this ){
1191 var _index = Util.getIndex( FILEDATA_ACCESS, _access );
1192 if( _index === -1 ) return;
1194 FILEDATA_ACCESS.splice( _index, 1 );
1195 delete _access.DATA;
1196 delete _access.TREE;
1197 delete _access.parentData;
1204 var FileDriverBase = function( driverClass ){
1205 this.getUID = function(){
1206 return Util.getIndex( API_USER_LIST, driverClass );
1208 this.getSeqentialFiles = function( _file ){
1210 this.getName = function( _file ){
1211 var _data = FILE_CONTROLER.getFileData( _file );
1212 return _data.name || 'No Name';
1214 this.getThumbnail = function( _file ){
1215 var _data = FILE_CONTROLER.getFileData( _file ),
1218 if( _type === Const.FILE.TYPE.FOLDER ){
1219 _className = 'folder';
1221 if( _type === Const.FILE.TYPE.IMAGE ){
1224 if( _type === Const.FILE.TYPE.TEXT ){
1227 if( _type === Const.FILE.TYPE.HTML ){
1230 if( _type === Const.FILE.TYPE.CSV ){
1233 if( _type === Const.FILE.TYPE.JSON ){
1236 if( _type === Const.FILE.TYPE.XML ){
1241 className: ' file-type-' + _className
1244 this.getSummary = function( _file ){
1245 var _data = FILE_CONTROLER.getFileData( _file ),
1247 if( _type === Const.FILE.TYPE.FOLDER ){
1250 if( _type === Const.FILE.TYPE.IMAGE ){
1251 return 'image file';
1253 if( _type === Const.FILE.TYPE.TEXT ){
1256 if( _type === Const.FILE.TYPE.HTML ){
1257 return 'html document file';
1259 if( _type === Const.FILE.TYPE.CSV ){
1260 return 'csv daat file';
1262 if( _type === Const.FILE.TYPE.JSON ){
1263 return 'json data file';
1265 if( _type === Const.FILE.TYPE.XML ){
1266 return 'xml data file';
1270 this.getUpdatePolicy = function( _file ){
1271 // debug用 全てのメニューを許可
1272 return Const.FILE.UPDATE_POLICY.DSRWC;
1274 this.read = function( FILEorDATA ){
1276 protects = Const.FILE.DATA_PROPERTY_RESERVED,
1279 getIndex = Util.getIndex;
1280 if( FILEorDATA instanceof FileClass ){
1281 data = FILE_CONTROLER.getFileData( FILEorDATA )
1286 function clone( src ) {
1288 if( Type.isArray( src ) === true ){
1289 i = getIndex( objSrc, src );
1290 if( i !== -1 ) return objCopy[ i ];
1292 objSrc[ objSrc.length ] = src;
1293 objCopy[ objCopy.length ] = ret;
1295 if( Type.isObject( src ) === true ){
1296 i = getIndex( objSrc, src );
1297 if( i !== -1 ) return objCopy[ i ];
1299 objSrc[ objSrc.length ] = src;
1300 objCopy[ objCopy.length ] = ret;
1302 if( Type.isNumber( src ) === true || Type.isString( src ) === true || Type.isBoolean( src ) === true ){
1308 if( getIndex( protects, key ) === -1 ){
1309 ret[ key ] = clone( src[ key ]);
1314 return clone( data );
1316 this.write = function( _file, _newData, _onUpdateFunction ){
1317 var _data = FILE_CONTROLER.getFileData( _file ),
1321 this.viewerApplicationList = function(){
1324 this.editorApplicationList = function(){
1327 this.onCreate = function(){
1330 this.onSort = function(){
1333 this.onCopy = function(){
1336 this.onDelete = function(){
1341 var BASE_DRIVER = new FileDriverBase();
1343 var ROOT_FILEDATA = {
1344 name: 'system root',
1345 type: FILE_TYPE_IS_FOLDER,
1348 SYSTEM_TREE = FILE_CONTROLER.createTree( SUPER_USER_KEY, ROOT_FILEDATA ),
1349 ROOT_FILE = SYSTEM_TREE.getRootFile();
1351 function createFileTypeID(){
1352 return ++numFileType;
1355 var FileAPIClass = function( driver ){
1357 this.createFolderUnderRoot = function( _fileData ){
1358 if( _fileData !== null && Type.isObject( _fileData ) === true ){
1359 ROOT_FILEDATA.children.push( _fileData );
1360 ROOT_FILE.dispatchEvent( new FileEventClass( Const.FILE.EVENT.GET_SEQENTIAL_FILES, ROOT_FILE, 'children', null ));
1363 this.createFileEvent = function( _eventType, _file, _key, _value ){
1364 return new FileEventClass( _eventType, _file, _key, _value );
1366 this.createFileTypeID = createFileTypeID;
1367 this.getFileDataAccess = FILE_CONTROLER.getFileDataAccess;
1368 this.getFileData = FILE_CONTROLER.getFileData;
1369 this.getJson = function( _data, _url, _onLoad, _onError ){
1370 REQUEST_CONTROLER.getJson( driver, _data, _url, _onLoad, _onError );
1372 this.createTree = function( _rootFile ){
1373 return FILE_CONTROLER.createTree( driver, _rootFile );
1375 this.isTreeInstance = function( _tree ){
1376 return _tree instanceof TreeClass;
1378 this.isFileInstance = function( _file ){
1379 return _file instanceof FileClass;
1381 this.isFileEvent = function( _event ){
1382 return _event instanceof FileEventClass;
1384 this.getConst = function(){
1385 return Const; // constObject = constObject || clone( Const )
1390 registerDriver: function( _class ){
1391 _class.prototype = new FileDriverBase( _class );
1392 var _driver = new _class();
1394 DRIVER_LIST.push( _driver );
1395 API_USER_LIST.push( _class );
1397 return new FileAPIClass( _driver );
1399 isDriver: function( _driver ){
1400 return _driver instanceof FileDriverBase;
1402 isTreeInstance: function( _tree ){
1403 return _tree instanceof TreeClass;
1405 isFileInstance: function( _file ){
1406 return _file instanceof FileClass;
1412 /* ----------------------------------------------------
1413 * ApplicationManager
1414 * window resize event, overlayApplication currentAplication に流す
1417 var APPLICATION_LIST = [];
1419 var ApplicationPrivateData = function(){};
1420 ApplicationPrivateData.prototype = {
1426 bgColor : '#C1CACF',
1438 init : function( appClass, displayName, isOverlay ){
1439 this.appClass = appClass;
1440 // this.application = app;
1441 this.displayName = displayName;
1442 this.isOverlay = isOverlay;
1443 this.rootElement = document.createElement( 'div' );
1444 this.styleCursor = this.rootElement.style;
1445 ApplicationPrivateData.list.push( this );
1447 detect : function(){
1448 if( this.rootElement.firstChild && this.fetchResource === 0 ){
1449 SystemTimer.remove( this.application, this.detect );
1453 onOpen : function(){
1454 this.rootElement.style.display = '';
1456 // this.layer !== null && this.layer.onResize( this.w, this.h );
1458 if( this.application.MIN_WIDTH > this.w || this.application.MIN_HEIGHT > this.h ){
1459 if( Type.isHTMLElement( this.rootElement ) === true ){
1463 if( this.bootParams.length > 2 ){
1464 this.application.onOpen.apply( this.application, this.bootParams );
1466 this.application.onOpen( this.w, this.h );
1470 fetchResourceComplete : function(){
1471 --this.fetchResource;
1474 ApplicationPrivateData.list = [];
1475 ApplicationPrivateData.get = function( app ){
1476 var list = ApplicationPrivateData.list,
1479 if( app instanceof list[ --i ].appClass ) return list[ i ];
1484 var AbstractApplication = function( appClass, displayName, isOverlay ){
1485 ( new ApplicationPrivateData() ).init( appClass, displayName, isOverlay );
1487 AbstractApplication.prototype = {
1488 getUID : function(){
1489 var data = ApplicationPrivateData.get( this );
1490 return Util.getIndex( API_USER_LIST, data.appClass );
1493 var data = ApplicationPrivateData.get( this );
1494 // this.rootElement = data.rootElement;
1495 // data.application = this;
1497 data.appClass === Page.appClass && Page.show();
1501 open : function( w, h /*, _option */ ){
1502 var data = ApplicationPrivateData.get( this );
1504 data.bootParams = Util.copyArray( arguments );
1507 if( data.rootElement.innerHTML && data.rootElement.innerHTML.length > 0 ){
1508 SystemTimer.add( this, data.detect, 16, false, data );
1513 resize : function( w, h ){
1514 var data = ApplicationPrivateData.get( this );
1515 if( data.phase !== 4 ) return;
1516 if( this.MIN_WIDTH > w || this.MIN_HEIGHT > h ){
1517 if( Type.isHTMLElement( this.rootElement ) === true ){
1522 this.onPaneResize( w, h );
1525 var data = ApplicationPrivateData.get( this );
1527 if( this.onClose() === false ){
1531 while( data.uiList.length > 0 ) data.uiList.shift().destroy();
1533 if( data.finderList ){
1534 while( data.finderList.length > 0 ) data.finderList.shift().destroy();
1537 data.eventRoot && PointingDeviceEventTree.destroyTree( data.eventRoot );
1538 MouseEvent.remove( this );
1539 KeyEvent.remove( this );
1540 SystemTimer.remove( this );
1541 AsyncCall.remove( this );
1542 StyleSheet.unload( this );
1544 var elm = this.rootElement;
1545 Util.removeAllChildren( elm );
1546 elm.parentNode.removeChild( elm );
1548 Application.shutdown( this, data.isOverlay );
1550 data.appClass === Page.appClass && Page.hide();
1554 var list = ApplicationPrivateData.list;
1555 list.splice( Util.getIndex( list, data ), 1 );
1557 createUIGroup : function( node ){
1558 var data = ApplicationPrivateData.get( this ),
1559 ui = UI.createUIGroup( this, node );
1560 if( data.uiList === null ) data.uiList = [];
1561 data.uiList.push( ui );
1564 createUIForm : function( nodeOrElm, opt_elmForm ){
1565 var data = ApplicationPrivateData.get( this ),
1566 form = UIForm.createForm( this, nodeOrElm, opt_elmForm );
1567 if( data.formList === null ) data.formList = [];
1568 data.formList.push( form );
1571 createFinder : function( _elmTarget, _tree, _onSelect, _viewerOption, _editorOption ){
1572 var data = ApplicationPrivateData.get( this ),
1573 finder = Finder.create( this, _elmTarget, _tree, _onSelect, _viewerOption, _editorOption );
1574 if( data.finderList === null ) data.finderList = [];
1575 data.finderList.push( finder );
1578 createDHTML : function( _elm ){
1579 return DHTML.create( this, _elm );
1581 addEventListener : function( element, eventType, handler, opt_thisObject ){
1582 MouseEvent.add( this, element, eventType, handler, opt_thisObject );
1584 removeEventListener : function( element, eventType, handler ){
1585 MouseEvent.remove( this, element, eventType, handler );
1587 getPointingDeviceEventTreeRoot : function(){
1588 var data = ApplicationPrivateData.get( this );
1589 if( data.phase === 1 ){
1590 data.eventRoot = PointingDeviceEventTree.create( this );
1591 data.styleCursor = PointingDeviceEventTree._getNodePrivateData( data.eventRoot ).elmMouseCatch.style;
1593 return data.eventRoot;
1595 updateCoursor : function( _cursor ){
1596 var data = ApplicationPrivateData.get( this );
1597 if( data.cursor !== _cursor ){
1598 data.styleCursor.cursor = data.cursor = _cursor;
1601 fetchCSS : function( url, opt_onload, opt_onerror ){
1602 var data = ApplicationPrivateData.get( this );
1603 if( data.phase === 1 ){
1604 ++data.fetchResource;
1605 StyleSheet.load( this, url, data.fetchResourceComplete, data.fetchResourceComplete, data );
1608 onInit : function(){},
1609 onOpen : function(){},
1610 onClose : function(){ return true; },
1611 onPaneResize : function( w, h ){},
1612 addKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){
1613 KeyEvent.add( this, _eventType, _handler, _keyCode, _shift, _ctrl );
1615 removeKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){
1616 KeyEvent.remove( this, _eventType, _handler, _keyCode, _shift, _ctrl );
1618 shiftEnabled : function(){
1619 return KeyEvent.shiftEnabled;
1621 ctrlEnabled : function(){
1622 return KeyEvent.ctrlEnabled;
1624 addTimer : function( handler, time, once ){
1625 SystemTimer.add( this, handler, time, !!once );
1627 removeTimer : function( handler ){
1628 SystemTimer.remove( this, handler );
1630 addAsyncCall : function( _callback, _argments, _thisObject ){
1631 AsyncCall.add( this, _callback, _argments, _thisObject );
1633 removeAsyncCall : function( _callback ){
1634 AsyncCall.remove( this, _callback );
1636 fetchHTMLElement : function( id ){
1637 var elm = document.getElementById( id );
1639 elm.removeAttribute( 'id' );
1640 elm.parentNode.removeChild( elm );
1646 var PointingDeviceEventTree = ( function(){
1648 currentRootData = null,
1649 targetNodeData = null,
1650 forceNodeData = null,
1653 function eventRellay( e ){
1654 var data = forceNodeData, // || targetNodeData,
1660 ret, systemOnly = false, addClass, removeClass,
1662 if( data && data.dispatchEvent( e, type, true ) === true ) return false;
1663 if( currentRootData === null ) return;
1664 targetNodeData = currentRootData;
1665 currentRootData._capcher( x, y );
1666 targetNodeData.apiuser.updateCoursor( targetNodeData._cursor );
1667 data = targetNodeData;
1669 ret = data.dispatchEvent( e, type, true, systemOnly );
1670 if( ret === true || ret === false ) break; // systemOnly = true;
1671 data = data.parentData;
1674 addClass = Util.addClass;
1675 removeClass = Util.removeClass;
1676 for( ; i < list.length; ){
1677 parent = data = list[ i ];
1678 while( parent.parentData && parent === parent.parentData.hitChild ){
1679 parent = parent.parentData;
1681 if( parent !== currentRootData ){
1682 data.hover === true && removeClass( data.elm, data.hoverClass );
1683 delete data.isHover;
1684 data.events && data.events.mouseout && data.fire( e, 'mouseout', false );
1685 delete data.hitSelf;
1686 list.splice( i, 1 );
1689 if( data.hover === true && data.isHover === false ){
1690 addClass( data.elm, data.hoverClass );
1691 data.isHover = true;
1693 if( data.hitSelf === false ){
1694 data.events && data.events.mouseover && data.fire( e, 'mouseover', true );
1695 data.hitSelf = true;
1702 var NodeClass = function( apiuser, rootData, /*parentLayer,*/ parentData, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){
1703 ( new NodePrivateData() ).init( apiuser, rootData, /*parentLayer,*/ parentData, this, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop );
1705 NodeClass.prototype = {
1706 createNode : function( rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ){
1707 var data = NodePrivateData.get( this ),
1709 if( Type.isHTMLElement( rangeOrElmData ) === true ){
1710 elm = rangeOrElmData;
1712 if( Type.isString( rangeOrElmData ) === true ){
1713 elm = document.getElementById( rangeOrElmData );
1715 elm = Util.pullHtmlAsTemplete( rangeOrElmData );
1717 if( !elm || Type.isHTMLElement( elm ) === false || elm.nodeType !== 1 ){
1718 throw new Error( "invalid HTMLElement." );
1721 if( Type.isObject( rangeOrElmData ) === false || Type.isFinite( rangeOrElmData.x ) === false || Type.isFinite( rangeOrElmData.y ) === false ){
1722 throw new Error( "No range" );
1725 if( elm && data.elm === null ){
1726 throw new Error( "MetaLayer don't containe HTMLElement-Layer." );
1728 if( data.elm && data.elm.style.hasLayout === false ){
1729 throw new Error( "[ie] OffsetParent is hasLayout === false." );
1732 var newNode = new NodeClass( data.apiuser, data.rootData, data, elm || rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ),
1733 newData = NodePrivateData.get( newNode );
1735 if( data.childData === null ) data.childData = [];
1736 data.childData.push( newData );
1739 createNodeAt : function(){
1741 remove : function(){
1742 NodePrivateData.get( this ).remove();
1744 nodeIndex : function( v ){
1745 return NodePrivateData.get( this ).nodeIndex( v );
1747 numNode : function(){
1748 return NodePrivateData.get( this ).numNode();
1750 disabled : function( v ){
1751 return NodePrivateData.get( this ).disabled( v );
1753 childrenDisabled : function( v ){
1754 return NodePrivateData.get( this ).disabled( v );
1756 mesure : function(){
1757 NodePrivateData.get( this ).mesure();
1759 mesureChildren : function(){
1760 NodePrivateData.get( this ).mesureChildren();
1762 update : function( x, y, w, h ){
1763 NodePrivateData.get( this ).update( x, y, w, h );
1765 setPosition : function( x, y ){
1766 NodePrivateData.get( this ).setPosition( x, y );
1768 setSize : function( w, h ){
1769 NodePrivateData.get( this ).setSize( w, h );
1771 cursor : function( v ){
1772 return NodePrivateData.get( this ).cursor( v );
1775 return NodePrivateData.get( this ).positionX( x );
1778 return NodePrivateData.get( this ).positionY( y );
1780 width : function( w ){
1781 return NodePrivateData.get( this ).width( w );
1783 height : function( h ){
1784 return NodePrivateData.get( this ).height( h );
1786 getAbsolutePositionX : function(){
1787 return NodePrivateData.get( this ).getAbsolutePositionX();
1789 getAbsolutePositionY : function(){
1790 return NodePrivateData.get( this ).getAbsolutePositionY();
1792 addEventListener : function( type, handler, opt_thisObject ){
1793 NodePrivateData.get( this ).addEventListener( type, handler, opt_thisObject );
1795 removeEventListener : function( type, handler ){
1796 NodePrivateData.get( this ).removeEventListener( type, handler );
1798 scrollTo : function( x, y ){
1799 NodePrivateData.get( this ).scrollTo( x, y );
1801 scrollX : function( v ){
1802 return NodePrivateData.get( this ).scrollX( v );
1804 scrollY : function( v ){
1805 return NodePrivateData.get( this ).scrollY( v );
1807 invalidateScrollbar : function(){
1808 ScrollBarManager.update( NodePrivateData.get( this ) );
1813 * clip : true の場合、子ノードの変更によってヒットエリアを変化させない.elm には overflow:hidden としておくのが通常.
1815 var NodePrivateData = function(){};
1816 NodePrivateData.prototype = {
1817 elmMouseCatch : null, // rootData only
1818 eventCounter : null, // rootData only
1819 cursorStyle : null, // rootData only
1823 elm : null, // resizeTarget
1826 elmScrollbar : null,
1842 // parentLayer : null,
1849 _childDisabled: false,
1850 layoutManager : null,
1859 init: function( apiuser, rootData, /*parentLayer,*/ parentData, node, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){
1860 this.apiuser = apiuser;
1861 this.rootData = rootData || this;
1862 // this.parentLayer = parentLayer;
1863 this.parentData = parentData;
1865 this.through = through;
1867 if( cursor ) this._cursor = cursor;
1869 if( Type.isHTMLElement( rangeOrElm ) === true ){
1870 this.elm = rangeOrElm;
1871 this.hover = !!hover;
1872 this.hoverClass = hover;
1873 this.scroll = clip && scroll;
1875 this.scroll === true && ScrollBarManager.register( this );
1877 this.update( rangeOrElm.x, rangeOrElm.y, rangeOrElm.w, rangeOrElm.h );
1880 NodePrivateData.dataList.push( this );
1882 mesure : function(){
1883 var x, y, w, h, parent, _this, _parent;
1885 w = this.elm.offsetWidth;
1886 h = this.elm.offsetHeight;
1887 _this = Position.cumulativeOffset( this.elm );
1888 _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ];
1889 x = _this[ 0 ] - _parent[ 0 ];
1890 y = _this[ 1 ] - _parent[ 1 ];
1891 if( this.x !== x || this.y !== y || this.w !== w || this.h !== h ){
1896 parent = this.parentData;
1897 parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY );
1898 this._updateRectangle();
1901 this._updateRectangle();
1904 mesureChildren : function(){
1906 if( nodes = this.childData ){
1907 for( i = nodes.length; i; ){
1908 nodes[ --i ].mesure();
1912 update : function( x, y, w, h ){
1913 var updateXY = false,
1919 if( Type.isFinite( w ) === true ){
1920 this.elm.style.width = w + 'px';
1922 if( Type.isString( w ) === true ){
1923 this.elm.style.width = w;
1924 w = this.elm.offsetWidth;
1926 //update = this.w !== w;
1929 if( Type.isFinite( h ) === true ){
1930 this.elm.style.height = h + 'px';
1932 if( Type.isString( h ) === true ){
1933 this.elm.style.height = w;
1934 h = this.elm.offsetHeight;
1936 //update = update || this.h !== h;
1939 if( Type.isFinite( x ) === true ){
1940 this.elm.style.left = x + 'px';
1942 if( Type.isString( x ) === true ){
1943 this.elm.style.left = x;
1950 if( Type.isFinite( y ) === true ){
1951 this.elm.style.top = y + 'px';
1953 if( Type.isString( y ) === true ){
1954 this.elm.style.top = y;
1959 if( updateXY === true ){
1960 _this = Position.cumulativeOffset( this.elm );
1961 _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ];
1962 x = _this[ 0 ] - _parent[ 0 ];
1963 y = _this[ 1 ] - _parent[ 1 ];
1965 //update = update || this.x !== x;
1966 //update = update || this.y !== y;
1968 //update === true && this._updateRectangle();
1971 x = Type.isFinite( x ) === true ? x : this.x;
1972 y = Type.isFinite( y ) === true ? y : this.y;
1973 w = Type.isFinite( w ) === true ? w : this.w;
1974 h = Type.isFinite( h ) === true ? h : this.h;
1975 if( this.x !== x || this.y !== y ){
1978 //console.log( 'xy ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h + ' absX:' + this.parentData.absoluteX )
1979 parent = this.parentData;
1980 parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY );
1981 this.w === w && this.h === h && this._updateRectangle();
1983 if( this.w !== w || this.h !== h ){
1986 //console.log( 'wh ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h )
1987 this._updateRectangle();
1990 ScrollBarManager.update( this );
1992 _updateAbsoluteXY : function( x, y, sX, sY ){
1994 this.absoluteX = x = this.x + x;
1995 this.absoluteY = y = this.y + y;
1996 if( nodes = this.childData ){
1997 for( i = nodes.length; i; ){
1998 nodes[ --i ]._updateAbsoluteXY( x, y, this.scrollingX, this.scrollingY );
2002 _updateRectangle : function(){
2011 nodes = this.childData,
2015 if( this.clip === false && nodes ){
2016 for( i = nodes.length; i; ){
2017 node = nodes[ --i ];
2018 if( node.l + x < l ) l = x + node.l;
2019 if( node.t + y < t ) t = y + node.t;
2020 if( r < node.r + x ) r = x + node.r;
2021 if( b < node.b + y ) b = y + node.b;
2025 if( b !== this.b || r !== this.r || t !== this.t || l !== this.l ){
2032 this.parentData && this.parentData.clip === false && this.parentData._updateRectangle();
2036 setPosition : function( x, y ){
2037 this.update( x, y );
2039 setSize : function( w, h ){
2040 this.update( undefined, undefined, w, h );
2042 positionX : function( x ){
2043 x !== undefined && this.update( x );
2046 positionY : function( y ){
2047 y !== undefined && this.update( undefined, y );
2050 width : function( w ){
2051 w !== undefined && this.update( undefined, undefined, w );
2054 height : function( h ){
2055 h !== undefined && this.update( undefined, undefined, undefined, h );
2058 getAbsolutePositionX : function(){
2059 return this.absoluteX;
2061 getAbsolutePositionY : function(){
2062 return this.absoluteY;
2064 cursor : function( v ){
2065 if( Type.isString( v ) === true ){
2067 this === targetNodeData && this.apiuser.updateCoursor( v );
2069 return this._cursor;
2071 addEventListener : function( eventType, handler, opt_thisObject ){
2072 var node = this.node,
2073 counter = this.rootData.eventCounter,
2075 if( this.events === null ) this.events = {};
2076 list = this.events[ eventType ];
2078 list = this.events[ eventType ] = [];
2080 for( i = list.length; i; ){
2081 if( list[ --i ].match( eventType, handler ) === true ){
2086 list.push( new EventTicketClass( this.node, eventType, handler, opt_thisObject ) );
2087 if( eventType !== 'mouseout' && eventType !== 'mouseover' ){
2088 if( counter[ eventType ] ){
2089 ++counter[ eventType ];
2091 //console.log( eventType );
2092 counter[ eventType ] = 1;
2093 MouseEvent.add( this.apiuser, this.rootData.elmMouseCatch, eventType, eventRellay );
2097 removeEventListener : function( eventType, handler ){
2098 var events = this.events,
2099 counter = this.rootData.eventCounter,
2101 if( events === null ) return;
2102 console.log( ' *** remove ' + eventType );
2103 for( type in events ){
2104 list = events[ type ];
2105 if( eventType && eventType !== type ) continue;
2106 for( ; i < list.length; ){
2107 if( list[ i ].destroy( type, handler ) === true ){
2108 console.log( ' *** removed! ' + type );
2109 list.splice( i, 1 );
2114 if( list.length === 0 ){
2115 // delete this[ type ];
2116 delete events[ type ];
2118 if( counter[ type ] ){
2120 if( counter[ type ] === 0 ){
2121 MouseEvent.remove( this.apiuser, this.rootData.elmMouseCatch, type, eventRellay );
2122 delete counter[ type ];
2127 _capcher : function( x, y ){
2128 var t = this, nodes, child, _x, _y, hit, i;
2129 if( t._disabled === true ) return false;
2133 if( nodes = t.childData ){
2134 _x = x - t.scrollingX;
2135 _y = y - t.scrollingY;
2136 for( i = nodes.length; i; ){
2137 child = nodes[ --i ];
2138 if( child._disabled === false && child.l <= _x && _x < child.r && child.t <= _y && _y < child.b && child._capcher( _x, _y ) === true ){
2144 if( t.through === true ){
2145 t.hitChild && t.hitSelf === false && hoverList.push( t );
2146 return !!t.hitChild;
2148 hit = 0 <= x && x < t.w && 0 <= y && y < t.h;
2149 ( t.hitChild || hit ) && t.hitSelf === false && hoverList.push( t );
2150 if( hit === true && t.hitChild === null ) targetNodeData = t;
2151 return hit || !!t.hitChild;
2153 fire : function( e, eventType, hit ){
2154 var list = this.events[ eventType ],
2156 e = NodePrivateData.createEvent( e, eventType, this, hit );
2157 for( ; i; ) list[ --i ].fire( e );
2158 // console.log( eventType + ' x:' + x + ' y:' + y );
2160 dispatchEvent : function( e, eventType, hit ){
2161 var ret, list, i, p, child;
2162 if( !this.events || !( list = this.events[ eventType ] ) ) return;
2164 child = !!this.hitChild;
2165 e = NodePrivateData.createEvent( e, eventType, this, hit );
2166 for( i = list.length; i; ){
2167 ret = list[ --i ].fire( e );
2168 if( ret === true && child === false ){
2169 forceNodeData = this;
2172 if( ret === false ) return false;
2174 forceNodeData = null;
2176 scrollTo : function( x, y ){
2179 ScrollBarManager.update( this );
2181 scrollX : function( v ){
2182 if( Type.isFinite( v ) === true ){
2184 ScrollBarManager.update( this );
2186 return this.scrollingX; // this._scrollX;
2188 scrollY : function( v ){
2189 if( Type.isFinite( v ) === true ){
2191 ScrollBarManager.update( this );
2193 return this.scrollingY; // this._scrollY;
2195 nodeIndex : function( v ){
2197 if( !this.parentData ) return 0;
2199 list = this.parentData.childData;
2200 i = Util.getIndex( list, this );
2201 if( Type.isFinite( v ) === false || i === v && v < 0 && list.length <= v ) return i;
2203 list.splice( i, 1 );
2204 list.length === v ? list.push( this ) : list.splice( v, 0, this );
2209 if( this.parentData.hitChild === this ){
2210 this.parentData.hitChild = null;
2211 this.isHover === true && hoverList.splice( Util.getIndex( hoverList, this ), 1 ) && Util.removeClass( this.elm, this.hoverClass );
2212 this.isHover = false;
2213 if( forceNodeData === this ) forceNodeData = null;
2214 if( targetNodeData === this ) targetNodeData = null;
2217 numNode : function(){
2218 return this.childData ? this.childData.length : 0;
2220 disabled : function( v ){
2221 if( Type.isBoolean( v ) === true ){
2227 return this._disabled;
2229 childrenDisabled : function( v ){
2230 if( Type.isBoolean( v ) === true ){
2231 this._childDisabled = v;
2233 return this._childDisabled;
2235 remove : function(){
2236 if( this === this.rootData ) return;
2237 var parent = this.parentData,
2238 nodes = parent.childData;
2240 if( parent.hitChild === this ) delete parent.hitChild;
2241 nodes.splice( Util.getIndex( nodes, this ), 1 );
2242 if( nodes.length === 0 ) delete parent.childData;
2243 parent.clip === false && parent._updateRectangle();
2245 _destroy : function(){
2246 var nodes = this.childData,
2247 list = NodePrivateData.dataList,
2249 this.removeEventListener();
2250 ScrollBarManager.remove( this );
2252 while( node = nodes.shift() ) node._destroy();
2253 delete this.childData;
2255 list.splice( Util.getIndex( list, this ), 1 );
2258 NodePrivateData.dataList = [];
2259 NodePrivateData.get = function( node ){
2260 // if( node instanceof NodePrivateData ) return node;
2261 // return NodePrivateData.dataList[ layer._getUID() ];
2262 var list = NodePrivateData.dataList;
2263 for( var i = list.length; i; ){
2264 if( list[ --i ].node === node ) return list[ i ];
2268 NodePrivateData.createEvent = function( e, eventType, data, hit ){
2270 layerX : e.clientX - data.absoluteX,
2271 layerY : e.clientY - data.absoluteY,
2272 clientX : e.clientX,
2273 clientY : e.clientY,
2274 dragOffsetX : e.dragOffsetX,
2275 dragOffsetY : e.dragOffsetY,
2276 dragPhase : e.dragPhase,
2277 eventType : eventType,
2280 wheelDelta : e.wheelDelta,
2281 target : forceNodeData ? forceNodeData.node : targetNodeData ? targetNodeData.node : null
2286 var EventTicketClass = function( node, eventType, handler, opt_thisObject ){
2288 this.type = eventType;
2289 this.handler = handler;
2290 this.thisObj = opt_thisObject || node;
2292 EventTicketClass.prototype = {
2293 match : function( eventType, handler ){
2294 if( handler && this.handler !== handler ) return false;
2295 if( eventType && this.type !== eventType ) return false;
2298 destroy : function( eventType, handler ){
2299 if( this.match( eventType, handler ) === false ) return false;
2302 delete this.handler;
2303 delete this.thisObj;
2306 fire : ( function(){
2307 if( Function.prototype.call ){
2308 return function( e ){
2309 return this.handler.call( this.thisObj, e );
2312 return function( e ){
2314 this.thisObj._currentHandler = this.handler;
2315 ret = this.thisObj._currentHandler( e );
2316 delete this.thisObj._currentHandler;
2322 /*-------------------------------------
2325 var StayEventTicketClass = function( node, data, stayhandler, opt_thisObject ){
2326 node.addEventListener( 'mouseover', this.mouseoverHandler, this );
2329 this.handler = stayhandler;
2330 this.thisObject = opt_thisObject;
2332 StayEventTicketClass.prototype = Util.extend( new EventTicketClass( null, 'mousestay' ), {
2333 // type : 'mousestay',
2335 mouseoverHandler : function( e ){
2336 this.e = NodePrivateData.createEvent( e, this.type, this.data, true );
2337 this.node.addEventListener( 'mouseout', this.mousestayHandler, this );
2338 this.node.addEventListener( 'mousemove', this.mousemoveHandler, this );
2339 SystemTimer.add( this.data.apiuser, this.timeoutHandler, null, this );
2341 timeoutHandler : function(){
2342 this.mouseoutHandler();
2343 return this.fire( this.e );
2345 mousemoveHandler : function( e ){
2346 this.e = NodePrivateData.createEvent( e, this.type, this.data, true );
2347 SystemTimer.remove( this.data.apiuser, this.timeoutHandler );
2348 SystemTimer.add( this.data.apiuser, this.timeoutHandler, null, this );
2350 mouseoutHandler : function( e ){
2351 this.node.removeEventListener( 'mouseout', this.mousestayHandler );
2352 this.node.removeEventListener( 'mousemove', this.mousemoveHandler );
2353 SystemTimer.remove( this.data.apiuser, this.timeoutHandler );
2358 var ScrollBarManager = ( function(){
2359 var elmScroller = document.createElement( 'div' ),
2360 elmBar = document.createElement( 'div' ),
2364 currentNodeData = null,
2369 var list = smoothList,
2371 for( i = 0; i < list.length; ){
2373 if( data.scrollingY !== data._scrollY ){
2374 y = data.scrollingY += data.smoothY;
2375 if( data.smoothY < 0 ){
2376 y = y < data._scrollY ? data._scrollY : y;
2378 y = data._scrollY < y ? data._scrollY : y;
2380 data.scrollingY = y;
2381 data.elm.scrollTop = -y;
2382 data.events && data.events.scroll && data.fire( currentEvent, 'scroll', true );
2384 if( data.scrollingY === data._scrollY ){
2385 list.splice( i, 1 );
2386 // data.events && data.events.scroll && data.fire( currentEvent, 'scroll', true );
2391 list.length === 0 && SystemTimer.remove( SUPER_USER_KEY, tick );
2392 currentEvent.type = 'updateAfterScroll';
2393 AsyncCall.add( data.apiuser, eventRellay, currentEvent ); // スクロール後の更新
2396 function scrollReady( e ){
2400 if( data === currentNodeData || dragPhase !== 2 ) return; // Drag中の場合は 他にスクロールを作らない
2401 currentNodeData && scrollRelease();
2404 data.elm.parentNode.appendChild( elmScroller );
2405 elmScroller.appendChild( data.elm );
2407 elmScroller.style.cssText = 'position:absolute;left:0;top:0;';
2408 elmScroller.appendChild( elmBar );
2410 data.elm.scrollTop = -data.scrollingY;
2411 data.rootData.addEventListener( 'mousewheel', onMouseWheelScroll, data );
2412 data.rootData.addEventListener( 'mousedrag', onMouseDragScroll, data );
2413 data.addEventListener( 'mouseout', onMouseOut, data );
2414 currentNodeData = data;
2415 ScrollBarManager.update( data );
2417 function scrollRelease(){
2418 var data = currentNodeData;
2419 var parent = elmScroller.parentNode;
2420 parent.appendChild( currentNodeData.elm );
2421 parent.removeChild( elmScroller );
2422 currentNodeData.elm.scrollTop = -data.scrollingY;
2424 data.rootData.removeEventListener( 'mousewheel', onMouseWheelScroll, data );
2425 data.rootData.removeEventListener( 'mousedrag', onMouseDragScroll, data );
2426 data.removeEventListener( 'mouseout', onMouseOut, data );
2427 currentNodeData = null;
2429 function onMouseOut( e ){
2431 console.log( 'mouseOut ' + dragPhase );
2432 dragPhase === 2 && scrollRelease(); // Dragしてのアウトの場合, scroll をリリースしない
2434 function onMouseWheelScroll( e ){
2436 this._scrollY += e.wheelDelta;
2437 ScrollBarManager.update( this );
2441 function onMouseDragScroll( e ){
2445 dragPhase = e.dragPhase;
2446 switch( dragPhase ){
2448 dragStartY = this.scrollingY;
2449 data.rootData.removeEventListener( 'mousewheel', onMouseWheelScroll, data );
2451 this._scrollY = dragStartY + e.dragOffsetY;
2452 ScrollBarManager.update( this );
2455 dragOut === true ? scrollRelease() : data.rootData.addEventListener( 'mousewheel', onMouseWheelScroll, data );
2461 register : function( data ){
2462 data.addEventListener( 'mouseover', scrollReady, data );
2464 update : function( data ){
2465 // if( data !== currentNodeData ) return;
2466 var isCurrent = data === currentNodeData;
2468 var contentH = data._scrollH = data.elm.scrollHeight,
2470 offsetH = contentH - clipH,
2471 scrollY = data._scrollY = 0 < data._scrollY ? 0 : ( data._scrollY < -offsetH ? -offsetH : data._scrollY ),
2473 if( isCurrent === true ){
2474 elmScroller.style.width = data.w + 'px';
2475 elmScroller.style.height = clipH + 'px';
2479 data._scrollY = scrollY = 0;
2480 if( isCurrent === true ) elmBar.style.display = 'none';
2482 if( isCurrent === true ){
2483 barH = Math.floor( clipH * ( clipH / contentH ) );
2484 barY = Math.floor( ( clipH - barH ) * - scrollY / offsetH );
2485 elmBar.style.cssText = [
2486 'position:absolute;',
2488 'background-color:#333;',
2490 'font-size:0;line-height:0;',
2491 'height:', barH, 'px;',
2492 'top:', data.y + barY, 'px;'
2495 data.smoothY = ( scrollY - data.scrollingY ) / 10;
2496 if( data.scrollingY !== scrollY && Util.getIndex( smoothList, data ) === -1 ){
2497 smoothList.length === 0 && SystemTimer.add( SUPER_USER_KEY, tick, 16 );
2498 smoothList.push( data );
2501 remove : function( data ){
2502 var list = smoothList,
2503 i = Util.getIndex( list, data );
2504 data === currentNodeData && scrollRelease();
2505 i !== -1 && list.splice( i, 1 );
2511 create : function( apiuser ){
2512 var elm = document.createElement( 'div' ),
2514 body.appendChild( elm );
2516 root = new NodeClass( apiuser, null, null, elm );
2517 data = NodePrivateData.get( root );
2519 // elm.style.cssText = 'position:absolute;top:0;left:0;height:100%;';
2520 elm.className = 'mouse-operation-catcher';
2521 elm.unselectable = 'on';
2522 data.elmMouseCatch = elm;
2524 data.eventCounter = {};
2525 ROOT_LIST.push( data );
2526 currentRootData = data;
2527 targetNodeData = null;
2528 forceNodeData = null;
2530 MouseEvent.add( apiuser, elm, 'mousemove', eventRellay );
2533 onCurrentApplicationChange : function( _application ){
2534 currentRootData = null;
2535 targetNodeData = null;
2536 forceNodeData = null;
2537 for( var i = ROOT_LIST.length; i; ){
2538 if( ROOT_LIST[ --i ].apiuser === _application ){
2539 currentRootData = ROOT_LIST[ i ];
2544 destroyTree : function( root ){
2545 var data = NodePrivateData.get( root );
2546 MouseEvent.remove( data.apiuser, data.elmMouseCatch, 'mousemove', eventRellay );
2547 body.removeChild( data.elmMouseCatch );
2549 ROOT_LIST.splice( Util.getIndex( ROOT_LIST, data ), 1 );
2550 if( currentRootData === data ){
2551 currentRootData = null;
2552 targetNodeData = null;
2553 forceNodeData = null;
2556 onSystemShutdown : function(){
2559 isNodeInstance : function( node ){
2560 return node instanceof NodeClass;
2562 _getNodePrivateData : function( node ){ // system only
2563 return NodePrivateData.get( node );
2568 var Application = ( function(){
2570 var LIVE_APPLICATION_LIST = [];
2572 var currentApplication = null,
2573 coveredApplication = null,
2577 var ApplicationReference = function( appClass, isOverlay, displayName, id, thumbnailUrl, tailColor ){
2579 var application = null;
2581 this.displayName = displayName;
2582 this.thumbnailUrl = thumbnailUrl;
2583 this.tailColor = tailColor;
2585 function asyncBoot(){
2586 application = Application.boot( appClass, displayName, self.getUID(), isOverlay, Util.copyArray( arguments ) );
2588 this.getUID = function(){
2589 return Util.getIndex( API_USER_LIST, appClass );
2591 this.getDisplayName = function(){
2592 return this.displayName;
2594 this.boot = function( /* _option */ ){
2595 AsyncCall.add( this, asyncBoot, Util.copyArray( arguments ) );
2597 this.shutdown = function(){
2598 if( !application ) return false;
2600 AsyncCall.add( application, ( isOverlay === true ? Overlay.hide : application.close ) );
2604 function asyncBootHome(){
2605 currentApplication === null && Home.boot();
2607 function asyncOpen( /* arguments */ ){
2608 var _arg = Util.copyArray( arguments );
2609 _arg.unshift( winW, winH );
2610 currentApplication.open.apply( currentApplication, _arg );
2613 register: function( _class, _overlay, _tail, _displayName, _id, _thumbnailUrl, _tailColor ){
2614 APPLICATION_LIST.push( _class );
2615 API_USER_LIST.push( _class );
2616 var _ref = new ApplicationReference( _class, _overlay, _displayName, _id, _thumbnailUrl, _tailColor );
2617 _tail === true && Home.add( _ref );
2620 isApplicationInstance: function( app ){
2621 return ApplicationPrivateData.get( app ) !== null;
2623 isApplicationReference: function( _reference ){
2624 return _reference instanceof ApplicationReference;
2626 isCurrentAppplication: function( app ){
2627 return app === currentApplication;
2629 boot: function( appClass, displayName, uid, isOverlay, arg ){
2630 if( currentApplication ){
2631 if( currentApplication.getUID() === uid ) return null;
2632 if( isOverlay === false && currentApplication.close() === false ) return null;
2635 appClass.prototype = new AbstractApplication( appClass, displayName, isOverlay );
2637 var application = new appClass(),
2638 data = ApplicationPrivateData.get( application );
2640 application.rootElement = data.rootElement;
2641 data.application = application;
2643 coveredApplication = isOverlay === true ? currentApplication : null;
2645 Application.onCurrentApplicationChange( application );
2647 if( isOverlay === false ){
2648 body.style.backgroundColor = application.bgColor;
2650 body.appendChild( data.rootElement );
2651 data.rootElement.style.display = 'none';
2654 application.addAsyncCall( asyncOpen, arg );
2656 Overlay.show( application, arg );
2661 shutdown: function( _application, isOverlay ){
2662 if( isOverlay === false ){
2663 currentApplication = null;
2664 AsyncCall.add( SUPER_USER_KEY, asyncBootHome );
2666 Application.onCurrentApplicationChange( coveredApplication );
2667 coveredApplication = null;
2670 onCurrentApplicationChange: function( _application ){
2671 if( Application.isApplicationInstance( _application ) === false ) return;
2672 if( currentApplication === _application ) return;
2673 currentApplication = _application;
2674 MouseEvent.onCurrentApplicationChange( _application );
2675 PointingDeviceEventTree.onCurrentApplicationChange( _application );
2676 KeyEvent.updateCurrentListener( _application );
2677 // InteractiveLayer.onCurrentApplicationChange( _application );
2679 onApplicationShutdown: function( _application ){
2680 LIVE_APPLICATION_LIST.splice( Util.getIndex( LIVE_APPLICATION_LIST, _application ) );
2682 onWindowResize: function( w, h ){
2685 currentApplication && currentApplication.resize( w, h );
2686 Overlay.onWindowResize( w, h );
2687 UI.onWindowResize( w, h );
2689 onSystemShutdown: function(){
2695 /* --------------------------------------------------------------
2699 var Home = ( function(){
2700 var APP_REF_LIST = [];
2701 var ELM_TAIL_ORIGIN = ( function(){
2702 var ret = document.createElement( 'div' ),
2703 h2 = document.createElement( 'h2' );
2704 ret.className = 'tail-wrapper';
2705 ret.appendChild( h2 );
2706 h2.appendChild( document.createTextNode( 'appName' ) );
2710 var TailClass = function( appRef ){
2711 this.elm = ELM_TAIL_ORIGIN.cloneNode( true );
2712 this.destroy = function(){
2713 appRef = self = elmName = null;
2717 elmName = this.elm.getElementsByTagName( 'h2' )[ 0 ].firstChild;
2719 this.elm.style.backgroundColor = appRef.tailColor;
2720 elmName.data = appRef.displayName;
2723 var ref = Application.register( function(){
2728 elmContainer, elmHeader;
2732 for( var i=0, l=APP_REF_LIST.length; i<l; ++i ){
2733 tail = new TailClass( APP_REF_LIST[ i ] );
2734 tailList.push( tail );
2736 elmContainer.appendChild( elm );
2737 self.addEventListener( elm, 'click', onTailClick );
2741 function onTailClick( e ){
2742 var _children = elmContainer.getElementsByTagName( 'div' );
2743 for( var i=0, l=_children.length; i<l; ++i ){
2744 if( this === _children[ i ] ){
2745 APP_REF_LIST[ i ].boot();
2751 this.bgColor = '#0F6D39';
2752 this.MIN_WIDTH = 320;
2753 this.MIN_HEIGHT = 320;
2754 this.onInit = function(){
2755 self.rootElement.id = 'home-root';
2757 elmContainer = document.createElement( 'div' );
2758 self.rootElement.appendChild( elmContainer );
2759 elmContainer.id = 'home-tail-container';
2761 elmHeader = document.createElement( 'div' );
2762 self.rootElement.appendChild( elmHeader );
2763 elmHeader.id = 'home-header';
2765 this.onOpen = function( _w, _h ){
2770 this.onPaneResize = function( _w, _h ){
2773 this.onClose = function(){
2774 self.removeEventListener();
2775 while( tailList.length > 0 ){
2776 tailList.shift().destroy();
2778 self = tailList = elmContainer = null;
2780 }, false, false, 'home', 'home', null );
2783 add: function( _appRef ){
2784 if( Application.isApplicationReference( _appRef ) === false ) return;
2785 Util.getIndex( APP_REF_LIST, _appRef ) === -1 && APP_REF_LIST.push( _appRef );
2793 var Page = ( function(){
2796 ignoreTagList = [ 'script', 'noscript', 'style' ];
2798 var MemoryClass = function( node ){
2801 MemoryClass.prototype = {
2803 var node = this.node,
2804 _nodeType = node.nodeType;
2805 if( _nodeType === 1 && Util.getIndex( ignoreTagList, node.tagName.toLowerCase() ) === -1 ){
2806 this.type = _nodeType;
2807 this.display = node.style.display;
2809 if( _nodeType === 3 ){
2810 if( node.data.replace( /\s/g, '' ).length !== 0 ){
2811 this.type = _nodeType;
2812 this.before = pageNodes.length === 0 ? null : pageNodes[ pageNodes.length - 1 ].node;
2814 body.removeChild( node );
2818 // body.removeChild( node );
2823 if( this.type === 1 ){
2825 this.node.style.display = this.display;
2827 this.node.style.display = '';
2831 body.insertBefore( this.node, this.before );
2833 body.appendChild( this.node );
2838 if( !this.node.parentNode ){
2841 if( this.type === 1 ){
2842 this.node.style.display = 'none';
2844 body.removeChild( this.node );
2850 onReady: function(){
2851 var _children = Util.copyArray( body.childNodes ),
2853 for( var i = 0, l = _children.length; i<l; ++i ){
2854 _mem = new MemoryClass( _children[ i ] );
2855 _mem.init() !== false && pageNodes.push( _mem );
2857 if( pageNodes.length !== 0 ){
2858 if( Type.isFunction( gOS.PageApplicationClass ) === true ){
2859 Page.appClass = gOS.PageApplicationClass;
2860 Page.appClass.bgColor = Page.appClass.bgColor;
2861 Page.appClass.MIN_WIDTH = Page.appClass.MIN_WIDTH || 240;
2862 Page.appClass.MIN_HEIGHT = Page.appClass.MIN_HEIGHT || 240;
2864 Page.appClass = function(){
2867 this.bgColor = '#ffffff';
2868 this.MIN_WIDTH = 200;
2869 this.MIN_HEIGHT = 200;
2870 this.onInit = function(){};
2871 this.onOpen = function( _w, _h ){
2872 KeyEvent.add( self, Const.KEY.EVENT.KEY_DOWN, ref.shutdown, 27 ); // 27.esc
2874 this.onPaneResize = function( _w, _h ){};
2875 this.onClose = function(){};
2878 ref = Application.register( Page.appClass, false, true, document.title, 'page', null, Page.appClass.tailColor || '#999999' );
2879 if( Type.isFunction( gOS.PageApplicationClass ) === true ){
2880 gOS.PageApplicationRef = ref;
2883 delete Page.onReady;
2886 for( var i = pageNodes.length; i; ){
2887 pageNodes[ --i ].show();
2891 for( var i = pageNodes.length; i; ){
2892 pageNodes[ --i ].hide();
2898 registered: function(){
2905 /* --------------------------------------------------------------
2909 * スクリーン座標は、コンピュータのディスプレイの左上を原点とする座標系である。screenX, screenY属性で取得できる。Javascritpでは、同名のプロパティとして実装されている。
2910 * しかし、これは、現実的には、何の役に立たない。ブラウザ自体がディスプレイのどの位置にいるのかがわからないので、画面上の位置を知ったところで、何にもならないからだ。
2913 * ウインドウ座標とは、現在のブラウザのウインドウの、ドキュメントを表示している部分の左上原点とした座標である。
2914 * 問題は、ウインドウは、必ずしもドキュメント全体を表示するとは限らない。スクロールと呼ばれるUIによって、ドキュメントの一部だけを表示しているかもしれない。
2916 var XBrowserEvent = ( function(){
2917 var wrappedHandlerClass,
2921 if( window.addEventListener ){
2922 wrappedHandlerClass = function( ticket ){
2923 this.handler = function( e ){
2924 if( ticket.fire( e ) !== false ) return;
2926 e.stopPropagation();
2929 this.destroy = function(){
2931 delete this.handler;
2932 delete this.destroy;
2936 wrappedEventClass = function( e, element ){
2939 this.target = e.srcElement;
2940 this.currentTarget = element;
2941 this.relatedTarget = e.formElement ? e.formElement : e.toElement;
2942 this.eventPhase = e.srcElement === element ? 2: 3;
2944 this.clientX = e.clientX;
2945 this.clientY = e.clientY;
2946 this.screenX = e.screenX;
2947 this.screenY = e.screenY;
2949 this.keyCode = e.keyCode;
2950 this.altKey = e.altKey;
2951 this.ctrlKey = e.ctrlKey;
2952 this.shiftKey = e.shiftKey;
2954 this.wheelDelta = e.wheelDelta;
2956 wrappedEventClass.prototype.stopPropagation = function(){
2957 this._event.cancelBubble = true;
2959 wrappedEventClass.prototype.preventDefault = function(){
2960 this._event.returnValue = false;
2963 if( document.attachEvent ){
2964 wrappedHandlerClass = function( ticket ){
2965 this.handler = function(){
2966 if( ticket === null ) alert( window.event.type )
2967 if( ticket.fire( new wrappedEventClass( window.event, ticket.element ) ) !== false ) return;
2968 // e.preventDefault();
2969 // e.stopPropagation();
2970 window.event.cancelBubble = true;
2971 window.event.returnValue = false;
2974 this.destroy = function(){
2976 delete this.handler;
2977 delete this.destroy;
2983 find: function( _ticket ){
2984 for( var i=0, l= tmp.list.length, _item; i<l; ++i ){
2985 _item = tmp.list[ i ];
2986 if( _item.element === _ticket.element && _item.eventType === _ticket.eventType ){
2993 tmp.TicketClass = function( _ticket ){
2995 this.element = _ticket.element;
2996 this.eventType = _ticket.eventType;
2997 this.tickets = [ _ticket ];
2998 this.onDestroy = function(){ self = null; };
3000 this.element[ 'on' + this.eventType ] = function( e ){ return self.fire( e );};
3003 tmp.TicketClass.prototype = {
3004 add: function( _ticket ){
3005 Util.getIndex( this.tickets, ticket ) === -1 && this.tickets.push( _ticket );
3007 remove: function( _ticket ){
3008 var i = Util.getIndex( this.tickets, _ticket );
3009 i !== -1 && this.tickets.splice( i, 1 );
3010 this.tickets.length === 0 && this.destroy();
3012 fire: function( e ){
3013 e = e || new wrappedEventClass( window.event, this.element );
3014 var i = this.tickets.length,
3017 if( this.tickets[ --i ].fire( e ) === false ) cancel = false;
3021 destroy: function(){
3023 this.element[ 'on' + this.eventType ] = '';
3024 tmp.list.splice( Util.getIndex( tmp.list, this ), 1 );
3025 delete this.element;
3026 delete this.eventType;
3027 delete this.tickets;
3028 delete this.onDestroy;
3035 add: function( _ticket ){
3036 if( document.addEventListener ){
3037 XBrowserEvent.add = function( _ticket ){
3038 _ticket.wrappedHandler = new wrappedHandlerClass( _ticket );
3039 _ticket.element.addEventListener( _ticket.eventType, _ticket.wrappedHandler.handler, false );
3042 if( document.attachEvent ){
3043 XBrowserEvent.add = function( _ticket ){
3044 _ticket.wrappedHandler = new wrappedHandlerClass( _ticket );
3045 _ticket.element.attachEvent( 'on' + _ticket.eventType, _ticket.wrappedHandler.handler );
3048 XBrowserEvent.add = function( _ticket ){
3049 var t = tmp.find( _ticket );
3053 tmp.list.push( new tmp.TicketClass( _ticket ) );
3058 XBrowserEvent.add( _ticket );
3060 remove: function( _ticket ){
3061 if( document.removeEventListener ){
3062 XBrowserEvent.remove = function( _ticket ){
3063 _ticket.element.removeEventListener( _ticket.eventType, _ticket.wrappedHandler.handler, false );
3064 _ticket.wrappedHandler.destroy();
3067 if( document.detachEvent ){
3068 XBrowserEvent.remove = function( _ticket ){
3069 _ticket.element.detachEvent( 'on' + _ticket.eventType, _ticket.wrappedHandler.handler );
3070 _ticket.wrappedHandler.destroy();
3073 XBrowserEvent.remove = function( _ticket ){
3074 var t = tmp.find( _ticket );
3076 t.remove( _ticket );
3081 XBrowserEvent.remove( _ticket );
3089 var EventTicketClass = function( _element, _eventType, _handler, opt_thisObject ){
3090 this.element = _element;
3091 this.eventType = _eventType;
3092 this.handler = _handler;
3093 this.wrappedHandler = null;
3094 this.thisObject = opt_thisObject;
3095 XBrowserEvent.add( this );
3097 EventTicketClass.prototype = {
3098 fire : ( function(){
3099 if( Function.prototype.call ){
3100 return function( e ){
3101 return this.handler.call( this.thisObject || this.element, e );
3104 return function( e ){
3105 var thisObj = this.thisObject || this.element,
3107 thisObj._currentHandler = this.handler;
3108 ret = thisObj._currentHandler( e );
3109 delete thisObj._currentHandler;
3113 match: function( _element, _eventType, _handler ){
3114 if( _handler && _handler !== this.handler ) return false;
3115 if( _eventType && _eventType !== this.eventType ) return false;
3116 if( _element && _element !== this.element ) return false;
3120 destroy: function( _element, _eventType, _handler ){
3121 if( this.match( _element, _eventType, _handler ) === false ) return false;
3123 XBrowserEvent.remove( this );
3125 delete this.element;
3126 delete this.eventType;
3127 delete this.handler;
3128 delete this.wrappedHandler;
3129 delete this.thisObject;
3134 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, i;
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;
3992 for( var i = 0; i < TICKET_LIST.length; ){
3993 t = TICKET_LIST[ i ];
3994 if( t.destroy( _apiuser, _url ) === true ){
3995 TICKET_LIST.splice( i, 1 );
4000 if( TICKET_LIST.length === 0 ){
4001 SystemTimer.remove( SUPER_USER_KEY, checkTimer );
4017 var Image = ( function(){
4020 * FetchClass original is
4023 * URL: http://d.hatena.ne.jp/uupaa/20080413/1208067631
4024 * AUTHOR: uupaa.js@gmail.com
4028 for( var i=0, t; i < TASK_LIST.length; ){
4030 if( t.complete() === true ){
4031 TASK_LIST.splice( i, 1 );
4036 TASK_LIST.length === 0 && SystemTimer.remove( SUPER_USER_KEY, detect );
4038 function getTask( img ){
4039 for( var i = TASK_LIST.length; i; ){
4040 if( TASK_LIST[ --i ].img === img ) return TASK_LIST[ i ];
4044 var task = getTask( this );
4045 if( task.finish === true ) return;
4047 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
4050 // if( finish === true ) return; // これがあると firefox3.6 で駄目、、、
4051 // if( timer ) return; // これがあると safari3.2 で駄目、、、
4052 var task = getTask( this );
4054 TASK_LIST.splice( Util.getIndex( TASK_LIST, task ), 1 );
4055 if( window.opera && !task.img.complete ){
4056 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
4059 task.size = Util.getImageSize( this );
4060 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
4064 var FetchClass = function( apiuser, abspath, onLoadCallback, onErrorCallback, timeout ){
4065 this.apiuser = apiuser;
4066 this.abspath = abspath;
4067 this.onLoadCallback = onLoadCallback;
4068 this.onErrorCallback = onErrorCallback;
4069 this.timeout = timeout;
4072 FetchClass.prototype = {
4078 var img = this.img = document.createElement( 'img' ); //var img = new Image(); ではieでimgのsizeが取れない、、、removeChildも失敗し、imgSizeGetterにimgが残る
4079 img.onabort = img.onerror = onError;
4080 img.onload = onLoad;
4081 img.src = this.abspath;
4083 complete: function(){
4084 if( this.finish === true ) return true;
4085 if( this.img.complete ){
4087 if( this.img.width ) return true;
4088 AsyncCall.add( this.apiuser, this.asyncCallback, null, this );
4091 if( ( this.tick += 250 ) > this.timeout ){
4093 AsyncCall.add( this.apiuser, this.asyncCallback, null, this );
4097 asyncCallback: function(){
4098 this.size ? this.onLoadCallback( this.abspath, this.size.width, this.size.height ) : this.onErrorCallback( this.abspath );
4101 destroy: function(){
4103 this.img.src = this.img.onload = this.img.onabort = this.img.onerror = '';
4106 delete this.onLoadCallback;
4107 delete this.onErrorCallback;
4110 timer !== null && window.clearTimeout( timer );
4116 load: function( URLorELM, onLoad, onError, opt_timeout ){
4118 if( Type.isString( URLorELM ) === true ){
4121 if( Type.isHTMLElement( URLorELM ) === true && URLorELM.tagName.toLowerCase() === 'img' ){
4127 fetch = new FetchClass(
4128 Util.getAbsolutePath( src ),
4130 Type.isFinite( opt_timeout ) === true ? opt_timeout : undefined
4132 TASK_LIST.push( fetch );
4134 SystemTimer.add( SUPER_USER_KEY, detect, 250 );
4136 unload: function( ){
4143 /* ----------------------------------------
4147 var Overlay = ( function(){
4148 var elmContainer, elmShadow, elmCloseButton,
4155 function onCloseClick( e ){
4159 function asyncInit( /* arguments */ ){
4161 //application.rootElement.style.display = 'none';
4163 elmContainer.style.cssText = "top:" + body.scrollTop + 'px;display:none;';
4164 $( elmContainer ).stop().fadeIn( onFadeInComplete );
4166 function asyncOpen( /* arguments */ ){
4171 function onFadeInComplete(){
4172 KeyEvent.add( application, Const.KEY.EVENT.KEY_DOWN, Overlay.hide, 27 ); // 27.esc
4173 MouseEvent.add( application, elmCloseButton, 'click', onCloseClick );
4175 var _arg = bootParams; //Util.copyArray( arguments );
4176 _arg.unshift( windowW, windowH );
4177 application.open.apply( application, _arg );
4179 function onFadeOutComplete(){
4180 Util.removeAllChildren( elmContainer );
4181 body.removeChild( elmContainer );
4182 elmContainer = elmShadow = elmCloseButton = null;
4185 show: function( _application, _bootParams ){
4186 if( visible === true && application === _application ) return;
4187 if( Application.isApplicationInstance( _application ) === false ) return;
4189 elmContainer = document.createElement( 'div' );
4190 body.appendChild( elmContainer );
4192 elmContainer.id = 'overlay-container';
4194 bodyOverflow = body.style.overflow;
4195 body.style.overflow = 'hidden';
4197 elmShadow = document.createElement( 'div' );
4198 elmContainer.appendChild( elmShadow );
4199 elmShadow.id = 'overlay-shadow';
4201 elmCloseButton = document.createElement( 'div' );
4202 elmContainer.appendChild( elmCloseButton );
4203 elmCloseButton.id = 'overlay-close-button';
4204 elmCloseButton.appendChild( document.createTextNode( 'x' ) );
4206 elmContainer.style.display = 'none'; // hide for fadeIn
4209 application = _application;
4212 elmContainer.insertBefore( application.rootElement, elmCloseButton );
4213 _application.addAsyncCall( asyncInit );
4214 // _application.addAsyncCall( asyncOpen, );
4216 bootParams = _bootParams;
4219 if( visible === false ) return;
4220 if( application.close() === false ) return false;
4222 body.style.overflow = bodyOverflow;
4224 $( elmContainer ).stop().css( {
4227 }).fadeOut( onFadeOutComplete );
4232 onWindowResize: function( _windowW, _windowH ){
4236 if( application === null ) return;
4238 elmContainer.style.height = _windowH + 'px';
4239 elmContainer.style.top = body.scrollTop + 'px';
4241 elmShadow.style.height = _windowH + 'px';
4243 AsyncCall.add( application, application.resize, [ _windowW, _windowH ] );
4248 /* ----------------------------------------
4252 * form -> overlay -> view
4256 var UI = ( function(){
4265 var CLASSNAME_COMBOBOX_OPTION = 'combobox-option',
4266 CLASSNAME_COMBOBOX_OPTION_CURRENT = CLASSNAME_COMBOBOX_OPTION + ' combobox-option-current',
4267 ELM_COMBOBOX = ( function(){
4268 var ret = document.createElement( 'a' ),
4269 elmToggle = document.createElement( 'span' ),
4270 elmValue = document.createElement( 'span' );
4272 ret.appendChild( elmToggle );
4273 ret.appendChild( elmValue );
4274 elmToggle.className = 'combobox-toggle';
4275 elmValue.className = 'combobox-value';
4277 elmToggle.appendChild( document.createTextNode( '▼' ));
4278 elmValue.appendChild( document.createTextNode( 'null' ));
4282 var UIItemPrivateData = function(){};
4283 UIItemPrivateData.prototype = {
4301 init : function( groupData, item, elm, value, onUpdate, validator, focus, visible, enabled ){
4302 this.groupData = groupData;
4306 this.onUpdate = onUpdate;
4307 this.validator = validator;
4308 this.focus = !!focus;
4309 this.visible = !!visible;
4310 this.enabled = !!enabled;
4311 UIItemPrivateData.list.push( this );
4313 destroy : function(){
4314 var list = UIItemPrivateData.list;
4315 list.splice( Util.getIndex( list, this ), 1 );
4317 list = this.groupData.itemList;
4318 var i = Util.getIndex( list, this.item );
4319 i !== -1 && list.splice( i, 1 );
4321 this.node && this.node.remove();
4324 UIItemPrivateData.list = [];
4325 UIItemPrivateData.get = function( item ){
4326 var list = UIItemPrivateData.list;
4327 for( i = list.length; i; ){
4328 if( list[ --i ].item === item ) return list[ i ];
4333 /* --------------------------------
4336 var TextInputManager = ( function(){
4337 var elmInput = ( function(){
4338 var ret = document.createElement( 'input' );
4340 ret.id = 'ui-textinput';
4345 function updateWrapperPosition(){
4346 var p = Position.cumulativeOffset( currentData.elmValue ),
4347 w = currentData.elmValue.offsetWidth - 2,
4349 elmInput.style.cssText = [
4350 'left:', p[ 0 ], 'px;',
4351 'top:', p[ 1 ], 'px;',//,
4352 'width:', w, 'px;'//,
4353 //'height:', data.elmValue.offsetHeight, 'px;',
4354 //'position:absolute;'
4357 //_w = elmInput.offsetWidth;
4358 //if( w !== _w ) elmInput.style.width = ( w - ( _w - w ) ) + 'px;';
4362 show: function( data ){
4363 // this.groupData.node.addEventListener( 'mouseout' );
4366 body.appendChild( elmInput );
4367 elmInput.value = data.value;
4368 updateWrapperPosition();
4373 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4375 hide : function( data ){
4376 if( currentData !== data ) return;
4378 body.removeChild( elmInput );
4379 var ret = elmInput.value;
4380 elmInput.value = '';
4381 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition );
4384 update : function( data ){
4385 elmInput.value = data.value;
4387 onWindowResize: function( _w, _h ){
4388 AsyncCall.add( currentUser, updateWrapperPosition );
4393 var TextInputClass = function( groupData, elmWrapper, elmValue, onUpdate, validater ){
4394 var data = new UIItemPrivateData();
4395 data.init( groupData, this, elmWrapper, elmValue.innerHTML, onUpdate, validater, false, true, true );
4396 Util.addClass( elmValue, 'editable-text' );
4397 data.elmValue = elmValue;
4398 this.value( data.value );
4399 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-inpittext-hover', 'pointer' );
4400 data.node.addEventListener( 'click', this.focus, this );
4401 //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', instance.focus );
4403 TextInputClass.prototype = {
4404 value : function( value ){
4405 var data = UIItemPrivateData.get( this );
4406 if( Type.isString( value ) === true || Type.isNumber( value ) === true ){
4407 data.elmValue.innerHTML = data.value = '' + value;
4408 data.focus === true && TextInputManager.update( data );
4410 data.focus === true && this.blur();
4413 focus : function( e ){
4414 var data = UIItemPrivateData.get( this );
4417 TextInputManager.show( data );
4420 blur : function( keep ){
4421 var data = UIItemPrivateData.get( this ),
4423 if( data.focus === false ) return;
4424 newValue = TextInputManager.hide( data );
4425 newValue = keep !== 27 ? ( data.validater ? '' + data.validater( newValue ) : newValue ) : data.value; // 27:ESC
4427 data.elmValue.innerHTML = newValue;
4429 data.onUpdate && newValue !== data.value && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ newValue, data.value ], this );
4431 data.value = newValue;
4435 enabled : function( v ){
4436 var data = UIItemPrivateData.get( this );
4437 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4438 Util.toggleClass( data.elm, 'ui-textinput-disabled', !v );
4439 if( data.focus === true && v === false ) this.blur();
4441 data.node.disabled( !( data.visible && v ) );
4443 return data.enabled;
4445 visible : function( v ){
4446 var data = UIItemPrivateData.get( this );
4447 if( Type.isBoolean( v ) === true && data.visible !== v ){
4448 data.elm.style.display = v ? '' : 'none';
4449 if( data.focus === true && v === false ) this.blur();
4451 data.node.disabled( !( data.enabled && v ) );
4453 return data.visible;
4455 destroy : function(){
4456 var data = UIItemPrivateData.get( this );
4457 data.focus === true && TextInputManager.hide( data );
4462 /* --------------------------------
4465 var FileInputManager = ( function(){
4472 function updateWrapperPosition(){
4473 var p = Position.cumulativeOffset( currentData.elmValue ),
4474 w = currentData.elmValue.offsetWidth,
4476 elmWrap.style.cssText = [
4477 'left:', p[ 0 ], 'px;',
4478 'top:', p[ 1 ], 'px;',//,
4479 'width:', w, 'px;'//,
4480 //'height:', data.elmValue.offsetHeight, 'px;',
4481 //'position:absolute;'
4484 _w = elmWrap.offsetWidth;
4485 if( w !== _w ) elmWrap.style.width = ( w - ( _w - w ) ) + 'px';
4488 function change( e ){
4489 var data = currentData,
4490 file = data.elmFileInputReal.value;
4491 file = file.split( '\\' );
4492 file = file[ file.length - 1 ];
4493 if( data.value !== file ){
4494 data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ file, data.value ], this );
4495 data.elmValue.innerHTML = data.value = file;
4497 currentData.item.blur();
4499 function asyncMouseout(){
4500 currentData && currentData.item.blur();
4503 MouseEvent.remove( currentUser, elmFileInput, 'mouseout', asyncMouseout );
4504 MouseEvent.remove( currentUser, elmFileInput, 'click', onClick );
4507 show : function( data ){
4510 elmFileInput = data.elmFileInputReal;
4511 elmWrap = elmFileInput.parentNode;
4514 updateWrapperPosition();
4515 elmFileInput.focus();
4516 //data.node.addEventListener( 'change', change, data );
4517 evt = new EventTicketClass( elmFileInput, 'change', change );
4518 MouseEvent.add( currentUser, elmFileInput, 'mouseout', asyncMouseout );
4519 MouseEvent.add( currentUser, elmFileInput, 'click', onClick );
4520 // currentData.elmFileInputReal.onchange = change;
4521 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4523 hide : function( data ){
4524 if( currentData !== data ) return;
4525 // data.node.removeEventListener( 'change', change );
4527 // MouseEvent.remove( currentUser, elmFileInput, 'mouseout', asyncMouseout );
4529 //currentData.elmFileInputReal.onchange = null;
4530 elmWrap.style.display = 'none';
4531 currentData = elmFileInput = null;
4532 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition );
4534 onWindowResize: function( _w, _h ){
4535 AsyncCall.add( currentUser, updateWrapperPosition );
4540 var FileInputClass = function( groupData, elmWrapper, onUpdate, validater, elmFileInputReal, elmValue ){
4541 var data = new UIItemPrivateData();
4542 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4543 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-fileinput-hover', 'pointer' );
4544 data.elmValue = elmValue;
4545 data.elmFileInputReal = elmFileInputReal;
4546 data.node.addEventListener( 'mouseover', this.focus, this );
4548 FileInputClass.prototype = {
4553 var data = UIItemPrivateData.get( this );
4555 Util.addClass( data.elm, 'fileinput-has-focus' );
4557 FileInputManager.show( data );
4559 blur : function( keyCode ){
4560 var data = UIItemPrivateData.get( this );
4561 Util.removeClass( data.elm, 'fileinput-has-focus' );
4563 FileInputManager.hide( data );
4566 enabled : function( v ){
4567 var data = UIItemPrivateData.get( this );
4568 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4569 if( data.focus === true && v === false ) this.blur();
4570 Util.toggleClass( data.elm, 'fileinput-disabled', !v );
4572 data.node.disabled( !( data.visible && v ) );
4574 return data.enabled;
4576 visible : function( v ){
4577 var data = UIItemPrivateData.get( this );
4578 if( Type.isBoolean( v ) === true && data.visible !== v ){
4579 if( data.focus === true && v === false ) this.blur();
4580 data.elm.style.display = v ? '' : 'none';
4582 data.node.disabled( !( data.enabled && v ) );
4584 return data.visible;
4586 destroy : function(){
4587 var data = UIItemPrivateData.get( this );
4588 data.focus === true && FileInputManager.hide( data );
4593 var ButtonClass = function( groupData, elmWrapper, onUpdate ){
4594 var data = new UIItemPrivateData();
4595 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4596 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-button-hover', 'pointer' );
4597 data.node.addEventListener( 'click', onUpdate );
4598 //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', onUpdate );
4600 ButtonClass.prototype = {
4602 var data = UIItemPrivateData.get( this );
4604 Util.addClass( data.elm, 'button-has-focus' );
4607 blur : function( keyCode ){
4608 var data = UIItemPrivateData.get( this );
4609 keyCode === 13 && data.onUpdate && data.onUpdate();
4610 Util.removeClass( data.elm, 'button-has-focus' );
4614 enabled : function( v ){
4615 var data = UIItemPrivateData.get( this );
4616 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4617 Util.toggleClass( data.elm, 'button-disabled', !v );
4619 data.node.disabled( !( data.visible && v ) );
4621 return data.enabled;
4623 visible : function( v ){
4624 var data = UIItemPrivateData.get( this );
4625 if( Type.isBoolean( v ) === true && data.visible !== v ){
4626 data.elm.style.display = v ? '' : 'none';
4628 data.node.disabled( !( data.enabled && v ) );
4630 return data.visible;
4632 destroy : function(){
4633 var data = UIItemPrivateData.get( this );
4634 // MouseEvent.remove( data.groupData.apiuser, data.elm );
4639 var ComboBoxClass = function( groupData, elmWrapper, onUpdate ){
4640 var elmA = ELM_COMBOBOX.cloneNode( true ),
4641 data = new UIItemPrivateData();
4642 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4644 data.elmBox = Util.getElementsByClassName( elmWrapper, 'combobox' )[ 0 ];
4645 data.elmBox.appendChild( elmA );
4647 data.elmToggle = Util.getElementsByClassName( elmA, 'combobox-toggle' )[ 0 ];
4648 data.elmValue = Util.getElementsByClassName( elmA, 'combobox-value' )[ 0 ].firstChild;
4649 data.selectIndex = 0;
4650 data.optionList = [];
4652 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-combobox-hover', 'pointer' );
4653 data.node.addEventListener( 'click', this.focus, this );
4655 ComboBoxClass.prototype = {
4656 focus : function( e ){
4657 var data = UIItemPrivateData.get( this );
4658 data.node.removeEventListener( 'click', this.focus );
4660 data.elmA.className = 'combobox-has-focus';
4662 OptionControl.show( data );
4665 blur : function( keyCode ){
4666 var data = UIItemPrivateData.get( this );
4667 OptionControl.hide( this );
4669 data.elmA.className = '';
4671 data.node.addEventListener( 'click', this.focus, this );
4673 enabled : function( v ){
4674 var data = UIItemPrivateData.get( this );
4675 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4676 Util.toggleClass( data.elm, 'ui-combobox-disabled', !v );
4677 if( data.focus === true && v === false ) this.blur();
4679 data.node.disabled( !( data.visible && v ) );
4681 return data.enabled;
4683 visible : function( v ){
4684 var data = UIItemPrivateData.get( this );
4685 if( Type.isBoolean( v ) === true && data.visible !== v ){
4686 data.elm.style.display = v ? '' : 'none';
4687 if( data.focus === true && v === false ) this.blur();
4689 data.node.disabled( !( data.enabled && v ) );
4691 return data.visible;
4693 value : function( _value ){
4694 var data = UIItemPrivateData.get( this ),
4696 list = data.optionList,
4699 if( Type.isString( _value ) === true && data.value !== _value ){
4700 for( ; i < l; ++i ){
4701 _option = list[ i ];
4702 if( _value === _option.value ){
4703 data.value = _value;
4705 data.elmValue.data = _option.displayValue;
4706 if( data.focus === true ){
4707 OptionControl.update( this, _value );
4709 data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, _value, this );
4716 selectIndex : function(){
4717 var data = UIItemPrivateData.get( this );
4718 return data.selectIndex;
4720 createOption : function( _displayValue, _value, _isSelected ){
4721 var data = UIItemPrivateData.get( this ),
4723 list = data.optionList,
4726 _value = _value || _displayValue;
4727 _isSelected = !!_isSelected;
4729 _option = list[ --i ];
4730 if( _value === _option.value ){
4735 if( _isSelected === true ){
4736 data.selectIndex = list.length;
4737 data.elmValue.data = _displayValue;
4739 option === null && list.push( new OptionDataClass( _displayValue, _value, _isSelected ) );
4741 destroy : function(){
4742 var data = UIItemPrivateData.get( this );
4743 data.focus === true && OptionControl.hide( this );
4745 // MouseEvent.remove( data.groupData.apiuser, data.elm );
4746 data.optionList.length = 0;
4750 var OptionDataClass = function( displayValue, value, isCurrent ){
4751 this.displayValue = displayValue;
4752 this.value = value || displayValue;
4753 this.current = isCurrent;
4754 displayValue = value = null;
4757 var OptionControl = ( function(){
4758 var ELM_OPTION_WRAPPER = ( function(){
4759 var ret = document.createElement( 'div' );
4760 ret.className = 'option-container';
4763 ELM_OPTION_ORIGIN = ( function(){
4764 var ret = document.createElement( 'a' );
4765 ret.appendChild( document.createTextNode( 'option' ) );
4770 var OptionClass = function( option ){
4771 this.elm = ELM_OPTION_ORIGIN.cloneNode( true );
4775 OptionClass.prototype = {
4777 ELM_OPTION_WRAPPER.appendChild( this.elm );
4778 this.elm.firstChild.data = this.data.displayValue;
4779 this.current( this.data.current );
4780 MouseEvent.add( SUPER_USER_KEY, this.elm, 'mousedown', onOptionSelect );// onclick では 選択ボックス 隠すように body に設定した onmouseup が先に動いてしまう!
4782 current: function( _current ){
4783 this.elm.className = _current === true ? CLASSNAME_COMBOBOX_OPTION_CURRENT : CLASSNAME_COMBOBOX_OPTION;
4784 this.data.current = _current;
4785 currentOption = _current === true ? this : currentOption;
4787 destroy: function(){
4788 MouseEvent.remove( SUPER_USER_KEY, this.elm );
4789 Util.removeAllChildren( this.elm );
4790 ELM_OPTION_WRAPPER.removeChild( this.elm );
4796 function onOptionSelect( e ){
4798 l = OPTION_LIST.length,
4800 for( ; i < l; ++i ){
4801 _option = OPTION_LIST[ i ];
4802 if( this === _option.elm ){
4803 updateCurrrentOption( _option.data.value, true );
4804 currentCombobox.blur();
4811 var OPTION_LIST = [],
4812 currentCombobox = null,
4818 function updateCurrrentOption( _value, _updateCombobox ){
4820 i = OPTION_LIST.length;
4822 _option = OPTION_LIST[ --i ];
4823 if( _value === _option.data.value ){
4824 currentOption && currentOption.current( false );
4825 _option.current( true );
4826 currentOption = _option;
4828 _updateCombobox === true && currentCombobox.value( _value );
4833 function bodyMouseupHandler(){
4834 currentCombobox.blur();
4835 OptionControl.hide( currentCombobox );
4837 function updateWrapperPosition(){
4838 var position = Util.getAbsolutePosition( elm );
4840 ELM_OPTION_WRAPPER.style.cssText = [
4841 'width:', elm.offsetWidth - 2, 'px;',
4842 'left:', position.x, 'px;',
4843 'top:', position.y + elm.offsetHeight, 'px;'
4846 function change( e ){
4847 var l = OPTION_LIST.length,
4848 i = currentIndex + ( e.keyCode === 40 ? -1 : 1 );
4849 if( currentCombobox === null || l < 2 ) return;
4853 updateCurrrentOption( OPTION_LIST[ i ].data.value, true );
4857 show: function( data ){
4858 var combobox = data.item,
4859 list = data.optionList,
4862 if( currentItem !== combobox || currentCombobox === combobox ) return;
4863 currentCombobox && currentCombobox.blur();
4865 apiuser = data.groupData.apiuser;
4866 currentCombobox = combobox;
4869 for( ; i < l; ++i ){
4870 OPTION_LIST.unshift( new OptionClass( list[ i ] ) );
4872 MouseEvent.add( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler );
4873 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 38 );
4874 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 40 );
4875 //KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter, 13 );
4876 //KeyEvent.updateCurrentListener( SUPER_USER_KEY );
4878 body.appendChild( ELM_OPTION_WRAPPER );
4880 updateCurrrentOption( combobox.value(), false );
4881 updateWrapperPosition();
4883 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4885 hide: function( _combobox ){
4886 if( currentCombobox !== _combobox || currentCombobox === null ) return;
4889 while( _option = OPTION_LIST.shift() ){
4893 body.removeChild( ELM_OPTION_WRAPPER );
4895 MouseEvent.remove( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler );
4896 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change );
4897 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change );
4898 //KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter );
4899 //KeyEvent.updateCurrentListener( apiuser );
4901 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition, 500 );
4904 currentCombobox = null;
4905 currentOption = null;
4908 onEnter: function(){
4909 currentCombobox.value( currentOption.data.value );
4910 //currentCombobox.blur();
4911 //OptionControl.hide( currentCombobox );
4913 update: function( data, _value ){
4914 if( currentCombobox !== data.item || currentItem !== data.item ) return;
4915 if( currentOption.data.value === _value ) return;
4916 updateCurrrentOption( _value, true );
4918 onWindowResize: function( _w, _h ){
4919 currentCombobox && AsyncCall.add( apiuser, updateWrapperPosition );
4924 var UIGroupPrivateData = function(){};
4925 UIGroupPrivateData.prototype = {
4932 init : function( apiuser, node, uigroup ){
4933 this.apiuser = apiuser;
4935 this.uigroup = uigroup;
4937 UIGroupPrivateData.list.push( this );
4939 destroy : function(){
4943 UIGroupPrivateData.list = [];
4944 UIGroupPrivateData.get = function( uigroup ){
4945 var list = UIGroupPrivateData.list,
4948 if( list[ --i ].uigroup === uigroup ) return list[ i ];
4953 var UIGroupClass = function( apiuser, node ){
4954 ( new UIGroupPrivateData() ).init( apiuser, node, this );
4956 UIGroupClass.prototype = {
4957 focus : function( _value ){
4958 var data = UIGroupPrivateData.get( this );
4960 if( _value === true ){
4962 start( apiuser, self, currentItem );
4964 if( itemList.length > 0 ){
4965 start( apiuser, self, itemList[ 0 ] );
4968 if( _value === false ){
4969 finish( apiuser, self, currentItem );
4972 if( _value && Util.getIndex( data.itemList, _value ) !== -1 ){
4973 // currentItem = _value;
4974 currentList = data.itemList;
4976 return currentUi === this;
4979 var data = UIGroupPrivateData.get( this );
4980 if( currentList === data.itemList ){
4984 createInputText : function( elmWrapper, onUpdate, validater ){
4985 var data = UIGroupPrivateData.get( this ),
4986 elmValue = Util.getElementsByClassName( elmWrapper, 'editable-value' )[ 0 ],
4989 ret = new TextInputClass( data, elmWrapper, elmValue, onUpdate, validater );
4990 data.itemList.push( ret );
4993 alert( 'error createInputText' );
4995 createButton : function( elm, onClick ){
4996 var data = UIGroupPrivateData.get( this ),
4997 ret = new ButtonClass( data, elm, onClick );
4998 data.itemList.push( ret );
5001 createFileInput : function( elm, onUpdate, validater, elmFileInputReal ){
5002 var data = UIGroupPrivateData.get( this ),
5003 elmValue = Util.getElementsByClassName( elm, 'fileinput-value' )[ 0 ],
5006 ret = new FileInputClass( data, elm, onUpdate, validater, elmFileInputReal, elmValue );
5007 data.itemList.push( ret );
5012 createCombobox : function( elm, onUpdate, optionList ){
5013 var data = UIGroupPrivateData.get( this ),
5014 ret = new ComboBoxClass( data, elm, onUpdate, optionList );
5015 data.itemList.push( ret );
5018 createCheckBox : function(){
5021 createRadio : function(){
5024 createSlider : function(){
5027 visible : function( v ){
5028 var data = UIGroupPrivateData.get( this );
5029 if( Type.isBoolean( v ) === true && data.visible !== v ){
5030 for( var i = data.itemList.length; i; ){
5031 data.itemList[ --i ].visible( v );
5034 data.node.disabled( !( data.enabled && v ) );
5036 return data.visible;
5038 enabled : function( v ){
5039 var data = UIGroupPrivateData.get( this );
5040 if( Type.isBoolean( v ) === true && data.enabled !== v ){
5041 for( var i = data.itemList.length; i; ){
5042 data.itemList[ --i ].enabled( v );
5045 data.node.disabled( !( data.visible && v ) );
5047 return data.enabled;
5049 destroy : function(){
5050 var data = UIGroupPrivateData.get( this ),
5052 if( currentUi === this ){
5054 // finish( UIItemPrivateData.get( currentItem ) );
5056 while( _item = data.itemList.shift() ){
5063 function start( data ){
5064 if( currentItem !== data.item ){
5065 currentUi !== data.groupData.uigroup && currentUi && currentUi.blur();
5067 currentItem !== null && currentItem.blur();
5069 currentUser = data.groupData.apiuser;
5070 currentUi = data.groupData.uigroup;
5071 currentItem = data.item;
5073 currentUi.focus( currentItem );
5075 // if( currentUser !== _apiuser ) {
5076 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 );
5077 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 );
5078 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 9 );
5079 KeyEvent.updateCurrentListener( SUPER_USER_KEY );
5083 function finish( data ){
5084 if( currentItem === data.item ){
5092 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 );
5093 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 );
5094 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 9 );
5095 KeyEvent.updateCurrentListener( data.groupData.apiuser );
5099 function onKeyDown( e ){
5100 if( currentItem === null ) return true;
5101 var keyCode = e.keyCode,
5102 index = Util.getIndex( currentList, currentItem );
5103 if( keyCode === 13 || keyCode === 27 || keyCode === 9 || keyCode === 18 || e.altKey === true ){ // 13.return 27.esc 9.tab 18.alt
5104 keyCode === 9 && tabShift( index, e.shiftKey === true ? -1 : 1 );
5105 keyCode === 13 && currentItem instanceof ComboBoxClass && OptionControl.onEnter();
5106 keyCode === 13 && tabShift( index, 1 );
5107 currentItem && currentItem.blur( keyCode );
5112 function tabShift( index, way ){
5113 var l = currentList.length,
5117 while( i !== index ){
5120 i < l ? i : 0; // 0 < i < l
5121 item = currentList[ i ];
5122 if( item.enabled() === true && item.visible() === true ){
5123 AsyncCall.add( currentUser, item.focus, null, item );
5131 createUIGroup: function( apiuser, node ){
5132 var uid = apiuser.getUID(),
5133 list = UI_LIST[ uid ],
5134 ui = new UIGroupClass( apiuser, node );
5135 if( Type.isArray( list ) === false ){
5136 list = UI_LIST[ uid ] = [];
5141 onWindowResize: function( w, h ){
5144 currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h );
5145 currentItem instanceof TextInputClass && TextInputManager.onWindowResize( w, h );
5146 currentItem instanceof FileInputClass && FileInputManager.onWindowResize( w, h );
5148 onCurrentApplicationChange: function( _apiuser ){
5149 currentList = UI_LIST[ _apiuser.getUID() ];
5151 onApplicationShutdown: function( _apiuser ){
5152 KeyEvent.remove( _apiuser );
5154 onSystemShutdown: function(){
5160 var UIForm = ( function(){
5162 var CLASSNAME_FORM = 'uiform-invisible';
5163 var CLASSNAME_FILE_WRAP = 'ui-fileinput-wrapper';
5164 var FormItemData = function(){};
5165 var windowW, windowH;
5166 FormItemData.prototype = {
5169 init : function( formData, uiItem ){
5170 this.formData = formData;
5171 this.uiItem = uiItem;
5173 onUpdate : function( v ){
5174 // var index = Util.getIndex( this.formData.itemList, this );
5178 var FormPrivateData = function(){};
5179 FormPrivateData.prototype = {
5187 init : function( apiuser, from, node, elm, elmForm ){
5188 this.apiuser = apiuser;
5190 this.ui = apiuser.createUIGroup( node );
5193 this.elmForm = elmForm;
5195 elmForm.className = CLASSNAME_FORM;
5196 FormPrivateData.list.push( this );
5198 var forms = Util.copyArray( elmForm.getElementsByTagName( '*' ) ),
5201 items = 'input,select,textarea,button',
5202 form, data, el, wrap;
5205 if( form.nodeType !== 1 ) continue;
5206 switch( form.tagName.toLowerCase() ){
5208 switch( form.type.toLowerCase() ){
5212 el = document.createElement( 'div' );
5213 el.className = 'uiform-file-container';
5214 el.appendChild( document.createElement( 'div' ) );
5215 el.appendChild( document.createElement( 'div' ) );
5216 el.firstChild.className = 'uiform-label';
5217 el.lastChild.className = 'uiform-file fileinput-value';
5218 // opera9 don't work for opera9;
5219 //el = Util.pullHtmlAsTemplete( '<div class="uiform-file-container"><div class="uiform-label"></div><div class="uiform-file fileinput-value"></div></div>' );
5220 elm.appendChild( el );
5221 data = new FormItemData();
5222 wrap = document.createElement( 'div' );
5223 form.parentNode.insertBefore( wrap, form );
5224 wrap.className = CLASSNAME_FILE_WRAP;
5225 wrap.appendChild( form );
5226 data.init( this, this.ui.createFileInput( el, data.onUpdate, null, form ) );
5227 this.itemList.push( data );
5246 destroy : function(){
5250 FormPrivateData.list = [];
5251 FormPrivateData.get = function( from ){
5252 var list = FormPrivateData.list,
5255 if( list[ --i ].form === form ) return list[ i ];
5260 var FormClass = function( apiuser, node, elm, elmForm ){
5261 ( new FormPrivateData() ).init( apiuser, this, node, elm, elmForm );
5263 FormClass.prototype = {
5264 createTextInput : function(){
5267 createMultiLineInput : function(){
5270 createFileInput : function(){
5273 createButton : function(){
5276 createComboBox : function(){
5279 submit : function(){
5285 createForm: function( apiuser, nodeOrElm, opt_elmForm ){
5286 var uid = apiuser.getUID(),
5287 list = FORM_LIST[ uid ],
5289 if( PointingDeviceEventTree.isNodeInstance( nodeOrElm ) === true ){
5291 elm = PointingDeviceEventTree._getNodePrivateData( nodeOrElm ).elm;
5293 // App が eventTree を持っている?
5294 // App が eventTree を持っていない
5297 form = new FormClass( apiuser, node, elm, opt_elmForm );
5298 if( Type.isArray( list ) === false ){
5299 list = FORM_LIST[ uid ] = [];
5304 onWindowResize: function( w, h ){
5307 currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h );
5308 currentItem instanceof TextInputClass && TextInputManager.onWindowResize( w, h );
5309 currentItem instanceof FileInputClass && FileInputManager.onWindowResize( w, h );
5311 onCurrentApplicationChange: function( _apiuser ){
5313 onApplicationShutdown: function( _apiuser ){
5315 onSystemShutdown: function(){
5321 var Finder = ( function(){
5322 var FINDER_LIST = [],
5323 ELM_ORIGIN_LOCATION_ITEM = Util.pullHtmlAsTemplete( '<div class="finder-location-item"></div>' ),
5324 HTML_FINDER_ICON = ( function(){
5325 return ( UA.isIE === true && UA.ieVersion < 8 ?
5327 '<div class="finder-icon fnder-icon-ie7">',
5328 '<div class="finder-icon-handle"></div>',
5329 '<div class="file-icon"><div></div></div>',
5330 '<span class="finder-icon-cell finder-icon-ie-filename">',
5331 '<span class="finder-icon-vertical-middle-outer">',
5332 '<span class="finder-icon-vertical-middle-inner">',
5333 '<span class="finder-icon-filename break-word">file name</span>',
5337 '<span class="finder-icon-cell finder-icon-ie-summary">',
5338 '<span class="finder-icon-vertical-middle-outer">',
5339 '<span class="finder-icon-vertical-middle-inner">',
5340 '<span class="finder-icon-summary break-word">file descriptiion</span>',
5344 '<div class="finder-icon-down"></div>',
5348 '<div class="finder-icon fnder-icon-modern">',
5349 '<div class="finder-icon-handle"></div>',
5350 '<div class="file-icon"><div></div></div>',
5351 '<div class="finder-icon-filename break-word">file name</div>',
5352 '<div class="finder-icon-summary break-word">file descriptiion</div>',
5353 '<div class="finder-icon-down">></div>',
5357 ELM_ORIGIN_FINDER_ICON = Util.pullHtmlAsTemplete( HTML_FINDER_ICON ),
5358 ICON_HEIGHT = Util.getElementSize( ELM_ORIGIN_FINDER_ICON ).height;
5361 // b : 開始の値(開始時の座標やスケールなど)
5363 // d : Tween(トゥイーン)の合計時間
5365 function easeOutQuad( t, b, c, d ){
5367 return -c * t*( t-2 ) + b;
5373 var FinderIconClass = function(){};
5374 FinderIconClass.prototype = {
5381 init : function( page, file, w, index, style ){
5382 if( !this.elm ) this.elm = ELM_ORIGIN_FINDER_ICON.cloneNode( true );
5384 if( this.page !== page ){
5386 page.elm.appendChild( this.elm );
5387 this.node && this.node.remove();
5388 this.node = page.node.createNode( this.elm, false, true, 'finder-icon-hover', '' );
5390 if( this.file !== file ){
5391 this.file && this.file.destroy();
5393 this._index = index;
5397 if( this._index !== index ){
5398 this._index = index;
5402 index : function( _index ){
5405 style : function( _style ){
5408 draw : function( w ){
5409 var file = this.file,
5411 thumb = file.getThumbnail(),
5412 elmThumb = Util.getElementsByClassName( elm, 'file-icon' )[ 0 ].firstChild,
5413 elmName = Util.getElementsByClassName( elm, 'finder-icon-filename' )[ 0 ],
5414 elmDesc = Util.getElementsByClassName( elm, 'finder-icon-summary' )[ 0 ];
5416 elmThumb.className = 'has-thumbnail';
5417 elmThumb.style.backgroundImage = [ 'url(', thumb.image, ')' ].join( '' );
5419 elmThumb.className = thumb.className;
5420 elmThumb.style.backgroundImage = '';
5423 elmName.firstChild.data = file.getName();
5424 elmDesc.firstChild.data = file.getSummary();
5428 resize : function( w ){
5429 this.node.update( 0, this._index * ICON_HEIGHT, w );
5431 onEditorClick : function( e ){
5432 this.onEditorCallback && this.onEditorCallback( this.file, this.file.editorApplicationList()[ 0 ] );
5435 onViwerClick : function( e ){
5436 this.onViewerCallback && this.onViewerCallback( this.file, this.file.viewerApplicationList()[ 0 ] );
5439 onActionClick : function( e ){
5440 this.onActionCallback && this.onActionCallback( this.file );
5443 destroy : function(){
5444 this.elm && this.elm.parentNode.removeChild( this.elm );
5445 this.file && this.file.destroy();
5446 this.node && this.node.remove();
5452 FinderIconClass.pool.push( this );
5455 FinderIconClass.pool = [];
5456 FinderIconClass.get = function( page, file, w, index, style ){
5457 var _icon = FinderIconClass.pool.length > 0 ? FinderIconClass.pool.shift() : new FinderIconClass();
5458 _icon.init( page, file, w, index, style );
5465 var PathClass = function(){};
5466 PathClass.prototype = {
5473 init : function( finderData, file, index ){
5474 if( !this.elm ) this.elm = ELM_ORIGIN_LOCATION_ITEM.cloneNode( true );
5476 if( this.finderData !== finderData ){
5477 this.finderData = finderData;
5478 finderData.elmPath.appendChild( this.elm );
5479 this.node && this.node.remove();
5482 if( this.file !== file ){
5486 this._index = index;
5487 if( !this.node ) this.node = finderData.nodePath.createNode( this.elm, false, true, 'finder-path-hover', 'pointer' );
5490 this.elm.className = 'file-icon-' + this.file.getType();
5491 this.elm.innerHTML = this.file.getName();
5493 textWidth : function(){
5494 this.elm.style.width = 'auto';
5495 var ret = this.elm.offsetWidth;
5496 this.elm.style.width = '';
5499 update : function( x, w ){
5500 this.node.update( x - 15, undefined, w );
5502 index : function( _index ){
5505 destroy : function(){
5506 this.finderData.elmPath.removeChild( this.elm );
5507 this.node && this.node.remove();
5509 delete this.finderData;
5514 PathClass.pool.push( this );
5517 PathClass.pool = [];
5518 PathClass.get = function( finderData, file, index ){
5519 var _bread = PathClass.pool.length > 0 ? PathClass.pool.shift() : new PathClass();
5520 _bread.init( finderData, file, index );
5528 var PageClass = function(){};
5529 PageClass.prototype = {
5544 init : function( nodeRoot, elmRoot, elmScroll ){
5545 this.nodeRoot = nodeRoot;
5546 this.elmRoot = elmRoot;
5547 this.elmScroll = elmScroll;
5549 if( this.elm === null ){
5550 this.elm = document.createElement( 'div' );
5552 elmScroll.appendChild( this.elm );
5553 this.elm.style.cssText = 'position:absolute;top:0;';
5554 // this.elm.style.display = 'none';
5555 this.node = this.nodeRoot.createNode( this.elm, true, false );
5556 if( this.iconList === null ){
5560 panInReady : function( way ){
5561 this.elm.style.display = '';
5562 var x = this.sliding === true ? this.currentX : way * this.nodeRoot.width();
5563 this.startX = this.currentX = x;
5567 this.panTotalTime = 20;
5568 this.sliding = true;
5569 this.isPanOut = false;
5570 // this.elm.style.left = x + 'px';
5573 panOutReady : function( way ){
5574 var x = -way * this.nodeRoot.width();
5575 this.startX = this.currentX || 0;
5577 this.offsetX = x - this.startX;
5579 this.panTotalTime = 20;
5580 this.sliding = true;
5581 this.isPanOut = true;
5585 x = page.currentX = easeOutQuad( page.panTime, page.startX, page.offsetX, page.panTotalTime );
5586 // page.elm.style.left = x + 'px';
5588 if( page.panTotalTime < ++page.panTime ){
5589 delete page.panTime;
5591 delete page.offsetX;
5592 delete page.panTotalTime;
5593 delete page.sliding;
5594 if( this.isPanOut === true ) this.elm.style.display = 'none';
5597 draw : function( folder ){
5598 var _w = this.nodeRoot.width();
5599 this.folder = folder;
5601 iconList = data.iconList,
5604 l = folder.getChildFileLength(),
5605 m = iconList.length,
5606 scrollY = -this.nodeRoot.scrollY(),
5607 rootH = scrollY + this.nodeRoot.height(),
5610 for( ; i < l; ++i ){
5611 if( ( i + 1 ) * ICON_HEIGHT < scrollY || rootH < i * ICON_HEIGHT ) continue;
5613 iconList[ j ].init( this, folder.getChildFileAt( i ), _w, i, data.style );
5615 iconList.push( FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) );
5619 data.elmRoot.className = folder.getState() === Const.FILE.STATE.LOADING ? 'finder-body loading' : 'finder-body';
5620 // data.elmRoot.style.height = ( data.h - data.headH ) + 'px';
5622 while( j < iconList.length ) iconList.pop().destroy();
5623 data.elmScroll.style.height = ( l * ICON_HEIGHT ) + 'px';
5625 onScroll : function(){
5626 var _w = this.nodeRoot.width();
5629 iconList = data.iconList,
5630 folder = this.folder,
5633 l = folder.getChildFileLength(),
5634 scrollY = -this.nodeRoot.scrollY(),
5635 rootH = scrollY + this.nodeRoot.height(),
5636 startIndex = 0 < iconList.length ? iconList[ 0 ]._index : 0,
5639 // console.log( ' > ' + scrollY + ' , ' + rootH )
5640 for( ; i < l; ++i ){
5641 if( ( i + 1 ) * ICON_HEIGHT < scrollY || rootH < i * ICON_HEIGHT ){
5642 if( iconList.length <= j ) continue;
5643 icon = iconList[ j ];
5644 if( icon._index !== i ) continue;
5646 iconList.splice( j, 1 );
5649 if( iconList.length <= j || iconList[ j ]._index !== i ){
5650 if( i < startIndex ){
5651 iconList.splice( j, 0, FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) );
5653 if( startIndex + iconList.length <= i ){
5654 iconList.push( FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) );
5660 //while( j < iconList.length ) iconList.pop().destroy();
5662 resize : function( w ){
5663 var list = this.iconList,
5665 for( ; i; ) list[ --i ].resize( w );
5667 destroy : function(){
5669 while( icon = this.iconList.shift() ) icon.destroy();
5671 this.elm.parentNode.removeChild( this.elm );
5675 var ApplicationButton = function(){};
5676 ApplicationButton.prototype = {
5682 init : function( ui, elmParent, app, file ){
5683 if( this.elm === null ){
5684 this.elm = document.createElement( 'div' );
5686 elmParent.appendChild( this.elm );
5687 this.elm.className = 'button';
5688 this.elm.innerHTML = app.getDisplayName();
5691 this.button = ui.createButton( this.elm, function(){
5698 this.fileUID = file.getUID();
5700 onClick : function(){
5701 this.app.boot( this.file );
5704 destroy : function(){
5706 elm.parentNode.removeChild( elm );
5708 this.button.destroy();
5714 var DetailPageClass = function(){};
5715 DetailPageClass.prototype = Util.extend( new PageClass(), {
5717 init : function( finderData ){
5718 this.finderData = finderData;
5719 this.apiuser = finderData.apiuser;
5720 this.nodeRoot = finderData.nodeRoot;
5721 this.elmRoot = finderData.elmRoot;
5722 this.elmScroll = finderData.elmScroll;
5724 if( this.elm === null ){
5725 this.elm = Util.pullHtmlAsTemplete( [
5726 '<div class="finder-detail">',
5727 '<div class="file-icon"><div></div></div>',
5728 '<div class="finder-detail-filename break-word">file name</div>',
5729 '<div class="finder-detail-summary break-word">file descriptiion</div>',
5730 '<div>View this file</div>',
5731 '<div class="viewer-apps"></div>',
5732 '<div>Edit this file</div>',
5733 '<div class="editor-apps"></div>',
5737 this.elm.style.display = 'none';
5738 this.elmScroll.appendChild( this.elm );
5739 this.node = this.nodeRoot.createNode( this.elm, true, false );
5741 this.ui = this.apiuser.createUIGroup( this.node );
5742 this.appButtons = [];
5744 draw : function( file ){
5746 thumb = file.getThumbnail(),
5747 elmThumb = Util.getElementsByClassName( elm, 'file-icon' )[ 0 ].firstChild,
5748 elmName = Util.getElementsByClassName( elm, 'finder-detail-filename' )[ 0 ],
5749 elmDesc = Util.getElementsByClassName( elm, 'finder-detail-summary' )[ 0 ],
5750 tmpButtons = Util.copyArray( this.appButtons ),
5751 apps, app, elmContainer, button;
5753 elmThumb.className = 'has-thumbnail';
5754 elmThumb.style.backgroundImage = [ 'url(', thumb.image, ')' ].join( '' );
5756 elmThumb.className = thumb.className;
5757 elmThumb.style.backgroundImage = '';
5760 elmName.firstChild.data = file.getName();
5761 elmDesc.firstChild.data = file.getSummary();
5762 this.node.width( this.nodeRoot.width() );
5763 this.node.height( this.nodeRoot.height() );
5765 this.appButtons.length = 0;
5767 apps = file.viewerApplicationList();
5768 elmContainer = Util.getElementsByClassName( elm, 'viewer-apps' )[ 0 ];
5769 for( i = 0; i < apps.length; ++i ){
5770 button = 0 < tmpButtons.length ? tmpButtons.shift() : new ApplicationButton();
5771 button.init( this.ui, elmContainer, apps[ i ], file );
5772 this.appButtons.push( button );
5774 apps = file.editorApplicationList();
5775 elmContainer = Util.getElementsByClassName( elm, 'editor-apps' )[ 0 ];
5776 for( i = 0; i < apps.length; ++i ){
5777 button = 0 < tmpButtons.length ? tmpButtons.shift() : new ApplicationButton();
5778 button.init( this.ui, elmContainer, apps[ i ], file );
5779 this.appButtons.push( button );
5782 while( button = tmpButtons.shift() ) button.destroy();
5788 x = page.currentX = easeOutQuad( page.panTime, page.startX, page.offsetX, page.panTotalTime );
5789 // page.elm.style.left = x + 'px';
5791 if( page.panTotalTime < ++page.panTime ){
5792 delete page.panTime;
5794 delete page.offsetX;
5795 delete page.panTotalTime;
5796 delete page.sliding;
5797 if( this.isPanOut === true ) this.elm.style.display = 'none';
5800 onScroll : function(){
5803 resize : function(){
5804 this.elmScroll.style.height = this.nodeRoot.height() + 'px';
5806 destroy : function(){
5808 while( button = this.appButtons.shift() ) button.destroy();
5817 var FinderPrivateData = Class.create(
5818 Class.PRIVATE_DATA, {
5828 viewerOption : null,
5829 editorOption : null,
5841 Constructor : function( finder, apiuser, elm, tree, onSelect, viewerOption, editorOption ){
5842 this.finder = finder;
5843 this.apiuser = apiuser;
5844 if( PointingDeviceEventTree.isNodeInstance( elm ) === true ){
5845 this.nodeRoot = elm;
5846 this.elmRoot = PointingDeviceEventTree._getNodePrivateData( elm ).elm;
5848 // App が eventTree を持っている?
5849 // App が eventTree を持っていない
5852 this.nodeRoot.addEventListener( 'click', this.onIconClick, this );
5853 this.nodeRoot.addEventListener( 'scroll', this.onScroll, this );
5855 this.elmScroll = document.createElement( 'div' );
5856 this.elmRoot.appendChild( this.elmScroll );
5857 this.elmScroll.className = 'finder-elm-scroll';
5858 this.elmScroll.style.cssText = 'width:100%;overflow:hidden;';
5861 this.onSelect = onSelect;
5862 this.viewerOption = viewerOption;
5863 this.editorOption = editorOption;
5865 var size = Util.getElementSize( ELM_ORIGIN_FINDER_ICON );
5866 this.iconW = size.width;
5867 this.iconH = size.height;
5869 tree.addTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw, this );
5870 Util.addClass( this.elmRoot, 'finder-body' );
5872 if( this.panInPage === null ){
5873 this.pageIcons1 = new PageClass();
5874 this.pageIcons2 = new PageClass();
5875 this.pageDetail = new DetailPageClass();
5877 this.pageIcons1.init( this.nodeRoot, this.elmRoot, this.elmScroll );
5878 this.pageIcons2.init( this.nodeRoot, this.elmRoot, this.elmScroll );
5879 this.pageDetail.init( this );
5881 onIconClick : function( e ){
5882 if( this.panInPage === this.pageDetail ) return;
5884 var target = e.target,
5885 list = this.panInPage.iconList,
5888 if( target === this.nodeRoot ) return;
5889 for( i = list.length; i; ){
5891 if( icon.node === target ){
5893 file = this.currentFile.getChildFileAt( i );
5894 if( target.width() - 30 < e.layerX ){
5895 this.tree.down( i );
5896 this.draw( this.w, this.h, 1, true );
5898 if( file.getChildFileLength() !== -1 || file.getType() === Const.FILE.TYPE.FOLDER ){
5899 this.tree.down( i );
5900 this.draw( this.w, this.h, 1 );
5902 if( Type.isFunction( this.onSelect ) === true ){ /* && this.onSelect( file ) === true */
5903 this.onSelect( file );
5905 this.tree.down( i );
5906 this.draw( this.w, this.h, 1 );
5913 onScroll : function( e ){
5914 this.panInPage.onScroll( e );
5916 onPathClick : function( e ){
5917 var target = e.target,
5918 i = target.nodeIndex();
5919 if( target === this.nodePath || this.nodePath.numNode() - 1 === i ) return;
5921 this.draw( this.w, this.h, -1 );
5923 draw : function( w, h, way, showDetail ){
5924 var data = this, page;
5925 data.w = w = Type.isFinite( w ) === true ? w : data.w;
5926 data.h = h = Type.isFinite( h ) === true ? h : data.h;
5928 var file = this.currentFile = this.tree.getCurrentFile(),
5929 isFolder = showDetail !== true && ( file.getChildFileLength() !== -1 || file.getType() === Const.FILE.TYPE.FOLDER );
5931 data.elmPath && data.drawPath( w );
5932 page = this.panInPage;
5933 if( Type.isNumber( way ) === true ){
5934 if( page.sliding === false ){
5935 if( isFolder === true ){
5936 this.panInPage = page === this.pageIcons1 ? this.pageIcons2 : ( page === this.pageIcons2 ? this.pageIcons1 : this.panOutPage );
5938 this.panInPage = this.pageDetail;
5940 this.panOutPage = page;
5942 this.panInPage.panInReady( way );
5943 //this.panInPage.elm.className = 'panIN';
5944 this.panOutPage.panOutReady( way );
5945 //this.panOutPage.elm.className = 'panOut';
5946 this.nodeRoot.disabled( true );
5947 SystemTimer.add( this.apiuser, this.tick, 16, false, this );
5949 if( isFolder === true ){
5950 this.panInPage = page === null ? this.pageIcons1 : page;
5952 this.panInPage = this.pageDetail;
5955 this.panInPage.draw( file );
5957 data.nodeRoot.invalidateScrollbar();
5960 if( this.panInPage.sliding === false && this.panOutPage.sliding === false ){
5961 SystemTimer.remove( this.apiuser, this.tick );
5962 this.nodeRoot.disabled( false );
5963 this.nodeRoot.invalidateScrollbar();
5966 this.panInPage.sliding === true && this.panInPage.pan();
5967 this.panOutPage.sliding === true && this.panOutPage.pan();
5969 drawPath : function( w ){
5970 if( !this.elmPath.parentNode ) return;
5971 w = this.nodePath.width();
5974 pathList = data.pathList,
5976 l = tree.hierarchy() + 1,
5977 m = pathList.length,
5980 minW = FinderPrivateData.MIN_PATH_WIDTH,
5981 file, path, pathW, offset, remove, pathX = 0, fit = false;
5983 for( ; i < l; ++i ){
5984 file = i !== l - 1 ? tree.getParentFileAt( i ) : this.currentFile;
5986 pathList[ i ].init( this, file, i );
5988 pathList.push( PathClass.get( this, file, i ) );
5991 while( l < pathList.length ) pathList.pop().destroy();
5994 pathW = pathList[ --i ].textWidth();
5995 wList.push( pathW );
5999 //if( minW * ( l + 1 ) * 1.2 < w ){
6000 console.log( totalW + ' , ' + w )
6002 if( fit === true ) break;
6003 for( i = 0; i < l; ++i ){
6004 offset = totalW - w;
6010 remove = offset < remove ? offset : remove;
6012 if( pathW - remove < minW ){
6013 totalW -= ( pathW - minW );
6016 wList[ i ] = pathW - remove;
6021 for( i = 0; i < l; ++i ){
6022 path = pathList[ i ];
6024 path.update( pathX, pathW );
6031 createPath : function( node ){
6032 if( this.elmPath ) return;
6034 if( PointingDeviceEventTree.isNodeInstance( node ) === true ){
6035 this.nodePath = node;
6036 this.elmPath = PointingDeviceEventTree._getNodePrivateData( node ).elm;
6038 node.addEventListener( 'click', this.onPathClick, this );
6039 Util.addClass( this.elmPath, 'finder-path' );
6040 // this.elmPath = document.createElement( 'div' );
6041 // this.elmPath.className = ;
6044 AsyncCall.add( this.apiuser, this.draw, null, this );
6047 onKill : function(){
6048 this.tree.removeTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw );
6050 if( this.pathList ){
6051 while( this.pathList.length > 0 ) this.pathList.shift().destroy();
6054 this.pageIcons1.destroy();
6055 this.pageIcons2.destroy();
6056 this.pageDetail.destroy();
6057 this.nodeRoot.remove();
6059 FINDER_LIST.splice( Util.getIndex( FINDER_LIST, this.finder ), 1 );
6060 var data = ApplicationPrivateData.get( this.apiuser ),
6061 list = data.finderList,
6062 i = Util.getIndex( list, this.finder );
6063 i !== -1 && list.splice( i, 1 );
6066 FinderPrivateData.MIN_PATH_WIDTH = 25;
6071 var Finder = Class.create(
6072 FinderPrivateData, {
6073 Constructor : function( application, elmRoot, tree, onSelect, viewerOption, editorOption ){
6074 Finder.newPrivateData( this, this, application, elmRoot, tree, onSelect, viewerOption, editorOption );
6078 resize : function( w, h ){
6079 var data = Finder.getPrivateData( this );
6080 data.panInPage && data.panInPage.resize( w );
6082 createPath : function( node ){
6083 return Finder.getPrivateData( this ).createPath( node );
6085 destroy : function(){
6094 create: function( application, elmTarget, tree, onSelect, viewerOption, editorOption ){
6095 //if( Application.isApplicationInstance( _application ) === false ) return;
6097 var finder = new Finder( application, elmTarget, tree, onSelect, viewerOption, editorOption );
6098 FINDER_LIST.push( finder );
6101 registerFinderHead: function(){
6104 registerFinderPane: function( _finderPane ){
6107 isFinderInstance: function( _finder ){
6108 return _finder instanceof Finder;
6110 isFinderPaneInstance: function(){
6113 isFinderHeadInstance: function(){
6121 * marginBottom, marginLeft, marginRight, marginTop, margin
6122 * padding, paddingBottom, paddingLeft, paddingRight, paddingTop
6123 * fontSize, textIndent
6125 * bottom, left, right, top (len, %)
6128 * borderBottomWidth, borderLeftWidth, borderRightWidth, borderTopWidth, borderWidth,
6133 * borderBottomColor, borderLeftColor, borderRightColor, borderTopColor, borderColor
6137 * clip rect(0px, 40px, 40px, 0px);
6138 * backgroundPosition (len, %)
6140 * lineHeight (len, %, num)
6144 var DHTML = ( function(){
6146 var TICKET_ARRAY = [],
6149 cround = function( v ){ return round( v * 100 ) / 100 };
6151 function startAnimation( _elm, _cssObject, _onComplete, _onEnterFrame, _numFrames ){
6152 var _ticket, i = TICKET_ARRAY.length;
6154 _ticket = TICKET_ARRAY[ --i ];
6155 if( _ticket.elm === _elm ){
6160 var _currentValues = [],
6163 _targetProperties = [],
6165 var target, current,
6166 inlineStyle = CSS.getInlineStyle( _elm ),
6167 currentStyle = CSS.getWrappedStyle( _elm ),
6168 targetStyle = CSS.getWrappedStyle( _elm, _cssObject );
6169 targetStyle.pxPerEm = currentStyle.get( 'fontSize' )._toPx();
6170 for( var p in _cssObject ){
6171 p = Util.camelize( p );
6172 target = targetStyle.get( p );
6173 current = currentStyle.get( p );
6175 if( target.isValid() === false || current.isValid() === false || current.equal( target ) !== false ){
6181 current.convert( target );
6182 // alert( current.getValue() + ' , ' + target.getValue() )
6183 _currentValues.push( current.getValue() );
6184 _offsetValues.push( current.getOffset( target ) );
6185 _endValues.push( target.getValue() );
6186 _targetProperties.push( p );
6187 _units.push( target.getUnit() );
6189 // IE has trouble with opacity if it does not have layout
6190 // Force it by setting the zoom level
6191 if( p === 'opacity' && SPECIAL.hasLayout ){
6192 if( SPECIAL.hasLayout( _elm ) === false ) inlineStyle.zoom = 1;
6193 inlineStyle.filter = current.getValueText();
6195 inlineStyle[ p ] = current.getValueText();
6202 var i, cssTexts = [];
6203 for( i = 0; i < _numFrames; ++i ){
6204 if( i < _numFrames - 1 ){
6205 tickValue( _currentValues, _offsetValues, _numFrames );
6206 cssTexts.push( createCssText( _currentValues, _targetProperties, targetStyle, inlineStyle ) );
6208 cssTexts.push( createCssText( _endValues, _targetProperties, targetStyle, inlineStyle ) );
6212 TICKET_ARRAY.push( new AnimationTaskClass(
6214 Type.isFunction( _onComplete ) === true ? _onComplete : null,
6215 Type.isFunction( _onEnterFrame ) === true ? _onEnterFrame : null,
6219 currentStyle.clear();
6220 targetStyle.clear();
6221 SystemTimer.add( SUPER_USER_KEY, onEnterFrame, 1000 / fpms );
6224 function tickValue( current, offset, numFrames ){
6225 if( Type.isArray( current ) === true ){
6226 var ret, i = current.length;
6229 ret = tickValue( current[ i ], offset[ i ], numFrames );
6230 if( Type.isNumber( ret ) === true ) current[ i ] = ret;
6233 return current + offset / numFrames;
6236 function createCssText( update, props, style, inline ){
6238 for( var i = props.length; i; ){
6239 prop = style.get( props[ --i ] );
6240 prop.setValue( update[ i ] );
6241 inline[ Util.uncamelize( prop.name ) ] = prop.getValueText();
6242 //if( prop.name === 'backgroundColor' ) alert( prop.getValueText() + '|' + update[ i ].join( ',') )
6245 return CSS.toCssText( inline );
6248 function onEnterFrame(){
6251 while( i < TICKET_ARRAY.length ){
6252 _ticket = TICKET_ARRAY[ i ];
6253 l = _ticket.cssTexts.length;
6254 _ticket.elm.style.cssText = _ticket.cssTexts.shift();
6256 _ticket.onComplete && _ticket.onComplete();
6258 delete _ticket.cssTexts;
6259 delete _ticket.onComplete;
6260 delete _ticket.onEnterFrame;
6261 delete _ticket.numFrame;
6262 TICKET_ARRAY.splice( i, 1 );
6264 _ticket.onEnterFrame && _ticket.onEnterFrame( l / _ticket.numFrame );
6268 if( TICKET_ARRAY.length === 0 ){
6269 SystemTimer.remove( SUPER_USER_KEY, onEnterFrame );
6273 var AnimationTaskClass = function( elm, cssTexts, onEnterFrame, onComplete, numFrame ){
6275 this.cssTexts = cssTexts;
6276 this.onEnterFrame = onEnterFrame;
6277 this.onComplete = onComplete;
6278 this.numFrame = numFrame;
6281 var VisualEffectClass = function( elm ){
6284 VisualEffectClass.prototype = {
6285 anime : function( _cssObject, _onComplete, _onEnterFrame, _time ){
6286 var _numFrames = Math.floor( _time / fpms );
6287 startAnimation( this.elm, _cssObject, _onComplete, _onEnterFrame, _numFrames );
6289 fadeIn : function(){
6292 fadeOut : function(){
6295 update : function( x, y, w, h ){
6296 var _cssText = this.elm.style.cssText;
6301 create: function( application, _elm ){
6302 return new VisualEffectClass( _elm );
6304 isInstanceOfVisualEffect: function( _instance){
6305 return _instance instanceof VisualEffectClass;
6311 /* --------------------------------------------
6315 Application.onCurrentApplicationChange( SUPER_USER_KEY );
6317 SERVICE_LIST.push( MouseEvent );
6319 new EventTicketClass( window, 'unload', function(){
6321 while( SERVICE_LIST.length > 0 ){
6322 _service = SERVICE_LIST.shift();
6323 Type.isFunction( _service.onSystemShutdown ) === true && _service.onSystemShutdown();
6329 /* ---------------------------------------------
6330 * broadcast to global
6334 gOS.registerApplication = Application.register;
6335 gOS.registerDriver = File.registerDriver;
6339 var DOM = ( function( window, document ){
6346 function correctNodes( node ){
6348 if( node && node.parentNode ){
6349 while( node.lastChild ) correctNodes( node.lastChild );
6350 node.parentNode.removeChild( node );
6351 if( node.nodeType === 1 ){
6352 switch( node.tagName ){
6354 DIV_LIST.push( node );
6357 SPAN_LIST.push( node );
6361 node.removeAttribute( 'className' );
6362 node.removeAttribute( 'style' );
6363 node.removeAttribute( 'id' );
6365 if( node.nodeType === 3 ){
6367 TEXT_LIST.push( node );
6373 createDiv : function(){
6374 return 0 < DIV_LIST.length ? DIV_LIST.shift() : document.createElement( 'div' );
6376 createSpan : function(){
6379 createText : function(){
6382 getTextSize : function( elm, content ){
6383 var span = DOM.createSpan(),
6384 text = DOM.createText(),
6386 elm.appendChild( span );
6387 span.style.cssText = 'visibility:hidden;position:absolute;';
6388 span.appendChild( text );
6389 text.data = content;
6390 w = span.offsetWidth;
6391 h = span.offsetHeight;
6392 DOM.correctNodes( span );
6395 correctNodes : function( node ){
6397 if( node && node.parentNode ){
6398 while( node.lastChild ) DOM.correctNodes( node.lastChild );
6399 node.parentNode.removeChild( node );
6400 if( node.nodeType === 1 ){
6401 switch( node.tagName ){
6403 DIV_LIST.push( node );
6406 SPAN_LIST.push( node );
6410 node.removeAttribute( 'className' );
6411 node.removeAttribute( 'style' );
6412 node.removeAttribute( 'id' );
6414 if( node.nodeType === 3 ){
6416 TEXT_LIST.push( node );
6421 })( window, document );
6423 var XBrowserStyle = ( function(){
6428 UNITS = 'px,cm,mm,in,pt,pc,em,%'.split( ',' ),
6429 CLIP_SEPARATOR = UA.isIE === true && UA.ieVersion < 8 ? ' ' : ',';
6431 var SPECIAL = ( function(){
6433 if( UA.isIE === true && UA.ieVersion < 9 ){
6434 if( UA.ACTIVEX === true ){
6435 // special.opacity = 'ActiveXOpacity';
6436 special.setFilters = function( style ){
6437 var filters = ( style.filter || '' ).split( ') ' ),
6440 filter, names, props, prop, j, l, key, v;
6442 filter = filters[ --i ].split( ' ' ).join( '' ).split( '(' );
6443 if( filter.length !== 2 ) continue;
6444 names = filter[ 0 ].split( '.' ); // progid:DXImageTransform.Microsoft.Shadow(color=#666666,direction=120,strength=9)
6445 props = filter[ 1 ].split( ',' ); //
6447 for( j = 0, l = props.length; j < l; ++j ){
6448 prop = props[ j ].split( '=' );
6449 key = prop[ 0 ].toLowerCase();
6451 filter[ key ] = v; //v.charAt( 0 ) === '#' ? v : parseInt( v );
6453 data[ names[ names.length - 1 ] ] = filter;
6456 style.filter = data;
6457 style.opacity = data.alpha && data.alpha.opacity ? data.alpha.opacity / 100 : 1;
6459 special.hasLayout = function( elm ){
6460 return elm.currentStyle.hasLayout;
6463 special.opacity = null;
6466 var style = document.documentElement.style;
6467 special.opacity = style.opacity !== undefined ? 'opacity' :
6468 style.MozOpacity !== undefined ? 'MozOpacity' :
6469 style.KhtmlOpacity !== undefined ? 'KhtmlOpacity' :
6470 style[ '-khtml-opacity' ] !== undefined ? 'KhtmlOpacity' : null;
6472 // if( style.backgroundPositionX === undefined ){
6473 special.setBackgroundPositionXY = function( style ){
6474 var bgp = ( style.backgroundPosition || '' ).split( ' ' );
6475 style.backgroundPositionX = bgp[ 0 ] || 0;
6476 style.backgroundPositionY = bgp[ 1 ] || 0;
6479 if( style.clipTop === undefined && style[ 'clip-top' ] === undefined ){
6480 special.setClipTopRightBottomLeft = function( style ){
6481 var clip = style.clip;
6482 if( !cliop || clip.indexOf( 'rect(' ) === -1 ){
6484 style.clipRight = 0;
6485 style.clipBottom = 0;
6489 clip = clip.split( '(' )[ 1 ].split( ')' )[ 0 ].split( clip.indexOf( ',' ) !== -1 ? ',' : ' ' );
6490 ret.clipTop = clip[ 0 ];
6491 ret.clipRight = clip[ 1 ];
6492 ret.clipBottom = clip[ 2 ];
6493 ret.clipLeft = clip[ 3 ];
6500 function cssToObject( css ){
6501 var ret = {}, i, nv, n, v,
6503 isNumber = Type.isNumber,
6504 camelize = Util.camelize;
6505 if( Type.isString( css ) === true ){
6506 css = css.split( SEMICORON );
6507 for( i = css.length; i; ){
6508 nv = css[ --i ].split( CORON ); // filter の場合, progid: がくる
6510 if( isNumber( parse( n ) ) === true ) continue;
6511 v = nv.join( EMPTY );
6512 while( v.charAt( 0 ) === ' ' ) v = v.substr( 1 );
6513 ret[ camelize( n ) ] = parse( v );
6517 if( Type.isNumber( parse( n ) ) === false ) ret[ n ] = parse( css[ n ] );
6521 if( SPECIAL.setFilters ){
6522 SPECIAL.setFilters( ret );
6524 ret.opacity = SPECIAL.opacity !== null ? ret[ SPECIAL.opacity ] : 1;
6527 SPECIAL.setBackgroundPositionXY && SPECIAL.setBackgroundPositionXY( ret );
6528 SPECIAL.setClipTopRightBottomLeft && SPECIAL.setClipTopRightBottomLeft( ret );
6533 var COLOR = ( function(){
6534 var ret = {}, v, name,
6543 'FF00FF', 'MAGENTA',
6544 'FF00FF', 'FUCHSIA',
6554 '696969', 'DIMGRAY',
6555 '708090', 'SLATEGRAY',
6556 'A9A9A9', 'DARKGRAY',
6557 'DCDCDC', 'GAINSBORO',
6558 '191970', 'MIDNIGHTBLUE',
6559 '6A5ACD', 'SLATEBLUE',
6560 '0000CD', 'MEDIUMBLUE',
6561 '4169E1', 'ROYALBLUE',
6562 '1E90FF', 'DODGERBLUE',
6563 '87CEEB', 'SKYBLUE',
6564 '4682B4', 'STEELBLUE',
6565 'ADD8E6', 'LIGHTBLUE',
6566 'AFEEEE', 'PALETURQUOISE',
6567 '40E0D0', 'TURQUOISE',
6568 'E0FFFF', 'LIGHTCYAN',
6569 '7FFFD4', 'AQUAMARINE',
6570 '006400', 'DARKGREEN',
6571 '2E8B57', 'SEAGREEN',
6572 '90EE90', 'LIGHTGREEN',
6573 '7FFF00', 'CHARTREUSE',
6574 'ADFF2F', 'GREENYELLOW',
6575 '32CD32', 'LIMEGREEN',
6576 '9ACD32', 'YELLOWGREEN',
6577 '6B8E23', 'OLIVEDRAB',
6578 'BCB76B', 'DARKKHAKI',
6579 'EEE8AA', 'PALEGOLDENROD',
6580 'FFFFE0', 'LIGHTYELLOW',
6582 'DAA520', 'GOLDENROD',
6583 'B8860B', 'DARKGOLDENROD',
6584 'BC8F8F', 'ROSYBROWN',
6585 'CD5C5C', 'INDIANRED',
6586 '8B4513', 'SADDLEBROWN',
6589 'DEB887', 'BURLYWOOD',
6592 'F4A460', 'SANDYBROWN',
6594 'D2691E', 'CHOCOLATE',
6595 'B22222', 'FIREBRICK',
6601 'FF69B4', 'HOTPINK',
6603 'FF1493', 'DEEPPINK',
6604 'DB7093', 'PALEVIOLETRED',
6607 'DA70D6', 'ORCHILD',
6608 '9400D3', 'DARKVIOLET',
6609 '8A2BE2', 'BLUEVIOLET',
6610 '9370DB', 'MEDIUMPURPLE',
6611 'D8BFD8', 'THISTLE',
6612 'E6E6FA', 'LAVENDER',
6613 'FFE4E1', 'MISTYROSE',
6615 'FFFACD', 'LEMONCHIFFON'
6617 for( i = list.length; i; ){
6620 ret[ name ] = parseInt( v, 16 );
6625 var PARAMS = ( function(){
6627 register( ret.percent = {},
6628 'marginBottom,marginLeft,marginRight,marginTop,paddingBottom,paddingLeft,paddingRight,paddingTop,fontSize,textIndent'
6630 register( ret.offset = {},
6631 'height,width,bottom,left,right,top'
6633 register( ret.size = {},
6634 'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth,letterSpacing'
6636 register( ret.color = {},
6637 'backgroundColor,borderBottomColor,borderLeftColor,borderRightColor,borderTopColor,color'
6639 register( ret.region = {},
6640 'margin,padding,borderWidth,borderColor'
6642 register( ret.special = {},
6643 'clip,backgroundPosition,opacity,lineHeight,zIndex'
6645 register( ret.unit = {}, 'px,cm,mm,in,pt,pc,em,%' );
6647 register( ret.margin = {}, 'marginBottom,marginLeft,marginRight,marginTop,paddingBottom' );
6648 register( ret.padding = {}, 'paddingBottom,paddingLeft,paddingRight,paddingTop' );
6649 register( ret.borderWidth = {}, 'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth' );
6650 register( ret.borderColor = {}, 'borderBottomColor,borderLeftColor,borderRightColor,borderTopColor' );
6652 function register( obj, params ){
6653 params = params.split( ',' );
6654 for( var i=params.length; i; ) obj[ params[ --i ] ] = true;
6662 var Property = Class.create(
6666 Constructor : function( name, value, unit, pxPerEm ){
6670 this.pxPerEm = pxPerEm; // XXpx = 1em;
6674 pxPerEm : 12, // 1em === ??px
6676 equal : function( prop ){
6677 if( this.unit === prop.unit ){
6678 return this.value === prop.value;
6680 return Math.abs( this.toPx() - prop.toPx() ) < 1;
6682 convert: function( prop ){
6683 var u = prop.unit, v;
6684 if( this.unit === u ) return;
6685 this.value = v = this.toPx();
6688 this.value = u === 'em' ? v / this.pxPerEm : Util.pxTo( v, u );
6691 setValue: function( v ){
6694 getValue: function(){
6697 getOffset: function( prop ){
6698 return prop.value - this.value;
6700 getUnit: function(){
6703 getValueText: function(){
6704 return this.value === 0 ? '0' : this.value + this.unit;
6707 var v = this.value, u = this.unit;
6708 if( u === px ) return v;
6709 if( u === 'em' ) return v * this.pxPerEm;
6710 if( u === '' && this.name === 'lineHeight' ) return v * this.pxPerEm;
6711 return Util.toPx( v, u );
6713 isValid: function( t ){
6718 z = u !== '' ? true : v === 0;
6719 if( PARAMS.percent[ n ] === true ) return z;
6720 if( PARAMS.offset[ n ] === true ) return z;
6721 if( PARAMS.size[ n ] === true ) return z && u !== '%';
6722 if( PARAMS.special[ n ] === true ){
6723 if( n === 'lineHeight' ) return true;
6724 if( n === 'opacity' ) return 0 <= v && v <= 1 && u === '';
6725 if( n === 'zIndex' ) return u === '';
6733 * backgroundPosition, clip
6735 var PropertyGroup = Class.create(
6739 Constructor : function( name ){
6742 for( var i = 1, l = arguments.length; i<l; ++i ){
6743 this.props.push( arguments[ i ] );
6747 equal : function( prop ){
6748 var ps = this.props, i = ps.length;
6751 if( ps[ i ].equal( prop[ i ] ) === false ) return false;
6755 convert : function( prop ){
6756 var ps = this.props, i = ps.length;
6759 ps[ i ].convert( prop[ i ] );
6762 setValue : function( ary ){
6763 var ps = this.props, i = 0, l = ps.length;
6765 ps[ i ].setValue( ary[ i ] );
6768 getValue : function(){
6769 var ret = [], ps = this.props, i = 0, l = ps.length;
6771 ret.push( ps[ i ].getValue() );
6775 getOffset : function( prop ){
6782 ret.push( ps[ i ].getOffset( _ps[ i ] ) );
6786 getUnit : function(){
6787 var ret = [], ps = this.props, i = 0, l = ps.length;
6789 ret.push( ps[ i ].getUnit() );
6793 getValueText : function(){
6794 var ret = [], ps = this.props, i = 0, l = ps.length;
6796 ret.push( ps[ i ].getValueText() );
6798 if( this.name === 'clip' ){
6799 return 'rect(' + ret.join( CLIP_SEPARATOR ) + ')';
6801 return ret.join( ' ' );
6803 onKill : function(){
6804 var ps = this.props, i = ps.length;
6809 isValid : function( t ){
6811 var ps = t.props, i = ps.length;
6813 if( ps[ --i ].isValid() === false ) return false;
6821 * margin, padding, borderWidth, borderColor
6823 var FrexibleProperty = PropertyGroup.inherits(
6825 Class.POOL_OBJECT, {
6826 Constructor : function( name ){
6829 for( var i = 1, l = arguments.length; i<l; ++i ){
6830 this.props.push( arguments[ i ] );
6832 // top, bottom, left, right, topbottom, leftright, all
6837 var ColorProperty = Class.create(
6839 Class.POOL_OBJECT, {
6840 Constructor : function( name, r, g, b, pct ){
6848 equal : function( prop ){
6849 if( this.pct === prop.pct ){
6850 return this.r === prop.r && this.g === prop.g && this.b === prop.b;
6852 var rgb = this._toPct(),
6853 _rgb = prop._toPct(),
6857 if( Math.abs( rgb[ i ] - _rgb[ i ] ) > 1 ) return false;
6861 convert : function( prop ){
6862 var u = prop.pct, x;
6863 if( this.pct === u ) return;
6864 x = u === true ? 100 / 255 : 2.55;
6870 setValue : function( rgb ){
6875 getValue : function(){
6876 return [ this.r, this.g, this.b ];
6878 getOffset : function( prop ){
6879 return [ prop.r - this.r, prop.g - this.g, prop.b - this.b ];
6881 getUnit : function(){
6882 return this.pct === true ? '%' : '';
6884 getValueText : function(){
6885 if( this.pct === true ){
6886 return [ 'rgb(', this.r, '%,', this.g, '%,', this.b, '%)' ].join( '' );
6888 var round = Math.round;
6889 //return [ 'rgb(', round( this.r ), ',', round( this.g ), ',', round( this.b ), ')' ].join( '' );
6891 var rgb = '00000' + ( ( round( this.r ) << 16 ) + ( round( this.g ) << 8 ) + round( this.b ) ).toString( 16 );
6892 return '#' + rgb.substr( rgb.length - 6 );
6894 _toPct : function(){
6895 if( this.pct === true ) return [ this.r, this.g, this.b ];
6896 return [ this.r / 2.55, this.g / 2.55, this.b / 2.55 ];
6898 isValid : function( t ){
6899 var isFinite = window.isFinite;
6900 if( !isFinite( this.r ) || !isFinite( this.g ) || !isFinite( this.b ) ) return false;
6901 if( 0 > this.r || 0 > this.g || 0 > this.b ) return false;
6902 if( this.pct === true ) return this.r <= 100 && this.g <= 100 && this.b <= 100;
6903 return this.r <= 255 && this.g <= 255 && this.b <= 255;
6908 var isString = Type.isString,
6909 isNumber = Type.isNumber;
6910 var REG_UINIT = /.*\d(\w{1,2})?/,
6913 REG_XXXXXX = /^#[\da-fA-F]{6}?/,
6914 REG_XXX = /^#[\da-fA-F]{3}?/;
6916 var WrappedStyle = Class.create(
6920 Constructor : function( style ){
6922 var fontsize = this.get( 'fontSize' );
6923 this.pxPerEm = fontsize.toPx();
6927 if( PARAMS.special[ p ] === true || PARAMS.region[ p ] === true ){
6928 if( p === 'clip' ) return this.getClip();
6929 if( p === 'margin' ) return this.getMarginPaddingBorder( p, '' );
6930 if( p === 'padding' ) return this.getMarginPaddingBorder( p, '' );
6931 if( p === 'borderWidth' ) return this.getMarginPaddingBorder( 'border', 'Width' );
6932 if( p === 'borderColor' ) return this.getBorderColor( 'borderColor' );
6933 if( p === 'backgroundPosition' ) return this.getBackgroundPosition( p );
6934 // opacity, zindex, lineHeight
6935 return new Property( p, this.getValue( x ), this.getUnit( x ), this.pxPerEm );
6937 var x = this.style[ p ], e, v, u;
6938 if( PARAMS.offset[ p ] === true ){
6939 return new Property( p, this.getValue( x ), this.getUnit( x, p ), this.pxPerEm );
6942 if( p === 'width' ) v = e.offsetWidth;
6943 if( p === 'height' ) v = e.offsetHeight;
6944 if( p === 'top' ) v = e.offsetTop;
6945 if( p === 'bottom' ) v = e.offsetBottom;
6946 if( p === 'left' ) v = e.offsetLeft;
6947 if( p === 'right' ) v = e.offsetRight;
6948 u = this.getUnit( x, p );
6949 // alert( p + this.pxTo( v, u ) + u )
6950 return new Property( p, this.pxTo( v, u ), u, this.pxPerEm ); */
6952 if( p === 'fontSize' ){ // xx-small 等
6953 v = Util.absoluteFontSizeToPx( x );
6955 return new Property( p, v, px, this.pxPerEm );
6958 if( PARAMS.percent[ p ] === true ){
6959 // alert( p + ' , ' + x + ' , ' + this.getUnit( x, p ) )
6960 return new Property( p, this.getValue( x ), this.getUnit( x, p ), this.pxPerEm );
6962 if( PARAMS.size[ p ] === true ){
6963 return new Property( p, this.getValue( x ), this.getUnit( x, p ), this.pxPerEm );
6965 if( PARAMS.color[ p ] === true ){
6966 return this.getColor( x, p );
6969 pxTo: function( px, unit ){
6970 if( unit === 'em' ) return px / this.pxPerEm;
6971 return Util.pxTo( px, unit );
6973 getValue: function( x ){
6974 return isString( x ) === true ? parseInt( x ) :
6975 isNumber( x ) === true ? x : 0;
6977 getUnit: function( x, p ){
6979 if( isString( x ) === true ){
6980 u = x.replace( REG_UINIT, $1 );
6981 if( p === 'lineHeight' ) return u;
6982 if( PARAMS.unit[ u ] !== true ) return px;
6987 getColor: function( x, p ){
6988 var rgb = COLOR[ x.toUpperCase() ],
6993 if( isNumber( rgb ) === true ){
6994 r = ( rgb & 0xff0000 ) >> 16;
6995 g = ( rgb & 0xff00 ) >> 8;
6998 if( x.match( REG_XXXXXX ) ){
6999 r = parseInt( x.charAt( 1 ) + x.charAt( 2 ), 16 );
7000 g = parseInt( x.charAt( 3 ) + x.charAt( 4 ), 16 );
7001 b = parseInt( x.charAt( 5 ) + x.charAt( 6 ), 16 );
7002 //alert( x + ' g: ' + g )
7004 if( x.match( REG_XXX ) ){
7005 r = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
7006 g = parseInt( x.charAt( 2 ) + x.charAt( 2 ), 16 );
7007 b = parseInt( x.charAt( 3 ) + x.charAt( 3 ), 16 );
7009 if( x.indexOf( 'rgb(' ) === 0 ){
7010 rgb = x.substr( 4 ).split( ',' );
7011 r = parseFloat( rgb[ 0 ] );
7012 g = parseFloat( rgb[ 1 ] );
7013 b = parseFloat( rgb[ 2 ] );
7014 if( x.indexOf( '%' ) !== -1 ) pct = true;
7020 return new ColorProperty( p, r, g, b, pct );
7022 getClip: function( name ){
7023 // rect(...) クリップします。<top>, <bottom> は上端からの、 <right>, <left> は左端からのオフセットで指定します。Internet Explorer 4~7 では、カンマの代わりにスペースで区切る必要があります。
7024 // position:absolute または position:fixed を適用した要素に対してのみ有効です。
7025 var top = this.get( name + 'Top' ),
7026 right = this.get( name + 'Right' ),
7027 bottom = this.get( name + 'Bottom' ),
7028 left = this.get( name + 'Left' ),
7029 ret = new PropertyGroup( name, top, right, bottom, left),
7031 if( ret.isValid() === true ) return ret;
7033 all = this.style[ name ].split( '(' )[ 1 ].split( ')' )[ 0 ].split( CLIP_SEPARATOR );
7034 return new PropertyGroup( name,
7035 new Property( name + 'Top', all[ 0 ], px, this.pxPerEm ),
7036 new Property( name + 'Right', all[ 1 ], px, this.pxPerEm ),
7037 new Property( name + 'Bottom', all[ 2 ], px, this.pxPerEm ),
7038 new Property( name + 'Left', all[ 3 ], px, this.pxPerEm )
7041 getBackgroundPosition: function( name ){
7042 var x = this.get( name + 'X' ),
7043 y = this.get( name + 'Y' ),
7044 ret = new PropertyGroup( name, x, y ),
7046 if( ret.isValid() === true ) return ret;
7048 xy = this.style[ name ].split( ' ' );
7049 return new PropertyGroup( name,
7050 new Property( name + 'X', this.getValue( xy[ 0 ] ), this.getUnit( xy[ 0 ] ), this.pxPerEm ),
7051 new Property( name + 'Y', this.getValue( xy[ 1 ] ), this.getUnit( xy[ 1 ] ), this.pxPerEm )
7054 getMarginPaddingBorder: function( name, width ){
7055 var props = [ name + 'Top' + width,
7056 name + 'Right' + width,
7057 name + 'Bottom' + width,
7058 name + 'Left' + width ],
7059 top = this.get( props[ 0 ] ),
7060 right = this.get( props[ 1 ] ),
7061 bottom = this.get( props[ 2 ] ),
7062 left = this.get( props[ 3 ] ),
7063 ret = new FrexibleProperty( name, top, right, bottom, left ),
7064 klass, pxPerEm, getValue, getUnit,
7065 all, _0, _1, _2, _3, v, u;
7066 if( ret.isValid() === true ) return ret;
7069 pxPerEm = this.pxPerEm;
7070 getValue = this.getValue;
7071 getUnit = this.getUnit;
7072 all = this.style[ name + width ].split( ' ' );
7079 switch( all.length ){
7081 top = new klass( props[ 0 ], v, u, pxPerEm );
7082 right = new klass( props[ 1 ], v, u, pxPerEm );
7083 bottom = new klass( props[ 2 ], v, u, pxPerEm );
7084 left = new klass( props[ 3 ], v, u, pxPerEm );
7087 top = new klass( props[ 0 ], v, u, pxPerEm );
7088 bottom = new klass( props[ 2 ], v, u, pxPerEm );
7091 right = new klass( props[ 1 ], v, u, pxPerEm );
7092 left = new klass( props[ 3 ], v, u, pxPerEm );
7095 top = new klass( props[ 0 ], v, u, pxPerEm );
7098 right = new klass( props[ 1 ], v, u, pxPerEm );
7099 left = new klass( props[ 3 ], v, u, pxPerEm );
7100 bottom = new klass( props[ 2 ], getValue( _2 ), getUnit( _2 ), pxPerEm );
7103 top = new klass( props[ 0 ], v, u, pxPerEm );
7104 right = new klass( props[ 1 ], getValue( _1 ), getUnit( _1 ), pxPerEm );
7105 bottom = new klass( props[ 2 ], getValue( _2 ), getUnit( _2 ), pxPerEm );
7106 left = new klass( props[ 3 ], getValue( _3 ), getUnit( _3 ), pxPerEm );
7109 return new FrexibleProperty( name, top, right, bottom, left );
7111 getBorderColor: function( name ){
7112 var props = 'borderTopColor,borderRightColor,borderBottomColor,borderLeftColor'.split( ',' ),
7113 top = this.get( props[ 0 ] ),
7114 right = this.get( props[ 1 ] ),
7115 bottom = this.get( props[ 2 ] ),
7116 left = this.get( props[ 3 ] ),
7117 ret = new FrexibleProperty( name, top, right, bottom, left ),
7118 all, _0, _1, getColor;
7119 if( ret.isValid() === true ) return ret;
7121 getColor = this.getColor;
7122 all = this.style[ name ].split( ' ' );
7125 switch( all.length ){
7127 top = getColor( _0, props[ 0 ] );
7128 right = getColor( _0, props[ 1 ] );
7129 bottom = getColor( _0, props[ 2 ] );
7130 left = getColor( _0, props[ 3 ] );
7133 top = getColor( _0, props[ 0 ] );
7134 right = getColor( _1, props[ 1 ] );
7135 bottom = getColor( _0, props[ 2 ] );
7136 left = getColor( _1, props[ 3 ] );
7139 top = getColor( _0, props[ 0 ] );
7140 right = getColor( _1, props[ 1 ] );
7141 bottom = getColor( all[ 2 ], props[ 2 ] );
7142 left = getColor( _1, props[ 3 ] );
7145 top = getColor( _0, props[ 0 ] );
7146 right = getColor( _1, props[ 1 ] );
7147 bottom = getColor( all[ 2 ], props[ 2 ] );
7148 left = getColor( all[ 3 ], props[ 3 ] );
7151 return new FrexibleProperty( name, top, right, bottom, left );
7155 function camelizeHash( obj ){
7156 var p, _p, came = Util.camelize;
7159 if( _p === p ) continue;
7160 obj[ _p ] = obj[ _p ] || obj[ p ];
7165 create: function( css ){
7166 return new WrappedStyle( camelizeHash( p ) );
7171 var XDocument = ( function( window, document ){
7173 var getIndex = Util.getIndex;
7176 var AUTO = undefined;
7177 var FULL = DEF_ATTRS; // something unigue value;
7178 var FLOOR = Math.floor;
7180 DEF_ATTRS.LENGTH = 1;
7181 DEF_ATTRS.PERCENT = 2;
7182 DEF_ATTRS.COLOR = 4;
7183 DEF_ATTRS.U_DECIMAL = 8;
7184 DEF_ATTRS.NUMERICAL = 16;
7185 DEF_ATTRS.BOOLEAN = 32;
7186 DEF_ATTRS.QUARTET = 64;
7187 DEF_ATTRS.URL = 128;
7188 DEF_ATTRS.FONT_NAME = 256;
7189 DEF_ATTRS.LIST = 512;
7190 DEF_ATTRS.AUTO = 1024;
7191 DEF_ATTRS.COMBI = 2048;
7192 DEF_ATTRS.BORDER_STYLE = 'none,hidden,dotted,dashed,solid,double,groove,ridge,inset,outset'.split(',');
7193 DEF_ATTRS.POSITION_X = 'left,center,right'.split(',');
7194 DEF_ATTRS.POSITION_Y = 'top,center,bottom'.split(',');
7195 DEF_ATTRS.ALIGN = 'left,center,right,justify'.split(',');
7196 DEF_ATTRS.TEXT_DECORATION = 'none,underline,overline,line-through,blink'.split(',');
7197 DEF_ATTRS.TEXT_TRANSFORM = 'none,capitalize,lowercase,uppercase'.split(',');
7198 DEF_ATTRS.WIDTH_HEIGHT = 'auto'.split(',');
7199 DEF_ATTRS.BOX_SIZING = 'content-box,padding-box,border-box,margin-box'.split(',');
7200 DEF_ATTRS.PAINT = 1; // 再描画のみ必要
7201 DEF_ATTRS.REFLOW = 2; // レイアウトの再計算が必要
7203 DEF_ATTRS.borderWidth = [ DEF_ATTRS.REFLOW, 0, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH ]; // em [ top, right, bottom, left ]
7204 DEF_ATTRS.borderColor = [ DEF_ATTRS.PAINT, 4, DEF_ATTRS.QUARTET | DEF_ATTRS.DEF_COLOR ]; // color [ top, right, bottom, left ]
7205 DEF_ATTRS.borderStyle = [ DEF_ATTRS.REFLOW, 8, DEF_ATTRS.QUARTET | DEF_ATTRS.LIST, DEF_ATTRS.BORDER_STYLE ]; // string [ top, right, bottom, left ]
7206 DEF_ATTRS.cornerRadius = [ DEF_ATTRS.PAINT, 12, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ]; // em, px [ top, right, bottom, left ]
7207 DEF_ATTRS.bgColor = [ DEF_ATTRS.PAINT, 16, DEF_ATTRS.COLOR ]; // color
7208 DEF_ATTRS.bgAlpha = [ DEF_ATTRS.PAINT, 17, DEF_ATTRS.U_DECIMAL ]; // 0 - 1
7209 DEF_ATTRS.bgImgUrl = [ DEF_ATTRS.PAINT, 18, DEF_ATTRS.URL ]; // url
7210 DEF_ATTRS.bgImgRepeatX = [ DEF_ATTRS.PAINT, 19, DEF_ATTRS.BOOLEAN ]; // true / false
7211 DEF_ATTRS.bgImgRepeatY = [ DEF_ATTRS.PAINT, 20, DEF_ATTRS.BOOLEAN ]; // true / false
7212 DEF_ATTRS.bgImgPositionX = [ DEF_ATTRS.PAINT, 21, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT | DEF_ATTRS.LIST, DEF_ATTRS.POSITION_X ]; // em %, px, string
7213 DEF_ATTRS.bgImgPositionY = [ DEF_ATTRS.PAINT, 22, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT | DEF_ATTRS.LIST, DEF_ATTRS.POSITION_Y ]; // em %, px, string
7214 DEF_ATTRS.shadowColor = [ DEF_ATTRS.PAINT, 23, DEF_ATTRS.COLOR ]; // color
7215 DEF_ATTRS.shadowAlpha = [ DEF_ATTRS.PAINT, 24, DEF_ATTRS.U_DECIMAL ]; // 0 - 1
7216 DEF_ATTRS.shadowOffsetX = [ DEF_ATTRS.PAINT, 25, DEF_ATTRS.LENGTH ]; // em
7217 DEF_ATTRS.shadowOffsetY = [ DEF_ATTRS.PAINT, 26, DEF_ATTRS.LENGTH ]; // em
7218 DEF_ATTRS.shadowBlur = [ DEF_ATTRS.PAINT, 27, DEF_ATTRS.LENGTH ]; // em
7219 DEF_ATTRS.shadowSpread = [ DEF_ATTRS.PAINT, 28, DEF_ATTRS.LENGTH ]; // em
7220 DEF_ATTRS.shadowInset = [ DEF_ATTRS.PAINT, 29, DEF_ATTRS.BOOLEAN ]; // true / false
7222 DEF_ATTRS.color = [ DEF_ATTRS.PAINT, 30, DEF_ATTRS.COLOR ]; // color
7223 DEF_ATTRS.fontFamily = [ DEF_ATTRS.REFLOW, 31, DEF_ATTRS.FONT_NAME ]; // string
7224 DEF_ATTRS.fontSize = [ DEF_ATTRS.REFLOW, 32, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ]; // em, %
7225 DEF_ATTRS.bold = [ DEF_ATTRS.REFLOW, 33, DEF_ATTRS.BOOLEAN ]; // true / false
7226 DEF_ATTRS.italic = [ DEF_ATTRS.REFLOW, 34, DEF_ATTRS.BOOLEAN ]; // true / false
7227 DEF_ATTRS.lineHeight = [ DEF_ATTRS.REFLOW, 35, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT | DEF_ATTRS.NUMERICAL ]; // em, %,
7228 DEF_ATTRS.letterSpacing = [ DEF_ATTRS.REFLOW, 36, DEF_ATTRS.LENGTH ]; // em
7229 DEF_ATTRS.wordSpacing = [ DEF_ATTRS.REFLOW, 37, DEF_ATTRS.LENGTH ];
7230 DEF_ATTRS.align = [ DEF_ATTRS.REFLOW, 38, DEF_ATTRS.LIST, DEF_ATTRS.ALIGN ];
7231 DEF_ATTRS.decoration = [ DEF_ATTRS.PAINT, 39, DEF_ATTRS.LIST, DEF_ATTRS.TEXT_DECORATION ];
7232 DEF_ATTRS.transform = [ DEF_ATTRS.REFLOW, 40, DEF_ATTRS.LIST, DEF_ATTRS.TEXT_TRANSFORM ];
7233 DEF_ATTRS.shadowColor = [ DEF_ATTRS.PAINT, 41, DEF_ATTRS.COLOR ];
7234 DEF_ATTRS.shadowOffsetX = [ DEF_ATTRS.PAINT, 42, DEF_ATTRS.LENGTH ];
7235 DEF_ATTRS.shadowOffsetY = [ DEF_ATTRS.PAINT, 43, DEF_ATTRS.LENGTH ];
7236 DEF_ATTRS.shadowBlur = [ DEF_ATTRS.PAINT, 44, DEF_ATTRS.LENGTH ];
7238 DEF_ATTRS.width = [ DEF_ATTRS.REFLOW, 45, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT, DEF_ATTRS.WIDTH_HEIGHT ];
7239 DEF_ATTRS.minWidth = [ DEF_ATTRS.REFLOW, 46, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7240 DEF_ATTRS.maxWidth = [ DEF_ATTRS.REFLOW, 47, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7241 DEF_ATTRS.height = [ DEF_ATTRS.REFLOW, 48, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT, DEF_ATTRS.WIDTH_HEIGHT ];
7242 DEF_ATTRS.minHeight = [ DEF_ATTRS.REFLOW, 49, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7243 DEF_ATTRS.maxHeight = [ DEF_ATTRS.REFLOW, 50, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7244 DEF_ATTRS.padding = [ DEF_ATTRS.REFLOW, 51, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7245 DEF_ATTRS.margin = [ DEF_ATTRS.REFLOW, 55, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7246 DEF_ATTRS.sizing = [ DEF_ATTRS.REFLOW, 59, DEF_ATTRS.LIST, DEF_ATTRS.BOX_SIZING ];
7247 DEF_ATTRS.pageBox = [ DEF_ATTRS.REFLOW, 60, DEF_ATTRS.BOOLEAN ]; // true / false
7248 DEF_ATTRS.x = DEF_ATTRS.left = [ DEF_ATTRS.REFLOW, 61, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7249 DEF_ATTRS.y = DEF_ATTRS.top = [ DEF_ATTRS.REFLOW, 62, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7250 DEF_ATTRS.bottom = [ DEF_ATTRS.REFLOW, 63, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7251 DEF_ATTRS.right = [ DEF_ATTRS.REFLOW, 64, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
7255 * redraw 再描画はパラメータ変更後に setTimeout で
7256 * reflow 再計算は値が get された場合 invalidate が サイズだったら
7257 * または再描画前に invalidate がサイズなフラグが足っていたら
7260 var BasicLayoutManager = Class.create(
7261 'BasicLayoutManager',
7264 Constructor : function(){
7267 redraw : function( nodeData ){
7268 var root = nodeData.__root;
7269 root.dirty === DEF_ATTRS.REFLOW && this.reflow( root );
7273 reflow : function( nodeData ){
7274 var parent = nodeData.__parent,
7275 allowW = parent.contentWidth,
7276 allowH = parent.contentHeight,
7277 autoW = parent.autoWidth,
7278 autoH = parent.autoHeight,
7279 offsetX = parent.offsetX,
7280 offsetY = parent.offsetY,
7281 children = nodeData.children,
7282 style = nodeData.__style,
7283 x, y, w, minW, maxW, h, minH, maxH,
7284 contentW, contentH, boxW, boxH,
7285 autoSize, sizing, page,
7286 paddingT, paddingR, paddingB, paddingL,
7287 borderT, borderR, borderB, borderL,
7288 marginT, marginR, marginB, marginL,
7291 styles, child, calc, i;
7294 styles = style.data;
7295 calc = BasicLayoutManager.calcValue;
7296 sizing = styles[ 53 ];
7297 page = styles[ 54 ];
7298 x = calc( styles[ 55 ], allowW );
7299 y = calc( styles[ 56 ], page === true ? allowH : allowW );
7301 minW = styles[ 46 ];
7302 maxW = styles[ 47 ];
7303 contentW = BasicLayoutManager.finalValue( w, minW, maxW, allowW );
7305 minW = styles[ 49 ];
7306 maxW = styles[ 50 ];
7307 contentH = BasicLayoutManager.finalValue( h, minW, maxW, allowH );
7308 autoSize = w === AUTO || h === AUTO;
7309 paddingT = calc( styles[ 51 ], page === true ? allowH : allowW );// paddingTRBL の % 指定は 最大幅に対して TB でも幅に対して
7310 paddingR = calc( styles[ 52 ], allowW );
7311 paddingT = calc( styles[ 53 ], page === true ? allowH : allowW );
7312 paddingL = calc( styles[ 54 ], allowW, autoW );
7313 borderT = styles[ 0 ];
7314 borderR = styles[ 1 ];
7315 borderB = styles[ 2 ];
7316 borderL = styles[ 3 ];
7317 marginT = calc( styles[ 55 ], page === true ? allowH : allowW );// marginTRBL の % 指定は 最大幅に対して TB でも幅に対して
7318 marginR = calc( styles[ 56 ], allowW );
7319 marginB = calc( styles[ 57 ], page === true ? allowH : allowW );
7320 marginL = calc( styles[ 58 ], allowW );
7324 case 3 : // margin-box
7325 contentW -= ( marginR + marginL );
7326 contentH -= ( marginT + marginR );
7328 case 2 : // border-box
7329 contentW -= ( borderR + borderL );
7330 contentH -= ( borderT + borderR );
7331 case 1 : // padding-box
7332 contentW -= ( paddingR + paddingL );
7333 contentH -= ( paddingT + paddingR );
7334 // case 0 : // content-box
7337 boxW = contentW = w = allowW;
7338 boxH = contentH = h = allowH;
7340 maxW = maxH = Infinity;
7344 if( nodeData.contentWidth !== contentW || nodeData.contentHeight === contentH ){
7345 if( autoSize === false ){
7346 nodeData.updateLayout();
7347 nodeData.contentWidth = contentW;
7348 nodeData.contentHeight = contentH;
7349 nodeData.boxWidth = boxW;
7350 nodeData.boxHeight = boxH;
7352 if( node instanceof LayoutBoxPrivate ){
7353 nodeData.Super.reflow.call( nodeData );
7360 for( i = children.length; i; ){
7361 child = children[ --i ];
7362 if( child instanceof LayoutBoxPrivate ){
7363 child.layoutManager.reflow( child );
7367 if( autoSize === false ) continue;
7368 if( childW < child.rectRight ) childW = child.rectRight;
7369 if( childH < child.rectBottom ) childH = child.rectBottom;
7371 if( autoSize === true ){
7372 if( w === AUTO && childW < contentW ) contentW = childW;
7373 if( h === AUTO && childH < contentH ) contentH = childH;
7374 if( contentW < minW ) contentW = minW;
7375 if( maxW < contentW ){
7376 nodeData.scrollWidth = contentW;
7379 if( contentH < minH ) contentH = minH;
7380 if( maxH < contentH ){
7381 nodeData.scrollHeight = contentH;
7384 nodeData.contentWidth = boxW = contentW;
7385 nodeData.contentHeight = boxH = contentH;
7387 case 3 : // margin-box
7388 boxW += ( marginR + marginL );
7389 boxH += ( marginT + marginR );
7390 case 2 : // border-box
7391 boxW += ( borderR + borderL );
7392 boxH += ( borderT + borderR );
7393 case 1 : // padding-box
7394 boxW += ( paddingR + paddingL );
7395 boxH += ( paddingT + paddingR );
7396 // case 0 : // content-box
7398 nodeData.boxWidth = boxW;
7399 nodeData.boxHeight = boxH;
7402 delete nodeData.dirty;
7406 BasicLayoutManager.finalValue = function( styleValue, styleMin, styleMax, srcValue ){
7407 var calc = BasicLayoutManager.calcValue,
7408 v = calc( styleValue, srcValue ),
7409 min = calc( styleMin, srcValue ),
7410 max = calc( styleMax, srcValue );
7411 if( v < min ) return min;
7412 if( max < v ) return max;
7415 BasicLayoutManager.calcValue = function( styleValue, srcValue ){
7416 if( styleValue === 0 ) return 0;
7418 if( styleValue === FULL || styleValue === AUTO ) return srcValue;
7419 if( 1 <= styleValue ) return styleValue; // legth
7420 if( -1 < styleValue ) return FLOOR( srcValue * styleValue ); // %
7421 return styleValue; // - length
7424 var NodeStylePrivate = Class.create(
7425 Class.PRIVATE_DATA | Class.POOL_OBJECT,
7427 colorCssText : null,
7428 layoutCssText : null,
7429 Constructor : function(){
7433 register : function( node ){
7434 var root = node.__root,
7435 roots = this.rootList,
7436 nodes = this.nodeList;
7438 this.rootList = [ root ];
7440 if( getIndex( roots, root ) === -1 ) roots[ roots.length ] = root;
7443 this.nodeList = [ node ];
7446 if( getIndex( nodes, node ) === -1 ) nodes[ nodes.length ] = node;
7448 unRegister : function( node ){
7449 var nodes = this.nodeList,
7450 i = getIndex( nodes, node ),
7452 roots = this.rootList,
7453 j = getIndex( roots, root );
7454 if( i !== -1 && nodes.splice( i, 1 ) && nodes.length === 0 ) delete this.nodeList;
7455 if( j !== -1 && roots.splice( j, 1 ) && roots.length === 0 ) delete this.rootList;
7458 var styleClass = Class.getClass( this.User ),
7459 dataClass = Class.getClass( this );
7461 attr : function( prop, v ){
7462 var update = prop[ 0 ],
7466 length = !!( type & DEF_ATTRS.LENGTH ),
7467 percent = !!( type & DEF_ATTRS.PERCENT ),
7468 color = !!( type & DEF_ATTRS.COLOR ),
7469 uDecimal = !!( type & DEF_ATTRS.U_DECIMAL ),
7470 numerical = !!( type & DEF_ATTRS.NUMERICAL ),
7471 flag = !!( type & DEF_ATTRS.BOOLEAN ),
7472 quartet = !!( type & DEF_ATTRS.QUARTET ),
7473 url = !!( type & DEF_ATTRS.URL ),
7474 fontName = !!( type & DEF_ATTRS.FONT_NAME ),
7475 //list = !!( type & DEF_ATTRS.LIST ),
7476 combi = !!( type & DEF_ATTRS.COMBI ),
7483 if( v !== undefined ){
7484 if( Type.isNumber( v ) === true ){
7485 if( numerical === false ){
7486 if( uDecimal === false || v < 0 || 1 < v ) throw new Error( '' );
7489 if( Type.isBoolean( v ) === true ){
7490 if( flag === false ) throw new Error( '' );
7492 if( Type.isString( v ) === true ){
7493 if( url === false && fontName === false ){
7494 if( v.indexOf( ' ' ) !== -1 ){
7497 if( length === false && percent === false && color === false ) throw new Error( '' );
7501 if( Type.isArray( v ) === true ){
7502 if( v.length <= 4 && quartet === true ){
7503 type ^= DEF_ATTRS.QUARTET;
7505 if( v.length === 2 && combi === true ){
7506 type ^= DEF_ATTRS.COMBI;
7508 throw new Error( '' );
7512 this.attr( [ propID , type, list ], v[ 0 ] );
7513 this.attr( [ ++propID, type, list ], v[ 0 ] );
7514 this.attr( [ ++propID, type, list ], v[ 0 ] );
7515 this.attr( [ ++propID, type, list ], v[ 0 ] );
7518 this.attr( [ propID , type, list ], v[ 0 ] );
7519 this.attr( [ ++propID, type, list ], v[ 1 ] );
7520 this.attr( [ ++propID, type, list ], v[ 0 ] );
7521 this.attr( [ ++propID, type, list ], v[ 1 ] );
7524 this.attr( [ propID , type, list ], v[ 0 ] );
7525 this.attr( [ ++propID, type, list ], v[ 1 ] );
7526 this.attr( [ ++propID, type, list ], v[ 2 ] );
7527 this.attr( [ ++propID, type, list ], v[ 1 ] );
7530 this.attr( [ propID , type, list ], v[ 0 ] );
7531 this.attr( [ ++propID, type, list ], v[ 1 ] );
7532 this.attr( [ ++propID, type, list ], v[ 2 ] );
7533 this.attr( [ ++propID, type, list ], v[ 3 ] );
7539 if( update === DEF_ATTRS.REFLOW ){
7540 delete this.layoutCssText;
7542 delete this.colorCssText;
7544 if( this.dirty < update ){
7545 this.dirty = update;
7546 roots = this.rootList;
7547 for( i = 0, l = roots.length; i < l; ++i ){
7549 if( root.dirty < update ) root.dirty = update;
7553 if( list ) _v = Util.getIndex( list, v );
7554 data[ propID ] = _v !== -1 ? _v : v;
7560 if( this.dirty === DEF_ATTRS.REFLOW ){
7561 roots = this.rootList;
7563 for( i = 0, l = roots.length; i < l; ++i ){
7564 roots[ i ].reflow();
7569 if( quartet === true ) return [ v, data[ ++propID ], data[ ++propID ], data[ ++propID ] ];
7570 if( combi === true ) return [ v, data[ ++propID ] ];
7571 if( list && Type.isNumber( v ) === true ) return list[ v ];
7574 cssText : function(){
7575 if( this.colorCssText === null ) this.colorCssText = this.createColorCssText();
7576 if( this.layoutCssText === null ) this.layoutCssText = this.createLayoutCssText();
7577 return this.colorCssText + ';' + this.layoutCssText;
7579 createColorCssText : function(){
7582 createLayoutCssText : function(){
7588 var NodeStyle = Class.create(
7593 Constructor : function(){
7594 NodeStyle.newPrivateData( this );
7596 borderWidth : function( v ){
7597 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.borderWidth, v );
7599 borderColor : function(){
7600 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.borderColor, v );
7602 borderStyle : function(){
7603 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.borderStyle, v );
7605 cornerRadius : function(){
7606 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.cornerRadius, v );
7608 bgColor : function(){
7609 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgColor, v );
7611 bgAlpha : function(){
7612 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgAlpha, v );
7614 bgImgUrl : function(){
7615 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgImgUrl, v );
7617 bgImgRepeatX : function(){
7618 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgImgRepeatX, v );
7620 bgImgRepeatY : function(){
7621 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgImgRepeatY, v );
7623 bgImgPositionX : function(){
7624 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgImgPositionX, v );
7626 bgImgPositionY : function(){
7627 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgImgPositionY, v );
7629 shadowColor : function(){
7630 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowColor, v );
7632 shadowAlpha : function(){
7633 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowAlpha, v );
7635 shadowOffsetX : function(){
7636 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowOffsetX, v );
7638 shadowOffsetY : function(){
7639 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowOffsetY, v );
7641 shadowBlur : function(){
7642 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowBlur, v );
7644 shadowSpread : function(){
7645 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowSpread, v );
7647 shadowInset : function(){
7648 return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowInset, v );
7650 color : function( v ){
7651 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.color, v );
7653 fontFamily : function( v ){
7654 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.fontFamily, v );
7656 fontSize : function( v ){
7657 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.fontSize, v );
7659 bold : function( v ){
7660 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.bold, v );
7662 italic : function( v ){
7663 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.italic, v );
7665 lineHeight : function( v ){
7666 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.lineHeight, v );
7668 letterSpacing : function( v ){
7669 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.letterSpacing, v );
7671 wordSpacing : function( v ){
7672 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.wordSpacing, v );
7674 align : function( v ){
7675 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.align, v );
7677 decoration : function( v ){
7678 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.decoration, v );
7680 transform : function( v ){
7681 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.transform, v );
7683 shadowColor : function( v ){
7684 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowColor, v );
7686 shadowOffsetX : function( v ){
7687 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowOffsetX, v );
7689 shadowOffsetY : function( v ){
7690 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowOffsetY, v );
7692 shadowBlur : function( v ){
7693 return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowBlur, v );
7695 cssText : function(){
7696 return TypoStyle.getPrivateData( this ).cssText();
7701 var NodePrivate = Class.create(
7703 Class.PRIVATE_DATA | Class.POOL_OBJECT,
7720 Constructor : function( __root, __parent ){
7721 this.__root = __root;
7722 if( __parent ) this.__parent = __parent;
7724 style : function( v ){
7725 if( v instanceof NodeStyle ){
7726 this.__style && this.__style.unRegister( this );
7728 this.__style = StylePrivate.getPrivateData( v );
7729 this.__style.register( this );
7733 this.__style && this.__style.unRegister( this );
7735 delete this.__style;
7742 * 2. auto 指定時は要素の高さ取得.
7743 * 3. 親の許す子の最大サイズと自信のスタイル指定から、自身の位置とサイズを計算
7746 reflow : function(){
7747 var content = this._textContent,
7748 style = this.__style,
7749 parent = this.__parent,
7752 if( content || ( style && style.hasPaint === true ) ){
7753 if( !this.elmWrap ){
7754 this.elmWrap = DOM.createDiv();
7755 parent.addDisplayElement( this );
7757 if( style && style.hasStyle === true ){
7758 this.elmWrap.style.cssText = style.cssText();
7761 if( !this.textNode ){
7762 this.textNode = DOM.cerateText();
7763 this.elmWrap.appendChild( this.textNode );
7765 if( style && ( style.autoWidth === true || style.autoHeight === true ) ){
7766 size = DOM.getTextSize( this.elmWrap, content );
7767 this.contentWidth = size[ 0 ];
7768 this.conetntHeight = size[ 1 ];
7770 this.textNode.data = content;
7772 if( this.textNode ){
7773 DOM.correct( this.textNode );
7774 delete this.textNode;
7775 delete this.contentWidth;
7776 delete this.conetntHeight;
7778 this.boxWidth = this.elmWrap.offsetWidth;
7779 this.boxHeight = this.elmWrap.offsetHeight;
7782 parent.removeDisplayElement( this );
7785 preSizing : function(){
7786 var parent = nodeData.__parent,
7787 allowW = parent.contentWidth,
7788 allowH = parent.contentHeight,
7789 style = nodeData.__style,
7790 x, y, w, minW, maxW, h, minH, maxH,
7793 paddingT, paddingR, paddingB, paddingL,
7794 borderT, borderR, borderB, borderL,
7795 marginT, marginR, marginB, marginL,
7799 styles = style.data;
7800 calc = BasicLayoutManager.calcValue;
7801 page = styles[ 54 ] === true ? allowH : allowW ;
7803 minW = styles[ 46 ];
7804 maxW = styles[ 47 ];
7805 contentW = BasicLayoutManager.finalValue( w, minW, maxW, allowW );
7807 minW = styles[ 49 ];
7808 maxW = styles[ 50 ];
7809 contentH = BasicLayoutManager.finalValue( h, minW, maxW, allowH );
7810 paddingT = calc( styles[ 51 ], page );// paddingTRBL の % 指定は 最大幅に対して TB でも幅に対して
7811 paddingR = calc( styles[ 52 ], allowW );
7812 paddingB = calc( styles[ 53 ], page );
7813 paddingL = calc( styles[ 54 ], allowW );
7814 borderT = styles[ 0 ];
7815 borderR = styles[ 1 ];
7816 borderB = styles[ 2 ];
7817 borderL = styles[ 3 ];
7818 marginT = calc( styles[ 55 ], page );// marginTRBL の % 指定は 最大幅に対して TB でも幅に対して
7819 marginR = calc( styles[ 56 ], allowW );
7820 marginB = calc( styles[ 57 ], page );
7821 marginL = calc( styles[ 58 ], allowW );
7822 this.boxWidth = contentW;
7823 this.boxHeight = contentH;
7824 switch( styles[ 53 ] ){
7825 case 3 : // margin-box
7826 contentW -= ( marginR + marginL );
7827 contentH -= ( marginT + marginR );
7829 case 2 : // border-box
7830 contentW -= ( borderR + borderL );
7831 contentH -= ( borderT + borderR );
7832 case 1 : // padding-box
7833 contentW -= ( paddingR + paddingL );
7834 contentH -= ( paddingT + paddingR );
7835 // case 0 : // content-box
7837 this.contentX = marginL + borderL + paddingL;
7838 this.contentY = marginT + borderT + paddingT;
7839 this.contentWidth = contentW;
7840 this.contentHeight = contentH;
7841 this.autoHeight = h === AUTO;
7842 this.autoWidth = w === AUTO;
7843 this.autoSize = this.autoWidth || this.autoHeight;
7845 this.boxWidth = this.contentWidth = allowW;
7846 this.boxHeight = this.contentHeight = allowH;
7847 delete this.contentX;
7848 delete this.contentY;
7849 delete this.autoSize;
7850 delete this.autoWidth;
7851 delete this.autoHeight;
7854 addDisplayElement : function( nodeData ){
7857 removeDisplayElement : function( nodeData ){
7858 DOM.correct( nodeData.elmWrap );
7859 delete nodeData.elmWrap;
7860 delete nodeData.textNode;
7861 delete nodeData.contentWidth;
7862 delete nodeData.conetntHeight;
7863 delete nodeData.currentWidth;
7864 delete nodeData.currentHeight;
7868 var Node = Class.create(
7873 Constructor : function( root, parent ){
7874 Node.newPrivateData( this, LayoutBox.getPrivateData( root ), parent ? LayoutBox.getPrivateData( parent ) : undefined, this );
7876 style : function( v ){
7877 return Node.getPrivateData( this ).paint( v );
7879 remove : function(){
7880 Node.getPrivateData( this ).remove();
7882 nodeIndex : function( v ){
7883 return Node.getPrivateData( this ).nodeIndex( v );
7885 displayIndex : function(){
7888 disabled : function( v ){
7889 return Node.getPrivateData( this ).disabled( v );
7891 cursor : function( v ){
7892 return Node.getPrivateData( this ).cursor( v );
7894 getAbsolutePositionX : function(){
7895 return Node.getPrivateData( this ).getAbsolutePositionX();
7897 getAbsolutePositionY : function(){
7898 return Node.getPrivateData( this ).getAbsolutePositionY();
7900 addEventListener : function( type, handler, opt_thisObject ){
7901 Node.getPrivateData( this ).addEventListener( type, handler, opt_thisObject );
7903 removeEventListener : function( type, handler ){
7904 Node.getPrivateData( this ).removeEventListener( type, handler );
7906 scrollTo : function( x, y ){
7907 Node.getPrivateData( this ).scrollTo( x, y );
7909 scrollX : function( v ){
7910 return Node.getPrivateData( this ).scrollX( v );
7912 scrollY : function( v ){
7913 return Node.getPrivateData( this ).scrollY( v );
7918 var LayoutBoxPrivate = NodePrivate.inherits(
7920 Class.POOL_OBJECT | Class.SUPER_ACCESS,
7922 Constructor : function( layoutManager, root, parent ){
7923 this.layoutManager = layoutManager;
7925 if( _parent ) this._parent = _parent;
7927 reflow : function(){
7928 this.layoutManager.reflow( this );
7933 var LayoutBox = Node.inherits(
7938 Constructor : function( layoutManager, root, parent ){
7939 LayoutBox.newPrivateData( this, layoutManager, LayoutBox.getPrivateData( root ), parent ? LayoutBox.getPrivateData( parent ) : undefined );
7941 layoutManager : function( v ){
7944 createLayoutBox : function(){
7947 createContentBox : function(){
7953 })( window, document );
7955 })( window, document );