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 CONSTRUCTOR = 'Constructor';
132 function getClass( instance ){
133 var clist = CLASS_LIST,
136 getIndex = Util.getIndex,
137 klass, def, live, pool;
139 klass = clist[ --i ];
141 //if( def.live && getIndex( def.live, instance ) !== -1 ) return klass;
142 if( def.pool && getIndex( def.pool, instance ) !== -1 ) return klass;
143 if( instance instanceof klass ) return klass;
145 // throw new Error( 'Class not found!' );
148 function getClassDef( KlassOrInstance ){
149 var i = Util.getIndex( CLASS_LIST, KlassOrInstance );
150 if( i === -1 ) i = Util.getIndex( CLASS_LIST, getClass( KlassOrInstance ) );
151 if( i !== -1 ) return DEF_LIST[ i ];
154 /* over のプロパティを target にコピーする.ただし target の プロパティが優先, force で解除 */
155 function override( target, over, force ){
156 for( var p in over ){
157 if( p === CONSTRUCTOR ) continue;
158 if( force === true || typeof target[ p ] === 'undefined' ){
159 target[ p ] = over[ p ];
166 * var subClass = superClass.inherits( ... )
167 * http://d.hatena.ne.jp/m-hiyama/20051018/1129605002
169 function inherits( /* classSetting, opt_PrivateClass, props */ ){
170 var args = c( arguments ),
172 superDef = getClassDef( Super ),
173 classSetting = args[ 0 ],
177 if( superDef.Final === true ) throw new Error( 'Class is final!' );
178 if( Type.isNumber( classSetting ) === true ){
179 opt_super = classSetting & Class.SUPER_ACCESS === 1;
182 opt_privateClass = getClass( args[ 0 ] );
183 opt_privateClass && args.shift();
184 abstractFlag = false;
187 klass = Class.create( classSetting, opt_privateClass || superDef.privateClass, override( Traits, args[ 0 ], true ) );
188 if( opt_super === true ) getClassDef( klass ).Super = Super.prototype;
192 /* Class.create で作られたクラスのインスタンスが共通で備えるメソッド */
197 klass = getClass( instance ),
198 def = getClassDef( klass ),
200 Type.isFunction( instance.onKill ) === true && instance.onKill();
202 for( p in instance ){
203 if( instance.hasOwnProperty && !instance.hasOwnProperty( p ) ) continue;
204 delete instance[ p ];
207 def.live.splice( Util.getIndex( def.live, instance ), 1 );
208 def.pool.push( instance );
210 if( def.privateClass ){
211 privateData = klass.getPrivateData( instance );
214 i = Util.getIndex( def.dataList, privateData );
215 def.dataList.splice( i, 1 );
216 def.userList.splice( i, 1 );
220 // myCallback を受け取った API への通知
222 myCallback : function( callback ){
223 var def = getClassDef( this ),
224 iList = def.callbackInstanceList,
225 rList = def.callbackRegisterList,
226 i, clist, myCallback;
228 iList = def.callbackInstanceList = [];
229 rList = def.callbackRegisterList = [];
231 i = Util.getIndex( iList, this );
234 index = iList.length;
239 for( i = cList.length; i; ){
240 if( cList[ --i ].callback === callback ) return cList[ i ];
243 myCallback = new Callback( this, callback );
244 cList.push( myCallback );
248 /* privateDataclass をもつクラスに追加されるメソッド */
249 function newPrivateData( instance /*, args */ ){
250 var def = getClassDef( instance ),
251 privateClass = def.privateClass,
252 i = Util.getIndex( def.userList, instance ),
253 args = c( arguments ),
256 throw new Error( 'PrivateData already exist!' );
260 data = I.apply( privateClass, args );
262 def.dataList.push( data );
263 def.userList.push( instance );
266 function getPrivateData( instance ){
267 var def = getClassDef( instance ),
268 i = Util.getIndex( def.userList, instance );
269 if( i !== -1 ) return def.dataList[ i ];
273 * new の実体.コンストラクタの機能は instance.Constructor に書く.
274 * これにより pool された オブジェクト(破棄されたインスタンス) を再利用できる
276 var abstractFlag = true,
283 def = getClassDef( klass ),
285 if( def.Abstract === true || abstractFlag === false ){
286 if( abstractFlag === true ){
287 throw new Error( 'AbstractClass!' );
290 instance = new klass();
294 if( def.isPrivate === true && privateFlag === true ){
295 throw new Error( 'use class.newPrivateData( instance, args )!' );
297 if( def.pool && def.pool.length > 0 ){
298 instance = def.pool.shift();
301 instance = new klass();
304 if( def.Super && !instance.Super ){
305 instance.Super = def.Super;
307 def[ CONSTRUCTOR ] && def[ CONSTRUCTOR ].apply( instance, c( arguments ) );
308 def.live && def.live.push( instance );
317 create : function( /* classSetting, opt_PrivateClass, props */ ){
318 var args = c( arguments ),
319 classSetting = args[ 0 ],
320 opt_pool, opt_abstract, opt_final,
325 if( Type.isNumber( classSetting ) === true ){
326 opt_pool = classSetting & Class.POOL_OBJECT === 1;
327 opt_abstract = classSetting & Class.ABSTRACT === 1;
328 opt_final = classSetting & Class.FINAL === 1;
331 if( opt_final === true && opt_abstract === true ){
332 throw new Error( 'final & Abstract!' );
335 privateDef = getClassDef( args[ 0 ] );
337 if( privateDef.isPrivate !== true ){
338 throw new Error( 'PrivateClass not found! please, Class.createPrivateData().' );
340 if( privateDef.Abstract === true ){
341 throw new Error( 'PrivateClass is Abstract!' );
343 classDef.privateClass = args[ 0 ];
344 klass.newPrivateData = newPrivateData;
345 klass.getPrivateData = getPrivateData;
350 if( props === null || Type.isObject( props ) === false ){
351 throw new Error( 'No Class Def!' );
354 klass = function(){ a = arguments; if( f ) return I.apply( a.callee, c( a ) )};
355 klass.prototype = override( override( {}, props, true ), ClassBase, false );
357 if( Type.isFunction( props[ CONSTRUCTOR ] ) === true ){
358 classDef[ CONSTRUCTOR ] = props[ CONSTRUCTOR ];
360 if( opt_final !== true ){
361 klass.inherits = inherits;
365 if( opt_abstract === true ){
366 classDef.Abstract = true;
368 if( opt_pool === true ){
372 CLASS_LIST.push( klass );
373 DEF_LIST.push( classDef );
376 createPrivateData : function( props, opt_abstract, opt_final ){
377 var klass = Class.create( props, true, opt_abstract, opt_final ),
378 classDef = getClassDef( klass );
379 classDef.isPrivate = true;
380 classDef.userList = [];
381 classDef.dataList = [];
384 onShutdown : function(){
391 * Callback 時に thisObject や args を指定したい場合に使用.
393 var Callback = Class.create(
394 Class.POOL_OBJECT | Class.FINAL, {
395 Constructor : function( thisObject, callback, opt_args ){
396 if( Type.isFunction( callback ) === false ){
397 throw new Error( 'Not function!' );
399 this.callback = callback;
400 if( thisObject ) this.thisObject = thisObject;
401 if( Type.isArray( opt_args ) === true ){
402 this.args = opt_args;
404 if( opt_args !== undefined ){
408 fire : function( /* args */ ){
409 var thisObject = this.thisObject || window,
410 args = Util.copyArray( arguments );
411 if( 0 < args.length ){
412 if( this.args !== undefined ){
413 args.push.apply( args, this.args );
415 if( this.arg !== undefined ){
416 args.push( this.arg );
418 this.callback.apply( thisObject, args );
420 if( this.args !== undefined ){
421 this.callback.apply( thisObject, this.args );
423 if( this.arg !== undefined ){
424 this.callback.call( thisObject, this.arg );
426 this.callback.call( thisObject );
430 registerUser : function( user ){
437 var TicketBase = function(){
438 this.kill = function(){
441 if( t.hasOwnProperty && !t.hasOwnProperty( p ) ) continue;
443 v && v instanceof TicketBase && v.kill();
451 /* --------------------------------------------------------------
456 var SystemTimer = ( function(){
457 var setTimeout = window.setTimeout;
458 var clearTimeout = window.clearTimeout;
459 var INTERVAL_TIME = 16;
460 var TICKET_LIST = [];
461 var timerId = undefined;
465 for( var i = 0; i < TICKET_LIST.length; ) {
466 if( TICKET_LIST[ i ].call( next ) !== false ) ++i;
472 var l = TICKET_LIST.length,
476 timerId !== undefined && clearTimeout( timerId );
480 for( var i = 0; i<l; i++ ){
481 c = TICKET_LIST[ i ].count;
484 if( next > n || timerId === undefined ){
485 timerId !== undefined && clearTimeout( timerId );
486 timerId = setTimeout( loop, INTERVAL_TIME * n );
491 var TimerTicketClass = function( _apiuser, _callback, _time, _once, opt_thisObject ){
492 this.apiuser = _apiuser;
493 this.callback = _callback;
497 this.thisObj = opt_thisObject;
499 TimerTicketClass.prototype = new TicketBase();
500 TimerTicketClass.prototype.call = function( c ){
502 if( this.count <= 0 ){
503 this.callback.call( this.thisObj || this.apiuser );
504 if( this.once === true ){
506 TICKET_LIST.splice( Util.getIndex( TICKET_LIST, this ), 1 );
509 this.count = this.time;
513 TimerTicketClass.prototype.destroy = function( _apiuser, _callback ){
514 if( _apiuser && _apiuser !== this.apiuser ) return false;
515 if( _callback && _callback !== this.callback ) return false;
522 add: function( _apiuser, _handler, _time, _once, opt_thisObject ){
523 if( Type.isNumber( _time ) === false || _time < INTERVAL_TIME ) _time = INTERVAL_TIME;
525 var _ticket = new TimerTicketClass( _apiuser, _handler, Math.ceil( _time / INTERVAL_TIME ), _once, opt_thisObject );
526 TICKET_LIST.push( _ticket );
530 remove: function( _apiuser, _handler ){
533 while( _ticket = TICKET_LIST[ i ] ){
534 if( _ticket.destroy( _apiuser, _handler ) === true ){
535 TICKET_LIST.splice( i, 1 );
545 /* --------------------------------------------------------------
549 var AsyncCall = ( function(){
550 var CALLBACK_LIST = [];
552 var CallbackTicketClass = function( _apiuser, _callback, _argments, _thisObject ){
553 this.apiuser = _apiuser;
554 this.callback = _callback;
555 this.argments = _argments;
556 this.thisObject = _thisObject;
558 CallbackTicketClass.prototype = new TicketBase();
559 CallbackTicketClass.prototype.call = function(){
560 var f = this.callback,
564 if( Type.isArray( a ) === true ){
570 CallbackTicketClass.prototype.destroy = function( _apiuser, _callback ){
571 if( _apiuser && _apiuser !== this.apiuser ) return false;
572 if( _callback && _callback !== this.callback ) return false;
579 var _ticket = CALLBACK_LIST.shift();
582 CALLBACK_LIST.length !== 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true );
587 add: function( _apiuser, _callback, _argments, _thisObject ){
588 CALLBACK_LIST.length === 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true );
589 CALLBACK_LIST.push( new CallbackTicketClass( _apiuser, _callback, _argments, _thisObject || _apiuser ) );
591 remove: function( _apiuser, _callback ){
594 while( _ticket = CALLBACK_LIST[ i ] ){
595 if( _ticket.destroy( _apiuser, _callback ) === true ){
596 CALLBACK_LIST.splice( i, 1 );
605 /* -----------------------------------------------------------
607 * お気に入り画像一覧 > tag:ペン次郎 > ペン次郎:笑う
608 * 最近アップロードされた画像 > images
610 * キャラクター画像庫 > アニマル系 > tag:ペン次郎 > ペン次郎:笑う
617 var File = ( function(){
618 var DRIVER_LIST = [];
620 var FILE_TYPE_IS_FOLDER = Const.FILE.TYPE.FOLDER,
621 numFileType = Const.FILE.TYPE.XML,
622 FILEDATA_RESITER = [], // store all of fileData( json object )
623 FILEDATA_ACCESS = [], // file operations for Kernel only ! hide from Out of File
624 FILE_OBJECT_POOL = [],
625 EVENT_LISTENER_REGISTER = [],
627 TREE_ACCESS_ARRAY = [];
629 var REQUEST_CONTROLER = ( function(){
630 var REQUEST_TICKET_RESISTER = [],
631 currentTicket = null,
633 DATA_TYPE_ARRAY = 'json,xml,html,text'.split( ','),
640 var RequestTicketClass = function( _apiuser, _type, _data, _url, _onLoad, _onError ){
641 this.apiuser = _apiuser;
645 this.onLoad = _onLoad;
646 this.onError = _onError;
648 _apiuser = _type = _data = _onLoad = _onError = null;
650 RequestTicketClass.prototype = new TicketBase();
651 RequestTicketClass.prototype.load = function( _data ){
652 AsyncCall.add( this.apiuser, this.onLoad, [ this.data, _data ] );
654 RequestTicketClass.prototype.error = function(){
655 AsyncCall.add( this.apiuser, this.onError, this.data );
659 if( currentTicket !== null || REQUEST_TICKET_RESISTER.length === 0 ) return;
660 currentTicket = REQUEST_TICKET_RESISTER.shift();
662 url: currentTicket.url,
663 dataType: DATA_TYPE_ARRAY[ currentTicket.type ],
668 function onSuccess( _data ){
669 currentTicket.load( _data );
670 currentTicket.kill();
671 currentTicket = null;
676 currentTicket.error();
677 currentTicket.kill(); // retry
678 currentTicket = null;
683 getNumTask: function(){
684 return REQUEST_TICKET_RESISTER.length;
686 getNumError: function(){
689 getJson: function( _apiuser, _data, _url, _onLoad, _onError ){
690 REQUEST_TICKET_RESISTER.push( new RequestTicketClass( _apiuser, DATA_IS_JSON, _data, _url, _onLoad, _onError ));
691 currentTicket === null && request();
696 var FILE_CONTROLER = {
697 createTree: function( _apiuser, _rootFileData ){
698 var _tree = new TreeClass( _apiuser, _rootFileData );
699 TREE_ARRAY.push( _tree );
702 getFileUID: function( FILEDATAorFILE ){
703 if( FILEDATAorFILE instanceof FileClass ){
704 return FILEDATAorFILE.getUID();
707 var uid = Util.getIndex( FILEDATA_RESITER, FILEDATAorFILE );
709 uid = FILEDATA_RESITER.length;
710 FILEDATA_RESITER.push( FILEDATAorFILE );
714 getFileDataAccess: function( UIDorFILEorFILEDATA ){
715 var _uid, _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA ), _access;
717 if( _data === null || typeof _data !== 'object' ) return null;
718 for( var i=0, l = FILEDATA_ACCESS.length; i<l; ++i ){
719 _access = FILEDATA_ACCESS[ i ];
720 if( _access.DATA === _data ) return _access;
724 getFileData: function( UIDorFILEorFILEDATA ){
725 if( typeof UIDorFILEorFILEDATA === 'number' ){
726 return FILEDATA_RESITER[ UIDorFILEorFILEDATA ] || null;
728 if( UIDorFILEorFILEDATA instanceof FileClass ){
729 return FILEDATA_RESITER[ UIDorFILEorFILEDATA.getUID() ] || null;
731 if( Util.getIndex( FILEDATA_RESITER, UIDorFILEorFILEDATA ) !== -1 ){
732 return UIDorFILEorFILEDATA;
736 getChildren: function( UIDorFILEorFILEDATA ){
737 var _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA );
738 return _data !== null ? _data.children || null : null;
740 getDriver: function( _file ){
741 var _data = FILE_CONTROLER.getFileData( _file );
742 return _data !== null && _data.driver ? _data.driver : BASE_DRIVER;
744 getUpdateFlag: function( _file, _bit ){
745 var _driver = FILE_CONTROLER.getDriver( _file ),
747 if( typeof _driver.getUpdatePolicy === 'function' ){
748 _policy = _driver.getUpdatePolicy( _file );
751 if( typeof _policy !== 'number' ) {
752 _policy = BASE_DRIVER.getUpdatePolicy( _file )
754 return _policy % ( _bit * 2 ) >= _bit;
756 move: function( _prentUID, _targetfile, _newFolder, _newIndex, _opt_callback ){
757 var _parentData = FILE_CONTROLER.getFileDataAccess( _prentUID ),
758 _parentType = _parentData.TYPE,
759 _targetData = FILE_CONTROLER.getFileDataAccess( _targetfile ),
760 _targetType = _targetData.TYPE;
762 replace: function( _uid, _file, _newIndex ){
765 addEventListener: function( FILEorNULL, _eventType, _callback, opt_thisObject ){
766 var _uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL;
767 EVENT_LISTENER_REGISTER.push( new FileEventTicketClass( _uid, _eventType, _callback, opt_thisObject ));
769 removeEventListener: function( FILEorNULL, _eventType, _callback ){
770 var _uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL,
772 for(var i=0, l = EVENT_LISTENER_REGISTER.length; i<l; ++i ){
773 _ticket = EVENT_LISTENER_REGISTER[ i ];
774 if( _ticket.fileUID === _uid && _ticket.eventType === _eventType && _ticket.callBack === _callback ){
775 EVENT_LISTENER_REGISTER.splice( i, 1 );
780 getTreeAccess: function(){
783 fileEventRellay: function( _uid, _event ){
784 var _fileAccess = FILE_CONTROLER.getFileDataAccess( _uid );
785 if( _fileAccess === null ) return;
786 var _treeUID = _fileAccess.TREE.getUID(),
787 _treeAccess = TREE_ACCESS_ARRAY[ _treeUID ],
788 _data = _fileAccess.DATA,
790 if( !_treeAccess ) return;
791 _treeAccess.dispatchFileEvent( _event );
792 for( var i=0, l = TREE_ARRAY.length; i<l; ++i ){
793 if( i !== _treeUID ){
794 _tree = TREE_ARRAY[ i ];
795 if( FILE_CONTROLER.getFileData( _tree.getCurrentFile() ) === _data ){
796 _treeAccess = TREE_ACCESS_ARRAY[ _tree.getUID() ];
797 _treeAccess && _treeAccess.dispatchFileEvent( _event );
804 var TreeClass = function( apiuser, rootFileData ){
805 var PARENT_FILE_RESITER = [],
808 dispatchFileEvent: dispatchFileEvent
810 EVENT_LISTENER_ARRAY = [],
812 rootFile = new FileClass( instance, null, rootFileData ),
813 currentFile = rootFile;
815 currentFile.getSeqentialFiles();
816 TREE_ACCESS_ARRAY.push( ACCESS );
818 function dispatchFileEvent( e ){
819 var _eventType = e.eventType,
820 _targetFile = e.targetFile,
821 _uid = _targetFile.getUID(),
822 _ticket, _type, _callback;
823 for( var i=0, l = EVENT_LISTENER_REGISTER.length; i<l; ++i ){
824 _ticket = EVENT_LISTENER_REGISTER[ i ];
825 _type = _ticket.eventType;
826 _callback = _ticket.callBack;
827 if( _eventType === _type && _uid === _ticket.fileUID ){
828 AsyncCall.add( apiuser, _callback, [ _eventType, _targetFile, e.key, e.value ], _ticket.thisObject || _targetFile );
830 if( _type === Const.TREE.EVENT.UPDATE && _eventType === Const.FILE.EVENT.GET_SEQENTIAL_FILES ){
831 //_callback( _eventType, _targetFile );
832 AsyncCall.add( apiuser, _callback, [ _eventType, _targetFile ], _ticket.thisObject || instance );
837 this.getUID = function(){
838 return Util.getIndex( TREE_ACCESS_ARRAY, ACCESS );
840 this.getRootFile = function(){
843 this.getCurrentFile = function(){
846 this.hierarchy = function(){
847 return PARENT_FILE_RESITER.length;
849 this.getParentFileAt = function( _index ){
850 var l = PARENT_FILE_RESITER.length;
851 if( typeof _index !== 'number' || _index < 0 || _index >= l ) return null;
852 return PARENT_FILE_RESITER[ l -1 -_index ];
854 this.down = function( _index ){
855 if( typeof _index !== 'number' || _index < 0 || _index >= currentFile.getChildFileLength()) return;
856 PARENT_FILE_RESITER.unshift( currentFile );
857 currentFile = currentFile.getChildFileAt( _index );
858 currentFile.getSeqentialFiles();
861 this.up = function( _index ){
862 var l = PARENT_FILE_RESITER.length;
863 if( l === 0 ) return null;
866 var _currentFile = currentFile;
868 _currentFile.destroy();
870 if( typeof _index === 'number' ){
871 if( _index >= l ) return null;
872 currentFile = this.getParentFileAt( _index );
873 PARENT_FILE_RESITER.splice( 0, l -_index);
875 currentFile = PARENT_FILE_RESITER.shift();
877 currentFile.getSeqentialFiles();
880 this.addTreeEventListener = function( _eventType, _callback, opt_thisObject ){
881 FILE_CONTROLER.addEventListener( null, _eventType, _callback, opt_thisObject );
883 this.removeTreeEventListener = function( _eventType, _callback ){
884 FILE_CONTROLER.removeEventListener( null, _eventType, _callback );
886 this.destroy = function( _apiuser ){
887 if( _apiuser && apiuser !== _apiuser ) return false;
889 var _currentFile = currentFile;
890 currentFile = rootFile = rootFileData = null;
891 // currentFile, rootFile を null にしないと .File.destroy() ができない.
892 _currentFile.destroy();
893 while( PARENT_FILE_RESITER.length > 0 ){
894 _currentFile = PARENT_FILE_RESITER.shift();
895 _currentFile.destroy();
898 AsyncCall.remove( apiuser );
899 instance = apiuser = null;
904 var FileEventTicketClass = function( uid, eventType, callback, opt_thisObject ){
906 this.eventType = eventType;
907 this.callBack = callback;
908 this.thisObject = opt_thisObject;
910 FileEventTicketClass.prototype = new TicketBase();
912 var FileEventClass = function( eventType, file, key, value ){
913 this.eventType = eventType;
914 this.targetFile = file;
915 this.updatedAttribute = key;
916 this.updatedValue = value;
920 * file の data は object で保持している。
921 * File の外からファイルをみるときは、FileClassを通して操作する。
922 * fileの変更、それに付随して追加されたイベントは、TreeClassで管理される。
923 * treeがdestryされると、fileのイベントリスナーも全て削除される。
924 * 他の tree も data の共通する currentFile に対してのみは、file の変更イベントを受け取って流す.
928 var FileClass = function( tree, parentData, data ){
929 var uid = FILE_CONTROLER.getFileUID( data );
931 FILEDATA_ACCESS.push( {
933 parentData: parentData,
937 tree = parentData = data = null;
939 this.getUID = function(){
944 FileClass.prototype = {
945 isChildFile: function( _FILEorFILEDATA ){
946 return this.getChildFileIndex( _FILEorFILEDATA) !== -1;
948 getSeqentialFiles: function(){
949 var _driver = FILE_CONTROLER.getDriver( this );
950 if( _driver !== null && typeof _driver.getSeqentialFiles === 'function' ){
951 _driver.getSeqentialFiles( this );
954 addEventListener: function( _eventType, _callback ){
955 FILE_CONTROLER.addEventListener( this, _eventType, _callback );
957 removeEventListener: function( _eventType, _callback ){
958 FILE_CONTROLER.removeEventListener( this, _eventType, _callback );
960 dispatchEvent: function( e ){
961 e instanceof FileEventClass && FILE_CONTROLER.fileEventRellay( this.getUID(), e );
963 getChildFileLength: function(){
964 var children = FILE_CONTROLER.getChildren( this );
965 return Type.isArray( children ) === true ? children.length : -1;
967 getChildFileIndex: function( _FILEorFILEDATA ){
968 var children = FILE_CONTROLER.getChildren( this );
969 if( Type.isArray( children ) === false ) return -1;
970 var l = children.length,
971 _fileData = FILE_CONTROLER.getFileData( _FILEorFILEDATA );
972 if( _fileData === null ) return -1;
973 for( var i=0; i<l; ++i ){
974 if( children[ i ] === _fileData ) return i;
978 getChildFileAt: function( _index ){
979 var _access = FILE_CONTROLER.getFileDataAccess( this ),
980 _children = FILE_CONTROLER.getChildren( this );
981 if( typeof _index !== 'number' || _index < 0 || Type.isArray( _children ) === false || _index >= _children.length ) return null;
982 var _file = new FileClass( _access.TREE, _access.DATA, _children[ _index ]);
987 var driver = FILE_CONTROLER.getDriver( this );
988 if( typeof driver.getName === 'function'){
989 return driver.getName( this );
991 return BASE_DRIVER.getName( this);
993 getThumbnail: function(){
994 var driver = FILE_CONTROLER.getDriver( this );
995 if( typeof driver.getThumbnail === 'function'){
996 return driver.getThumbnail( this );
998 return BASE_DRIVER.getThumbnail( this );
1000 getType: function(){
1001 var _data = FILE_CONTROLER.getFileData( this );
1002 return typeof _data.type === 'number' ? _data.type : Const.FILE.TYPE.UNKNOWN;
1004 getState: function(){
1005 var _data = FILE_CONTROLER.getFileData( this );
1006 return typeof _data.state === 'number' ? _data.state : Const.FILE.STATE.OK;
1008 getSummary: function(){
1009 var driver = FILE_CONTROLER.getDriver( this );
1010 if( typeof driver.getSummary === 'function'){
1011 return driver.getSummary( this );
1013 return BASE_DRIVER.getSummary( this );
1015 isWritable: function(){
1016 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.WRITE );
1018 isSortable: function(){
1019 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.SORT );
1021 isCreatable: function(){
1022 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.CREATE );
1024 isRenamable: function(){
1025 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.RENAME );
1027 isDeletable: function(){
1028 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.DELETE );
1032 var driver = FILE_CONTROLER.getDriver( this ),
1034 if( typeof driver.read === 'function'){
1035 data = driver.read( this );
1037 return BASE_DRIVER.read( data || this );
1039 write: function( _newData, _onUpdateFunction ){
1040 var driver = FILE_CONTROLER.getDriver( this );
1041 if( typeof driver.write === 'function'){
1042 return driver.write( this, _newData, _onUpdateFunction );
1044 return BASE_DRIVER.write( this, _newData, _onUpdateFunction );
1046 viewerApplicationList: function(){
1047 var driver = FILE_CONTROLER.getDriver( this );
1048 if( typeof driver.viewerApplicationList === 'function'){
1049 return driver.viewerApplicationList( this );
1051 return BASE_DRIVER.viewerApplicationList( this );
1053 editorApplicationList: function(){
1054 var driver = FILE_CONTROLER.getDriver( this );
1055 if( typeof driver.editorApplicationList === 'function'){
1056 return driver.editorApplicationList( this );
1058 return BASE_DRIVER.viwerApps( this );
1069 onDelete: function(){
1072 move: function( _newFolder, _newIndex, opt_callback ){
1073 var _access = FILE_CONTROLER.getFileDataAccess( this );
1074 _access.TREE.move( _access.parentData, this.getUID(), _newFolder, _newIndex, opt_callback );
1076 replace: function( _newIndex, opt_callback ){
1077 var _access = FILE_CONTROLER.getFileDataAccess( this );
1078 _access.TREE.replace( _access.parentData, this.getUID(), _newIndex, opt_callback);
1082 * 探しているファイルの属性と値を指定.一致する child の index を配列で返す.
1084 search: function( obj, rule ){
1085 var _children = FILE_CONTROLER.getChildren( this ),
1088 for( var i=0, l=_children.length; i<l; ++i ){
1089 _child = _children[ i ];
1092 if( obj[ k ] !== _child[ k ] ){
1097 c === true && ret.push( i );
1101 destroy: function(){
1102 var _access = FILE_CONTROLER.getFileDataAccess( this );
1103 var _tree = _access.TREE;
1104 if( _tree.getCurrentFile() === this ) return;
1105 if( _tree.getRootFile() === this ) return;
1106 for( var i=0, l = _tree.hierarchy(); i<l; ++i ){
1107 if( _tree.getParentFileAt( i ) === this ){
1111 var _index = Util.getIndex( FILEDATA_ACCESS, _access );
1112 if( _index === -1 ) return;
1114 FILEDATA_ACCESS.splice( _index, 1 );
1115 delete _access.DATA;
1116 delete _access.TREE;
1117 delete _access.parentData;
1124 var FileDriverBase = function( driverClass ){
1125 this.getUID = function(){
1126 return Util.getIndex( API_USER_LIST, driverClass );
1128 this.getSeqentialFiles = function( _file ){
1130 this.getName = function( _file ){
1131 var _data = FILE_CONTROLER.getFileData( _file );
1132 return _data.name || 'No Name';
1134 this.getThumbnail = function( _file ){
1135 var _data = FILE_CONTROLER.getFileData( _file ),
1138 if( _type === Const.FILE.TYPE.FOLDER ){
1139 _className = 'folder';
1141 if( _type === Const.FILE.TYPE.IMAGE ){
1144 if( _type === Const.FILE.TYPE.TEXT ){
1147 if( _type === Const.FILE.TYPE.HTML ){
1150 if( _type === Const.FILE.TYPE.CSV ){
1153 if( _type === Const.FILE.TYPE.JSON ){
1156 if( _type === Const.FILE.TYPE.XML ){
1161 className: ' file-type-' + _className
1164 this.getSummary = function( _file ){
1165 var _data = FILE_CONTROLER.getFileData( _file ),
1167 if( _type === Const.FILE.TYPE.FOLDER ){
1170 if( _type === Const.FILE.TYPE.IMAGE ){
1171 return 'image file';
1173 if( _type === Const.FILE.TYPE.TEXT ){
1176 if( _type === Const.FILE.TYPE.HTML ){
1177 return 'html document file';
1179 if( _type === Const.FILE.TYPE.CSV ){
1180 return 'csv daat file';
1182 if( _type === Const.FILE.TYPE.JSON ){
1183 return 'json data file';
1185 if( _type === Const.FILE.TYPE.XML ){
1186 return 'xml data file';
1190 this.getUpdatePolicy = function( _file ){
1191 // debug用 全てのメニューを許可
1192 return Const.FILE.UPDATE_POLICY.DSRWC;
1194 this.read = function( _FILEorDATA ){
1196 protects = Const.FILE.DATA_PROPERTY_RESERVED;
1197 if( _FILEorDATA instanceof FileClass ){
1198 data = FILE_CONTROLER.getFileData( _FILEorDATA )
1203 function clone( src ) {
1205 if( Type.isArray(src) === true ){
1208 if( Type.isObject(src) === true ){
1211 if( Type.isNumber(src) === true || Type.isString(src) === true || Type.isBoolean( src ) === true ){
1216 for( var key in src ){
1217 if( Util.getIndex( protects, key ) === -1 ){
1218 ret[ key ] = clone( src[ key ]);
1224 return clone( data );
1226 this.write = function( _file, _newData, _onUpdateFunction ){
1227 var _data = FILE_CONTROLER.getFileData( _file ),
1231 this.viewerApplicationList = function(){
1234 this.editorApplicationList = function(){
1237 this.onCreate = function(){
1240 this.onSort = function(){
1243 this.onCopy = function(){
1246 this.onDelete = function(){
1251 var BASE_DRIVER = new FileDriverBase();
1253 var ROOT_FILEDATA = {
1254 name: 'system root',
1255 type: FILE_TYPE_IS_FOLDER,
1258 SYSTEM_TREE = FILE_CONTROLER.createTree( SUPER_USER_KEY, ROOT_FILEDATA ),
1259 ROOT_FILE = SYSTEM_TREE.getRootFile();
1261 function createFileTypeID(){
1262 return ++numFileType;
1265 var FileAPIClass = function( driver ){
1267 this.createFolderUnderRoot = function( _fileData ){
1268 if( _fileData !== null && Type.isObject( _fileData ) === true ){
1269 ROOT_FILEDATA.children.push( _fileData );
1270 ROOT_FILE.dispatchEvent( new FileEventClass( Const.FILE.EVENT.GET_SEQENTIAL_FILES, ROOT_FILE, 'children', null ));
1273 this.createFileEvent = function( _eventType, _file, _key, _value ){
1274 return new FileEventClass( _eventType, _file, _key, _value );
1276 this.createFileTypeID = createFileTypeID;
1277 this.getFileDataAccess = FILE_CONTROLER.getFileDataAccess;
1278 this.getFileData = FILE_CONTROLER.getFileData;
1279 this.getJson = function( _data, _url, _onLoad, _onError ){
1280 REQUEST_CONTROLER.getJson( driver, _data, _url, _onLoad, _onError );
1282 this.createTree = function( _rootFile ){
1283 return FILE_CONTROLER.createTree( driver, _rootFile );
1285 this.isTreeInstance = function( _tree ){
1286 return _tree instanceof TreeClass;
1288 this.isFileInstance = function( _file ){
1289 return _file instanceof FileClass;
1291 this.isFileEvent = function( _event ){
1292 return _event instanceof FileEventClass;
1294 this.getConst = function(){
1295 return Const; // constObject = constObject || clone( Const )
1300 registerDriver: function( _class ){
1301 _class.prototype = new FileDriverBase( _class );
1302 var _driver = new _class();
1304 DRIVER_LIST.push( _driver );
1305 API_USER_LIST.push( _class );
1307 return new FileAPIClass( _driver );
1309 isDriver: function( _driver ){
1310 return _driver instanceof FileDriverBase;
1312 isTreeInstance: function( _tree ){
1313 return _tree instanceof TreeClass;
1315 isFileInstance: function( _file ){
1316 return _file instanceof FileClass;
1322 /* ----------------------------------------------------
1323 * ApplicationManager
1324 * window resize event, overlayApplication currentAplication に流す
1327 var APPLICATION_LIST = [];
1329 var ApplicationPrivateData = function(){};
1330 ApplicationPrivateData.prototype = {
1336 bgColor : '#C1CACF',
1348 init : function( appClass, displayName, isOverlay ){
1349 this.appClass = appClass;
1350 // this.application = app;
1351 this.displayName = displayName;
1352 this.isOverlay = isOverlay;
1353 this.rootElement = document.createElement( 'div' );
1354 this.styleCursor = this.rootElement.style;
1355 ApplicationPrivateData.list.push( this );
1357 detect : function(){
1358 if( this.rootElement.firstChild && this.fetchResource === 0 ){
1359 SystemTimer.remove( this.application, this.detect );
1363 onOpen : function(){
1364 this.rootElement.style.display = '';
1366 // this.layer !== null && this.layer.onResize( this.w, this.h );
1368 if( this.application.MIN_WIDTH > this.w || this.application.MIN_HEIGHT > this.h ){
1369 if( Type.isHTMLElement( this.rootElement ) === true ){
1373 if( this.bootParams.length > 2 ){
1374 this.application.onOpen.apply( this.application, this.bootParams );
1376 this.application.onOpen( this.w, this.h );
1380 fetchResourceComplete : function(){
1381 --this.fetchResource;
1384 ApplicationPrivateData.list = [];
1385 ApplicationPrivateData.get = function( app ){
1386 var list = ApplicationPrivateData.list,
1389 if( app instanceof list[ --i ].appClass ) return list[ i ];
1394 var AbstractApplication = function( appClass, displayName, isOverlay ){
1395 ( new ApplicationPrivateData() ).init( appClass, displayName, isOverlay );
1397 AbstractApplication.prototype = {
1398 getUID : function(){
1399 var data = ApplicationPrivateData.get( this );
1400 return Util.getIndex( API_USER_LIST, data.appClass );
1403 var data = ApplicationPrivateData.get( this );
1404 // this.rootElement = data.rootElement;
1405 // data.application = this;
1407 data.appClass === Page.appClass && Page.show();
1411 open : function( w, h /*, _option */ ){
1412 var data = ApplicationPrivateData.get( this );
1414 data.bootParams = Util.copyArray( arguments );
1417 if( data.rootElement.innerHTML && data.rootElement.innerHTML.length > 0 ){
1418 SystemTimer.add( this, data.detect, 16, false, data );
1423 resize : function( w, h ){
1424 var data = ApplicationPrivateData.get( this );
1425 if( data.phase !== 4 ) return;
1426 if( this.MIN_WIDTH > w || this.MIN_HEIGHT > h ){
1427 if( Type.isHTMLElement( this.rootElement ) === true ){
1432 this.onPaneResize( w, h );
1435 var data = ApplicationPrivateData.get( this );
1437 if( this.onClose() === false ){
1441 while( data.uiList.length > 0 ) data.uiList.shift().destroy();
1443 if( data.finderList ){
1444 while( data.finderList.length > 0 ) data.finderList.shift().destroy();
1447 data.eventRoot && PointingDeviceEventTree.destroyTree( data.eventRoot );
1448 MouseEvent.remove( this );
1449 KeyEvent.remove( this );
1450 SystemTimer.remove( this );
1451 AsyncCall.remove( this );
1452 StyleSheet.unload( this );
1454 var elm = this.rootElement;
1455 Util.removeAllChildren( elm );
1456 elm.parentNode.removeChild( elm );
1458 Application.shutdown( this, data.isOverlay );
1460 data.appClass === Page.appClass && Page.hide();
1464 var list = ApplicationPrivateData.list;
1465 list.splice( Util.getIndex( list, data ), 1 );
1467 createUIGroup : function( node ){
1468 var data = ApplicationPrivateData.get( this ),
1469 ui = UI.createUIGroup( this, node );
1470 if( data.uiList === null ) data.uiList = [];
1471 data.uiList.push( ui );
1474 createUIForm : function( nodeOrElm, opt_elmForm ){
1475 var data = ApplicationPrivateData.get( this ),
1476 form = UIForm.createForm( this, nodeOrElm, opt_elmForm );
1477 if( data.formList === null ) data.formList = [];
1478 data.formList.push( form );
1481 createFinder : function( _elmTarget, _tree, _onSelect, _viewerOption, _editorOption ){
1482 var data = ApplicationPrivateData.get( this ),
1483 finder = Finder.create( this, _elmTarget, _tree, _onSelect, _viewerOption, _editorOption );
1484 if( data.finderList === null ) data.finderList = [];
1485 data.finderList.push( finder );
1488 createDHTML : function( _elm ){
1489 return DHTML.create( this, _elm );
1491 addEventListener : function( element, eventType, handler, opt_thisObject ){
1492 MouseEvent.add( this, element, eventType, handler, opt_thisObject );
1494 removeEventListener : function( element, eventType, handler ){
1495 MouseEvent.remove( this, element, eventType, handler );
1497 getPointingDeviceEventTreeRoot : function(){
1498 var data = ApplicationPrivateData.get( this );
1499 if( data.phase === 1 ){
1500 data.eventRoot = PointingDeviceEventTree.create( this );
1501 data.styleCursor = PointingDeviceEventTree._getNodePrivateData( data.eventRoot ).elmMouseCatch.style;
1503 return data.eventRoot;
1505 updateCoursor : function( _cursor ){
1506 var data = ApplicationPrivateData.get( this );
1507 if( data.cursor !== _cursor ){
1508 data.styleCursor.cursor = data.cursor = _cursor;
1511 fetchCSS : function( url, opt_onload, opt_onerror ){
1512 var data = ApplicationPrivateData.get( this );
1513 if( data.phase === 1 ){
1514 ++data.fetchResource;
1515 StyleSheet.load( this, url, data.fetchResourceComplete, data.fetchResourceComplete, data );
1518 onInit : function(){},
1519 onOpen : function(){},
1520 onClose : function(){ return true; },
1521 onPaneResize : function( w, h ){},
1522 addKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){
1523 KeyEvent.add( this, _eventType, _handler, _keyCode, _shift, _ctrl );
1525 removeKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){
1526 KeyEvent.remove( this, _eventType, _handler, _keyCode, _shift, _ctrl );
1528 shiftEnabled : function(){
1529 return KeyEvent.shiftEnabled;
1531 ctrlEnabled : function(){
1532 return KeyEvent.ctrlEnabled;
1534 addTimer : function( handler, time, once ){
1535 SystemTimer.add( this, handler, time, !!once );
1537 removeTimer : function( handler ){
1538 SystemTimer.remove( this, handler );
1540 addAsyncCall : function( _callback, _argments, _thisObject ){
1541 AsyncCall.add( this, _callback, _argments, _thisObject );
1543 removeAsyncCall : function( _callback ){
1544 AsyncCall.remove( this, _callback );
1546 fetchHTMLElement : function( id ){
1547 var elm = document.getElementById( id );
1549 elm.removeAttribute( 'id' );
1550 elm.parentNode.removeChild( elm );
1556 var PointingDeviceEventTree = ( function(){
1558 currentRootData = null,
1559 targetNodeData = null,
1560 forceNodeData = null,
1563 function eventRellay( e ){
1564 var data = forceNodeData, // || targetNodeData,
1570 ret, systemOnly = false, addClass, removeClass,
1572 if( data && data.dispatchEvent( e, type, true ) === true ) return false;
1573 if( currentRootData === null ) return;
1574 targetNodeData = currentRootData;
1575 currentRootData._capcher( x, y );
1576 targetNodeData.apiuser.updateCoursor( targetNodeData._cursor );
1577 data = targetNodeData;
1579 ret = data.dispatchEvent( e, type, true, systemOnly );
1580 if( ret === true || ret === false ) break; // systemOnly = true;
1581 data = data.parentData;
1584 addClass = Util.addClass;
1585 removeClass = Util.removeClass;
1586 for( ; i < list.length; ){
1587 parent = data = list[ i ];
1588 while( parent.parentData && parent === parent.parentData.hitChild ){
1589 parent = parent.parentData;
1591 if( parent !== currentRootData ){
1592 data.hover === true && removeClass( data.elm, data.hoverClass );
1593 delete data.isHover;
1594 data.events && data.events.mouseout && data.fire( e, 'mouseout', false );
1595 delete data.hitSelf;
1596 list.splice( i, 1 );
1599 if( data.hover === true && data.isHover === false ){
1600 addClass( data.elm, data.hoverClass );
1601 data.isHover = true;
1603 if( data.hitSelf === false ){
1604 data.events && data.events.mouseover && data.fire( e, 'mouseover', true );
1605 data.hitSelf = true;
1612 var NodeClass = function( apiuser, rootData, /*parentLayer,*/ parentData, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){
1613 ( new NodePrivateData() ).init( apiuser, rootData, /*parentLayer,*/ parentData, this, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop );
1615 NodeClass.prototype = {
1616 createNode : function( rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ){
1617 var data = NodePrivateData.get( this ),
1619 if( Type.isHTMLElement( rangeOrElmData ) === true ){
1620 elm = rangeOrElmData;
1622 if( Type.isString( rangeOrElmData ) === true ){
1623 elm = document.getElementById( rangeOrElmData );
1625 elm = Util.pullHtmlAsTemplete( rangeOrElmData );
1627 if( !elm || Type.isHTMLElement( elm ) === false || elm.nodeType !== 1 ){
1628 throw new Error( "invalid HTMLElement." );
1631 if( Type.isObject( rangeOrElmData ) === false || Type.isFinite( rangeOrElmData.x ) === false || Type.isFinite( rangeOrElmData.y ) === false ){
1632 throw new Error( "No range" );
1635 if( elm && data.elm === null ){
1636 throw new Error( "MetaLayer don't containe HTMLElement-Layer." );
1638 if( data.elm && data.elm.style.hasLayout === false ){
1639 throw new Error( "[ie] OffsetParent is hasLayout === false." );
1642 var newNode = new NodeClass( data.apiuser, data.rootData, data, elm || rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ),
1643 newData = NodePrivateData.get( newNode );
1645 if( data.childData === null ) data.childData = [];
1646 data.childData.push( newData );
1649 createNodeAt : function(){
1651 remove : function(){
1652 NodePrivateData.get( this ).remove();
1654 nodeIndex : function( v ){
1655 return NodePrivateData.get( this ).nodeIndex( v );
1657 numNode : function(){
1658 return NodePrivateData.get( this ).numNode();
1660 disabled : function( v ){
1661 return NodePrivateData.get( this ).disabled( v );
1663 childrenDisabled : function( v ){
1664 return NodePrivateData.get( this ).disabled( v );
1666 mesure : function(){
1667 NodePrivateData.get( this ).mesure();
1669 mesureChildren : function(){
1670 NodePrivateData.get( this ).mesureChildren();
1672 update : function( x, y, w, h ){
1673 NodePrivateData.get( this ).update( x, y, w, h );
1675 setPosition : function( x, y ){
1676 NodePrivateData.get( this ).setPosition( x, y );
1678 setSize : function( w, h ){
1679 NodePrivateData.get( this ).setSize( w, h );
1681 cursor : function( v ){
1682 return NodePrivateData.get( this ).cursor( v );
1685 return NodePrivateData.get( this ).positionX( x );
1688 return NodePrivateData.get( this ).positionY( y );
1690 width : function( w ){
1691 return NodePrivateData.get( this ).width( w );
1693 height : function( h ){
1694 return NodePrivateData.get( this ).height( h );
1696 getAbsolutePositionX : function(){
1697 return NodePrivateData.get( this ).getAbsolutePositionX();
1699 getAbsolutePositionY : function(){
1700 return NodePrivateData.get( this ).getAbsolutePositionY();
1702 addEventListener : function( type, handler, opt_thisObject ){
1703 NodePrivateData.get( this ).addEventListener( type, handler, opt_thisObject );
1705 removeEventListener : function( type, handler ){
1706 NodePrivateData.get( this ).removeEventListener( type, handler );
1708 scrollTo : function( x, y ){
1709 NodePrivateData.get( this ).scrollTo( x, y );
1711 scrollX : function( v ){
1712 return NodePrivateData.get( this ).scrollX( v );
1714 scrollY : function( v ){
1715 return NodePrivateData.get( this ).scrollY( v );
1717 invalidateScrollbar : function(){
1718 ScrollBarManager.update( NodePrivateData.get( this ) );
1723 * clip : true の場合、子ノードの変更によってヒットエリアを変化させない.elm には overflow:hidden としておくのが通常.
1725 var NodePrivateData = function(){};
1726 NodePrivateData.prototype = {
1727 elmMouseCatch : null, // rootData only
1728 eventCounter : null, // rootData only
1729 cursorStyle : null, // rootData only
1733 elm : null, // resizeTarget
1736 elmScrollbar : null,
1752 // parentLayer : null,
1759 _childDisabled: false,
1760 layoutManager : null,
1769 init: function( apiuser, rootData, /*parentLayer,*/ parentData, node, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){
1770 this.apiuser = apiuser;
1771 this.rootData = rootData || this;
1772 // this.parentLayer = parentLayer;
1773 this.parentData = parentData;
1775 this.through = through;
1777 if( cursor ) this._cursor = cursor;
1779 if( Type.isHTMLElement( rangeOrElm ) === true ){
1780 this.elm = rangeOrElm;
1781 this.hover = !!hover;
1782 this.hoverClass = hover;
1783 this.scroll = clip && scroll;
1785 this.scroll === true && ScrollBarManager.register( this );
1787 this.update( rangeOrElm.x, rangeOrElm.y, rangeOrElm.w, rangeOrElm.h );
1790 NodePrivateData.dataList.push( this );
1792 mesure : function(){
1793 var x, y, w, h, parent, _this, _parent;
1795 w = this.elm.offsetWidth;
1796 h = this.elm.offsetHeight;
1797 _this = Position.cumulativeOffset( this.elm );
1798 _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ];
1799 x = _this[ 0 ] - _parent[ 0 ];
1800 y = _this[ 1 ] - _parent[ 1 ];
1801 if( this.x !== x || this.y !== y || this.w !== w || this.h !== h ){
1806 parent = this.parentData;
1807 parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY );
1808 this._updateRectangle();
1811 this._updateRectangle();
1814 mesureChildren : function(){
1816 if( nodes = this.childData ){
1817 for( i = nodes.length; i; ){
1818 nodes[ --i ].mesure();
1822 update : function( x, y, w, h ){
1823 var updateXY = false,
1829 if( Type.isFinite( w ) === true ){
1830 this.elm.style.width = w + 'px';
1832 if( Type.isString( w ) === true ){
1833 this.elm.style.width = w;
1834 w = this.elm.offsetWidth;
1836 //update = this.w !== w;
1839 if( Type.isFinite( h ) === true ){
1840 this.elm.style.height = h + 'px';
1842 if( Type.isString( h ) === true ){
1843 this.elm.style.height = w;
1844 h = this.elm.offsetHeight;
1846 //update = update || this.h !== h;
1849 if( Type.isFinite( x ) === true ){
1850 this.elm.style.left = x + 'px';
1852 if( Type.isString( x ) === true ){
1853 this.elm.style.left = x;
1860 if( Type.isFinite( y ) === true ){
1861 this.elm.style.top = y + 'px';
1863 if( Type.isString( y ) === true ){
1864 this.elm.style.top = y;
1869 if( updateXY === true ){
1870 _this = Position.cumulativeOffset( this.elm );
1871 _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ];
1872 x = _this[ 0 ] - _parent[ 0 ];
1873 y = _this[ 1 ] - _parent[ 1 ];
1875 //update = update || this.x !== x;
1876 //update = update || this.y !== y;
1878 //update === true && this._updateRectangle();
1881 x = Type.isFinite( x ) === true ? x : this.x;
1882 y = Type.isFinite( y ) === true ? y : this.y;
1883 w = Type.isFinite( w ) === true ? w : this.w;
1884 h = Type.isFinite( h ) === true ? h : this.h;
1885 if( this.x !== x || this.y !== y ){
1888 //console.log( 'xy ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h + ' absX:' + this.parentData.absoluteX )
1889 parent = this.parentData;
1890 parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY );
1891 this.w === w && this.h === h && this._updateRectangle();
1893 if( this.w !== w || this.h !== h ){
1896 //console.log( 'wh ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h )
1897 this._updateRectangle();
1900 ScrollBarManager.update( this );
1902 _updateAbsoluteXY : function( x, y, sX, sY ){
1904 this.absoluteX = x = this.x + x;
1905 this.absoluteY = y = this.y + y;
1906 if( nodes = this.childData ){
1907 for( i = nodes.length; i; ){
1908 nodes[ --i ]._updateAbsoluteXY( x, y, this.scrollingX, this.scrollingY );
1912 _updateRectangle : function(){
1921 nodes = this.childData,
1925 if( this.clip === false && nodes ){
1926 for( i = nodes.length; i; ){
1927 node = nodes[ --i ];
1928 if( node.l + x < l ) l = x + node.l;
1929 if( node.t + y < t ) t = y + node.t;
1930 if( r < node.r + x ) r = x + node.r;
1931 if( b < node.b + y ) b = y + node.b;
1935 if( b !== this.b || r !== this.r || t !== this.t || l !== this.l ){
1942 this.parentData && this.parentData.clip === false && this.parentData._updateRectangle();
1946 setPosition : function( x, y ){
1947 this.update( x, y );
1949 setSize : function( w, h ){
1950 this.update( undefined, undefined, w, h );
1952 positionX : function( x ){
1953 x !== undefined && this.update( x );
1956 positionY : function( y ){
1957 y !== undefined && this.update( undefined, y );
1960 width : function( w ){
1961 w !== undefined && this.update( undefined, undefined, w );
1964 height : function( h ){
1965 h !== undefined && this.update( undefined, undefined, undefined, h );
1968 getAbsolutePositionX : function(){
1969 return this.absoluteX;
1971 getAbsolutePositionY : function(){
1972 return this.absoluteY;
1974 cursor : function( v ){
1975 if( Type.isString( v ) === true ){
1977 this === targetNodeData && this.apiuser.updateCoursor( v );
1979 return this._cursor;
1981 addEventListener : function( eventType, handler, opt_thisObject ){
1982 var node = this.node,
1983 counter = this.rootData.eventCounter,
1985 if( this.events === null ) this.events = {};
1986 list = this.events[ eventType ];
1988 list = this.events[ eventType ] = [];
1990 for( i = list.length; i; ){
1991 if( list[ --i ].match( eventType, handler ) === true ){
1996 list.push( new EventTicketClass( this.node, eventType, handler, opt_thisObject ) );
1997 if( eventType !== 'mouseout' && eventType !== 'mouseover' ){
1998 if( counter[ eventType ] ){
1999 ++counter[ eventType ];
2001 //console.log( eventType );
2002 counter[ eventType ] = 1;
2003 MouseEvent.add( this.apiuser, this.rootData.elmMouseCatch, eventType, eventRellay );
2007 removeEventListener : function( eventType, handler ){
2008 var events = this.events,
2009 counter = this.rootData.eventCounter,
2011 if( events === null ) return;
2012 console.log( ' *** remove ' + eventType );
2013 for( type in events ){
2014 list = events[ type ];
2015 if( eventType && eventType !== type ) continue;
2016 for( ; i < list.length; ){
2017 if( list[ i ].destroy( type, handler ) === true ){
2018 console.log( ' *** removed! ' + type );
2019 list.splice( i, 1 );
2024 if( list.length === 0 ){
2025 // delete this[ type ];
2026 delete events[ type ];
2028 if( counter[ type ] ){
2030 if( counter[ type ] === 0 ){
2031 MouseEvent.remove( this.apiuser, this.rootData.elmMouseCatch, type, eventRellay );
2032 delete counter[ type ];
2037 _capcher : function( x, y ){
2038 var t = this, nodes, child, _x, _y, hit, i;
2039 if( t._disabled === true ) return false;
2043 if( nodes = t.childData ){
2044 _x = x - t.scrollingX;
2045 _y = y - t.scrollingY;
2046 for( i = nodes.length; i; ){
2047 child = nodes[ --i ];
2048 if( child._disabled === false && child.l <= _x && _x < child.r && child.t <= _y && _y < child.b && child._capcher( _x, _y ) === true ){
2054 if( t.through === true ){
2055 t.hitChild && t.hitSelf === false && hoverList.push( t );
2056 return !!t.hitChild;
2058 hit = 0 <= x && x < t.w && 0 <= y && y < t.h;
2059 ( t.hitChild || hit ) && t.hitSelf === false && hoverList.push( t );
2060 if( hit === true && t.hitChild === null ) targetNodeData = t;
2061 return hit || !!t.hitChild;
2063 fire : function( e, eventType, hit ){
2064 var list = this.events[ eventType ],
2066 e = NodePrivateData.createEvent( e, eventType, this, hit );
2067 for( ; i; ) list[ --i ].fire( e );
2068 // console.log( eventType + ' x:' + x + ' y:' + y );
2070 dispatchEvent : function( e, eventType, hit ){
2071 var ret, list, i, p, child;
2072 if( !this.events || !( list = this.events[ eventType ] ) ) return;
2074 child = !!this.hitChild;
2075 e = NodePrivateData.createEvent( e, eventType, this, hit );
2076 for( i = list.length; i; ){
2077 ret = list[ --i ].fire( e );
2078 if( ret === true && child === false ){
2079 forceNodeData = this;
2082 if( ret === false ) return false;
2084 forceNodeData = null;
2086 scrollTo : function( x, y ){
2089 ScrollBarManager.update( this );
2091 scrollX : function( v ){
2092 if( Type.isFinite( v ) === true ){
2094 ScrollBarManager.update( this );
2096 return this.scrollingX; // this._scrollX;
2098 scrollY : function( v ){
2099 if( Type.isFinite( v ) === true ){
2101 ScrollBarManager.update( this );
2103 return this.scrollingY; // this._scrollY;
2105 nodeIndex : function( v ){
2107 if( !this.parentData ) return 0;
2109 list = this.parentData.childData;
2110 i = Util.getIndex( list, this );
2111 if( Type.isFinite( v ) === false || i === v && v < 0 && list.length <= v ) return i;
2113 list.splice( i, 1 );
2114 list.length === v ? list.push( this ) : list.splice( v, 0, this );
2119 if( this.parentData.hitChild === this ){
2120 this.parentData.hitChild = null;
2121 this.isHover === true && hoverList.splice( Util.getIndex( hoverList, this ), 1 ) && Util.removeClass( this.elm, this.hoverClass );
2122 this.isHover = false;
2123 if( forceNodeData === this ) forceNodeData = null;
2124 if( targetNodeData === this ) targetNodeData = null;
2127 numNode : function(){
2128 return this.childData ? this.childData.length : 0;
2130 disabled : function( v ){
2131 if( Type.isBoolean( v ) === true ){
2137 return this._disabled;
2139 childrenDisabled : function( v ){
2140 if( Type.isBoolean( v ) === true ){
2141 this._childDisabled = v;
2143 return this._childDisabled;
2145 remove : function(){
2146 if( this === this.rootData ) return;
2147 var parent = this.parentData,
2148 nodes = parent.childData;
2150 if( parent.hitChild === this ) delete parent.hitChild;
2151 nodes.splice( Util.getIndex( nodes, this ), 1 );
2152 if( nodes.length === 0 ) delete parent.childData;
2153 parent.clip === false && parent._updateRectangle();
2155 _destroy : function(){
2156 var nodes = this.childData,
2157 list = NodePrivateData.dataList,
2159 this.removeEventListener();
2160 ScrollBarManager.remove( this );
2162 while( node = nodes.shift() ) node._destroy();
2163 delete this.childData;
2165 list.splice( Util.getIndex( list, this ), 1 );
2168 NodePrivateData.dataList = [];
2169 NodePrivateData.get = function( node ){
2170 // if( node instanceof NodePrivateData ) return node;
2171 // return NodePrivateData.dataList[ layer._getUID() ];
2172 var list = NodePrivateData.dataList;
2173 for( var i = list.length; i; ){
2174 if( list[ --i ].node === node ) return list[ i ];
2178 NodePrivateData.createEvent = function( e, eventType, data, hit ){
2180 layerX : e.clientX - data.absoluteX,
2181 layerY : e.clientY - data.absoluteY,
2182 clientX : e.clientX,
2183 clientY : e.clientY,
2184 dragOffsetX : e.dragOffsetX,
2185 dragOffsetY : e.dragOffsetY,
2186 dragPhase : e.dragPhase,
2187 eventType : eventType,
2190 wheelDelta : e.wheelDelta,
2191 target : forceNodeData ? forceNodeData.node : targetNodeData ? targetNodeData.node : null
2196 var EventTicketClass = function( node, eventType, handler, opt_thisObject ){
2198 this.type = eventType;
2199 this.handler = handler;
2200 this.thisObj = opt_thisObject || node;
2202 EventTicketClass.prototype = {
2203 match : function( eventType, handler ){
2204 if( handler && this.handler !== handler ) return false;
2205 if( eventType && this.type !== eventType ) return false;
2208 destroy : function( eventType, handler ){
2209 if( this.match( eventType, handler ) === false ) return false;
2212 delete this.handler;
2213 delete this.thisObj;
2216 fire : ( function(){
2217 if( Function.prototype.call ){
2218 return function( e ){
2219 return this.handler.call( this.thisObj, e );
2222 return function( e ){
2224 this.thisObj._currentHandler = this.handler;
2225 ret = this.thisObj._currentHandler( e );
2226 delete this.thisObj._currentHandler;
2232 /*-------------------------------------
2235 var StayEventTicketClass = function( node, data, stayhandler, opt_thisObject ){
2236 node.addEventListener( 'mouseover', this.mouseoverHandler, this );
2239 this.handler = stayhandler;
2240 this.thisObject = opt_thisObject;
2242 StayEventTicketClass.prototype = Util.extend( new EventTicketClass( null, 'mousestay' ), {
2243 // type : 'mousestay',
2245 mouseoverHandler : function( e ){
2246 this.e = NodePrivateData.createEvent( e, this.type, this.data, true );
2247 this.node.addEventListener( 'mouseout', this.mousestayHandler, this );
2248 this.node.addEventListener( 'mousemove', this.mousemoveHandler, this );
2249 SystemTimer.add( this.data.apiuser, this.timeoutHandler, null, this );
2251 timeoutHandler : function(){
2252 this.mouseoutHandler();
2253 return this.fire( this.e );
2255 mousemoveHandler : function( e ){
2256 this.e = NodePrivateData.createEvent( e, this.type, this.data, true );
2257 SystemTimer.remove( this.data.apiuser, this.timeoutHandler );
2258 SystemTimer.add( this.data.apiuser, this.timeoutHandler, null, this );
2260 mouseoutHandler : function( e ){
2261 this.node.removeEventListener( 'mouseout', this.mousestayHandler );
2262 this.node.removeEventListener( 'mousemove', this.mousemoveHandler );
2263 SystemTimer.remove( this.data.apiuser, this.timeoutHandler );
2268 var ScrollBarManager = ( function(){
2269 var elmScroller = document.createElement( 'div' ),
2270 elmBar = document.createElement( 'div' ),
2274 currentNodeData = null,
2279 var list = smoothList,
2281 for( i = 0; i < list.length; ){
2283 if( data.scrollingY !== data._scrollY ){
2284 y = data.scrollingY += data.smoothY;
2285 if( data.smoothY < 0 ){
2286 y = y < data._scrollY ? data._scrollY : y;
2288 y = data._scrollY < y ? data._scrollY : y;
2290 data.scrollingY = y;
2291 data.elm.scrollTop = -y;
2292 data.events && data.events.scroll && data.fire( currentEvent, 'scroll', true );
2294 if( data.scrollingY === data._scrollY ){
2295 list.splice( i, 1 );
2296 // data.events && data.events.scroll && data.fire( currentEvent, 'scroll', true );
2301 list.length === 0 && SystemTimer.remove( SUPER_USER_KEY, tick );
2302 currentEvent.type = 'updateAfterScroll';
2303 AsyncCall.add( data.apiuser, eventRellay, currentEvent ); // スクロール後の更新
2306 function scrollReady( e ){
2310 if( data === currentNodeData || dragPhase !== 2 ) return; // Drag中の場合は 他にスクロールを作らない
2311 currentNodeData && scrollRelease();
2314 data.elm.parentNode.appendChild( elmScroller );
2315 elmScroller.appendChild( data.elm );
2317 elmScroller.style.cssText = 'position:absolute;left:0;top:0;';
2318 elmScroller.appendChild( elmBar );
2320 data.elm.scrollTop = -data.scrollingY;
2321 data.rootData.addEventListener( 'mousewheel', onMouseWheelScroll, data );
2322 data.rootData.addEventListener( 'mousedrag', onMouseDragScroll, data );
2323 data.addEventListener( 'mouseout', onMouseOut, data );
2324 currentNodeData = data;
2325 ScrollBarManager.update( data );
2327 function scrollRelease(){
2328 var data = currentNodeData;
2329 var parent = elmScroller.parentNode;
2330 parent.appendChild( currentNodeData.elm );
2331 parent.removeChild( elmScroller );
2332 currentNodeData.elm.scrollTop = -data.scrollingY;
2334 data.rootData.removeEventListener( 'mousewheel', onMouseWheelScroll, data );
2335 data.rootData.removeEventListener( 'mousedrag', onMouseDragScroll, data );
2336 data.removeEventListener( 'mouseout', onMouseOut, data );
2337 currentNodeData = null;
2339 function onMouseOut( e ){
2341 console.log( 'mouseOut ' + dragPhase );
2342 dragPhase === 2 && scrollRelease(); // Dragしてのアウトの場合, scroll をリリースしない
2344 function onMouseWheelScroll( e ){
2346 this._scrollY += e.wheelDelta;
2347 ScrollBarManager.update( this );
2351 function onMouseDragScroll( e ){
2355 dragPhase = e.dragPhase;
2356 switch( dragPhase ){
2358 dragStartY = this.scrollingY;
2359 data.rootData.removeEventListener( 'mousewheel', onMouseWheelScroll, data );
2361 this._scrollY = dragStartY + e.dragOffsetY;
2362 ScrollBarManager.update( this );
2365 dragOut === true ? scrollRelease() : data.rootData.addEventListener( 'mousewheel', onMouseWheelScroll, data );
2371 register : function( data ){
2372 data.addEventListener( 'mouseover', scrollReady, data );
2374 update : function( data ){
2375 // if( data !== currentNodeData ) return;
2376 var isCurrent = data === currentNodeData;
2378 var contentH = data._scrollH = data.elm.scrollHeight,
2380 offsetH = contentH - clipH,
2381 scrollY = data._scrollY = 0 < data._scrollY ? 0 : ( data._scrollY < -offsetH ? -offsetH : data._scrollY ),
2383 if( isCurrent === true ){
2384 elmScroller.style.width = data.w + 'px';
2385 elmScroller.style.height = clipH + 'px';
2389 data._scrollY = scrollY = 0;
2390 if( isCurrent === true ) elmBar.style.display = 'none';
2392 if( isCurrent === true ){
2393 barH = Math.floor( clipH * ( clipH / contentH ) );
2394 barY = Math.floor( ( clipH - barH ) * - scrollY / offsetH );
2395 elmBar.style.cssText = [
2396 'position:absolute;',
2398 'background-color:#333;',
2400 'font-size:0;line-height:0;',
2401 'height:', barH, 'px;',
2402 'top:', data.y + barY, 'px;'
2405 data.smoothY = ( scrollY - data.scrollingY ) / 10;
2406 if( data.scrollingY !== scrollY && Util.getIndex( smoothList, data ) === -1 ){
2407 smoothList.length === 0 && SystemTimer.add( SUPER_USER_KEY, tick, 16 );
2408 smoothList.push( data );
2411 remove : function( data ){
2412 var list = smoothList,
2413 i = Util.getIndex( list, data );
2414 data === currentNodeData && scrollRelease();
2415 i !== -1 && list.splice( i, 1 );
2421 create : function( apiuser ){
2422 var elm = document.createElement( 'div' ),
2424 body.appendChild( elm );
2426 root = new NodeClass( apiuser, null, null, elm );
2427 data = NodePrivateData.get( root );
2429 // elm.style.cssText = 'position:absolute;top:0;left:0;height:100%;';
2430 elm.className = 'mouse-operation-catcher';
2431 elm.unselectable = 'on';
2432 data.elmMouseCatch = elm;
2434 data.eventCounter = {};
2435 ROOT_LIST.push( data );
2436 currentRootData = data;
2437 targetNodeData = null;
2438 forceNodeData = null;
2440 MouseEvent.add( apiuser, elm, 'mousemove', eventRellay );
2443 onCurrentApplicationChange : function( _application ){
2444 currentRootData = null;
2445 targetNodeData = null;
2446 forceNodeData = null;
2447 for( var i = ROOT_LIST.length; i; ){
2448 if( ROOT_LIST[ --i ].apiuser === _application ){
2449 currentRootData = ROOT_LIST[ i ];
2454 destroyTree : function( root ){
2455 var data = NodePrivateData.get( root );
2456 MouseEvent.remove( data.apiuser, data.elmMouseCatch, 'mousemove', eventRellay );
2457 body.removeChild( data.elmMouseCatch );
2459 ROOT_LIST.splice( Util.getIndex( ROOT_LIST, data ), 1 );
2460 if( currentRootData === data ){
2461 currentRootData = null;
2462 targetNodeData = null;
2463 forceNodeData = null;
2466 onSystemShutdown : function(){
2469 isNodeInstance : function( node ){
2470 return node instanceof NodeClass;
2472 _getNodePrivateData : function( node ){ // system only
2473 return NodePrivateData.get( node );
2478 var Application = ( function(){
2480 var LIVE_APPLICATION_LIST = [];
2482 var currentApplication = null,
2483 coveredApplication = null,
2487 var ApplicationReference = function( appClass, isOverlay, displayName, id, thumbnailUrl, tailColor ){
2489 var application = null;
2491 this.displayName = displayName;
2492 this.thumbnailUrl = thumbnailUrl;
2493 this.tailColor = tailColor;
2495 function asyncBoot(){
2496 application = Application.boot( appClass, displayName, self.getUID(), isOverlay, Util.copyArray( arguments ) );
2498 this.getUID = function(){
2499 return Util.getIndex( API_USER_LIST, appClass );
2501 this.getDisplayName = function(){
2502 return this.displayName;
2504 this.boot = function( /* _option */ ){
2505 AsyncCall.add( this, asyncBoot, Util.copyArray( arguments ) );
2507 this.shutdown = function(){
2508 if( !application ) return false;
2510 AsyncCall.add( application, ( isOverlay === true ? Overlay.hide : application.close ) );
2514 function asyncBootHome(){
2515 currentApplication === null && Home.boot();
2517 function asyncOpen( /* arguments */ ){
2518 var _arg = Util.copyArray( arguments );
2519 _arg.unshift( winW, winH );
2520 currentApplication.open.apply( currentApplication, _arg );
2523 register: function( _class, _overlay, _tail, _displayName, _id, _thumbnailUrl, _tailColor ){
2524 APPLICATION_LIST.push( _class );
2525 API_USER_LIST.push( _class );
2526 var _ref = new ApplicationReference( _class, _overlay, _displayName, _id, _thumbnailUrl, _tailColor );
2527 _tail === true && Home.add( _ref );
2530 isApplicationInstance: function( app ){
2531 return ApplicationPrivateData.get( app ) !== null;
2533 isApplicationReference: function( _reference ){
2534 return _reference instanceof ApplicationReference;
2536 isCurrentAppplication: function( app ){
2537 return app === currentApplication;
2539 boot: function( appClass, displayName, uid, isOverlay, arg ){
2540 if( currentApplication ){
2541 if( currentApplication.getUID() === uid ) return null;
2542 if( isOverlay === false && currentApplication.close() === false ) return null;
2545 appClass.prototype = new AbstractApplication( appClass, displayName, isOverlay );
2547 var application = new appClass(),
2548 data = ApplicationPrivateData.get( application );
2550 application.rootElement = data.rootElement;
2551 data.application = application;
2553 coveredApplication = isOverlay === true ? currentApplication : null;
2555 Application.onCurrentApplicationChange( application );
2557 if( isOverlay === false ){
2558 body.style.backgroundColor = application.bgColor;
2560 body.appendChild( data.rootElement );
2561 data.rootElement.style.display = 'none';
2564 application.addAsyncCall( asyncOpen, arg );
2566 Overlay.show( application, arg );
2571 shutdown: function( _application, isOverlay ){
2572 if( isOverlay === false ){
2573 currentApplication = null;
2574 AsyncCall.add( SUPER_USER_KEY, asyncBootHome );
2576 Application.onCurrentApplicationChange( coveredApplication );
2577 coveredApplication = null;
2580 onCurrentApplicationChange: function( _application ){
2581 if( Application.isApplicationInstance( _application ) === false ) return;
2582 if( currentApplication === _application ) return;
2583 currentApplication = _application;
2584 MouseEvent.onCurrentApplicationChange( _application );
2585 PointingDeviceEventTree.onCurrentApplicationChange( _application );
2586 KeyEvent.updateCurrentListener( _application );
2587 // InteractiveLayer.onCurrentApplicationChange( _application );
2589 onApplicationShutdown: function( _application ){
2590 LIVE_APPLICATION_LIST.splice( Util.getIndex( LIVE_APPLICATION_LIST, _application ) );
2592 onWindowResize: function( w, h ){
2595 currentApplication && currentApplication.resize( w, h );
2596 Overlay.onWindowResize( w, h );
2597 UI.onWindowResize( w, h );
2599 onSystemShutdown: function(){
2605 /* --------------------------------------------------------------
2609 var Home = ( function(){
2610 var APP_REF_LIST = [];
2611 var ELM_TAIL_ORIGIN = ( function(){
2612 var ret = document.createElement( 'div' ),
2613 h2 = document.createElement( 'h2' );
2614 ret.className = 'tail-wrapper';
2615 ret.appendChild( h2 );
2616 h2.appendChild( document.createTextNode( 'appName' ) );
2620 var TailClass = function( appRef ){
2621 this.elm = ELM_TAIL_ORIGIN.cloneNode( true );
2622 this.destroy = function(){
2623 appRef = self = elmName = null;
2627 elmName = this.elm.getElementsByTagName( 'h2' )[ 0 ].firstChild;
2629 this.elm.style.backgroundColor = appRef.tailColor;
2630 elmName.data = appRef.displayName;
2633 var ref = Application.register( function(){
2638 elmContainer, elmHeader;
2642 for( var i=0, l=APP_REF_LIST.length; i<l; ++i ){
2643 tail = new TailClass( APP_REF_LIST[ i ] );
2644 tailList.push( tail );
2646 elmContainer.appendChild( elm );
2647 self.addEventListener( elm, 'click', onTailClick );
2651 function onTailClick( e ){
2652 var _children = elmContainer.getElementsByTagName( 'div' );
2653 for( var i=0, l=_children.length; i<l; ++i ){
2654 if( this === _children[ i ] ){
2655 APP_REF_LIST[ i ].boot();
2661 this.bgColor = '#0F6D39';
2662 this.MIN_WIDTH = 320;
2663 this.MIN_HEIGHT = 320;
2664 this.onInit = function(){
2665 self.rootElement.id = 'home-root';
2667 elmContainer = document.createElement( 'div' );
2668 self.rootElement.appendChild( elmContainer );
2669 elmContainer.id = 'home-tail-container';
2671 elmHeader = document.createElement( 'div' );
2672 self.rootElement.appendChild( elmHeader );
2673 elmHeader.id = 'home-header';
2675 this.onOpen = function( _w, _h ){
2680 this.onPaneResize = function( _w, _h ){
2683 this.onClose = function(){
2684 self.removeEventListener();
2685 while( tailList.length > 0 ){
2686 tailList.shift().destroy();
2688 self = tailList = elmContainer = null;
2690 }, false, false, 'home', 'home', null );
2693 add: function( _appRef ){
2694 if( Application.isApplicationReference( _appRef ) === false ) return;
2695 Util.getIndex( APP_REF_LIST, _appRef ) === -1 && APP_REF_LIST.push( _appRef );
2703 var Page = ( function(){
2706 ignoreTagList = [ 'script', 'noscript', 'style' ];
2708 var MemoryClass = function( node ){
2711 MemoryClass.prototype = {
2713 var node = this.node,
2714 _nodeType = node.nodeType;
2715 if( _nodeType === 1 && Util.getIndex( ignoreTagList, node.tagName.toLowerCase() ) === -1 ){
2716 this.type = _nodeType;
2717 this.display = node.style.display;
2719 if( _nodeType === 3 ){
2720 if( node.data.replace( /\s/g, '' ).length !== 0 ){
2721 this.type = _nodeType;
2722 this.before = pageNodes.length === 0 ? null : pageNodes[ pageNodes.length - 1 ].node;
2724 body.removeChild( node );
2728 // body.removeChild( node );
2733 if( this.type === 1 ){
2735 this.node.style.display = this.display;
2737 this.node.style.display = '';
2741 body.insertBefore( this.node, this.before );
2743 body.appendChild( this.node );
2748 if( !this.node.parentNode ){
2751 if( this.type === 1 ){
2752 this.node.style.display = 'none';
2754 body.removeChild( this.node );
2760 onReady: function(){
2761 var _children = Util.copyArray( body.childNodes ),
2763 for( var i = 0, l = _children.length; i<l; ++i ){
2764 _mem = new MemoryClass( _children[ i ] );
2765 _mem.init() !== false && pageNodes.push( _mem );
2767 if( pageNodes.length !== 0 ){
2768 if( Type.isFunction( gOS.PageApplicationClass ) === true ){
2769 Page.appClass = gOS.PageApplicationClass;
2770 Page.appClass.bgColor = Page.appClass.bgColor;
2771 Page.appClass.MIN_WIDTH = Page.appClass.MIN_WIDTH || 240;
2772 Page.appClass.MIN_HEIGHT = Page.appClass.MIN_HEIGHT || 240;
2774 Page.appClass = function(){
2777 this.bgColor = '#ffffff';
2778 this.MIN_WIDTH = 200;
2779 this.MIN_HEIGHT = 200;
2780 this.onInit = function(){};
2781 this.onOpen = function( _w, _h ){
2782 KeyEvent.add( self, Const.KEY.EVENT.KEY_DOWN, ref.shutdown, 27 ); // 27.esc
2784 this.onPaneResize = function( _w, _h ){};
2785 this.onClose = function(){};
2788 ref = Application.register( Page.appClass, false, true, document.title, 'page', null, Page.appClass.tailColor || '#999999' );
2789 if( Type.isFunction( gOS.PageApplicationClass ) === true ){
2790 gOS.PageApplicationRef = ref;
2793 delete Page.onReady;
2796 for( var i = pageNodes.length; i; ){
2797 pageNodes[ --i ].show();
2801 for( var i = pageNodes.length; i; ){
2802 pageNodes[ --i ].hide();
2808 registered: function(){
2815 /* --------------------------------------------------------------
2819 * スクリーン座標は、コンピュータのディスプレイの左上を原点とする座標系である。screenX, screenY属性で取得できる。Javascritpでは、同名のプロパティとして実装されている。
2820 * しかし、これは、現実的には、何の役に立たない。ブラウザ自体がディスプレイのどの位置にいるのかがわからないので、画面上の位置を知ったところで、何にもならないからだ。
2823 * ウインドウ座標とは、現在のブラウザのウインドウの、ドキュメントを表示している部分の左上原点とした座標である。
2824 * 問題は、ウインドウは、必ずしもドキュメント全体を表示するとは限らない。スクロールと呼ばれるUIによって、ドキュメントの一部だけを表示しているかもしれない。
2826 var XBrowserEvent = ( function(){
2827 var wrappedHandlerClass,
2831 if( window.addEventListener ){
2832 wrappedHandlerClass = function( ticket ){
2833 this.handler = function( e ){
2834 if( ticket.fire( e ) !== false ) return;
2836 e.stopPropagation();
2839 this.destroy = function(){
2841 delete this.handler;
2842 delete this.destroy;
2846 wrappedEventClass = function( e, element ){
2849 this.target = e.srcElement;
2850 this.currentTarget = element;
2851 this.relatedTarget = e.formElement ? e.formElement : e.toElement;
2852 this.eventPhase = e.srcElement === element ? 2: 3;
2854 this.clientX = e.clientX;
2855 this.clientY = e.clientY;
2856 this.screenX = e.screenX;
2857 this.screenY = e.screenY;
2859 this.keyCode = e.keyCode;
2860 this.altKey = e.altKey;
2861 this.ctrlKey = e.ctrlKey;
2862 this.shiftKey = e.shiftKey;
2864 this.wheelDelta = e.wheelDelta;
2866 wrappedEventClass.prototype.stopPropagation = function(){
2867 this._event.cancelBubble = true;
2869 wrappedEventClass.prototype.preventDefault = function(){
2870 this._event.returnValue = false;
2873 if( document.attachEvent ){
2874 wrappedHandlerClass = function( ticket ){
2875 this.handler = function(){
2876 if( ticket === null ) alert( window.event.type )
2877 if( ticket.fire( new wrappedEventClass( window.event, ticket.element ) ) !== false ) return;
2878 // e.preventDefault();
2879 // e.stopPropagation();
2880 window.event.cancelBubble = true;
2881 window.event.returnValue = false;
2884 this.destroy = function(){
2886 delete this.handler;
2887 delete this.destroy;
2893 find: function( _ticket ){
2894 for( var i=0, l= tmp.list.length, _item; i<l; ++i ){
2895 _item = tmp.list[ i ];
2896 if( _item.element === _ticket.element && _item.eventType === _ticket.eventType ){
2903 tmp.TicketClass = function( _ticket ){
2905 this.element = _ticket.element;
2906 this.eventType = _ticket.eventType;
2907 this.tickets = [ _ticket ];
2908 this.onDestroy = function(){ self = null; };
2910 this.element[ 'on' + this.eventType ] = function( e ){ return self.fire( e );};
2913 tmp.TicketClass.prototype = {
2914 add: function( _ticket ){
2915 Util.getIndex( this.tickets, ticket ) === -1 && this.tickets.push( _ticket );
2917 remove: function( _ticket ){
2918 var i = Util.getIndex( this.tickets, _ticket );
2919 i !== -1 && this.tickets.splice( i, 1 );
2920 this.tickets.length === 0 && this.destroy();
2922 fire: function( e ){
2923 e = e || new wrappedEventClass( window.event, this.element );
2924 var i = this.tickets.length,
2927 if( this.tickets[ --i ].fire( e ) === false ) cancel = false;
2931 destroy: function(){
2933 this.element[ 'on' + this.eventType ] = '';
2934 tmp.list.splice( Util.getIndex( tmp.list, this ), 1 );
2935 delete this.element;
2936 delete this.eventType;
2937 delete this.tickets;
2938 delete this.onDestroy;
2945 add: function( _ticket ){
2946 if( document.addEventListener ){
2947 XBrowserEvent.add = function( _ticket ){
2948 _ticket.wrappedHandler = new wrappedHandlerClass( _ticket );
2949 _ticket.element.addEventListener( _ticket.eventType, _ticket.wrappedHandler.handler, false );
2952 if( document.attachEvent ){
2953 XBrowserEvent.add = function( _ticket ){
2954 _ticket.wrappedHandler = new wrappedHandlerClass( _ticket );
2955 _ticket.element.attachEvent( 'on' + _ticket.eventType, _ticket.wrappedHandler.handler );
2958 XBrowserEvent.add = function( _ticket ){
2959 var t = tmp.find( _ticket );
2963 tmp.list.push( new tmp.TicketClass( _ticket ) );
2968 XBrowserEvent.add( _ticket );
2970 remove: function( _ticket ){
2971 if( document.removeEventListener ){
2972 XBrowserEvent.remove = function( _ticket ){
2973 _ticket.element.removeEventListener( _ticket.eventType, _ticket.wrappedHandler.handler, false );
2974 _ticket.wrappedHandler.destroy();
2977 if( document.detachEvent ){
2978 XBrowserEvent.remove = function( _ticket ){
2979 _ticket.element.detachEvent( 'on' + _ticket.eventType, _ticket.wrappedHandler.handler );
2980 _ticket.wrappedHandler.destroy();
2983 XBrowserEvent.remove = function( _ticket ){
2984 var t = tmp.find( _ticket );
2986 t.remove( _ticket );
2991 XBrowserEvent.remove( _ticket );
2999 var EventTicketClass = function( _element, _eventType, _handler, opt_thisObject ){
3000 this.element = _element;
3001 this.eventType = _eventType;
3002 this.handler = _handler;
3003 this.wrappedHandler = null;
3004 this.thisObject = opt_thisObject;
3005 XBrowserEvent.add( this );
3007 EventTicketClass.prototype = {
3008 fire : ( function(){
3009 if( Function.prototype.call ){
3010 return function( e ){
3011 return this.handler.call( this.thisObject || this.element, e );
3014 return function( e ){
3015 var thisObj = this.thisObject || this.element,
3017 thisObj._currentHandler = this.handler;
3018 ret = thisObj._currentHandler( e );
3019 delete thisObj._currentHandler;
3023 match: function( _element, _eventType, _handler ){
3024 if( _handler && _handler !== this.handler ) return false;
3025 if( _eventType && _eventType !== this.eventType ) return false;
3026 if( _element && _element !== this.element ) return false;
3030 destroy: function( _element, _eventType, _handler ){
3031 if( this.match( _element, _eventType, _handler ) === false ) return false;
3033 XBrowserEvent.remove( this );
3035 delete this.element;
3036 delete this.eventType;
3037 delete this.handler;
3038 delete this.wrappedHandler;
3039 delete this.thisObject;
3044 var ReadyEvent = ( function(){
3048 function webkitDetect(){
3049 var state = document.readyState;
3050 if( state === 'loaded' || state === 'complete' ){
3051 SystemTimer.remove( SUPER_USER_KEY, webkitDetect );
3056 function ieDetect(){
3057 if( this.readyState === 'complete' ){ // this.readyState === 'loaded' ||
3058 this.onreadystatechange = new Function();
3059 this.onreadystatechange = null;
3060 AsyncCall.remove( SUPER_USER_KEY, ieScroll );
3064 function ieScroll(){
3066 document.documentElement.doScroll( 'left' );
3068 AsyncCall.add( SUPER_USER_KEY, ieScroll );
3072 document.onreadystatechange = new Function();
3073 document.onreadystatechange = null;
3078 ticketReady && ticketReady.destroy();
3079 ticketLoad && ticketLoad.destroy();
3080 ticketReady = ticketLoad = null;
3082 if( Page.registered() === true ){
3089 // Apple WebKit (Safari, OmniWeb, ...)
3090 if( document.readyState && !!UA.WEBKIT ){
3091 SystemTimer.add( SUPER_USER_KEY, webkitDetect, 50 );
3093 if( document.readyState && UA.isIE && UA.ieVersion < 9 ){
3095 document.onreadystatechange = ieDetect; */
3097 ticketReady = new EventTicketClass( document, 'DOMContentLoaded', onReady );
3098 ticketLoad = new EventTicketClass( window, 'load', onReady );
3105 /* =====================================================
3110 var ResizeEvent = ( function(){
3111 var _globalLock = 0;
3116 function getInnerSize(){
3118 w : root.innerWidth || root.clientWidth,
3119 h : root.innerHeight || root.clientHeight
3126 if( document.uniqueID ){
3127 _resize = function(){
3128 root = (document.compatMode || "") !== "CSS1Compat" ? document.body : document.documentElement;
3132 if( !_globalLock++ ){
3133 var size = getInnerSize();
3134 if( w !== size.w || h !== size.h ){// resized
3138 Application.onWindowResize( w, h );
3140 window.setTimeout( unlock, 0 );
3143 window.setTimeout( loop, 100 );
3148 _resize = function(){
3149 new EventTicketClass( window, 'resize', onResize );
3151 function onResize(){
3152 if( !_globalLock++ ) {
3153 var size = getInnerSize();
3154 if( w !== size.w || h !== size.h ){// resized
3158 Application.onWindowResize( w, h );
3160 window.setTimeout( unlock, 0 );
3166 AsyncCall.add( SUPER_USER_KEY, _resize );
3169 getSize: getInnerSize,
3170 onSystemShutdown: function(){
3177 /* =====================================================
3181 var MouseEvent = ( function(){
3182 var CLICK_OFFSET = 2 * 2,
3183 DRAG_OFFSET = 4 * 4;
3185 var EVENT_LIST_MAP = [],
3188 /*-------------------------------------
3190 * mousedown, mouseup, の移動距離を調べて clickハンドラ を呼ぶ
3192 var ClickEventTicketClass = function( element, clickhandler, opt_thisObject ){
3193 this.mousedownTicket = new EventTicketClass( element, 'mousedown', this.mousedownHandler, this );
3194 this.element = element;
3195 this.handler = clickhandler;
3196 this.thisObject = opt_thisObject;
3198 ClickEventTicketClass.prototype = {
3204 mousedownTicket : null,
3205 mousemoveTicket : null,
3206 mouseupTicket : null,
3207 mouseoutTicket : null,
3208 eventType : 'click',
3209 fire : EventTicketClass.prototype.fire,
3210 match : EventTicketClass.prototype.match,
3211 mousedownHandler : function( e ){
3212 this.startX = e.clientX;
3213 this.startY = e.clientY;
3215 this.mousemoveTicket = new EventTicketClass( this.element, 'mousemove', this.mousemoveHandler, this );
3216 this.mouseupTicket = new EventTicketClass( this.element, 'mouseup', this.mouseupHandler, this );
3217 this.mouseoutTicket = new EventTicketClass( this.element, 'mouseout', this.mouseoutHandler, this );
3220 mousemoveHandler : function( e ){
3221 var offsetX = e.clientX - this.startX,
3222 offsetY = e.clientY - this.startY;
3223 offsetX * offsetX + offsetY * offsetY >= CLICK_OFFSET && this.mouseoutHandler();
3226 mouseupHandler : function( e ){
3227 this.mouseoutHandler();
3228 return this.fire( ClickEventTicketClass.createEvent( e ) );
3230 mouseoutHandler : function( e ){
3231 this.mousemoveTicket && this.mousemoveTicket.destroy();
3232 this.mouseupTicket && this.mouseupTicket.destroy();
3233 this.mouseoutTicket && this.mouseoutTicket.destroy();
3234 if( this.mousemoveTicket ) delete this.mousemoveTicket;
3235 if( this.mouseupTicket ) delete this.mouseupTicket;
3236 if( this.mouseoutTicket ) delete this.mouseoutTicket;
3239 destroy : function( _element, _eventType, _handler ){
3240 if( this.match( _element, _eventType, _handler ) === false ) return false;
3242 this.mouseoutHandler();
3243 this.mousedownTicket.destroy();
3245 delete this.element;
3246 delete this.handler;
3247 delete this.thisObject;
3248 delete this.mousedownTicket;
3252 if( document.createEvent ){
3253 ClickEventTicketClass.createEvent = function( e ){
3254 var _e = document.createEvent( 'MouseEvents' );
3256 'click' , false, true, e.view,
3257 e.detail, e.screenX, e.screenY, e.clientX, e.clientY,
3258 e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
3259 e.button, e.relatedTarget
3264 if( document.attachEvent ){
3265 ClickEventTicketClass.createEvent = function( e ){
3273 /*-------------------------------------
3276 var WheelEventTicketClass = ( function(){
3278 return function( element, wheelhandler, opt_thisObject ){
3279 this.wheelTicket = new EventTicketClass( element, 'DOMMouseScroll', this.onGeckoWheel, this );
3280 this.element = element;
3281 this.handler = wheelhandler;
3282 this.thisObject = opt_thisObject;
3285 if( true || UA.isIE ){
3286 return function( element, wheelhandler, opt_thisObject ){
3287 this.wheelTicket = new EventTicketClass( element, this.eventType, wheelhandler );
3288 this.element = element;
3289 this.handler = wheelhandler;
3290 this.thisObject = opt_thisObject;
3293 TMP.wheelHandlerList = [];
3294 TMP.wheelThisObjList = [];
3295 //TMP.wheelLegacy = undefined;
3296 TMP.onWheel = function( e ){
3297 e = e || window.event;
3299 f = TMP.wheelLegacy;
3300 if( f ) cancel = f.call( this, e );
3302 for( i = TMP.wheelHandlerList.length; i; ){
3303 if( TMP.wheelHandlerList[ --i ].call( TMP.wheelThisObjList[ i ] || this, e ) === false ) cancel = false;
3307 return function( element, wheelhandler, opt_thisObject ){
3308 this.element = element;
3309 this.handler = wheelhandler;
3310 this.thisObject = opt_thisObject;
3312 if( TMP.wheelHandlerList.length === 0 ){
3313 //TMP.wheelLegacy = Type.isFunction( window.onmousewheel ) === true ? window.onmousewheel : undefined;
3314 element.onmousewheel = TMP.onWheel;
3316 TMP.wheelHandlerList.push( wheelhandler );
3317 TMP.wheelThisObjList.push( opt_thisObject )
3321 WheelEventTicketClass.prototype = {
3322 eventType : 'mousewheel',
3323 match : EventTicketClass.prototype.match,
3324 destroy : function( _element, _eventType, _handler ){
3325 if( this.match( _element, _eventType, _handler ) === false ) return false;
3327 this.wheelTicket && this.wheelTicket.destroy();
3329 delete this.wheelTicket;
3330 delete this.element;
3331 delete this.handler;
3332 delete this.thisObject;
3334 this.onDestroy && this.onDestroy();
3339 WheelEventTicketClass.prototype.onGeckoWheel = function( e ){
3340 var _e = document.createEvent( 'MouseEvents' );
3342 'mousewheel' , false, true, e.view,
3343 e.detail, e.screenX, e.screenY, e.clientX, e.clientY,
3344 e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
3345 e.button, e.relatedTarget
3347 _e.wheelDelta = e.detail * -40;
3348 return this.handler.call( this.thisObject || this.element, _e );
3351 if( true || UA.isIE ){
3354 WheelEventTicketClass.prototype.onDestroy = function(){
3355 TMP.wheelHandlerList.splice( Util.getIndex( TMP.wheelHandlerList, this.handler ), 1 );
3356 TMP.wheelThisObjList.splice( Util.getIndex( TMP.wheelThisObjList, this.handler ), 1 );
3357 if( TMP.wheelHandlerList.length === 0 ) this.element.onmousewheel = '';
3361 /*-------------------------------------
3364 var DragEventTicketClass = function( element, draghandler, opt_thisObject ){
3365 this.mousedownTicket = new EventTicketClass( element, 'mousedown', this.mousedownHandler, this );
3366 this.element = element;
3367 this.handler = draghandler;
3368 this.thisObject = opt_thisObject;
3370 DragEventTicketClass.prototype = {
3377 mousedownTicket : null,
3378 mousemoveTicket : null,
3379 mouseupTicket : null,
3380 mouseoutTicket : null,
3381 eventType : 'mousedrag',
3382 fire : EventTicketClass.prototype.fire,
3383 match : EventTicketClass.prototype.match,
3384 mousedownHandler: function( e ){
3385 this.startX = e.clientX;
3386 this.startY = e.clientY;
3388 this.mousemoveTicket = new EventTicketClass( this.element, 'mousemove', this.dragMoveHandler, this );
3389 this.mouseupTicket = new EventTicketClass( this.element, 'mouseup', this.dragEndHandler, this );
3390 this.mouseoutTicket = new EventTicketClass( this.element, 'mouseout', this.dragEndHandler, this );
3394 dragMoveHandler : function( e ){
3395 var offsetX = e.clientX - this.startX,
3396 offsetY = e.clientY - this.startY;
3397 if( this.dragging === false ){
3398 if( offsetX * offsetX + offsetY * offsetY < DRAG_OFFSET ) return;
3399 console.log( 'Drag start' );
3401 this.dragging = true;
3402 return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 0 ) );
3404 return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 1 ) );
3406 dragEndHandler : function( e ){
3407 if( this.dragging === true ){
3408 console.log( 'Drag End ' + e.type );
3409 this.removeEvents();
3411 return this.fire( DragEventTicketClass.createEvent( e, e.clientX - this.startX, e.clientY - this.startY, 2 ) );
3413 this.removeEvents();
3416 removeEvents : function(){
3417 this.dragging = false;
3418 if( this.mousemoveTicket ){
3419 this.mousemoveTicket.destroy();
3420 delete this.mousemoveTicket;
3422 if( this.mouseupTicket ){
3423 this.mouseupTicket.destroy();
3424 delete this.mouseupTicket;
3426 if( this.mouseoutTicke ){
3427 this.mouseoutTicket.destroy();
3428 delete this.mouseoutTicket;
3431 destroy : function( _element, _eventType, _handler ){
3432 if( this.match( _element, _eventType, _handler ) === false ) return false;
3434 this.removeEvents();
3435 this.mousedownTicket.destroy();
3437 delete this.element;
3438 delete this.handler;
3439 delete this.thisObject;
3440 delete this.mousedownTicket;
3444 if( document.createEvent ){
3445 DragEventTicketClass.createEvent = function( e, offsetX, offsetY, dragPhase ){
3446 var _e = document.createEvent( 'MouseEvents' );
3448 DragEventTicketClass.prototype.eventType , false, true, e.view,
3449 e.detail, e.screenX, e.screenY, e.clientX, e.clientY,
3450 e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
3451 e.button, e.relatedTarget
3453 _e.dragPhase = dragPhase;
3454 _e.dragOffsetX = offsetX;
3455 _e.dragOffsetY = offsetY;
3459 if( document.attachEvent ){
3460 DragEventTicketClass.createEvent = function( e, offsetX, offsetY, dragPhase ){
3461 e.type = DragEventTicketClass.prototype.eventType;
3462 e.dragPhase = dragPhase;
3463 e.dragOffsetX = offsetX;
3464 e.dragOffsetY = offsetY;
3472 add: function( _apiuser, _element, _eventType, _handler, opt_thisObject ){
3473 if( isApiUser( _apiuser ) === true &&
3474 ( Type.isHTMLElement( _element ) === true || _element === window || _element === document ) &&
3475 Type.isString( _eventType ) === true &&
3476 Type.isFunction( _handler ) === true
3478 var _uid = _apiuser.getUID(),
3479 _events = EVENT_LIST_MAP[ _uid ];
3480 if( Type.isArray( _events ) === false ){
3481 _events = EVENT_LIST_MAP[ _uid ] = [];
3484 for( var i=0, l=_events.length; i<l; ++i ){
3485 if( _events[ i ].match( _element, _eventType, _handler ) === true ) return;
3488 switch( _eventType ){
3490 _events.push( new ClickEventTicketClass( _element, _handler, opt_thisObject ) );
3493 _events.push( new WheelEventTicketClass( _element, _handler, opt_thisObject ) );
3496 _events.push( new DragEventTicketClass( _element, _handler, opt_thisObject ) );
3499 _events.push( new EventTicketClass( _element, _eventType, _handler, opt_thisObject ) );
3503 remove: function( apiuser, element, eventType, handler ){
3504 if( isApiUser( apiuser ) === true ){
3505 var uid = apiuser.getUID(),
3506 list = EVENT_LIST_MAP[ uid ],
3508 if( Type.isArray( list ) === false ) return;
3509 for( ;i < list.length; ){
3510 if( list[ i ].destroy( element, eventType, handler ) === true ){
3511 list.splice( i, 1 );
3516 if( list.length === 0 ){
3517 EVENT_LIST_MAP[ uid ] = null;
3521 onCurrentApplicationChange: function(){
3524 onApplicationShutdown: function(){
3527 onSystemShutdown: function(){
3533 /* ----------------------------------------
3536 * - EDITABLE_TEXT_CONTROL
3538 * .SHIFT_DOWN_EVENT: 'shiftDown',
3539 * .SHIFT_UP_EVENT: 'shiftUp',
3540 * .CTRL_DOWN_EVENT: 'ctrlDown',
3541 * .CTRL_UP_EVENT: 'ctrlUp',
3542 * .SPACE_DOWN_EVENT: 'spaceDown',
3543 * .SPACE_UP_EVENT: 'spaceUp',
3545 * .addKeyDownEvent: function,
3546 * .keyEventDispatcher: function,
3548 * ショートカットキーの監視とテキスト入力(input, textarea)、チェックボックスを管理する。
3549 * キー入力はdocumentで受けて、テキスト編集中(input, textarea)はそちらにキーイベント流す。
3552 var KeyEvent = ( function(){
3553 var EVENT_LIST_MAP = [],
3561 var focusTicket = null,
3562 keydownTicket = null,
3565 keypressTicket = null;
3567 function unlock( lock, key ){
3568 lock.splice( Util.getIndex( lock, key ), 1 );
3571 function onKeyChange( e ){
3574 key = e.keyCode, // || e.which,
3575 shift = Type.isBoolean( e.shiftKey ) === true ? e.shiftKey : ( e.modifiers & Event.SHIFT_MASK ),
3576 ctrl = Type.isBoolean( e.ctrlKey ) === true ? e.ctrlKey : ( e.modifiers & Event.CONTROL_MASK ),
3577 lock = type === 'keyup' ? LOCK_UP : LOCK_DOWN,
3581 if( Util.getIndex( lock, key ) !== -1 ) return;
3583 AsyncCall.add( SUPER_USER_KEY, unlock, [ lock, key ] );
3585 if( key === 16 || shift === true ){
3586 KeyEvent.shiftEnabled = type !== 'keyup';
3588 if( key === 17 || ctrl === true ){
3589 KeyEvent.ctrlEnabled = type !== 'keyup';
3591 for( i = currentList.length; i; ){
3592 t = currentList[ --i ];
3593 if( Type.isFunction( t[ type ] ) === true && t.keyCode === key && ( t.shift === undefined || t.shift === shift ) && ( t.ctrl === undefined || t.ctrl === ctrl )){
3594 if( t[ type ].call( t.apiuser, e ) === false ){
3600 if( cancel === true || key === 18 || key === 9 || key === 27 || e.altKey === true ){ // 13.enter 18.esc 9.tab 27.esc || ( key === 13 && overlayEnabled === false)
3605 if( UA.isIE === true && UA.ieRenderingVersion < 9 ){
3606 keyPress = function( e ){
3607 var key = e.keyCode;
3608 if( key === 13 || key === 27 ){
3610 return onKeyChange( e );
3615 var KeyEventTicketClass = function( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ){
3616 this.apiuser = _apiuser;
3618 this.keydown = _onKeydown;
3619 this.keyup = _onKeyup;
3620 this.keyCode = _keyCode;
3621 this.shift = _shift;
3623 _apiuser = _onKeydown = _onKeyup = null;
3625 KeyEventTicketClass.prototype = {
3626 match: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3627 if( _apiuser && _apiuser !== this.apiuser ) return false;
3628 if( _type && _type !== this.type ) return false;
3630 if( this.type === 'keydown' ){
3631 if( _handler !== this.keydown ) return false;
3633 if( _handler !== this.keyup ) return false;
3636 if( _keyCode && _keyCode !== this.keyCode ) return false;
3637 if( _shift && _shift !== this.shift ) return false;
3638 if( _ctrl && _ctrl !== this.ctrl ) return false;
3641 destroy: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3642 if( this.match( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ) === false ) return false;
3644 delete this.apiuser;
3645 delete this.keydown;
3652 function registerEvent( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ){
3653 var _uid = _apiuser.getUID(),
3654 _list = EVENT_LIST_MAP[ _uid ];
3655 if( Type.isArray( _list ) === false ){
3656 _list = EVENT_LIST_MAP[ _uid ] = [];
3658 for( var i=0, l=_list.length; i<l; ++i ){
3659 if( _list[ i ].match( _apiuser, _type, _onKeydown || _onKeyup, _keyCode, _shift, _ctrl ) === true ) return;
3661 _list.push( new KeyEventTicketClass( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ));
3663 if( _apiuser === application ) KeyEvent.updateCurrentListener( _apiuser );
3667 add: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3668 if( _type === 'keydown' ){
3669 registerEvent( _apiuser, _type, _handler, null, _keyCode, _shift, _ctrl );
3671 if( _type === 'keyup' ){
3672 registerEvent( _apiuser, _type, null, _handler, _keyCode, _shift, _ctrl );
3674 if( _type === 'keychange' ){
3675 registerEvent( _apiuser, _type, _handler, _handler, _keyCode, _shift, _ctrl );
3677 if( _type === 'cursol' ){
3681 remove: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3682 var _list = EVENT_LIST_MAP[ _apiuser.getUID() ],
3684 if( Type.isArray( _list ) === true ){
3685 while( i < _list.length ){
3686 if( _list[ i ].destroy( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ) === true ){
3687 _list.splice( i, 1 );
3693 if( _apiuser === application ) KeyEvent.updateCurrentListener( _apiuser );
3695 shiftEnabled: false,
3699 * currrentApplication ( overlay Application ) or
3702 updateCurrentListener: function( _apiuser ){
3703 application = _apiuser;
3704 var _uid = _apiuser.getUID();
3705 currentList = EVENT_LIST_MAP[ _uid ] || ( EVENT_LIST_MAP[ _uid ] = [] );
3710 for( var i=currentList.length; _ticket = currentList[ --i ]; ){
3711 if( _down === false ) _down = !!_ticket.keydown;
3712 if( _up === false ) _up = !!_ticket.keyup;
3713 if( _down && _up ) break;
3715 if( _down === true ){
3716 keydownTicket = new EventTicketClass( document, 'keydown', onKeyChange );
3717 keypressTicket = keyPress !== null ? new EventTicketClass( document, 'keypress', keyPress ) : null;
3719 keydownTicket && keydownTicket.destroy();
3720 keypressTicket && keypressTicket.destroy();
3721 keydownTicket = keypressTicket = null;
3724 keyupTicket = new EventTicketClass( document, 'keyup', onKeyChange );
3726 keyupTicket && keyupTicket.destroy();
3730 if( _down === true || _up === true ){
3731 focusTicket = new EventTicketClass( document, 'mouseenter', window.focus );
3733 focusTicket && focusTicket.destroy();
3737 onApplicationShutdown: function( _apiuser ){
3738 KeyEvent.remove( _apiuser );
3740 onSystemShutdown: function(){
3748 * http://thudjs.tumblr.com/post/637855087/stylesheet-onload-or-lack-thereof
3751 var StyleSheet = ( function(){
3752 var head = document.getElementsByTagName( 'head' )[ 0 ];
3754 var TICKET_LIST = [];
3755 var STATE_LIST = 'loaded,complete,uninitialized'.split( ',' );
3757 var cssRules, sheet;
3759 var FetchCssTicketClass = function( _apiuser, _url, _elm, _onload, _onerror, opt_thisObject ){
3760 this.apiusers = [ _apiuser ];
3763 this.onload = [ _onload ];
3764 this.onerror = [ _onerror ];
3765 this.thisObj = [ opt_thisObject ];
3768 FetchCssTicketClass.prototype = {
3769 match: function( _apiuser, _url ){
3770 if( _apiuser && Util.getIndex( this.apiusers, _apiuser ) === -1 ) return false;
3771 if( _url && _url !== this.url ) return false;
3774 destroy: function( _apiuser, _url ){
3775 if( this.match( _apiuser, _url ) === false ) return false;
3777 var i = Util.getIndex( this.apiusers, _apiuser );
3779 this.apiusers.splice( i, 1 );
3780 this.onload.splice( i, 1 );
3781 this.onerror.splice( i, 1 );
3782 this.thisObj.splice( i, 1 );
3784 if( this.apiusers.length !== 0 ) return false;
3786 head.removeChild( this.elm );
3787 this.elm.onreadystatechange = new Function();
3788 this.elm.onload = null;
3790 delete this.apiusers;
3794 delete this.onerror;
3795 delete this.thisObj;
3801 for( var i = this.onload.length, f; i; ){
3802 f = this.onload[ --i ];
3803 Type.isFunction( f ) === true && AsyncCall.add( this.apiusers[ i ], f, this.url, this.thisObj[ i ] || this.apiusers[ i ] );
3804 this.onload[ i ] = this.onerror[ i ] = null;
3808 for( var i = this.onerror.length, f; i; ){
3809 f = this.onerror[ --i ];
3810 Type.isFunction( f ) === true && AsyncCall.add( this.apiusers[ i ], f, this.url, this.thisObj[ i ] || this.apiusers[ i ] );
3811 this.onload[ i ] = this.onerror[ i ] = null;
3817 return el[ sheet ] && el[ sheet ][ cssRules ].length > 0;
3825 function getTicket( elm ){
3826 for( var i = TICKET_LIST.length, t; i; ){
3827 t = TICKET_LIST[ --i ];
3828 if( t.elm === elm ) return t;
3833 var t = getTicket( this ), rs = this.readyState, c;
3834 if( t && t.done === false && ( !rs || Util.getIndex( STATE_LIST, rs ) !== -1 ) ){
3837 this.onreadystatechange = new Function();
3842 function checkTimer(){
3843 var l = TICKET_LIST.length,
3845 for( var i = 0; i < l; ++i ){
3846 t = TICKET_LIST[ i ];
3848 if( t.check() === true ){
3858 l === n && SystemTimer.remove( SUPER_USER_KEY, checkTimer );
3862 load: function( _apiuser, _url, opt_onload, opt_onerror, opt_thisObject ){
3863 _url = Util.getAbsolutePath( _url );
3865 for( var i=TICKET_LIST.length; i; ){
3866 t = TICKET_LIST[ --i ];
3867 if( t.match( null, _url ) === true ){
3868 if( t.match( _apiuser, _url ) === false ){
3869 t.apiusers.push( _apiuser );
3870 t.onload.push( opt_onload );
3871 t.onerror.push( opt_onerror );
3872 t.thisObj.push( opt_thisObject );
3874 SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 );
3878 var elm = document.createElement( 'link' );
3879 head.appendChild( elm );
3880 elm.rel = 'stylesheet';
3881 elm.type = 'text\/css';
3882 elm.onreadystatechange = elm.onload = detect;
3885 if( !sheet ){ // only assign these once
3886 cssRules = 'cssRules';
3888 if ( !( sheet in elm ) ) { // MSIE uses non-standard property names
3890 sheet = 'styleSheet';
3894 TICKET_LIST.push( new FetchCssTicketClass( _apiuser, _url, elm, opt_onload, opt_onerror, opt_thisObject ) );
3896 SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 );
3898 unload: function( _apiuser, _url ){
3899 _url = _url ? Util.getAbsolutePath( _url ) : null;
3900 for( var i = 0; i < TICKET_LIST.length; ){
3901 t = TICKET_LIST[ i ];
3902 if( t.destroy( _apiuser, _url ) === true ){
3903 TICKET_LIST.splice( i, 1 );
3908 if( TICKET_LIST.length === 0 ){
3909 SystemTimer.remove( SUPER_USER_KEY, checkTimer );
3925 var Image = ( function(){
3928 * FetchClass original is
3931 * URL: http://d.hatena.ne.jp/uupaa/20080413/1208067631
3932 * AUTHOR: uupaa.js@gmail.com
3936 for( var i=0, t; i < TASK_LIST.length; ){
3938 if( t.complete() === true ){
3939 TASK_LIST.splice( i, 1 );
3944 TASK_LIST.length === 0 && SystemTimer.remove( SUPER_USER_KEY, detect );
3946 function getTask( img ){
3947 for( var i = TASK_LIST.length; i; ){
3948 if( TASK_LIST[ --i ].img === img ) return TASK_LIST[ i ];
3952 var task = getTask( this );
3953 if( task.finish === true ) return;
3955 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
3958 // if( finish === true ) return; // これがあると firefox3.6 で駄目、、、
3959 // if( timer ) return; // これがあると safari3.2 で駄目、、、
3960 var task = getTask( this );
3962 TASK_LIST.splice( Util.getIndex( TASK_LIST, task ), 1 );
3963 if( window.opera && !task.img.complete ){
3964 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
3967 task.size = Util.getImageSize( this );
3968 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
3972 var FetchClass = function( apiuser, abspath, onLoadCallback, onErrorCallback, timeout ){
3973 this.apiuser = apiuser;
3974 this.abspath = abspath;
3975 this.onLoadCallback = onLoadCallback;
3976 this.onErrorCallback = onErrorCallback;
3977 this.timeout = timeout;
3980 FetchClass.prototype = {
3986 var img = this.img = document.createElement( 'img' ); //var img = new Image(); ではieでimgのsizeが取れない、、、removeChildも失敗し、imgSizeGetterにimgが残る
3987 img.onabort = img.onerror = onError;
3988 img.onload = onLoad;
3989 img.src = this.abspath;
3991 complete: function(){
3992 if( this.finish === true ) return true;
3993 if( this.img.complete ){
3995 if( this.img.width ) return true;
3996 AsyncCall.add( this.apiuser, this.asyncCallback, null, this );
3999 if( ( this.tick += 250 ) > this.timeout ){
4001 AsyncCall.add( this.apiuser, this.asyncCallback, null, this );
4005 asyncCallback: function(){
4006 this.size ? this.onLoadCallback( this.abspath, this.size.width, this.size.height ) : this.onErrorCallback( this.abspath );
4009 destroy: function(){
4011 this.img.src = this.img.onload = this.img.onabort = this.img.onerror = '';
4014 delete this.onLoadCallback;
4015 delete this.onErrorCallback;
4018 timer !== null && window.clearTimeout( timer );
4024 load: function( URLorELM, onLoad, onError, opt_timeout ){
4026 if( Type.isString( URLorELM ) === true ){
4029 if( Type.isHTMLElement( URLorELM ) === true && URLorELM.tagName.toLowerCase() === 'img' ){
4035 fetch = new FetchClass(
4036 Util.getAbsolutePath( src ),
4038 Type.isFinite( opt_timeout ) === true ? opt_timeout : undefined
4040 TASK_LIST.push( fetch );
4042 SystemTimer.add( SUPER_USER_KEY, detect, 250 );
4044 unload: function( ){
4051 /* ----------------------------------------
4055 var Overlay = ( function(){
4056 var elmContainer, elmShadow, elmCloseButton,
4063 function onCloseClick( e ){
4067 function asyncInit( /* arguments */ ){
4069 //application.rootElement.style.display = 'none';
4071 elmContainer.style.cssText = "top:" + body.scrollTop + 'px;display:none;';
4072 $( elmContainer ).stop().fadeIn( onFadeInComplete );
4074 function asyncOpen( /* arguments */ ){
4079 function onFadeInComplete(){
4080 KeyEvent.add( application, Const.KEY.EVENT.KEY_DOWN, Overlay.hide, 27 ); // 27.esc
4081 MouseEvent.add( application, elmCloseButton, 'click', onCloseClick );
4083 var _arg = bootParams; //Util.copyArray( arguments );
4084 _arg.unshift( windowW, windowH );
4085 application.open.apply( application, _arg );
4087 function onFadeOutComplete(){
4088 Util.removeAllChildren( elmContainer );
4089 body.removeChild( elmContainer );
4090 elmContainer = elmShadow = elmCloseButton = null;
4093 show: function( _application, _bootParams ){
4094 if( visible === true && application === _application ) return;
4095 if( Application.isApplicationInstance( _application ) === false ) return;
4097 elmContainer = document.createElement( 'div' );
4098 body.appendChild( elmContainer );
4100 elmContainer.id = 'overlay-container';
4102 bodyOverflow = body.style.overflow;
4103 body.style.overflow = 'hidden';
4105 elmShadow = document.createElement( 'div' );
4106 elmContainer.appendChild( elmShadow );
4107 elmShadow.id = 'overlay-shadow';
4109 elmCloseButton = document.createElement( 'div' );
4110 elmContainer.appendChild( elmCloseButton );
4111 elmCloseButton.id = 'overlay-close-button';
4112 elmCloseButton.appendChild( document.createTextNode( 'x' ) );
4114 elmContainer.style.display = 'none'; // hide for fadeIn
4117 application = _application;
4120 elmContainer.insertBefore( application.rootElement, elmCloseButton );
4121 _application.addAsyncCall( asyncInit );
4122 // _application.addAsyncCall( asyncOpen, );
4124 bootParams = _bootParams;
4127 if( visible === false ) return;
4128 if( application.close() === false ) return false;
4130 body.style.overflow = bodyOverflow;
4132 $( elmContainer ).stop().css( {
4135 }).fadeOut( onFadeOutComplete );
4140 onWindowResize: function( _windowW, _windowH ){
4144 if( application === null ) return;
4146 elmContainer.style.height = _windowH + 'px';
4147 elmContainer.style.top = body.scrollTop + 'px';
4149 elmShadow.style.height = _windowH + 'px';
4151 AsyncCall.add( application, application.resize, [ _windowW, _windowH ] );
4156 /* ----------------------------------------
4160 * form -> overlay -> view
4164 var UI = ( function(){
4173 var CLASSNAME_COMBOBOX_OPTION = 'combobox-option',
4174 CLASSNAME_COMBOBOX_OPTION_CURRENT = CLASSNAME_COMBOBOX_OPTION + ' combobox-option-current',
4175 ELM_COMBOBOX = ( function(){
4176 var ret = document.createElement( 'a' ),
4177 elmToggle = document.createElement( 'span' ),
4178 elmValue = document.createElement( 'span' );
4180 ret.appendChild( elmToggle );
4181 ret.appendChild( elmValue );
4182 elmToggle.className = 'combobox-toggle';
4183 elmValue.className = 'combobox-value';
4185 elmToggle.appendChild( document.createTextNode( '▼' ));
4186 elmValue.appendChild( document.createTextNode( 'null' ));
4190 var UIItemPrivateData = function(){};
4191 UIItemPrivateData.prototype = {
4209 init : function( groupData, item, elm, value, onUpdate, validator, focus, visible, enabled ){
4210 this.groupData = groupData;
4214 this.onUpdate = onUpdate;
4215 this.validator = validator;
4216 this.focus = !!focus;
4217 this.visible = !!visible;
4218 this.enabled = !!enabled;
4219 UIItemPrivateData.list.push( this );
4221 destroy : function(){
4222 var list = UIItemPrivateData.list;
4223 list.splice( Util.getIndex( list, this ), 1 );
4225 list = this.groupData.itemList;
4226 var i = Util.getIndex( list, this.item );
4227 i !== -1 && list.splice( i, 1 );
4229 this.node && this.node.remove();
4232 UIItemPrivateData.list = [];
4233 UIItemPrivateData.get = function( item ){
4234 var list = UIItemPrivateData.list;
4235 for( i = list.length; i; ){
4236 if( list[ --i ].item === item ) return list[ i ];
4241 /* --------------------------------
4244 var TextInputManager = ( function(){
4245 var elmInput = ( function(){
4246 var ret = document.createElement( 'input' );
4248 ret.id = 'ui-textinput';
4253 function updateWrapperPosition(){
4254 var p = Position.cumulativeOffset( currentData.elmValue ),
4255 w = currentData.elmValue.offsetWidth - 2,
4257 elmInput.style.cssText = [
4258 'left:', p[ 0 ], 'px;',
4259 'top:', p[ 1 ], 'px;',//,
4260 'width:', w, 'px;'//,
4261 //'height:', data.elmValue.offsetHeight, 'px;',
4262 //'position:absolute;'
4265 //_w = elmInput.offsetWidth;
4266 //if( w !== _w ) elmInput.style.width = ( w - ( _w - w ) ) + 'px;';
4270 show: function( data ){
4271 // this.groupData.node.addEventListener( 'mouseout' );
4274 body.appendChild( elmInput );
4275 elmInput.value = data.value;
4276 updateWrapperPosition();
4281 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4283 hide : function( data ){
4284 if( currentData !== data ) return;
4286 body.removeChild( elmInput );
4287 var ret = elmInput.value;
4288 elmInput.value = '';
4289 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition );
4292 update : function( data ){
4293 elmInput.value = data.value;
4295 onWindowResize: function( _w, _h ){
4296 AsyncCall.add( currentUser, updateWrapperPosition );
4301 var TextInputClass = function( groupData, elmWrapper, elmValue, onUpdate, validater ){
4302 var data = new UIItemPrivateData();
4303 data.init( groupData, this, elmWrapper, elmValue.innerHTML, onUpdate, validater, false, true, true );
4304 Util.addClass( elmValue, 'editable-text' );
4305 data.elmValue = elmValue;
4306 this.value( data.value );
4307 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-inpittext-hover', 'pointer' );
4308 data.node.addEventListener( 'click', this.focus, this );
4309 //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', instance.focus );
4311 TextInputClass.prototype = {
4312 value : function( value ){
4313 var data = UIItemPrivateData.get( this );
4314 if( Type.isString( value ) === true || Type.isNumber( value ) === true ){
4315 data.elmValue.innerHTML = data.value = '' + value;
4316 data.focus === true && TextInputManager.update( data );
4318 data.focus === true && this.blur();
4321 focus : function( e ){
4322 var data = UIItemPrivateData.get( this );
4325 TextInputManager.show( data );
4328 blur : function( keep ){
4329 var data = UIItemPrivateData.get( this ),
4331 if( data.focus === false ) return;
4332 newValue = TextInputManager.hide( data );
4333 newValue = keep !== 27 ? ( data.validater ? '' + data.validater( newValue ) : newValue ) : data.value; // 27:ESC
4335 data.elmValue.innerHTML = newValue;
4337 data.onUpdate && newValue !== data.value && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ newValue, data.value ], this );
4339 data.value = newValue;
4343 enabled : function( v ){
4344 var data = UIItemPrivateData.get( this );
4345 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4346 Util.toggleClass( data.elm, 'ui-textinput-disabled', !v );
4347 if( data.focus === true && v === false ) this.blur();
4349 data.node.disabled( !( data.visible && v ) );
4351 return data.enabled;
4353 visible : function( v ){
4354 var data = UIItemPrivateData.get( this );
4355 if( Type.isBoolean( v ) === true && data.visible !== v ){
4356 data.elm.style.display = v ? '' : 'none';
4357 if( data.focus === true && v === false ) this.blur();
4359 data.node.disabled( !( data.enabled && v ) );
4361 return data.visible;
4363 destroy : function(){
4364 var data = UIItemPrivateData.get( this );
4365 data.focus === true && TextInputManager.hide( data );
4370 /* --------------------------------
4373 var FileInputManager = ( function(){
4380 function updateWrapperPosition(){
4381 var p = Position.cumulativeOffset( currentData.elmValue ),
4382 w = currentData.elmValue.offsetWidth,
4384 elmWrap.style.cssText = [
4385 'left:', p[ 0 ], 'px;',
4386 'top:', p[ 1 ], 'px;',//,
4387 'width:', w, 'px;'//,
4388 //'height:', data.elmValue.offsetHeight, 'px;',
4389 //'position:absolute;'
4392 _w = elmWrap.offsetWidth;
4393 if( w !== _w ) elmWrap.style.width = ( w - ( _w - w ) ) + 'px';
4396 function change( e ){
4397 var data = currentData,
4398 file = data.elmFileInputReal.value;
4399 file = file.split( '\\' );
4400 file = file[ file.length - 1 ];
4401 if( data.value !== file ){
4402 data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ file, data.value ], this );
4403 data.elmValue.innerHTML = data.value = file;
4405 currentData.item.blur();
4407 function asyncMouseout(){
4408 currentData && currentData.item.blur();
4411 MouseEvent.remove( currentUser, elmFileInput, 'mouseout', asyncMouseout );
4412 MouseEvent.remove( currentUser, elmFileInput, 'click', onClick );
4415 show : function( data ){
4418 elmFileInput = data.elmFileInputReal;
4419 elmWrap = elmFileInput.parentNode;
4422 updateWrapperPosition();
4423 elmFileInput.focus();
4424 //data.node.addEventListener( 'change', change, data );
4425 evt = new EventTicketClass( elmFileInput, 'change', change );
4426 MouseEvent.add( currentUser, elmFileInput, 'mouseout', asyncMouseout );
4427 MouseEvent.add( currentUser, elmFileInput, 'click', onClick );
4428 // currentData.elmFileInputReal.onchange = change;
4429 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4431 hide : function( data ){
4432 if( currentData !== data ) return;
4433 // data.node.removeEventListener( 'change', change );
4435 // MouseEvent.remove( currentUser, elmFileInput, 'mouseout', asyncMouseout );
4437 //currentData.elmFileInputReal.onchange = null;
4438 elmWrap.style.display = 'none';
4439 currentData = elmFileInput = null;
4440 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition );
4442 onWindowResize: function( _w, _h ){
4443 AsyncCall.add( currentUser, updateWrapperPosition );
4448 var FileInputClass = function( groupData, elmWrapper, onUpdate, validater, elmFileInputReal, elmValue ){
4449 var data = new UIItemPrivateData();
4450 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4451 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-fileinput-hover', 'pointer' );
4452 data.elmValue = elmValue;
4453 data.elmFileInputReal = elmFileInputReal;
4454 data.node.addEventListener( 'mouseover', this.focus, this );
4456 FileInputClass.prototype = {
4461 var data = UIItemPrivateData.get( this );
4463 Util.addClass( data.elm, 'fileinput-has-focus' );
4465 FileInputManager.show( data );
4467 blur : function( keyCode ){
4468 var data = UIItemPrivateData.get( this );
4469 Util.removeClass( data.elm, 'fileinput-has-focus' );
4471 FileInputManager.hide( data );
4474 enabled : function( v ){
4475 var data = UIItemPrivateData.get( this );
4476 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4477 if( data.focus === true && v === false ) this.blur();
4478 Util.toggleClass( data.elm, 'fileinput-disabled', !v );
4480 data.node.disabled( !( data.visible && v ) );
4482 return data.enabled;
4484 visible : function( v ){
4485 var data = UIItemPrivateData.get( this );
4486 if( Type.isBoolean( v ) === true && data.visible !== v ){
4487 if( data.focus === true && v === false ) this.blur();
4488 data.elm.style.display = v ? '' : 'none';
4490 data.node.disabled( !( data.enabled && v ) );
4492 return data.visible;
4494 destroy : function(){
4495 var data = UIItemPrivateData.get( this );
4496 data.focus === true && FileInputManager.hide( data );
4501 var ButtonClass = function( groupData, elmWrapper, onUpdate ){
4502 var data = new UIItemPrivateData();
4503 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4504 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-button-hover', 'pointer' );
4505 data.node.addEventListener( 'click', onUpdate );
4506 //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', onUpdate );
4508 ButtonClass.prototype = {
4510 var data = UIItemPrivateData.get( this );
4512 Util.addClass( data.elm, 'button-has-focus' );
4515 blur : function( keyCode ){
4516 var data = UIItemPrivateData.get( this );
4517 keyCode === 13 && data.onUpdate && data.onUpdate();
4518 Util.removeClass( data.elm, 'button-has-focus' );
4522 enabled : function( v ){
4523 var data = UIItemPrivateData.get( this );
4524 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4525 Util.toggleClass( data.elm, 'button-disabled', !v );
4527 data.node.disabled( !( data.visible && v ) );
4529 return data.enabled;
4531 visible : function( v ){
4532 var data = UIItemPrivateData.get( this );
4533 if( Type.isBoolean( v ) === true && data.visible !== v ){
4534 data.elm.style.display = v ? '' : 'none';
4536 data.node.disabled( !( data.enabled && v ) );
4538 return data.visible;
4540 destroy : function(){
4541 var data = UIItemPrivateData.get( this );
4542 // MouseEvent.remove( data.groupData.apiuser, data.elm );
4547 var ComboBoxClass = function( groupData, elmWrapper, onUpdate ){
4548 var elmA = ELM_COMBOBOX.cloneNode( true ),
4549 data = new UIItemPrivateData();
4550 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4552 data.elmBox = Util.getElementsByClassName( elmWrapper, 'combobox' )[ 0 ];
4553 data.elmBox.appendChild( elmA );
4555 data.elmToggle = Util.getElementsByClassName( elmA, 'combobox-toggle' )[ 0 ];
4556 data.elmValue = Util.getElementsByClassName( elmA, 'combobox-value' )[ 0 ].firstChild;
4557 data.selectIndex = 0;
4558 data.optionList = [];
4560 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-combobox-hover', 'pointer' );
4561 data.node.addEventListener( 'click', this.focus, this );
4563 ComboBoxClass.prototype = {
4564 focus : function( e ){
4565 var data = UIItemPrivateData.get( this );
4566 data.node.removeEventListener( 'click', this.focus );
4568 data.elmA.className = 'combobox-has-focus';
4570 OptionControl.show( data );
4573 blur : function( keyCode ){
4574 var data = UIItemPrivateData.get( this );
4575 OptionControl.hide( this );
4577 data.elmA.className = '';
4579 data.node.addEventListener( 'click', this.focus, this );
4581 enabled : function( v ){
4582 var data = UIItemPrivateData.get( this );
4583 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4584 Util.toggleClass( data.elm, 'ui-combobox-disabled', !v );
4585 if( data.focus === true && v === false ) this.blur();
4587 data.node.disabled( !( data.visible && v ) );
4589 return data.enabled;
4591 visible : function( v ){
4592 var data = UIItemPrivateData.get( this );
4593 if( Type.isBoolean( v ) === true && data.visible !== v ){
4594 data.elm.style.display = v ? '' : 'none';
4595 if( data.focus === true && v === false ) this.blur();
4597 data.node.disabled( !( data.enabled && v ) );
4599 return data.visible;
4601 value : function( _value ){
4602 var data = UIItemPrivateData.get( this ),
4604 list = data.optionList,
4607 if( Type.isString( _value ) === true && data.value !== _value ){
4608 for( ; i < l; ++i ){
4609 _option = list[ i ];
4610 if( _value === _option.value ){
4611 data.value = _value;
4613 data.elmValue.data = _option.displayValue;
4614 if( data.focus === true ){
4615 OptionControl.update( this, _value );
4617 data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, _value, this );
4624 selectIndex : function(){
4625 var data = UIItemPrivateData.get( this );
4626 return data.selectIndex;
4628 createOption : function( _displayValue, _value, _isSelected ){
4629 var data = UIItemPrivateData.get( this ),
4631 list = data.optionList,
4634 _value = _value || _displayValue;
4635 _isSelected = !!_isSelected;
4637 _option = list[ --i ];
4638 if( _value === _option.value ){
4643 if( _isSelected === true ){
4644 data.selectIndex = list.length;
4645 data.elmValue.data = _displayValue;
4647 option === null && list.push( new OptionDataClass( _displayValue, _value, _isSelected ) );
4649 destroy : function(){
4650 var data = UIItemPrivateData.get( this );
4651 data.focus === true && OptionControl.hide( this );
4653 // MouseEvent.remove( data.groupData.apiuser, data.elm );
4654 data.optionList.length = 0;
4658 var OptionDataClass = function( displayValue, value, isCurrent ){
4659 this.displayValue = displayValue;
4660 this.value = value || displayValue;
4661 this.current = isCurrent;
4662 displayValue = value = null;
4665 var OptionControl = ( function(){
4666 var ELM_OPTION_WRAPPER = ( function(){
4667 var ret = document.createElement( 'div' );
4668 ret.className = 'option-container';
4671 ELM_OPTION_ORIGIN = ( function(){
4672 var ret = document.createElement( 'a' );
4673 ret.appendChild( document.createTextNode( 'option' ) );
4678 var OptionClass = function( option ){
4679 this.elm = ELM_OPTION_ORIGIN.cloneNode( true );
4683 OptionClass.prototype = {
4685 ELM_OPTION_WRAPPER.appendChild( this.elm );
4686 this.elm.firstChild.data = this.data.displayValue;
4687 this.current( this.data.current );
4688 MouseEvent.add( SUPER_USER_KEY, this.elm, 'mousedown', onOptionSelect );// onclick では 選択ボックス 隠すように body に設定した onmouseup が先に動いてしまう!
4690 current: function( _current ){
4691 this.elm.className = _current === true ? CLASSNAME_COMBOBOX_OPTION_CURRENT : CLASSNAME_COMBOBOX_OPTION;
4692 this.data.current = _current;
4693 currentOption = _current === true ? this : currentOption;
4695 destroy: function(){
4696 MouseEvent.remove( SUPER_USER_KEY, this.elm );
4697 Util.removeAllChildren( this.elm );
4698 ELM_OPTION_WRAPPER.removeChild( this.elm );
4704 function onOptionSelect( e ){
4706 l = OPTION_LIST.length,
4708 for( ; i < l; ++i ){
4709 _option = OPTION_LIST[ i ];
4710 if( this === _option.elm ){
4711 updateCurrrentOption( _option.data.value, true );
4712 currentCombobox.blur();
4719 var OPTION_LIST = [],
4720 currentCombobox = null,
4726 function updateCurrrentOption( _value, _updateCombobox ){
4728 i = OPTION_LIST.length;
4730 _option = OPTION_LIST[ --i ];
4731 if( _value === _option.data.value ){
4732 currentOption && currentOption.current( false );
4733 _option.current( true );
4734 currentOption = _option;
4736 _updateCombobox === true && currentCombobox.value( _value );
4741 function bodyMouseupHandler(){
4742 currentCombobox.blur();
4743 OptionControl.hide( currentCombobox );
4745 function updateWrapperPosition(){
4746 var position = Util.getAbsolutePosition( elm );
4748 ELM_OPTION_WRAPPER.style.cssText = [
4749 'width:', elm.offsetWidth - 2, 'px;',
4750 'left:', position.x, 'px;',
4751 'top:', position.y + elm.offsetHeight, 'px;'
4754 function change( e ){
4755 var l = OPTION_LIST.length,
4756 i = currentIndex + ( e.keyCode === 40 ? -1 : 1 );
4757 if( currentCombobox === null || l < 2 ) return;
4761 updateCurrrentOption( OPTION_LIST[ i ].data.value, true );
4765 show: function( data ){
4766 var combobox = data.item,
4767 list = data.optionList,
4770 if( currentItem !== combobox || currentCombobox === combobox ) return;
4771 currentCombobox && currentCombobox.blur();
4773 apiuser = data.groupData.apiuser;
4774 currentCombobox = combobox;
4777 for( ; i < l; ++i ){
4778 OPTION_LIST.unshift( new OptionClass( list[ i ] ) );
4780 MouseEvent.add( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler );
4781 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 38 );
4782 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 40 );
4783 //KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter, 13 );
4784 //KeyEvent.updateCurrentListener( SUPER_USER_KEY );
4786 body.appendChild( ELM_OPTION_WRAPPER );
4788 updateCurrrentOption( combobox.value(), false );
4789 updateWrapperPosition();
4791 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4793 hide: function( _combobox ){
4794 if( currentCombobox !== _combobox || currentCombobox === null ) return;
4797 while( _option = OPTION_LIST.shift() ){
4801 body.removeChild( ELM_OPTION_WRAPPER );
4803 MouseEvent.remove( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler );
4804 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change );
4805 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change );
4806 //KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter );
4807 //KeyEvent.updateCurrentListener( apiuser );
4809 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition, 500 );
4812 currentCombobox = null;
4813 currentOption = null;
4816 onEnter: function(){
4817 currentCombobox.value( currentOption.data.value );
4818 //currentCombobox.blur();
4819 //OptionControl.hide( currentCombobox );
4821 update: function( data, _value ){
4822 if( currentCombobox !== data.item || currentItem !== data.item ) return;
4823 if( currentOption.data.value === _value ) return;
4824 updateCurrrentOption( _value, true );
4826 onWindowResize: function( _w, _h ){
4827 currentCombobox && AsyncCall.add( apiuser, updateWrapperPosition );
4832 var UIGroupPrivateData = function(){};
4833 UIGroupPrivateData.prototype = {
4840 init : function( apiuser, node, uigroup ){
4841 this.apiuser = apiuser;
4843 this.uigroup = uigroup;
4845 UIGroupPrivateData.list.push( this );
4847 destroy : function(){
4851 UIGroupPrivateData.list = [];
4852 UIGroupPrivateData.get = function( uigroup ){
4853 var list = UIGroupPrivateData.list,
4856 if( list[ --i ].uigroup === uigroup ) return list[ i ];
4861 var UIGroupClass = function( apiuser, node ){
4862 ( new UIGroupPrivateData() ).init( apiuser, node, this );
4864 UIGroupClass.prototype = {
4865 focus : function( _value ){
4866 var data = UIGroupPrivateData.get( this );
4868 if( _value === true ){
4870 start( apiuser, self, currentItem );
4872 if( itemList.length > 0 ){
4873 start( apiuser, self, itemList[ 0 ] );
4876 if( _value === false ){
4877 finish( apiuser, self, currentItem );
4880 if( _value && Util.getIndex( data.itemList, _value ) !== -1 ){
4881 // currentItem = _value;
4882 currentList = data.itemList;
4884 return currentUi === this;
4887 var data = UIGroupPrivateData.get( this );
4888 if( currentList === data.itemList ){
4892 createInputText : function( elmWrapper, onUpdate, validater ){
4893 var data = UIGroupPrivateData.get( this ),
4894 elmValue = Util.getElementsByClassName( elmWrapper, 'editable-value' )[ 0 ],
4897 ret = new TextInputClass( data, elmWrapper, elmValue, onUpdate, validater );
4898 data.itemList.push( ret );
4901 alert( 'error createInputText' );
4903 createButton : function( elm, onClick ){
4904 var data = UIGroupPrivateData.get( this ),
4905 ret = new ButtonClass( data, elm, onClick );
4906 data.itemList.push( ret );
4909 createFileInput : function( elm, onUpdate, validater, elmFileInputReal ){
4910 var data = UIGroupPrivateData.get( this ),
4911 elmValue = Util.getElementsByClassName( elm, 'fileinput-value' )[ 0 ],
4914 ret = new FileInputClass( data, elm, onUpdate, validater, elmFileInputReal, elmValue );
4915 data.itemList.push( ret );
4920 createCombobox : function( elm, onUpdate, optionList ){
4921 var data = UIGroupPrivateData.get( this ),
4922 ret = new ComboBoxClass( data, elm, onUpdate, optionList );
4923 data.itemList.push( ret );
4926 createCheckBox : function(){
4929 createRadio : function(){
4932 createSlider : function(){
4935 visible : function( v ){
4936 var data = UIGroupPrivateData.get( this );
4937 if( Type.isBoolean( v ) === true && data.visible !== v ){
4938 for( var i = data.itemList.length; i; ){
4939 data.itemList[ --i ].visible( v );
4942 data.node.disabled( !( data.enabled && v ) );
4944 return data.visible;
4946 enabled : function( v ){
4947 var data = UIGroupPrivateData.get( this );
4948 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4949 for( var i = data.itemList.length; i; ){
4950 data.itemList[ --i ].enabled( v );
4953 data.node.disabled( !( data.visible && v ) );
4955 return data.enabled;
4957 destroy : function(){
4958 var data = UIGroupPrivateData.get( this ),
4960 if( currentUi === this ){
4962 // finish( UIItemPrivateData.get( currentItem ) );
4964 while( _item = data.itemList.shift() ){
4971 function start( data ){
4972 if( currentItem !== data.item ){
4973 currentUi !== data.groupData.uigroup && currentUi && currentUi.blur();
4975 currentItem !== null && currentItem.blur();
4977 currentUser = data.groupData.apiuser;
4978 currentUi = data.groupData.uigroup;
4979 currentItem = data.item;
4981 currentUi.focus( currentItem );
4983 // if( currentUser !== _apiuser ) {
4984 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 );
4985 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 );
4986 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 9 );
4987 KeyEvent.updateCurrentListener( SUPER_USER_KEY );
4991 function finish( data ){
4992 if( currentItem === data.item ){
5000 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 );
5001 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 );
5002 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 9 );
5003 KeyEvent.updateCurrentListener( data.groupData.apiuser );
5007 function onKeyDown( e ){
5008 if( currentItem === null ) return true;
5009 var keyCode = e.keyCode,
5010 index = Util.getIndex( currentList, currentItem );
5011 if( keyCode === 13 || keyCode === 27 || keyCode === 9 || keyCode === 18 || e.altKey === true ){ // 13.return 27.esc 9.tab 18.alt
5012 keyCode === 9 && tabShift( index, e.shiftKey === true ? -1 : 1 );
5013 keyCode === 13 && currentItem instanceof ComboBoxClass && OptionControl.onEnter();
5014 keyCode === 13 && tabShift( index, 1 );
5015 currentItem && currentItem.blur( keyCode );
5020 function tabShift( index, way ){
5021 var l = currentList.length,
5025 while( i !== index ){
5028 i < l ? i : 0; // 0 < i < l
5029 item = currentList[ i ];
5030 if( item.enabled() === true && item.visible() === true ){
5031 AsyncCall.add( currentUser, item.focus, null, item );
5039 createUIGroup: function( apiuser, node ){
5040 var uid = apiuser.getUID(),
5041 list = UI_LIST[ uid ],
5042 ui = new UIGroupClass( apiuser, node );
5043 if( Type.isArray( list ) === false ){
5044 list = UI_LIST[ uid ] = [];
5049 onWindowResize: function( w, h ){
5052 currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h );
5053 currentItem instanceof TextInputClass && TextInputManager.onWindowResize( w, h );
5054 currentItem instanceof FileInputClass && FileInputManager.onWindowResize( w, h );
5056 onCurrentApplicationChange: function( _apiuser ){
5057 currentList = UI_LIST[ _apiuser.getUID() ];
5059 onApplicationShutdown: function( _apiuser ){
5060 KeyEvent.remove( _apiuser );
5062 onSystemShutdown: function(){
5068 var UIForm = ( function(){
5070 var CLASSNAME_FORM = 'uiform-invisible';
5071 var CLASSNAME_FILE_WRAP = 'ui-fileinput-wrapper';
5072 var FormItemData = function(){};
5073 FormItemData.prototype = {
5076 init : function( formData, uiItem ){
5077 this.formData = formData;
5078 this.uiItem = uiItem;
5080 onUpdate : function( v ){
5081 // var index = Util.getIndex( this.formData.itemList, this );
5085 var FormPrivateData = function(){};
5086 FormPrivateData.prototype = {
5094 init : function( apiuser, from, node, elm, elmForm ){
5095 this.apiuser = apiuser;
5097 this.ui = apiuser.createUIGroup( node );
5100 this.elmForm = elmForm;
5102 elmForm.className = CLASSNAME_FORM;
5103 FormPrivateData.list.push( this );
5105 var forms = Util.copyArray( elmForm.getElementsByTagName( '*' ) ),
5108 items = 'input,select,textarea,button',
5109 form, data, el, wrap;
5112 if( form.nodeType !== 1 ) continue;
5113 switch( form.tagName.toLowerCase() ){
5115 switch( form.type.toLowerCase() ){
5119 el = document.createElement( 'div' );
5120 el.className = 'uiform-file-container';
5121 el.appendChild( document.createElement( 'div' ) );
5122 el.appendChild( document.createElement( 'div' ) );
5123 el.firstChild.className = 'uiform-label';
5124 el.lastChild.className = 'uiform-file fileinput-value';
5125 // opera9 don't work for opera9;
5126 //el = Util.pullHtmlAsTemplete( '<div class="uiform-file-container"><div class="uiform-label"></div><div class="uiform-file fileinput-value"></div></div>' );
5127 elm.appendChild( el );
5128 data = new FormItemData();
5129 wrap = document.createElement( 'div' );
5130 form.parentNode.insertBefore( wrap, form );
5131 wrap.className = CLASSNAME_FILE_WRAP;
5132 wrap.appendChild( form );
5133 data.init( this, this.ui.createFileInput( el, data.onUpdate, null, form ) );
5134 this.itemList.push( data );
5153 destroy : function(){
5157 FormPrivateData.list = [];
5158 FormPrivateData.get = function( from ){
5159 var list = FormPrivateData.list,
5162 if( list[ --i ].form === form ) return list[ i ];
5167 var FormClass = function( apiuser, node, elm, elmForm ){
5168 ( new FormPrivateData() ).init( apiuser, this, node, elm, elmForm );
5170 FormClass.prototype = {
5171 createTextInput : function(){
5174 createMultiLineInput : function(){
5177 createFileInput : function(){
5180 createButton : function(){
5183 createComboBox : function(){
5186 submit : function(){
5192 createForm: function( apiuser, nodeOrElm, opt_elmForm ){
5193 var uid = apiuser.getUID(),
5194 list = FORM_LIST[ uid ],
5196 if( PointingDeviceEventTree.isNodeInstance( nodeOrElm ) === true ){
5198 elm = PointingDeviceEventTree._getNodePrivateData( nodeOrElm ).elm;
5200 // App が eventTree を持っている?
5201 // App が eventTree を持っていない
5204 form = new FormClass( apiuser, node, elm, opt_elmForm );
5205 if( Type.isArray( list ) === false ){
5206 list = FORM_LIST[ uid ] = [];
5211 onWindowResize: function( w, h ){
5214 currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h );
5215 currentItem instanceof TextInputClass && TextInputManager.onWindowResize( w, h );
5216 currentItem instanceof FileInputClass && FileInputManager.onWindowResize( w, h );
5218 onCurrentApplicationChange: function( _apiuser ){
5220 onApplicationShutdown: function( _apiuser ){
5222 onSystemShutdown: function(){
5228 var Finder = ( function(){
5229 var FINDER_LIST = [],
5230 ELM_ORIGIN_LOCATION_ITEM = Util.pullHtmlAsTemplete( '<div class="finder-location-item"></div>' ),
5231 HTML_FINDER_ICON = ( function(){
5232 return ( UA.isIE === true && UA.ieVersion < 8 ?
5234 '<div class="finder-icon fnder-icon-ie7">',
5235 '<div class="finder-icon-handle"></div>',
5236 '<div class="file-icon"><div></div></div>',
5237 '<span class="finder-icon-cell finder-icon-ie-filename">',
5238 '<span class="finder-icon-vertical-middle-outer">',
5239 '<span class="finder-icon-vertical-middle-inner">',
5240 '<span class="finder-icon-filename break-word">file name</span>',
5244 '<span class="finder-icon-cell finder-icon-ie-summary">',
5245 '<span class="finder-icon-vertical-middle-outer">',
5246 '<span class="finder-icon-vertical-middle-inner">',
5247 '<span class="finder-icon-summary break-word">file descriptiion</span>',
5251 '<div class="finder-icon-down"></div>',
5255 '<div class="finder-icon fnder-icon-modern">',
5256 '<div class="finder-icon-handle"></div>',
5257 '<div class="file-icon"><div></div></div>',
5258 '<div class="finder-icon-filename break-word">file name</div>',
5259 '<div class="finder-icon-summary break-word">file descriptiion</div>',
5260 '<div class="finder-icon-down">></div>',
5264 ELM_ORIGIN_FINDER_ICON = Util.pullHtmlAsTemplete( HTML_FINDER_ICON ),
5265 ICON_HEIGHT = Util.getElementSize( ELM_ORIGIN_FINDER_ICON ).height;
5268 // b : 開始の値(開始時の座標やスケールなど)
5270 // d : Tween(トゥイーン)の合計時間
5272 function easeOutQuad( t, b, c, d ){
5274 return -c * t*( t-2 ) + b;
5280 var FinderIconClass = function(){};
5281 FinderIconClass.prototype = {
5288 init : function( page, file, w, index, style ){
5289 if( !this.elm ) this.elm = ELM_ORIGIN_FINDER_ICON.cloneNode( true );
5291 if( this.page !== page ){
5293 page.elm.appendChild( this.elm );
5294 this.node && this.node.remove();
5295 this.node = page.node.createNode( this.elm, false, true, 'finder-icon-hover', '' );
5297 if( this.file !== file ){
5298 this.file && this.file.destroy();
5300 this._index = index;
5304 if( this._index !== index ){
5305 this._index = index;
5309 index : function( _index ){
5312 style : function( _style ){
5315 draw : function( w ){
5316 var file = this.file,
5318 thumb = file.getThumbnail(),
5319 elmThumb = Util.getElementsByClassName( elm, 'file-icon' )[ 0 ].firstChild,
5320 elmName = Util.getElementsByClassName( elm, 'finder-icon-filename' )[ 0 ],
5321 elmDesc = Util.getElementsByClassName( elm, 'finder-icon-summary' )[ 0 ];
5323 elmThumb.className = 'has-thumbnail';
5324 elmThumb.style.backgroundImage = [ 'url(', thumb.image, ')' ].join( '' );
5326 elmThumb.className = thumb.className;
5327 elmThumb.style.backgroundImage = '';
5330 elmName.firstChild.data = file.getName();
5331 elmDesc.firstChild.data = file.getSummary();
5335 resize : function( w ){
5336 this.node.update( 0, this._index * ICON_HEIGHT, w );
5338 onEditorClick : function( e ){
5339 this.onEditorCallback && this.onEditorCallback( this.file, this.file.editorApplicationList()[ 0 ] );
5342 onViwerClick : function( e ){
5343 this.onViewerCallback && this.onViewerCallback( this.file, this.file.viewerApplicationList()[ 0 ] );
5346 onActionClick : function( e ){
5347 this.onActionCallback && this.onActionCallback( this.file );
5350 destroy : function(){
5351 this.elm && this.elm.parentNode.removeChild( this.elm );
5352 this.file && this.file.destroy();
5353 this.node && this.node.remove();
5359 FinderIconClass.pool.push( this );
5362 FinderIconClass.pool = [];
5363 FinderIconClass.get = function( page, file, w, index, style ){
5364 var _icon = FinderIconClass.pool.length > 0 ? FinderIconClass.pool.shift() : new FinderIconClass();
5365 _icon.init( page, file, w, index, style );
5372 var PathClass = function(){};
5373 PathClass.prototype = {
5380 init : function( finderData, file, index ){
5381 if( !this.elm ) this.elm = ELM_ORIGIN_LOCATION_ITEM.cloneNode( true );
5383 if( this.finderData !== finderData ){
5384 this.finderData = finderData;
5385 finderData.elmPath.appendChild( this.elm );
5386 this.node && this.node.remove();
5389 if( this.file !== file ){
5393 this._index = index;
5394 if( !this.node ) this.node = finderData.nodePath.createNode( this.elm, false, true, 'finder-path-hover', 'pointer' );
5397 this.elm.className = 'file-icon-' + this.file.getType();
5398 this.elm.innerHTML = this.file.getName();
5400 textWidth : function(){
5401 this.elm.style.width = 'auto';
5402 var ret = this.elm.offsetWidth;
5403 this.elm.style.width = '';
5406 update : function( x, w ){
5407 this.node.update( x - 15, undefined, w );
5409 index : function( _index ){
5412 destroy : function(){
5413 this.finderData.elmPath.removeChild( this.elm );
5414 this.node && this.node.remove();
5416 delete this.finderData;
5421 PathClass.pool.push( this );
5424 PathClass.pool = [];
5425 PathClass.get = function( finderData, file, index ){
5426 var _bread = PathClass.pool.length > 0 ? PathClass.pool.shift() : new PathClass();
5427 _bread.init( finderData, file, index );
5435 var PageClass = function(){};
5436 PageClass.prototype = {
5451 init : function( nodeRoot, elmRoot, elmScroll ){
5452 this.nodeRoot = nodeRoot;
5453 this.elmRoot = elmRoot;
5454 this.elmScroll = elmScroll;
5456 if( this.elm === null ){
5457 this.elm = document.createElement( 'div' );
5459 elmScroll.appendChild( this.elm );
5460 this.elm.style.cssText = 'position:absolute;top:0;';
5461 // this.elm.style.display = 'none';
5462 this.node = this.nodeRoot.createNode( this.elm, true, false );
5463 if( this.iconList === null ){
5467 panInReady : function( way ){
5468 this.elm.style.display = '';
5469 var x = this.sliding === true ? this.currentX : way * this.nodeRoot.width();
5470 this.startX = this.currentX = x;
5474 this.panTotalTime = 20;
5475 this.sliding = true;
5476 this.isPanOut = false;
5477 // this.elm.style.left = x + 'px';
5480 panOutReady : function( way ){
5481 var x = -way * this.nodeRoot.width();
5482 this.startX = this.currentX || 0;
5484 this.offsetX = x - this.startX;
5486 this.panTotalTime = 20;
5487 this.sliding = true;
5488 this.isPanOut = true;
5492 x = page.currentX = easeOutQuad( page.panTime, page.startX, page.offsetX, page.panTotalTime );
5493 // page.elm.style.left = x + 'px';
5495 if( page.panTotalTime < ++page.panTime ){
5496 delete page.panTime;
5498 delete page.offsetX;
5499 delete page.panTotalTime;
5500 delete page.sliding;
5501 if( this.isPanOut === true ) this.elm.style.display = 'none';
5504 draw : function( folder ){
5505 _w = this.nodeRoot.width();
5506 this.folder = folder;
5508 iconList = data.iconList,
5511 l = folder.getChildFileLength(),
5512 m = iconList.length,
5513 scrollY = -this.nodeRoot.scrollY(),
5514 rootH = scrollY + this.nodeRoot.height(),
5517 for( ; i < l; ++i ){
5518 if( ( i + 1 ) * ICON_HEIGHT < scrollY || rootH < i * ICON_HEIGHT ) continue;
5520 iconList[ j ].init( this, folder.getChildFileAt( i ), _w, i, data.style );
5522 iconList.push( FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) );
5526 data.elmRoot.className = folder.getState() === Const.FILE.STATE.LOADING ? 'finder-body loading' : 'finder-body';
5527 // data.elmRoot.style.height = ( data.h - data.headH ) + 'px';
5529 while( j < iconList.length ) iconList.pop().destroy();
5530 data.elmScroll.style.height = ( l * ICON_HEIGHT ) + 'px';
5532 onScroll : function(){
5533 var _w = this.nodeRoot.width();
5536 iconList = data.iconList,
5537 folder = this.folder,
5540 l = folder.getChildFileLength(),
5541 scrollY = -this.nodeRoot.scrollY(),
5542 rootH = scrollY + this.nodeRoot.height(),
5543 startIndex = 0 < iconList.length ? iconList[ 0 ]._index : 0,
5546 // console.log( ' > ' + scrollY + ' , ' + rootH )
5547 for( ; i < l; ++i ){
5548 if( ( i + 1 ) * ICON_HEIGHT < scrollY || rootH < i * ICON_HEIGHT ){
5549 if( iconList.length <= j ) continue;
5550 icon = iconList[ j ];
5551 if( icon._index !== i ) continue;
5553 iconList.splice( j, 1 );
5556 if( iconList.length <= j || iconList[ j ]._index !== i ){
5557 if( i < startIndex ){
5558 iconList.splice( j, 0, FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) );
5560 if( startIndex + iconList.length <= i ){
5561 iconList.push( FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) );
5567 //while( j < iconList.length ) iconList.pop().destroy();
5569 resize : function( w ){
5570 var list = this.iconList,
5572 for( ; i; ) list[ --i ].resize( w );
5574 destroy : function(){
5576 while( icon = this.iconList.shift() ) icon.destroy();
5578 this.elm.parentNode.removeChild( this.elm );
5582 var ApplicationButton = function(){};
5583 ApplicationButton.prototype = {
5589 init : function( ui, elmParent, app, file ){
5590 if( this.elm === null ){
5591 this.elm = document.createElement( 'div' );
5593 elmParent.appendChild( this.elm );
5594 this.elm.className = 'button';
5595 this.elm.innerHTML = app.getDisplayName();
5598 this.button = ui.createButton( this.elm, function(){
5605 this.fileUID = file.getUID();
5607 onClick : function(){
5608 this.app.boot( this.file );
5611 destroy : function(){
5613 elm.parentNode.removeChild( elm );
5615 this.button.destroy();
5621 var DetailPageClass = function(){};
5622 DetailPageClass.prototype = Util.extend( new PageClass(), {
5624 init : function( finderData ){
5625 this.finderData = finderData;
5626 this.apiuser = finderData.apiuser;
5627 this.nodeRoot = finderData.nodeRoot;
5628 this.elmRoot = finderData.elmRoot;
5629 this.elmScroll = finderData.elmScroll;
5631 if( this.elm === null ){
5632 this.elm = Util.pullHtmlAsTemplete( [
5633 '<div class="finder-detail">',
5634 '<div class="file-icon"><div></div></div>',
5635 '<div class="finder-detail-filename break-word">file name</div>',
5636 '<div class="finder-detail-summary break-word">file descriptiion</div>',
5637 '<div>View this file</div>',
5638 '<div class="viewer-apps"></div>',
5639 '<div>Edit this file</div>',
5640 '<div class="editor-apps"></div>',
5644 this.elm.style.display = 'none';
5645 this.elmScroll.appendChild( this.elm );
5646 this.node = this.nodeRoot.createNode( this.elm, true, false );
5648 this.ui = this.apiuser.createUIGroup( this.node );
5649 this.appButtons = [];
5651 draw : function( file ){
5653 thumb = file.getThumbnail(),
5654 elmThumb = Util.getElementsByClassName( elm, 'file-icon' )[ 0 ].firstChild,
5655 elmName = Util.getElementsByClassName( elm, 'finder-detail-filename' )[ 0 ],
5656 elmDesc = Util.getElementsByClassName( elm, 'finder-detail-summary' )[ 0 ],
5657 tmpButtons = Util.copyArray( this.appButtons ),
5658 apps, app, elmContainer;
5660 elmThumb.className = 'has-thumbnail';
5661 elmThumb.style.backgroundImage = [ 'url(', thumb.image, ')' ].join( '' );
5663 elmThumb.className = thumb.className;
5664 elmThumb.style.backgroundImage = '';
5667 elmName.firstChild.data = file.getName();
5668 elmDesc.firstChild.data = file.getSummary();
5669 this.node.width( this.nodeRoot.width() );
5670 this.node.height( this.nodeRoot.height() );
5672 this.appButtons.length = 0;
5674 apps = file.viewerApplicationList();
5675 elmContainer = Util.getElementsByClassName( elm, 'viewer-apps' )[ 0 ];
5676 for( i = 0; i < apps.length; ++i ){
5677 button = 0 < tmpButtons.length ? tmpButtons.shift() : new ApplicationButton();
5678 button.init( this.ui, elmContainer, apps[ i ], file );
5679 this.appButtons.push( button );
5681 apps = file.editorApplicationList();
5682 elmContainer = Util.getElementsByClassName( elm, 'editor-apps' )[ 0 ];
5683 for( i = 0; i < apps.length; ++i ){
5684 button = 0 < tmpButtons.length ? tmpButtons.shift() : new ApplicationButton();
5685 button.init( this.ui, elmContainer, apps[ i ], file );
5686 this.appButtons.push( button );
5689 while( button = tmpButtons.shift() ) button.destroy();
5695 x = page.currentX = easeOutQuad( page.panTime, page.startX, page.offsetX, page.panTotalTime );
5696 // page.elm.style.left = x + 'px';
5698 if( page.panTotalTime < ++page.panTime ){
5699 delete page.panTime;
5701 delete page.offsetX;
5702 delete page.panTotalTime;
5703 delete page.sliding;
5704 if( this.isPanOut === true ) this.elm.style.display = 'none';
5707 onScroll : function(){
5710 resize : function(){
5711 this.elmScroll.style.height = this.nodeRoot.height() + 'px';
5713 destroy : function(){
5715 while( button = this.appButtons.shift() ) button.destroy();
5724 var FinderPrivateData = function(){};
5725 FinderPrivateData.MIN_PATH_WIDTH = 25;
5726 FinderPrivateData.prototype = {
5736 viewerOption : null,
5737 editorOption : null,
5749 init : function( finder, apiuser, elm, tree, onSelect, viewerOption, editorOption ){
5750 this.finder = finder;
5751 this.apiuser = apiuser;
5752 if( PointingDeviceEventTree.isNodeInstance( elm ) === true ){
5753 this.nodeRoot = elm;
5754 this.elmRoot = PointingDeviceEventTree._getNodePrivateData( elm ).elm;
5756 // App が eventTree を持っている?
5757 // App が eventTree を持っていない
5760 this.nodeRoot.addEventListener( 'click', this.onIconClick, this );
5761 this.nodeRoot.addEventListener( 'scroll', this.onScroll, this );
5763 this.elmScroll = document.createElement( 'div' );
5764 this.elmRoot.appendChild( this.elmScroll );
5765 this.elmScroll.className = 'finder-elm-scroll';
5766 this.elmScroll.style.cssText = 'width:100%;overflow:hidden;';
5769 this.onSelect = onSelect;
5770 this.viewerOption = viewerOption;
5771 this.editorOption = editorOption;
5773 var size = Util.getElementSize( ELM_ORIGIN_FINDER_ICON );
5774 this.iconW = size.width;
5775 this.iconH = size.height;
5777 tree.addTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw, this );
5778 Util.addClass( this.elmRoot, 'finder-body' );
5780 if( this.panInPage === null ){
5781 this.pageIcons1 = new PageClass();
5782 this.pageIcons2 = new PageClass();
5783 this.pageDetail = new DetailPageClass();
5785 this.pageIcons1.init( this.nodeRoot, this.elmRoot, this.elmScroll );
5786 this.pageIcons2.init( this.nodeRoot, this.elmRoot, this.elmScroll );
5787 this.pageDetail.init( this );
5788 FinderPrivateData.LIST.push( this );
5790 onIconClick : function( e ){
5791 if( this.panInPage === this.pageDetail ) return;
5793 var target = e.target,
5794 list = this.panInPage.iconList,
5797 if( target === this.nodeRoot ) return;
5798 for( i = list.length; i; ){
5800 if( icon.node === target ){
5802 file = this.currentFile.getChildFileAt( i );
5803 if( target.width() - 30 < e.layerX ){
5804 this.tree.down( i );
5805 this.draw( this.w, this.h, 1, true );
5807 if( file.getChildFileLength() !== -1 || file.getType() === Const.FILE.TYPE.FOLDER ){
5808 this.tree.down( i );
5809 this.draw( this.w, this.h, 1 );
5811 if( Type.isFunction( this.onSelect ) === true ){ /* && this.onSelect( file ) === true */
5812 this.onSelect( file );
5814 this.tree.down( i );
5815 this.draw( this.w, this.h, 1 );
5822 onScroll : function( e ){
5823 this.panInPage.onScroll( e );
5825 onPathClick : function( e ){
5826 var target = e.target,
5827 i = target.nodeIndex();
5828 if( target === this.nodePath || this.nodePath.numNode() - 1 === i ) return;
5830 this.draw( this.w, this.h, -1 );
5832 draw : function( w, h, way, showDetail ){
5833 var data = this, page;
5834 data.w = w = Type.isFinite( w ) === true ? w : data.w;
5835 data.h = h = Type.isFinite( h ) === true ? h : data.h;
5837 var file = this.currentFile = this.tree.getCurrentFile(),
5838 isFolder = showDetail !== true && ( file.getChildFileLength() !== -1 || file.getType() === Const.FILE.TYPE.FOLDER );
5840 data.elmPath && data.drawPath( w );
5841 page = this.panInPage;
5842 if( Type.isNumber( way ) === true ){
5843 if( page.sliding === false ){
5844 if( isFolder === true ){
5845 this.panInPage = page === this.pageIcons1 ? this.pageIcons2 : ( page === this.pageIcons2 ? this.pageIcons1 : this.panOutPage );
5847 this.panInPage = this.pageDetail;
5849 this.panOutPage = page;
5851 this.panInPage.panInReady( way );
5852 //this.panInPage.elm.className = 'panIN';
5853 this.panOutPage.panOutReady( way );
5854 //this.panOutPage.elm.className = 'panOut';
5855 this.nodeRoot.disabled( true );
5856 SystemTimer.add( this.apiuser, this.tick, 16, false, this );
5858 if( isFolder === true ){
5859 this.panInPage = page === null ? this.pageIcons1 : page;
5861 this.panInPage = this.pageDetail;
5864 this.panInPage.draw( file );
5866 data.nodeRoot.invalidateScrollbar();
5869 if( this.panInPage.sliding === false && this.panOutPage.sliding === false ){
5870 SystemTimer.remove( this.apiuser, this.tick );
5871 this.nodeRoot.disabled( false );
5872 this.nodeRoot.invalidateScrollbar();
5875 this.panInPage.sliding === true && this.panInPage.pan();
5876 this.panOutPage.sliding === true && this.panOutPage.pan();
5878 drawPath : function( w ){
5879 if( !this.elmPath.parentNode ) return;
5880 w = this.nodePath.width();
5883 pathList = data.pathList,
5885 l = tree.hierarchy() + 1,
5886 m = pathList.length,
5889 minW = FinderPrivateData.MIN_PATH_WIDTH,
5890 file, path, pathW, offset, remove, pathX = 0, fit = false;
5892 for( ; i < l; ++i ){
5893 file = i !== l - 1 ? tree.getParentFileAt( i ) : this.currentFile;
5895 pathList[ i ].init( this, file, i );
5897 pathList.push( PathClass.get( this, file, i ) );
5900 while( l < pathList.length ) pathList.pop().destroy();
5903 pathW = pathList[ --i ].textWidth();
5904 wList.push( pathW );
5908 //if( minW * ( l + 1 ) * 1.2 < w ){
5909 console.log( totalW + ' , ' + w )
5911 if( fit === true ) break;
5912 for( i = 0; i < l; ++i ){
5913 offset = totalW - w;
5919 remove = offset < remove ? offset : remove;
5921 if( pathW - remove < minW ){
5922 totalW -= ( pathW - minW );
5925 wList[ i ] = pathW - remove;
5930 for( i = 0; i < l; ++i ){
5931 path = pathList[ i ];
5933 path.update( pathX, pathW );
5940 createPath : function( node ){
5941 if( this.elmPath ) return;
5943 if( PointingDeviceEventTree.isNodeInstance( node ) === true ){
5944 this.nodePath = node;
5945 this.elmPath = PointingDeviceEventTree._getNodePrivateData( node ).elm;
5947 node.addEventListener( 'click', this.onPathClick, this );
5948 Util.addClass( this.elmPath, 'finder-path' );
5949 // this.elmPath = document.createElement( 'div' );
5950 // this.elmPath.className = ;
5953 AsyncCall.add( this.apiuser, this.draw, null, this );
5956 destroy : function(){
5957 this.tree.removeTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw );
5959 if( this.pathList ){
5960 while( this.pathList.length > 0 ) this.pathList.shift().destroy();
5963 this.pageIcons1.destroy();
5964 this.pageIcons2.destroy();
5965 this.pageDetail.destroy();
5966 this.nodeRoot.remove();
5968 FINDER_LIST.splice( Util.getIndex( FINDER_LIST, this.finder ), 1 );
5969 var data = ApplicationPrivateData.get( this.apiuser ),
5970 list = data.finderList,
5971 i = Util.getIndex( list, this.finder );
5972 i !== -1 && list.splice( i, 1 );
5975 FinderPrivateData.LIST = [];
5976 FinderPrivateData.get = function( finderOrTree ){
5977 var list = FinderPrivateData.LIST,
5982 if( data === finderOrTree || data.finder === finderOrTree || data.tree === finderOrTree ) return data;
5990 var FinderClass = function( application, elmRoot, tree, onSelect, viewerOption, editorOption ){
5991 ( new FinderPrivateData() ).init( this, application, elmRoot, tree, onSelect, viewerOption, editorOption );
5993 FinderClass.prototype = {
5998 resize : function( w, h ){
5999 var data = FinderPrivateData.get( this );
6000 data.panInPage && data.panInPage.resize( w );
6002 createPath : function( node ){
6003 return FinderPrivateData.get( this ).createPath( node );
6005 destroy : function(){
6006 FinderPrivateData.get( this ).destroy();
6014 create: function( application, elmTarget, tree, onSelect, viewerOption, editorOption ){
6015 //if( Application.isApplicationInstance( _application ) === false ) return;
6017 var finder = new FinderClass( application, elmTarget, tree, onSelect, viewerOption, editorOption );
6019 FINDER_LIST.push( finder );
6022 registerFinderHead: function(){
6025 registerFinderPane: function( _finderPane ){
6028 isFinderInstance: function( _finder ){
6029 return _finder instanceof FinderClass;
6031 isFinderPaneInstance: function(){
6034 isFinderHeadInstance: function(){
6042 * marginBottom, marginLeft, marginRight, marginTop, margin
6043 * padding, paddingBottom, paddingLeft, paddingRight, paddingTop
6044 * fontSize, textIndent
6046 * bottom, left, right, top (len, %)
6049 * borderBottomWidth, borderLeftWidth, borderRightWidth, borderTopWidth, borderWidth,
6054 * borderBottomColor, borderLeftColor, borderRightColor, borderTopColor, borderColor
6058 * clip rect(0px, 40px, 40px, 0px);
6059 * backgroundPosition (len, %)
6061 * lineHeight (len, %, num)
6065 var DHTML = ( function(){
6067 var TICKET_ARRAY = [],
6070 cround = function( v ){ return round( v * 100 ) / 100 };
6072 function startAnimation( _elm, _cssObject, _onComplete, _onEnterFrame, _numFrames ){
6073 var _ticket, i = TICKET_ARRAY.length;
6075 _ticket = TICKET_ARRAY[ --i ];
6076 if( _ticket.elm === _elm ){
6081 var _currentValues = [],
6084 _targetProperties = [],
6086 var target, current,
6087 inlineStyle = CSS.getInlineStyle( _elm ),
6088 currentStyle = CSS.getWrappedStyle( _elm ),
6089 targetStyle = CSS.getWrappedStyle( _elm, _cssObject );
6090 targetStyle.pxPerEm = currentStyle.get( 'fontSize' )._toPx();
6091 for( var p in _cssObject ){
6092 p = Util.camelize( p );
6093 target = targetStyle.get( p );
6094 current = currentStyle.get( p );
6096 if( target.isValid() === false || current.isValid() === false || current.equal( target ) !== false ){
6102 current.convert( target );
6103 // alert( current.getValue() + ' , ' + target.getValue() )
6104 _currentValues.push( current.getValue() );
6105 _offsetValues.push( current.getOffset( target ) );
6106 _endValues.push( target.getValue() );
6107 _targetProperties.push( p );
6108 _units.push( target.getUnit() );
6110 // IE has trouble with opacity if it does not have layout
6111 // Force it by setting the zoom level
6112 if( p === 'opacity' && SPECIAL.hasLayout ){
6113 if( SPECIAL.hasLayout( _elm ) === false ) inlineStyle.zoom = 1;
6114 inlineStyle.filter = current.getValueText();
6116 inlineStyle[ p ] = current.getValueText();
6123 var i, cssTexts = [];
6124 for( i = 0; i < _numFrames; ++i ){
6125 if( i < _numFrames - 1 ){
6126 tickValue( _currentValues, _offsetValues, _numFrames );
6127 cssTexts.push( createCssText( _currentValues, _targetProperties, targetStyle, inlineStyle ) );
6129 cssTexts.push( createCssText( _endValues, _targetProperties, targetStyle, inlineStyle ) );
6133 TICKET_ARRAY.push( new AnimationTaskClass(
6135 Type.isFunction( _onComplete ) === true ? _onComplete : null,
6136 Type.isFunction( _onEnterFrame ) === true ? _onEnterFrame : null,
6140 currentStyle.clear();
6141 targetStyle.clear();
6142 SystemTimer.add( SUPER_USER_KEY, onEnterFrame, 1000 / fpms );
6145 function tickValue( current, offset, numFrames ){
6146 if( Type.isArray( current ) === true ){
6147 var ret, i = current.length;
6150 ret = tickValue( current[ i ], offset[ i ], numFrames );
6151 if( Type.isNumber( ret ) === true ) current[ i ] = ret;
6154 return current + offset / numFrames;
6157 function createCssText( update, props, style, inline ){
6159 for( var i = props.length; i; ){
6160 prop = style.get( props[ --i ] );
6161 prop.setValue( update[ i ] );
6162 inline[ Util.uncamelize( prop.name ) ] = prop.getValueText();
6163 //if( prop.name === 'backgroundColor' ) alert( prop.getValueText() + '|' + update[ i ].join( ',') )
6166 return CSS.toCssText( inline );
6169 function onEnterFrame(){
6172 while( i < TICKET_ARRAY.length ){
6173 _ticket = TICKET_ARRAY[ i ];
6174 l = _ticket.cssTexts.length;
6175 _ticket.elm.style.cssText = _ticket.cssTexts.shift();
6177 _ticket.onComplete && _ticket.onComplete();
6179 delete _ticket.cssTexts;
6180 delete _ticket.onComplete;
6181 delete _ticket.onEnterFrame;
6182 delete _ticket.numFrame;
6183 TICKET_ARRAY.splice( i, 1 );
6185 _ticket.onEnterFrame && _ticket.onEnterFrame( l / _ticket.numFrame );
6189 if( TICKET_ARRAY.length === 0 ){
6190 SystemTimer.remove( SUPER_USER_KEY, onEnterFrame );
6194 var AnimationTaskClass = function( elm, cssTexts, onEnterFrame, onComplete, numFrame ){
6196 this.cssTexts = cssTexts;
6197 this.onEnterFrame = onEnterFrame;
6198 this.onComplete = onComplete;
6199 this.numFrame = numFrame;
6202 var VisualEffectClass = function( elm ){
6205 VisualEffectClass.prototype = {
6206 anime : function( _cssObject, _onComplete, _onEnterFrame, _time ){
6207 var _numFrames = Math.floor( _time / fpms );
6208 startAnimation( this.elm, _cssObject, _onComplete, _onEnterFrame, _numFrames );
6210 fadeIn : function(){
6213 fadeOut : function(){
6216 update : function( x, y, w, h ){
6217 var _cssText = this.elm.style.cssText;
6222 create: function( application, _elm ){
6223 return new VisualEffectClass( _elm );
6225 isInstanceOfVisualEffect: function( _instance){
6226 return _instance instanceof VisualEffectClass;
6232 /* --------------------------------------------
6236 Application.onCurrentApplicationChange( SUPER_USER_KEY );
6238 SERVICE_LIST.push( MouseEvent );
6240 new EventTicketClass( window, 'unload', function(){
6242 while( SERVICE_LIST.length > 0 ){
6243 _service = SERVICE_LIST.shift();
6244 Type.isFunction( _service.onSystemShutdown ) === true && _service.onSystemShutdown();
6250 /* ---------------------------------------------
6251 * broadcast to global
6255 gOS.registerApplication = Application.register;
6256 gOS.registerDriver = File.registerDriver;
6258 })( window, document );