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 isApiUser( _user ){
21 return _user === SUPER_USER_KEY ||
22 File.isDriver( _user ) === true ||
23 Application.isApplicationInstance( _user ) === true;
46 _____: parseInt( '00000', 2 ),
47 ____C: parseInt( '00001', 2 ), // hasCreateMenu
48 ___W_: parseInt( '00010', 2 ), // isWritable
49 ___WC: parseInt( '00011', 2 ), // isWritable
50 __R__: parseInt( '00100', 2 ), // isRenamable
51 __R_C: parseInt( '00101', 2 ), // hasCreateMenu
52 __RW_: parseInt( '00110', 2 ), // isWritable
53 __RWC: parseInt( '00111', 2 ), // isWritable
54 _S___: parseInt( '01000', 2 ), // childrenIsSortable
55 _S__C: parseInt( '01001', 2 ),
56 _S_W_: parseInt( '01010', 2 ),
57 _S_WC: parseInt( '01011', 2 ),
58 _SR__: parseInt( '01100', 2 ),
59 _SR_C: parseInt( '01101', 2 ),
60 _SRW_: parseInt( '01110', 2 ),
61 _SRWC: parseInt( '01111', 2 ),
62 D____: parseInt( '10000', 2 ),
63 D___C: parseInt( '10001', 2 ), // hasCreateMenu
64 D__W_: parseInt( '10010', 2 ), // isWritable
65 D__WC: parseInt( '10011', 2 ), // isWritable
66 D_R__: parseInt( '10100', 2 ), // isRenamable
67 D_R_C: parseInt( '10101', 2 ), // hasCreateMenu
68 D_RW_: parseInt( '10110', 2 ), // isWritable
69 D_RWC: parseInt( '10111', 2 ), // isWritable
70 DS___: parseInt( '11000', 2 ), // childrenIsSortable
71 DS__C: parseInt( '11001', 2 ),
72 DS_W_: parseInt( '11010', 2 ),
73 DS_WC: parseInt( '11011', 2 ),
74 DSR__: parseInt( '11100', 2 ),
75 DSR_C: parseInt( '11101', 2 ),
76 DSRW_: parseInt( '11110', 2 ),
77 DSRWC: parseInt( '11111', 2 ),
85 UPDATE_ATTRIVUTE: 'onFileUpdate',
86 GET_SEQENTIAL_FILES:'gotSeqentilFiles'
88 DATA_PROPERTY_RESERVED: [
89 'children', 'driver', 'state', 'type'
94 UPDATE: 'onTreeUpdate'
101 KEY_CHANGE: 'keychange',
114 var Class = ( function(){
115 function clone( src ){
117 if( Type.isArray(src) === true ){
120 if( Type.isObject(src) === true ){
123 if( Type.isNumber(src) === true || Type.isString(src) === true || Type.isBoolean( src ) === true ){
128 for( var key in src ){
129 ret[ key ] = clone( src[ key ]);
139 var c = Util.copyArray;
144 var instance = klass.pool.shift() || new klass();
146 instance.init.apply( instance, c( arguments ) );
147 klass.live.push( instance );
152 create : function( def, final, pool, abstract ){
153 var klass = function(){
155 if( f ) return I.apply( a.collee, c( a ) );
157 klass.prototype = def;
167 var TicketBase = function(){
168 this.kill = function(){
171 if( t.hasOwnProperty && !t.hasOwnProperty( p ) ) continue;
173 v && v instanceof TicketBase && v.kill();
181 /* --------------------------------------------------------------
186 var SystemTimer = ( function(){
187 var setTimeout = window.setTimeout;
188 var clearTimeout = window.clearTimeout;
189 var INTERVAL_TIME = 16;
190 var TICKET_LIST = [];
191 var timerId = undefined;
195 for( var i = 0; i < TICKET_LIST.length; ) {
196 if( TICKET_LIST[ i ].call( next ) !== false ) ++i;
202 var l = TICKET_LIST.length,
206 timerId !== undefined && clearTimeout( timerId );
210 for( var i = 0; i<l; i++ ){
211 c = TICKET_LIST[ i ].count;
214 if( next > n || timerId === undefined ){
215 timerId !== undefined && clearTimeout( timerId );
216 timerId = setTimeout( loop, INTERVAL_TIME * n );
221 var TimerTicketClass = function( _apiuser, _callback, _time, _once, opt_thisObject ){
222 this.apiuser = _apiuser;
223 this.callback = _callback;
227 this.thisObj = opt_thisObject;
229 TimerTicketClass.prototype = new TicketBase();
230 TimerTicketClass.prototype.call = function( c ){
232 if( this.count <= 0 ){
233 this.callback.call( this.thisObj || this.apiuser );
234 if( this.once === true ){
236 TICKET_LIST.splice( Util.getIndex( TICKET_LIST, this ), 1 );
239 this.count = this.time;
243 TimerTicketClass.prototype.destroy = function( _apiuser, _callback ){
244 if( _apiuser && _apiuser !== this.apiuser ) return false;
245 if( _callback && _callback !== this.callback ) return false;
252 add: function( _apiuser, _handler, _time, _once, opt_thisObject ){
253 if( Type.isNumber( _time ) === false || _time < INTERVAL_TIME ) _time = INTERVAL_TIME;
255 var _ticket = new TimerTicketClass( _apiuser, _handler, Math.ceil( _time / INTERVAL_TIME ), _once, opt_thisObject );
256 TICKET_LIST.push( _ticket );
260 remove: function( _apiuser, _handler ){
263 while( _ticket = TICKET_LIST[ i ] ){
264 if( _ticket.destroy( _apiuser, _handler ) === true ){
265 TICKET_LIST.splice( i, 1 );
275 /* --------------------------------------------------------------
279 var AsyncCall = ( function(){
280 var CALLBACK_LIST = [];
282 var CallbackTicketClass = function( _apiuser, _callback, _argments, _thisObject ){
283 this.apiuser = _apiuser;
284 this.callback = _callback;
285 this.argments = _argments;
286 this.thisObject = _thisObject;
288 CallbackTicketClass.prototype = new TicketBase();
289 CallbackTicketClass.prototype.call = function(){
290 var f = this.callback,
294 if( Type.isArray( a ) === true ){
300 CallbackTicketClass.prototype.destroy = function( _apiuser, _callback ){
301 if( _apiuser && _apiuser !== this.apiuser ) return false;
302 if( _callback && _callback !== this.callback ) return false;
309 var _ticket = CALLBACK_LIST.shift();
312 CALLBACK_LIST.length !== 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true );
317 add: function( _apiuser, _callback, _argments, _thisObject ){
318 CALLBACK_LIST.length === 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true );
319 CALLBACK_LIST.push( new CallbackTicketClass( _apiuser, _callback, _argments, _thisObject || _apiuser ) );
321 remove: function( _apiuser, _callback ){
324 while( _ticket = CALLBACK_LIST[ i ] ){
325 if( _ticket.destroy( _apiuser, _callback ) === true ){
326 CALLBACK_LIST.splice( i, 1 );
335 /* -----------------------------------------------------------
337 * お気に入り画像一覧 > tag:ペン次郎 > ペン次郎:笑う
338 * 最近アップロードされた画像 > images
340 * キャラクター画像庫 > アニマル系 > tag:ペン次郎 > ペン次郎:笑う
347 var File = ( function(){
348 var DRIVER_LIST = [];
350 var FILE_TYPE_IS_FOLDER = Const.FILE.TYPE.FOLDER,
351 numFileType = Const.FILE.TYPE.XML,
352 FILEDATA_RESITER = [], // store all of fileData( json object )
353 FILEDATA_ACCESS = [], // file operations for Kernel only ! hide from Out of File
354 FILE_OBJECT_POOL = [],
355 EVENT_LISTENER_REGISTER = [],
357 TREE_ACCESS_ARRAY = [];
359 var REQUEST_CONTROLER = ( function(){
360 var REQUEST_TICKET_RESISTER = [],
361 currentTicket = null,
363 DATA_TYPE_ARRAY = 'json,xml,html,text'.split( ','),
370 var RequestTicketClass = function( _apiuser, _type, _data, _url, _onLoad, _onError ){
371 this.apiuser = _apiuser;
375 this.onLoad = _onLoad;
376 this.onError = _onError;
378 _apiuser = _type = _data = _onLoad = _onError = null;
380 RequestTicketClass.prototype = new TicketBase();
381 RequestTicketClass.prototype.load = function( _data ){
382 AsyncCall.add( this.apiuser, this.onLoad, [ this.data, _data ] );
384 RequestTicketClass.prototype.error = function(){
385 AsyncCall.add( this.apiuser, this.onError, this.data );
389 if( currentTicket !== null || REQUEST_TICKET_RESISTER.length === 0 ) return;
390 currentTicket = REQUEST_TICKET_RESISTER.shift();
392 url: currentTicket.url,
393 dataType: DATA_TYPE_ARRAY[ currentTicket.type ],
398 function onSuccess( _data ){
399 currentTicket.load( _data );
400 currentTicket.kill();
401 currentTicket = null;
406 currentTicket.error();
407 currentTicket.kill(); // retry
408 currentTicket = null;
413 getNumTask: function(){
414 return REQUEST_TICKET_RESISTER.length;
416 getNumError: function(){
419 getJson: function( _apiuser, _data, _url, _onLoad, _onError ){
420 REQUEST_TICKET_RESISTER.push( new RequestTicketClass( _apiuser, DATA_IS_JSON, _data, _url, _onLoad, _onError ));
421 currentTicket === null && request();
426 var FILE_CONTROLER = {
427 createTree: function( _apiuser, _rootFileData ){
428 var _tree = new TreeClass( _apiuser, _rootFileData );
429 TREE_ARRAY.push( _tree );
432 getFileUID: function( FILEDATAorFILE ){
433 if( FILEDATAorFILE instanceof FileClass ){
434 return FILEDATAorFILE.getUID();
437 var uid = Util.getIndex( FILEDATA_RESITER, FILEDATAorFILE );
439 uid = FILEDATA_RESITER.length;
440 FILEDATA_RESITER.push( FILEDATAorFILE );
444 getFileDataAccess: function( UIDorFILEorFILEDATA ){
445 var _uid, _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA ), _access;
447 if( _data === null || typeof _data !== 'object' ) return null;
448 for( var i=0, l = FILEDATA_ACCESS.length; i<l; ++i ){
449 _access = FILEDATA_ACCESS[ i ];
450 if( _access.DATA === _data ) return _access;
454 getFileData: function( UIDorFILEorFILEDATA ){
455 if( typeof UIDorFILEorFILEDATA === 'number' ){
456 return FILEDATA_RESITER[ UIDorFILEorFILEDATA ] || null;
458 if( UIDorFILEorFILEDATA instanceof FileClass ){
459 return FILEDATA_RESITER[ UIDorFILEorFILEDATA.getUID() ] || null;
461 if( Util.getIndex( FILEDATA_RESITER, UIDorFILEorFILEDATA ) !== -1 ){
462 return UIDorFILEorFILEDATA;
466 getChildren: function( UIDorFILEorFILEDATA ){
467 var _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA );
468 return _data !== null ? _data.children || null : null;
470 getDriver: function( _file ){
471 var _data = FILE_CONTROLER.getFileData( _file );
472 return _data !== null && _data.driver ? _data.driver : BASE_DRIVER;
474 getUpdateFlag: function( _file, _bit ){
475 var _driver = FILE_CONTROLER.getDriver( _file ),
477 if( typeof _driver.getUpdatePolicy === 'function' ){
478 _policy = _driver.getUpdatePolicy( _file );
481 if( typeof _policy !== 'number' ) {
482 _policy = BASE_DRIVER.getUpdatePolicy( _file )
484 return _policy % ( _bit * 2 ) >= _bit;
486 move: function( _prentUID, _targetfile, _newFolder, _newIndex, _opt_callback ){
487 var _parentData = FILE_CONTROLER.getFileDataAccess( _prentUID ),
488 _parentType = _parentData.TYPE,
489 _targetData = FILE_CONTROLER.getFileDataAccess( _targetfile ),
490 _targetType = _targetData.TYPE;
492 replace: function( _uid, _file, _newIndex ){
495 addEventListener: function( FILEorNULL, _eventType, _callback, opt_thisObject ){
496 var _uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL;
497 EVENT_LISTENER_REGISTER.push( new FileEventTicketClass( _uid, _eventType, _callback, opt_thisObject ));
499 removeEventListener: function( FILEorNULL, _eventType, _callback ){
500 var _uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL,
502 for(var i=0, l = EVENT_LISTENER_REGISTER.length; i<l; ++i ){
503 _ticket = EVENT_LISTENER_REGISTER[ i ];
504 if( _ticket.fileUID === _uid && _ticket.eventType === _eventType && _ticket.callBack === _callback ){
505 EVENT_LISTENER_REGISTER.splice( i, 1 );
510 getTreeAccess: function(){
513 fileEventRellay: function( _uid, _event ){
514 var _fileAccess = FILE_CONTROLER.getFileDataAccess( _uid );
515 if( _fileAccess === null ) return;
516 var _treeUID = _fileAccess.TREE.getUID(),
517 _treeAccess = TREE_ACCESS_ARRAY[ _treeUID ],
518 _data = _fileAccess.DATA,
520 if( !_treeAccess ) return;
521 _treeAccess.dispatchFileEvent( _event );
522 for( var i=0, l = TREE_ARRAY.length; i<l; ++i ){
523 if( i !== _treeUID ){
524 _tree = TREE_ARRAY[ i ];
525 if( FILE_CONTROLER.getFileData( _tree.getCurrentFile() ) === _data ){
526 _treeAccess = TREE_ACCESS_ARRAY[ _tree.getUID() ];
527 _treeAccess && _treeAccess.dispatchFileEvent( _event );
534 var TreeClass = function( apiuser, rootFileData ){
535 var PARENT_FILE_RESITER = [],
538 dispatchFileEvent: dispatchFileEvent
540 EVENT_LISTENER_ARRAY = [],
542 rootFile = new FileClass( instance, null, rootFileData ),
543 currentFile = rootFile;
545 currentFile.getSeqentialFiles();
546 TREE_ACCESS_ARRAY.push( ACCESS );
548 function dispatchFileEvent( e ){
549 var _eventType = e.eventType,
550 _targetFile = e.targetFile,
551 _uid = _targetFile.getUID(),
552 _ticket, _type, _callback;
553 for( var i=0, l = EVENT_LISTENER_REGISTER.length; i<l; ++i ){
554 _ticket = EVENT_LISTENER_REGISTER[ i ];
555 _type = _ticket.eventType;
556 _callback = _ticket.callBack;
557 if( _eventType === _type && _uid === _ticket.fileUID ){
558 AsyncCall.add( apiuser, _callback, [ _eventType, _targetFile, e.key, e.value ], _ticket.thisObject || _targetFile );
560 if( _type === Const.TREE.EVENT.UPDATE && _eventType === Const.FILE.EVENT.GET_SEQENTIAL_FILES ){
561 //_callback( _eventType, _targetFile );
562 AsyncCall.add( apiuser, _callback, [ _eventType, _targetFile ], _ticket.thisObject || instance );
567 this.getUID = function(){
568 return Util.getIndex( TREE_ACCESS_ARRAY, ACCESS );
570 this.getRootFile = function(){
573 this.getCurrentFile = function(){
576 this.hierarchy = function(){
577 return PARENT_FILE_RESITER.length;
579 this.getParentFileAt = function( _index ){
580 var l = PARENT_FILE_RESITER.length;
581 if( typeof _index !== 'number' || _index < 0 || _index >= l ) return null;
582 return PARENT_FILE_RESITER[ l -1 -_index ];
584 this.down = function( _index ){
585 if( typeof _index !== 'number' || _index < 0 || _index >= currentFile.getChildFileLength()) return;
586 PARENT_FILE_RESITER.unshift( currentFile );
587 currentFile = currentFile.getChildFileByIndex( _index );
588 currentFile.getSeqentialFiles();
591 this.up = function( _index ){
592 var l = PARENT_FILE_RESITER.length;
593 if( l === 0 ) return null;
596 var _currentFile = currentFile;
598 _currentFile.destroy();
600 if( typeof _index === 'number' ){
601 if( _index >= l ) return null;
602 currentFile = this.getParentFileAt( _index );
603 PARENT_FILE_RESITER.splice( 0, l -_index);
605 currentFile = PARENT_FILE_RESITER.shift();
607 currentFile.getSeqentialFiles();
610 this.addTreeEventListener = function( _eventType, _callback, opt_thisObject ){
611 FILE_CONTROLER.addEventListener( null, _eventType, _callback, opt_thisObject );
613 this.removeTreeEventListener = function( _eventType, _callback ){
614 FILE_CONTROLER.removeEventListener( null, _eventType, _callback );
616 this.destroy = function( _apiuser ){
617 if( _apiuser && apiuser !== _apiuser ) return false;
619 var _currentFile = currentFile;
620 currentFile = rootFile = rootFileData = null;
621 // currentFile, rootFile を null にしないと .File.destroy() ができない.
622 _currentFile.destroy();
623 while( PARENT_FILE_RESITER.length > 0 ){
624 _currentFile = PARENT_FILE_RESITER.shift();
625 _currentFile.destroy();
628 AsyncCall.remove( apiuser );
629 instance = apiuser = null;
634 var FileEventTicketClass = function( uid, eventType, callback, opt_thisObject ){
636 this.eventType = eventType;
637 this.callBack = callback;
638 this.thisObject = opt_thisObject;
640 FileEventTicketClass.prototype = new TicketBase();
642 var FileEventClass = function( eventType, file, key, value ){
643 this.eventType = eventType;
644 this.targetFile = file;
645 this.updatedAttribute = key;
646 this.updatedValue = value;
650 * file の data は object で保持している。
651 * File の外からファイルをみるときは、FileClassを通して操作する。
652 * fileの変更、それに付随して追加されたイベントは、TreeClassで管理される。
653 * treeがdestryされると、fileのイベントリスナーも全て削除される。
654 * 他の tree も data の共通する currentFile に対してのみは、file の変更イベントを受け取って流す.
658 var FileClass = function( tree, parentData, data ){
659 var uid = FILE_CONTROLER.getFileUID( data );
661 FILEDATA_ACCESS.push( {
663 parentData: parentData,
667 tree = parentData = data = null;
669 this.getUID = function(){
674 FileClass.prototype = {
675 isChildFile: function( _FILEorFILEDATA ){
676 return this.getChildFileIndex( _FILEorFILEDATA) !== -1;
678 getSeqentialFiles: function(){
679 var _driver = FILE_CONTROLER.getDriver( this );
680 if( _driver !== null && typeof _driver.getSeqentialFiles === 'function' ){
681 _driver.getSeqentialFiles( this );
684 addEventListener: function( _eventType, _callback ){
685 FILE_CONTROLER.addEventListener( this, _eventType, _callback );
687 removeEventListener: function( _eventType, _callback ){
688 FILE_CONTROLER.removeEventListener( this, _eventType, _callback );
690 dispatchEvent: function( e ){
691 e instanceof FileEventClass && FILE_CONTROLER.fileEventRellay( this.getUID(), e );
693 getChildFileLength: function(){
694 var children = FILE_CONTROLER.getChildren( this );
695 return Type.isArray( children ) === true ? children.length : -1;
697 getChildFileIndex: function( _FILEorFILEDATA ){
698 var children = FILE_CONTROLER.getChildren( this );
699 if( Type.isArray( children ) === false ) return -1;
700 var l = children.length,
701 _fileData = FILE_CONTROLER.getFileData( _FILEorFILEDATA );
702 if( _fileData === null ) return -1;
703 for( var i=0; i<l; ++i ){
704 if( children[ i ] === _fileData ) return i;
708 getChildFileByIndex: function( _index ){
709 var _access = FILE_CONTROLER.getFileDataAccess( this ),
710 _children = FILE_CONTROLER.getChildren( this );
711 if( typeof _index !== 'number' || _index < 0 || Type.isArray( _children ) === false || _index >= _children.length) return null;
712 var _file = new FileClass( _access.TREE, _access.DATA, _children[ _index ]);
717 var driver = FILE_CONTROLER.getDriver( this );
718 if( typeof driver.getName === 'function'){
719 return driver.getName( this );
721 return BASE_DRIVER.getName( this);
723 getThumbnail: function(){
724 var driver = FILE_CONTROLER.getDriver( this );
725 if( typeof driver.getThumbnail === 'function'){
726 return driver.getThumbnail( this );
728 return BASE_DRIVER.getThumbnail( this );
731 var _data = FILE_CONTROLER.getFileData( this );
732 return typeof _data.type === 'number' ? _data.type : Const.FILE.TYPE.UNKNOWN;
734 getState: function(){
735 var _data = FILE_CONTROLER.getFileData( this );
736 return typeof _data.state === 'number' ? _data.state : Const.FILE.STATE.OK;
738 getSummary: function(){
739 var driver = FILE_CONTROLER.getDriver( this );
740 if( typeof driver.getSummary === 'function'){
741 return driver.getSummary( this );
743 return BASE_DRIVER.getSummary( this );
745 isWritable: function(){
746 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.WRITE );
748 isSortable: function(){
749 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.SORT );
751 isCreatable: function(){
752 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.CREATE );
754 isRenamable: function(){
755 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.RENAME );
757 isDeletable: function(){
758 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.DELETE );
762 var driver = FILE_CONTROLER.getDriver( this ),
764 if( typeof driver.read === 'function'){
765 data = driver.read( this );
767 return BASE_DRIVER.read( data || this );
769 write: function( _newData, _onUpdateFunction ){
770 var driver = FILE_CONTROLER.getDriver( this );
771 if( typeof driver.write === 'function'){
772 return driver.write( this, _newData, _onUpdateFunction );
774 return BASE_DRIVER.write( this, _newData, _onUpdateFunction );
776 viewerApplicationList: function(){
777 var driver = FILE_CONTROLER.getDriver( this );
778 if( typeof driver.viewerApplicationList === 'function'){
779 return driver.viewerApplicationList( this );
781 return BASE_DRIVER.viewerApplicationList( this );
783 editorApplicationList: function(){
784 var driver = FILE_CONTROLER.getDriver( this );
785 if( typeof driver.editorApplicationList === 'function'){
786 return driver.editorApplicationList( this );
788 return BASE_DRIVER.viwerApps( this );
799 onDelete: function(){
802 move: function( _newFolder, _newIndex, opt_callback ){
803 var _access = FILE_CONTROLER.getFileDataAccess( this );
804 _access.TREE.move( _access.parentData, this.getUID(), _newFolder, _newIndex, opt_callback );
806 replace: function( _newIndex, opt_callback ){
807 var _access = FILE_CONTROLER.getFileDataAccess( this );
808 _access.TREE.replace( _access.parentData, this.getUID(), _newIndex, opt_callback);
812 * 探しているファイルの属性と値を指定.一致する child の index を配列で返す.
814 search: function( obj, rule ){
815 var _children = FILE_CONTROLER.getChildren( this ),
818 for( var i=0, l=_children.length; i<l; ++i ){
819 _child = _children[ i ];
822 if( obj[ k ] !== _child[ k ] ){
827 c === true && ret.push( i );
832 var _access = FILE_CONTROLER.getFileDataAccess( this );
833 var _tree = _access.TREE;
834 if( _tree.getCurrentFile() === this ) return;
835 if( _tree.getRootFile() === this ) return;
836 for( var i=0, l = _tree.hierarchy(); i<l; ++i ){
837 if( _tree.getParentFileAt( i ) === this ){
841 var _index = Util.getIndex( FILEDATA_ACCESS, _access );
842 if( _index === -1 ) return;
844 FILEDATA_ACCESS.splice( _index, 1 );
847 delete _access.parentData;
854 var FileDriverBase = function( driverClass ){
855 this.getUID = function(){
856 return Util.getIndex( API_USER_LIST, driverClass );
858 this.getSeqentialFiles = function( _file ){
860 this.getName = function( _file ){
861 var _data = FILE_CONTROLER.getFileData( _file );
862 return _data.name || 'No Name';
864 this.getThumbnail = function( _file ){
865 var _data = FILE_CONTROLER.getFileData( _file ),
868 if( _type === Const.FILE.TYPE.FOLDER ){
869 _className = 'folder';
871 if( _type === Const.FILE.TYPE.IMAGE ){
874 if( _type === Const.FILE.TYPE.TEXT ){
877 if( _type === Const.FILE.TYPE.HTML ){
880 if( _type === Const.FILE.TYPE.CSV ){
883 if( _type === Const.FILE.TYPE.JSON ){
886 if( _type === Const.FILE.TYPE.XML ){
891 className: ' file-type-' + _className
894 this.getSummary = function( _file ){
895 var _data = FILE_CONTROLER.getFileData( _file ),
897 if( _type === Const.FILE.TYPE.FOLDER ){
900 if( _type === Const.FILE.TYPE.IMAGE ){
903 if( _type === Const.FILE.TYPE.TEXT ){
906 if( _type === Const.FILE.TYPE.HTML ){
907 return 'html document file';
909 if( _type === Const.FILE.TYPE.CSV ){
910 return 'csv daat file';
912 if( _type === Const.FILE.TYPE.JSON ){
913 return 'json data file';
915 if( _type === Const.FILE.TYPE.XML ){
916 return 'xml data file';
920 this.getUpdatePolicy = function( _file ){
922 return Const.FILE.UPDATE_POLICY.DSRWC;
924 this.read = function( _FILEorDATA ){
926 protects = Const.FILE.DATA_PROPERTY_RESERVED;
927 if( _FILEorDATA instanceof FileClass ){
928 data = FILE_CONTROLER.getFileData( _FILEorDATA )
933 function clone( src ) {
935 if( Type.isArray(src) === true ){
938 if( Type.isObject(src) === true ){
941 if( Type.isNumber(src) === true || Type.isString(src) === true || Type.isBoolean( src ) === true ){
946 for( var key in src ){
947 if( Util.getIndex( protects, key ) === -1 ){
948 ret[ key ] = clone( src[ key ]);
954 return clone( data );
956 this.write = function( _file, _newData, _onUpdateFunction ){
957 var _data = FILE_CONTROLER.getFileData( _file ),
961 this.viewerApplicationList = function(){
964 this.editorApplicationList = function(){
967 this.onCreate = function(){
970 this.onSort = function(){
973 this.onCopy = function(){
976 this.onDelete = function(){
981 var BASE_DRIVER = new FileDriverBase();
983 var ROOT_FILEDATA = {
985 type: FILE_TYPE_IS_FOLDER,
988 SYSTEM_TREE = FILE_CONTROLER.createTree( SUPER_USER_KEY, ROOT_FILEDATA ),
989 ROOT_FILE = SYSTEM_TREE.getRootFile();
991 function createFileTypeID(){
992 return ++numFileType;
995 var FileAPIClass = function( driver ){
997 this.createFolderUnderRoot = function( _fileData ){
998 if( _fileData !== null && Type.isObject( _fileData ) === true ){
999 ROOT_FILEDATA.children.push( _fileData );
1000 ROOT_FILE.dispatchEvent( new FileEventClass( Const.FILE.EVENT.GET_SEQENTIAL_FILES, ROOT_FILE, 'children', null ));
1003 this.createFileEvent = function( _eventType, _file, _key, _value ){
1004 return new FileEventClass( _eventType, _file, _key, _value );
1006 this.createFileTypeID = createFileTypeID;
1007 this.getFileDataAccess = FILE_CONTROLER.getFileDataAccess;
1008 this.getFileData = FILE_CONTROLER.getFileData;
1009 this.getJson = function( _data, _url, _onLoad, _onError ){
1010 REQUEST_CONTROLER.getJson( driver, _data, _url, _onLoad, _onError );
1012 this.createTree = function( _rootFile ){
1013 return FILE_CONTROLER.createTree( driver, _rootFile );
1015 this.isTreeInstance = function( _tree ){
1016 return _tree instanceof TreeClass;
1018 this.isFileInstance = function( _file ){
1019 return _file instanceof FileClass;
1021 this.isFileEvent = function( _event ){
1022 return _event instanceof FileEventClass;
1024 this.getConst = function(){
1025 return Const; // constObject = constObject || clone( Const )
1030 registerDriver: function( _class ){
1031 _class.prototype = new FileDriverBase( _class );
1032 var _driver = new _class();
1034 DRIVER_LIST.push( _driver );
1035 API_USER_LIST.push( _class );
1037 return new FileAPIClass( _driver );
1039 isDriver: function( _driver ){
1040 return _driver instanceof FileDriverBase;
1042 isTreeInstance: function( _tree ){
1043 return _tree instanceof TreeClass;
1045 isFileInstance: function( _file ){
1046 return _file instanceof FileClass;
1052 /* ----------------------------------------------------
1053 * ApplicationManager
1054 * window resize event, overlayApplication currentAplication に流す
1057 var APPLICATION_LIST = [];
1059 var ApplicationPrivateData = function(){};
1060 ApplicationPrivateData.prototype = {
1066 bgColor : '#C1CACF',
1077 init : function( appClass, displayName, isOverlay ){
1078 this.appClass = appClass;
1079 this.displayName = displayName;
1080 this.isOverlay = isOverlay;
1081 this.rootElement = document.createElement( 'div' );
1082 this.styleCursor = this.rootElement.style;
1083 ApplicationPrivateData.list.push( this );
1085 detect : function(){
1086 if( this.rootElement.firstChild && this.fetchResource === 0 ){
1087 SystemTimer.remove( this.application, this.detect );
1091 onOpen : function(){
1092 this.rootElement.style.display = '';
1094 // this.layer !== null && this.layer.onResize( this.w, this.h );
1096 if( this.application.MIN_WIDTH > this.w || this.application.MIN_HEIGHT > this.h ){
1097 if( Type.isHTMLElement( this.rootElement ) === true ){
1101 if( this.bootParams.length > 2 ){
1102 this.application.onOpen.apply( this.application, this.bootParams );
1104 this.application.onOpen( this.w, this.h );
1108 fetchResourceComplete : function(){
1109 --this.fetchResource;
1112 ApplicationPrivateData.list = [];
1113 ApplicationPrivateData.get = function( app ){
1114 var list = ApplicationPrivateData.list,
1117 if( app instanceof list[ --i ].appClass ) return list[ i ];
1122 var AbstractApplication = function( appClass, displayName, isOverlay ){
1123 ( new ApplicationPrivateData() ).init( appClass, displayName, isOverlay );
1125 AbstractApplication.prototype = {
1126 getUID : function(){
1127 var data = ApplicationPrivateData.get( this );
1128 return Util.getIndex( API_USER_LIST, data.appClass );
1131 var data = ApplicationPrivateData.get( this );
1132 this.rootElement = data.rootElement;
1133 data.application = this;
1135 data.appClass === Page.appClass && Page.show();
1139 open : function( w, h /*, _option */ ){
1140 var data = ApplicationPrivateData.get( this );
1142 data.bootParams = Util.copyArray( arguments );
1145 if( data.rootElement.innerHTML && data.rootElement.innerHTML.length > 0 ){
1146 SystemTimer.add( this, data.detect, 16, false, data );
1151 resize : function( w, h ){
1152 var data = ApplicationPrivateData.get( this );
1153 if( data.phase !== 4 ) return;
1154 if( this.MIN_WIDTH > w || this.MIN_HEIGHT > h ){
1155 if( Type.isHTMLElement( this.rootElement ) === true ){
1160 this.onPaneResize( w, h );
1163 var data = ApplicationPrivateData.get( this );
1165 if( this.onClose() === false ){
1169 while( data.uiList.length > 0 ) data.uiList.shift().destroy();
1171 if( data.finderList ){
1172 while( data.finderList.length > 0 ) data.finderList.shift().destroy();
1175 data.eventRoot && PointingDeviceEventTree.destroyTree( data.eventRoot );
1176 MouseEvent.remove( this );
1177 KeyEvent.remove( this );
1178 SystemTimer.remove( this );
1179 AsyncCall.remove( this );
1180 StyleSheet.unload( this );
1182 var elm = this.rootElement;
1183 Util.removeAllChildren( elm );
1184 elm.parentNode.removeChild( elm );
1186 Application.shutdown( this, data.isOverlay );
1188 data.appClass === Page.appClass && Page.hide();
1192 var list = ApplicationPrivateData.list;
1193 list.splice( Util.getIndex( list, data ), 1 );
1195 createUIGroup : function( node ){
1196 var data = ApplicationPrivateData.get( this ),
1197 ui = UI.createUIGroup( this, node );
1198 if( data.uiList === null ) data.uiList = [];
1199 data.uiList.push( ui );
1202 createFinder : function( _elmTarget, _tree, _onSelect, _viewerOption, _editorOption ){
1203 var data = ApplicationPrivateData.get( this ),
1204 finder = Finder.create( this, _elmTarget, _tree, _onSelect, _viewerOption, _editorOption );
1205 if( data.finderList === null ) data.finderList = [];
1206 data.finderList.push( finder );
1209 createDHTML : function( _elm ){
1210 return DHTML.create( this, _elm );
1212 addEventListener : function( element, eventType, handler, opt_thisObject ){
1213 MouseEvent.add( this, element, eventType, handler, opt_thisObject );
1215 removeEventListener : function( element, eventType, handler ){
1216 MouseEvent.remove( this, element, eventType, handler );
1218 getPointingDeviceEventTreeRoot : function(){
1219 var data = ApplicationPrivateData.get( this );
1220 if( data.phase === 1 ){
1221 data.eventRoot = PointingDeviceEventTree.create( this );
1222 data.styleCursor = PointingDeviceEventTree._getNodePrivateData( data.eventRoot ).elmMouseCatch.style;
1224 return data.eventRoot;
1226 updateCoursor : function( _cursor ){
1227 var data = ApplicationPrivateData.get( this );
1228 if( data.cursor !== _cursor ){
1229 data.styleCursor.cursor = data.cursor = _cursor;
1232 fetchCSS : function( url, opt_onload, opt_onerror ){
1233 var data = ApplicationPrivateData.get( this );
1234 if( data.phase === 1 ){
1235 ++data.fetchResource;
1236 StyleSheet.load( this, url, data.fetchResourceComplete, data.fetchResourceComplete, data );
1239 onInit : function(){},
1240 onOpen : function(){},
1241 onClose : function(){ return true; },
1242 onPaneResize : function( w, h ){},
1243 addKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){
1244 KeyEvent.add( this, _eventType, _handler, _keyCode, _shift, _ctrl );
1246 removeKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){
1247 KeyEvent.remove( this, _eventType, _handler, _keyCode, _shift, _ctrl );
1249 shiftEnabled : function(){
1250 return KeyEvent.shiftEnabled;
1252 ctrlEnabled : function(){
1253 return KeyEvent.ctrlEnabled;
1255 addTimer : function( handler, time, once ){
1256 SystemTimer.add( this, handler, time, !!once );
1258 removeTimer : function( handler ){
1259 SystemTimer.remove( this, handler );
1261 addAsyncCall : function( _callback, _argments, _thisObject ){
1262 AsyncCall.add( this, _callback, _argments, _thisObject );
1264 removeAsyncCall : function( _callback ){
1265 AsyncCall.remove( this, _callback );
1267 fetchHTMLElement : function( id ){
1268 var elm = document.getElementById( id );
1270 elm.removeAttribute( 'id' );
1271 elm.parentNode.removeChild( elm );
1277 var PointingDeviceEventTree = ( function(){
1279 currentRootData = null,
1280 targetNodeData = null,
1281 forceNodeData = null,
1285 function eventRellay( e ){
1286 var data = forceNodeData, // || targetNodeData,
1292 ret, systemOnly = false, addClass, removeClass,
1294 if( data && data.dispatchEvent( e, type, true ) === true ) return false;
1295 if( currentRootData === null ) return;
1296 targetNodeData = currentRootData;
1297 currentRootData._capcher( x, y );
1298 targetNodeData.apiuser.updateCoursor( targetNodeData._cursor );
1299 data = targetNodeData;
1301 ret = data.dispatchEvent( e, type, true, systemOnly );
1302 if( ret === true || ret === false ) break; // systemOnly = true;
1303 data = data.parentData;
1306 addClass = Util.addClass;
1307 removeClass = Util.removeClass;
1308 for( ; i < list.length; ){
1309 parent = data = list[ i ];
1310 while( parent.parentData && parent === parent.parentData.hitChild ){
1311 parent = parent.parentData;
1313 if( parent !== currentRootData ){
1314 data.hover === true && removeClass( data.elm, data.hoverClass );
1315 delete data.isHover;
1316 data.events && data.events.mouseout && data.fire( e, 'mouseout', false );
1317 delete data.hitSelf;
1318 list.splice( i, 1 );
1321 if( data.hover === true && data.isHover === false ){
1322 addClass( data.elm, data.hoverClass );
1323 data.isHover = true;
1325 if( data.hitSelf === false ){
1326 data.events && data.events.mouseover && data.fire( e, 'mouseover', true );
1327 data.hitSelf = true;
1334 var NodeClass = function( apiuser, rootData, /*parentLayer,*/ parentData, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){
1335 ( new NodePrivateData() ).init( apiuser, rootData, /*parentLayer,*/ parentData, this, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop );
1337 NodeClass.prototype = {
1338 createNode : function( rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ){
1339 var data = NodePrivateData.get( this ),
1341 if( Type.isHTMLElement( rangeOrElmData ) === true ){
1342 elm = rangeOrElmData;
1344 if( Type.isString( rangeOrElmData ) === true ){
1345 elm = document.getElementById( rangeOrElmData );
1347 elm = Util.pullHtmlAsTemplete( rangeOrElmData );
1349 if( !elm || Type.isHTMLElement( elm ) === false || elm.nodeType !== 1 ){
1350 throw new Error( "invalid HTMLElement." );
1353 if( Type.isObject( rangeOrElmData ) === false || Type.isFinite( rangeOrElmData.x ) === false || Type.isFinite( rangeOrElmData.y ) === false ){
1354 throw new Error( "No range" );
1357 if( elm && data.elm === null ){
1358 throw new Error( "MetaLayer don't containe HTMLElement-Layer." );
1360 if( data.elm && data.elm.style.hasLayout === false ){
1361 throw new Error( "[ie] OffsetParent is hasLayout === false." );
1364 var newNode = new NodeClass( data.apiuser, data.rootData, data, elm || rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ),
1365 newData = NodePrivateData.get( newNode );
1367 if( data.childData === null ) data.childData = [];
1368 data.childData.push( newData );
1371 createNodeAt : function(){
1373 remove : function(){
1374 NodePrivateData.get( this ).remove();
1376 nodeIndex : function( v ){
1377 return NodePrivateData.get( this ).nodeIndex( v );
1379 numNode : function(){
1380 return NodePrivateData.get( this ).numNode();
1382 disabled : function( v ){
1383 return NodePrivateData.get( this ).disabled( v );
1385 childrenDisabled : function( v ){
1386 return NodePrivateData.get( this ).disabled( v );
1388 mesure : function(){
1389 NodePrivateData.get( this ).mesure();
1391 mesureChildren : function(){
1392 NodePrivateData.get( this ).mesureChildren();
1394 update : function( x, y, w, h ){
1395 NodePrivateData.get( this ).update( x, y, w, h );
1397 setPosition : function( x, y ){
1398 NodePrivateData.get( this ).setPosition( x, y );
1400 setSize : function( w, h ){
1401 NodePrivateData.get( this ).setSize( w, h );
1403 cursor : function( v ){
1404 return NodePrivateData.get( this ).cursor( v );
1407 return NodePrivateData.get( this ).positionX( x );
1410 return NodePrivateData.get( this ).positionY( y );
1412 width : function( w ){
1413 return NodePrivateData.get( this ).width( w );
1415 height : function( h ){
1416 return NodePrivateData.get( this ).height( h );
1418 getAbsolutePositionX : function(){
1419 return NodePrivateData.get( this ).getAbsolutePositionX();
1421 getAbsolutePositionY : function(){
1422 return NodePrivateData.get( this ).getAbsolutePositionY();
1424 addEventListener : function( type, handler, opt_thisObject ){
1425 NodePrivateData.get( this ).addEventListener( type, handler, opt_thisObject );
1427 removeEventListener : function( type, handler ){
1428 NodePrivateData.get( this ).removeEventListener( type, handler );
1430 scrollTo : function( x, y ){
1431 NodePrivateData.get( this ).scrollTo( x, y );
1433 scrollX : function( v ){
1434 return NodePrivateData.get( this ).scrollX( v );
1436 scrollY : function( v ){
1437 return NodePrivateData.get( this ).scrollY( v );
1439 invalidateScrollbar : function(){
1440 ScrollBarManager.update( NodePrivateData.get( this ) );
1445 * clip : true の場合、子ノードの変更によってヒットエリアを変化させない.elm には overflow:hidden としておくのが通常.
1447 var NodePrivateData = function(){};
1448 NodePrivateData.prototype = {
1449 elmMouseCatch : null, // rootData only
1450 eventCounter : null, // rootData only
1451 cursorStyle : null, // rootData only
1455 elm : null, // resizeTarget
1458 elmScrollbar : null,
1476 // parentLayer : null,
1483 _childDisabled: false,
1484 layoutManager : null,
1493 init: function( apiuser, rootData, /*parentLayer,*/ parentData, node, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){
1494 this.apiuser = apiuser;
1495 this.rootData = rootData || this;
1496 // this.parentLayer = parentLayer;
1497 this.parentData = parentData;
1499 this.through = through;
1501 if( cursor ) this._cursor = cursor;
1503 if( Type.isHTMLElement( rangeOrElm ) === true ){
1504 this.elm = rangeOrElm;
1505 this.hover = !!hover;
1506 this.hoverClass = hover;
1507 this.scroll = clip && scroll;
1509 this.scroll === true && ScrollBarManager.register( this );
1511 this.update( rangeOrElm.x, rangeOrElm.y, rangeOrElm.w, rangeOrElm.h );
1514 NodePrivateData.dataList.push( this );
1516 mesure : function(){
1517 var x, y, w, h, parent, _this, _parent;
1519 w = this.elm.offsetWidth;
1520 h = this.elm.offsetHeight;
1521 _this = Position.cumulativeOffset( this.elm );
1522 _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ];
1523 x = _this[ 0 ] - _parent[ 0 ];
1524 y = _this[ 1 ] - _parent[ 1 ];
1525 if( this.x !== x || this.y !== y || this.w !== w || this.h !== h ){
1530 parent = this.parentData;
1531 parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY );
1532 this._updateRectangle();
1535 this._updateRectangle();
1538 mesureChildren : function(){
1540 if( nodes = this.childData ){
1541 for( i = nodes.length; i; ){
1542 nodes[ --i ].mesure();
1546 update : function( x, y, w, h ){
1547 var updateXY = false,
1553 if( Type.isFinite( w ) === true ){
1554 this.elm.style.width = w + 'px';
1556 if( Type.isString( w ) === true ){
1557 this.elm.style.width = w;
1558 w = this.elm.offsetWidth;
1560 //update = this.w !== w;
1563 if( Type.isFinite( h ) === true ){
1564 this.elm.style.height = h + 'px';
1566 if( Type.isString( h ) === true ){
1567 this.elm.style.height = w;
1568 h = this.elm.offsetHeight;
1570 //update = update || this.h !== h;
1573 if( Type.isFinite( x ) === true ){
1574 this.elm.style.left = x + 'px';
1576 if( Type.isString( x ) === true ){
1577 this.elm.style.left = x;
1584 if( Type.isFinite( y ) === true ){
1585 this.elm.style.top = y + 'px';
1587 if( Type.isString( y ) === true ){
1588 this.elm.style.top = y;
1593 if( updateXY === true ){
1594 _this = Position.cumulativeOffset( this.elm );
1595 _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ];
1596 x = _this[ 0 ] - _parent[ 0 ];
1597 y = _this[ 1 ] - _parent[ 1 ];
1599 //update = update || this.x !== x;
1600 //update = update || this.y !== y;
1602 //update === true && this._updateRectangle();
1605 x = Type.isFinite( x ) === true ? x : this.x;
1606 y = Type.isFinite( y ) === true ? y : this.y;
1607 w = Type.isFinite( w ) === true ? w : this.w;
1608 h = Type.isFinite( h ) === true ? h : this.h;
1609 if( this.x !== x || this.y !== y ){
1612 console.log( 'xy ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h + ' absX:' + this.parentData.absoluteX )
1613 parent = this.parentData;
1614 parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY );
1615 this.w === w && this.h === h && this._updateRectangle();
1617 if( this.w !== w || this.h !== h ){
1620 console.log( 'wh ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h )
1621 this._updateRectangle();
1624 ScrollBarManager.update( this );
1626 _updateAbsoluteXY : function( x, y, sX, sY ){
1628 this.absoluteX = x = this.x + x;
1629 this.absoluteY = y = this.y + y;
1630 if( nodes = this.childData ){
1631 for( i = nodes.length; i; ){
1632 nodes[ --i ]._updateAbsoluteXY( x, y, this.scrollingX, this.scrollingY );
1636 _updateRectangle : function(){
1645 nodes = this.childData,
1649 if( this.clip === false && nodes ){
1650 for( i = nodes.length; i; ){
1651 node = nodes[ --i ];
1652 if( node.l + x < l ) l = x + node.l;
1653 if( node.t + y < t ) t = y + node.t;
1654 if( r < node.r + x ) r = x + node.r;
1655 if( b < node.b + y ) b = y + node.b;
1659 if( b !== this.b || r !== this.r || t !== this.t || l !== this.l ){
1666 this.parentData && this.parentData.clip === false && this.parentData._updateRectangle();
1670 setPosition : function( x, y ){
1671 this.update( x, y );
1673 setSize : function( w, h ){
1674 this.update( undefined, undefined, w, h );
1676 positionX : function( x ){
1677 x !== undefined && this.update( x );
1680 positionY : function( y ){
1681 y !== undefined && this.update( undefined, y );
1684 width : function( w ){
1685 w !== undefined && this.update( undefined, undefined, w );
1688 height : function( h ){
1689 h !== undefined && this.update( undefined, undefined, undefined, h );
1692 getAbsolutePositionX : function(){
1693 return this.absoluteX;
1695 getAbsolutePositionY : function(){
1696 return this.absoluteY;
1698 cursor : function( v ){
1699 if( Type.isString( v ) === true ){
1701 this === targetNodeData && this.apiuser.updateCoursor( v );
1703 return this._cursor;
1705 addEventListener : function( eventType, handler, opt_thisObject ){
1706 var node = this.node,
1707 counter = this.rootData.eventCounter,
1709 if( this.events === null ) this.events = {};
1710 list = this.events[ eventType ];
1712 list = this.events[ eventType ] = [];
1714 for( i = list.length; i; ){
1715 if( list[ --i ].match( eventType, handler ) === true ){
1720 list.push( new EventTicketClass( this.node, eventType, handler, opt_thisObject ) );
1721 if( eventType !== 'mouseout' && eventType !== 'mouseover' ){
1722 if( counter[ eventType ] ){
1723 ++counter[ eventType ];
1725 console.log( eventType );
1726 counter[ eventType ] = 1;
1727 MouseEvent.add( this.apiuser, this.rootData.elmMouseCatch, eventType, eventRellay );
1731 removeEventListener : function( eventType, handler ){
1732 var events = this.events,
1733 counter = this.rootData.eventCounter,
1735 if( events === null ) return;
1736 console.log( ' *** remove ' + eventType );
1737 for( type in events ){
1738 list = events[ type ];
1739 if( eventType && eventType !== type ) continue;
1740 for( ; i < list.length; ){
1741 if( list[ i ].destroy( type, handler ) === true ){
1742 console.log( ' *** removed! ' + type );
1743 list.splice( i, 1 );
1748 if( list.length === 0 ){
1749 // delete this[ type ];
1750 delete events[ type ];
1752 if( counter[ type ] ){
1754 if( counter[ type ] === 0 ){
1755 MouseEvent.remove( this.apiuser, this.rootData.elmMouseCatch, type, eventRellay );
1756 delete counter[ type ];
1761 _capcher : function( x, y ){
1762 var t = this, nodes, child, _x, _y, hit, i;
1763 if( t._disabled === true ) return false;
1767 if( nodes = t.childData ){
1768 _x = x - t._scrollX;
1769 _y = y - t._scrollY;
1770 for( i = nodes.length; i; ){
1771 child = nodes[ --i ];
1772 if( child._disabled === false && child.l <= _x && _x < child.r && child.t <= _y && _y < child.b && child._capcher( _x, _y ) === true ){
1778 if( t.through === true ){
1779 t.hitChild && t.hitSelf === false && hoverList.push( t );
1780 return !!t.hitChild;
1782 hit = 0 <= x && x < t.w && 0 <= y && y < t.h;
1783 ( t.hitChild || hit ) && t.hitSelf === false && hoverList.push( t );
1784 if( hit === true && t.hitChild === null ) targetNodeData = t;
1785 return hit || !!t.hitChild;
1787 fire : function( e, eventType, hit ){
1788 var list = this.events[ eventType ],
1790 e = NodePrivateData.createEvent( e, eventType, this, hit );
1791 for( ; i; ) list[ --i ].fire( e );
1792 // console.log( eventType + ' x:' + x + ' y:' + y );
1794 dispatchEvent : function( e, eventType, hit ){
1795 var ret, list, i, p, child;
1796 if( !this.events || !( list = this.events[ eventType ] ) ) return;
1798 child = !!this.hitChild;
1799 e = NodePrivateData.createEvent( e, eventType, this, hit );
1800 for( i = list.length; i; ){
1801 ret = list[ --i ].fire( e );
1802 if( ret === true && child === false ){
1803 forceNodeData = this;
1806 if( ret === false ) return false;
1808 forceNodeData = null;
1810 scrollTo : function( x, y ){
1813 ScrollBarManager.update( this );
1815 scrollX : function( v ){
1816 if( Type.isFinite( v ) === true ){
1818 ScrollBarManager.update( this );
1820 return this._scrollX;
1822 scrollY : function( v ){
1823 if( Type.isFinite( v ) === true ){
1825 ScrollBarManager.update( this );
1827 return this._scrollY;
1829 nodeIndex : function( v ){
1831 if( !this.parentData ) return 0;
1833 list = this.parentData.childData;
1834 i = Util.getIndex( list, this );
1835 if( Type.isFinite( v ) === false || i === v && v < 0 && list.length <= v ) return i;
1837 list.splice( i, 1 );
1838 list.length === v ? list.push( this ) : list.splice( v, 0, this );
1843 if( this.parentData.hitChild === this ){
1844 this.parentData.hitChild = null;
1845 this.isHover === true && hoverList.splice( Util.getIndex( hoverList, this ), 1 ) && Util.removeClass( this.elm, this.hoverClass );
1846 this.isHover = false;
1847 if( forceNodeData === this ) forceNodeData = null;
1848 if( targetNodeData === this ) targetNodeData = null;
1851 numNode : function(){
1852 return this.childData ? this.childData.length : 0;
1854 disabled : function( v ){
1855 if( Type.isBoolean( v ) === true ){
1861 return this._disabled;
1863 childrenDisabled : function( v ){
1864 if( Type.isBoolean( v ) === true ){
1865 this._childDisabled = v;
1867 return this._childDisabled;
1869 remove : function(){
1870 if( this === this.rootData ) return;
1871 var parent = this.parentData,
1872 nodes = parent.childData;
1874 if( parent.hitChild === this ) delete parent.hitChild;
1875 nodes.splice( Util.getIndex( nodes, this ), 1 );
1876 if( nodes.length === 0 ) delete parent.childData;
1877 parent.clip === false && parent._updateRectangle();
1879 _destroy : function(){
1880 var nodes = this.childData,
1881 list = NodePrivateData.dataList,
1883 this.removeEventListener();
1885 while( node = nodes.shift() ) node._destroy();
1886 delete this.childData;
1888 list.splice( Util.getIndex( list, this ), 1 );
1891 NodePrivateData.dataList = [];
1892 NodePrivateData.get = function( node ){
1893 // if( node instanceof NodePrivateData ) return node;
1894 // return NodePrivateData.dataList[ layer._getUID() ];
1895 var list = NodePrivateData.dataList;
1896 for( var i = list.length; i; ){
1897 if( list[ --i ].node === node ) return list[ i ];
1901 NodePrivateData.createEvent = function( e, eventType, data, hit ){
1903 layerX : e.clientX - data.absoluteX,
1904 layerY : e.clientY - data.absoluteY,
1905 clientX : e.clientX,
1906 clientY : e.clientY,
1907 dragOffsetX : e.dragOffsetX,
1908 dragOffsetY : e.dragOffsetY,
1909 eventType : eventType,
1912 wheelDelta : e.wheelDelta,
1913 target : forceNodeData ? forceNodeData.node : targetNodeData ? targetNodeData.node : null
1918 var EventTicketClass = function( node, eventType, handler, opt_thisObject ){
1920 this.type = eventType;
1921 this.handler = handler;
1922 this.thisObj = opt_thisObject || node;
1924 EventTicketClass.prototype = {
1925 match : function( eventType, handler ){
1926 if( handler && this.handler !== handler ) return false;
1927 if( eventType && this.type !== eventType ) return false;
1930 destroy : function( eventType, handler ){
1931 if( this.match( eventType, handler ) === false ) return false;
1934 delete this.handler;
1935 delete this.thisObj;
1938 fire : ( function(){
1939 if( Function.prototype.call ){
1940 return function( e ){
1941 return this.handler.call( this.thisObj, e );
1944 return function( e ){
1946 this.thisObj._currentHandler = this.handler;
1947 ret = this.thisObj._currentHandler( e );
1948 delete this.thisObj._currentHandler;
1954 var ScrollBarManager = ( function(){
1955 var elmScroller = document.createElement( 'div' ),
1956 elmBar = document.createElement( 'div' ),
1958 currentNodeData = null;
1961 var list = smoothList,
1963 for( i = 0; i < list.length; ){
1965 if( data.scrollingY !== data._scrollY ){
1966 y = data.scrollingY += data.smoothY;
1967 if( data.smoothY < 0 ){
1968 y = y < data._scrollY ? data._scrollY : y;
1970 y = data._scrollY < y ? data._scrollY : y;
1972 data.scrollingY = y;
1973 data.elm.scrollTop = -y;
1975 if( data.scrollingY === data._scrollY ){
1976 list.splice( i, 1 );
1981 list.length === 0 && SystemTimer.remove( SUPER_USER_KEY, tick );
1984 function onScrollStart( e ){
1986 if( data === currentNodeData ) return;
1987 currentNodeData && onScrollComplete();
1989 data.elm.parentNode.appendChild( elmScroller );
1990 elmScroller.appendChild( data.elm );
1992 elmScroller.style.cssText = 'position:absolute;left:0;top:0;';
1993 elmScroller.appendChild( elmBar );
1995 data.scrollStartX = data.scrollingX;
1996 data.scrollStartY = data.scrollingY;
1997 data.elm.scrollTop = -data.scrollingY;
1998 data.addEventListener( 'mousewheel', onMouseWheelScroll, data );
1999 data.addEventListener( 'mousedrag', onMouseDragScroll, data );
2000 data.addEventListener( 'mouseout', onScrollComplete, data );
2001 currentNodeData = data;
2002 ScrollBarManager.update( data );
2004 function onScrollComplete( e ){
2005 if( currentNodeData === null ) return;
2007 var data = currentNodeData;
2008 var parent = elmScroller.parentNode;
2009 parent.appendChild( currentNodeData.elm );
2010 parent.removeChild( elmScroller );
2011 currentNodeData.elm.scrollTop = -data.scrollingY;
2013 data.removeEventListener( 'mousewheel', onMouseWheelScroll, data );
2014 data.removeEventListener( 'mousedrag', onMouseDragScroll, data );
2015 data.removeEventListener( 'mouseout', onScrollComplete, data );
2016 currentNodeData = null;
2018 function onMouseWheelScroll( e ){
2020 this._scrollY += e.wheelDelta;
2021 ScrollBarManager.update( this );
2024 function onMouseDragScroll( e ){
2027 this._scrollY = this.scrollStartY + e.dragOffsetY;
2028 ScrollBarManager.update( this );
2029 this.scrollStartY = this._scrollY;
2034 register : function( data ){
2035 data.addEventListener( 'mouseover', onScrollStart, data );
2037 update : function( data ){
2038 if( data !== currentNodeData ) return;
2040 var contentH = data._scrollH = data.elm.scrollHeight,
2042 offsetH = contentH - clipH,
2043 scrollY = data._scrollY = 0 < data._scrollY ? 0 : ( data._scrollY < -offsetH ? -offsetH : data._scrollY ),
2045 elmScroller.style.width = data.w + 'px';
2046 elmScroller.style.height = clipH + 'px';
2048 data._scrollY = scrollY = 0;
2049 elmBar.style.display = 'none';
2051 barH = Math.floor( clipH * ( clipH / contentH ) );
2052 barY = Math.floor( ( clipH - barH ) * - scrollY / offsetH );
2053 elmBar.style.cssText = [
2054 'position:absolute;',
2056 'background-color:#333;',
2058 'font-size:0;line-height:0;',
2059 'height:', barH, 'px;',
2060 'top:', data.y + barY, 'px;'
2063 data.smoothY = ( scrollY - data.scrollingY ) / 10;
2064 if( data.scrollingY !== scrollY && Util.getIndex( smoothList, data ) === -1 ){
2065 smoothList.length === 0 && SystemTimer.add( SUPER_USER_KEY, tick, 16 );
2066 smoothList.push( data );
2073 create : function( apiuser ){
2074 var elm = document.createElement( 'div' ),
2076 body.appendChild( elm );
2078 root = new NodeClass( apiuser, null, null, elm );
2079 data = NodePrivateData.get( root );
2081 // elm.style.cssText = 'position:absolute;top:0;left:0;height:100%;';
2082 elm.className = 'mouse-operation-catcher';
2083 elm.unselectable = 'on';
2084 data.elmMouseCatch = elm;
2086 data.eventCounter = {};
2087 ROOT_LIST.push( data );
2088 currentRootData = data;
2089 targetNodeData = null;
2090 forceNodeData = null;
2092 MouseEvent.add( apiuser, elm, 'mousemove', eventRellay );
2095 onCurrentApplicationChange : function( _application ){
2096 currentRootData = null;
2097 targetNodeData = null;
2098 forceNodeData = null;
2099 for( var i = ROOT_LIST.length; i; ){
2100 if( ROOT_LIST[ --i ].apiuser === _application ){
2101 currentRootData = ROOT_LIST[ i ];
2106 destroyTree : function( root ){
2107 var data = NodePrivateData.get( root );
2108 MouseEvent.remove( data.apiuser, data.elmMouseCatch, 'mousemove', eventRellay );
2109 body.removeChild( data.elmMouseCatch );
2111 ROOT_LIST.splice( Util.getIndex( ROOT_LIST, data ), 1 );
2112 if( currentRootData === data ){
2113 currentRootData = null;
2114 targetNodeData = null;
2115 forceNodeData = null;
2118 onSystemShutdown : function(){
2121 isNodeInstance : function( node ){
2122 return node instanceof NodeClass;
2124 _getNodePrivateData : function( node ){ // system only
2125 return NodePrivateData.get( node );
2130 var Application = ( function(){
2132 var LIVE_APPLICATION_LIST = [];
2134 var currentApplication = null,
2135 coveredApplication = null,
2139 var ApplicationReference = function( appClass, isOverlay, displayName, id, thumbnailUrl, tailColor ){
2141 var application = null;
2143 this.displayName = displayName;
2144 this.thumbnailUrl = thumbnailUrl;
2145 this.tailColor = tailColor;
2147 function asyncBoot(){
2148 application = Application.boot( appClass, displayName, self.getUID(), isOverlay, Util.copyArray( arguments ) );
2151 this.getUID = function(){
2152 return Util.getIndex( API_USER_LIST, appClass );
2154 this.boot = function( /* _option */ ){
2155 AsyncCall.add( this, asyncBoot, Util.copyArray( arguments ) );
2157 this.shutdown = function(){
2158 if( !application ) return false;
2160 AsyncCall.add( application, ( isOverlay === true ? Overlay.hide : application.close ) );
2164 function asyncBootHome(){
2165 currentApplication === null && Home.boot();
2167 function asyncOpen( /* arguments */ ){
2168 var _arg = Util.copyArray( arguments );
2169 _arg.unshift( winW, winH );
2170 currentApplication.open.apply( currentApplication, _arg );
2173 register: function( _class, _overlay, _tail, _displayName, _id, _thumbnailUrl, _tailColor ){
2174 APPLICATION_LIST.push( _class );
2175 API_USER_LIST.push( _class );
2176 var _ref = new ApplicationReference( _class, _overlay, _displayName, _id, _thumbnailUrl, _tailColor );
2177 _tail === true && Home.add( _ref );
2180 isApplicationInstance: function( app ){
2181 return ApplicationPrivateData.get( app ) !== null;
2183 isApplicationReference: function( _reference ){
2184 return _reference instanceof ApplicationReference;
2186 isCurrentAppplication: function( app ){
2187 return app === currentApplication;
2189 boot: function( appClass, displayName, uid, isOverlay, arg ){
2190 if( currentApplication ){
2191 if( currentApplication.getUID() === uid ) return null;
2192 if( isOverlay === false && currentApplication.close() === false ) return null;
2195 appClass.prototype = new AbstractApplication( appClass, displayName, isOverlay );
2197 var application = new appClass(),
2198 data = ApplicationPrivateData.get( application );
2200 coveredApplication = isOverlay === true ? currentApplication : null;
2202 Application.onCurrentApplicationChange( application );
2204 if( isOverlay === false ){
2205 body.style.backgroundColor = application.bgColor;
2207 body.appendChild( data.rootElement );
2208 data.rootElement.style.display = 'none';
2211 application.addAsyncCall( asyncOpen, arg );
2213 Overlay.show( application, arg );
2218 shutdown: function( _application, isOverlay ){
2219 if( isOverlay === false ){
2220 currentApplication = null;
2221 AsyncCall.add( SUPER_USER_KEY, asyncBootHome );
2223 Application.onCurrentApplicationChange( coveredApplication );
2224 coveredApplication = null;
2227 onCurrentApplicationChange: function( _application ){
2228 if( Application.isApplicationInstance( _application ) === false ) return;
2229 if( currentApplication === _application ) return;
2230 currentApplication = _application;
2231 MouseEvent.onCurrentApplicationChange( _application );
2232 PointingDeviceEventTree.onCurrentApplicationChange( _application );
2233 KeyEvent.updateCurrentListener( _application );
2234 // InteractiveLayer.onCurrentApplicationChange( _application );
2236 onApplicationShutdown: function( _application ){
2237 LIVE_APPLICATION_LIST.splice( Util.getIndex( LIVE_APPLICATION_LIST, _application ) );
2239 onWindowResize: function( w, h ){
2242 currentApplication && currentApplication.resize( w, h );
2243 Overlay.onWindowResize( w, h );
2244 UI.onWindowResize( w, h );
2246 onSystemShutdown: function(){
2252 /* --------------------------------------------------------------
2256 var Home = ( function(){
2257 var APP_REF_LIST = [];
2258 var ELM_TAIL_ORIGIN = ( function(){
2259 var ret = document.createElement( 'div' ),
2260 h2 = document.createElement( 'h2' );
2261 ret.className = 'tail-wrapper';
2262 ret.appendChild( h2 );
2263 h2.appendChild( document.createTextNode( 'appName' ) );
2267 var TailClass = function( appRef ){
2268 this.elm = ELM_TAIL_ORIGIN.cloneNode( true );
2269 this.destroy = function(){
2270 appRef = self = elmName = null;
2274 elmName = this.elm.getElementsByTagName( 'h2' )[ 0 ].firstChild;
2276 this.elm.style.backgroundColor = appRef.tailColor;
2277 elmName.data = appRef.displayName;
2280 var ref = Application.register( function(){
2285 elmContainer, elmHeader;
2289 for( var i=0, l=APP_REF_LIST.length; i<l; ++i ){
2290 tail = new TailClass( APP_REF_LIST[ i ] );
2291 tailList.push( tail );
2293 elmContainer.appendChild( elm );
2294 self.addEventListener( elm, 'click', onTailClick );
2298 function onTailClick( e ){
2299 var _children = elmContainer.getElementsByTagName( 'div' );
2300 for( var i=0, l=_children.length; i<l; ++i ){
2301 if( this === _children[ i ] ){
2302 APP_REF_LIST[ i ].boot();
2308 this.bgColor = '#0F6D39';
2309 this.MIN_WIDTH = 320;
2310 this.MIN_HEIGHT = 320;
2311 this.onInit = function(){
2312 self.rootElement.id = 'home-root';
2314 elmContainer = document.createElement( 'div' );
2315 self.rootElement.appendChild( elmContainer );
2316 elmContainer.id = 'home-tail-container';
2318 elmHeader = document.createElement( 'div' );
2319 self.rootElement.appendChild( elmHeader );
2320 elmHeader.id = 'home-header';
2322 this.onOpen = function( _w, _h ){
2327 this.onPaneResize = function( _w, _h ){
2330 this.onClose = function(){
2331 self.removeEventListener();
2332 while( tailList.length > 0 ){
2333 tailList.shift().destroy();
2335 self = tailList = elmContainer = null;
2337 }, false, false, 'home', 'home', null );
2340 add: function( _appRef ){
2341 if( Application.isApplicationReference( _appRef ) === false ) return;
2342 Util.getIndex( APP_REF_LIST, _appRef ) === -1 && APP_REF_LIST.push( _appRef );
2350 var Page = ( function(){
2353 ignoreTagList = [ 'script', 'noscript', 'style' ];
2355 var MemoryClass = function( node ){
2358 MemoryClass.prototype = {
2360 var node = this.node,
2361 _nodeType = node.nodeType;
2362 if( _nodeType === 1 && Util.getIndex( ignoreTagList, node.tagName.toLowerCase() ) === -1 ){
2363 this.type = _nodeType;
2364 this.display = node.style.display;
2366 if( _nodeType === 3 ){
2367 if( node.data.replace( /\s/g, '' ).length !== 0 ){
2368 this.type = _nodeType;
2369 this.before = pageNodes.length === 0 ? null : pageNodes[ pageNodes.length - 1 ].node;
2371 body.removeChild( node );
2375 // body.removeChild( node );
2380 if( this.type === 1 ){
2382 this.node.style.display = this.display;
2384 this.node.style.display = '';
2388 body.insertBefore( this.node, this.before );
2390 body.appendChild( this.node );
2395 if( !this.node.parentNode ){
2398 if( this.type === 1 ){
2399 this.node.style.display = 'none';
2401 body.removeChild( this.node );
2407 onReady: function(){
2408 var _children = Util.copyArray( body.childNodes ),
2410 for( var i = 0, l = _children.length; i<l; ++i ){
2411 _mem = new MemoryClass( _children[ i ] );
2412 _mem.init() !== false && pageNodes.push( _mem );
2414 if( pageNodes.length !== 0 ){
2415 if( Type.isFunction( gOS.PageApplicationClass ) === true ){
2416 Page.appClass = gOS.PageApplicationClass;
2417 Page.appClass.bgColor = Page.appClass.bgColor || '#ffffff';
2418 Page.appClass.MIN_WIDTH = Page.appClass.MIN_WIDTH || 240;
2419 Page.appClass.MIN_HEIGHT = Page.appClass.MIN_HEIGHT || 240;
2421 Page.appClass = function(){
2424 this.bgColor = '#ffffff';
2425 this.MIN_WIDTH = 200;
2426 this.MIN_HEIGHT = 200;
2427 this.onInit = function(){};
2428 this.onOpen = function( _w, _h ){
2429 KeyEvent.add( self, Const.KEY.EVENT.KEY_DOWN, ref.shutdown, 27 ); // 27.esc
2431 this.onPaneResize = function( _w, _h ){};
2432 this.onClose = function(){};
2435 ref = Application.register( Page.appClass, false, true, document.title, 'page', null, Page.appClass.tailColor || '#999999' );
2437 delete Page.onReady;
2440 for( var i = pageNodes.length; i; ){
2441 pageNodes[ --i ].show();
2445 for( var i = pageNodes.length; i; ){
2446 pageNodes[ --i ].hide();
2452 registered: function(){
2459 /* --------------------------------------------------------------
2463 * スクリーン座標は、コンピュータのディスプレイの左上を原点とする座標系である。screenX, screenY属性で取得できる。Javascritpでは、同名のプロパティとして実装されている。
2464 * しかし、これは、現実的には、何の役に立たない。ブラウザ自体がディスプレイのどの位置にいるのかがわからないので、画面上の位置を知ったところで、何にもならないからだ。
2467 * ウインドウ座標とは、現在のブラウザのウインドウの、ドキュメントを表示している部分の左上原点とした座標である。
2468 * 問題は、ウインドウは、必ずしもドキュメント全体を表示するとは限らない。スクロールと呼ばれるUIによって、ドキュメントの一部だけを表示しているかもしれない。
2470 var XBrowserEvent = ( function(){
2471 var wrappedHandlerClass,
2475 if( window.addEventListener ){
2476 wrappedHandlerClass = function( ticket ){
2477 this.handler = function( e ){
2478 if( ticket.fire( e ) !== false ) return;
2480 e.stopPropagation();
2483 this.destroy = function(){
2485 delete this.handler;
2486 delete this.destroy;
2490 wrappedEventClass = function( e, element ){
2493 this.target = e.srcElement;
2494 this.currentTarget = element;
2495 this.relatedTarget = e.formElement ? e.formElement : e.toElement;
2496 this.eventPhase = e.srcElement === element ? 2: 3;
2498 this.clientX = e.clientX;
2499 this.clientY = e.clientY;
2500 this.screenX = e.screenX;
2501 this.screenY = e.screenY;
2503 this.keyCode = e.keyCode;
2504 this.altKey = e.altKey;
2505 this.ctrlKey = e.ctrlKey;
2506 this.shiftKey = e.shiftKey;
2508 this.wheelDelta = e.wheelDelta;
2510 wrappedEventClass.prototype.stopPropagation = function(){
2511 this._event.cancelBubble = true;
2513 wrappedEventClass.prototype.preventDefault = function(){
2514 this._event.returnValue = false;
2517 if( document.attachEvent ){
2518 wrappedHandlerClass = function( ticket ){
2519 this.handler = function(){
2520 if( ticket === null ) alert( window.event.type )
2521 if( ticket.fire( new wrappedEventClass( window.event, ticket.element ) ) !== false ) return;
2522 // e.preventDefault();
2523 // e.stopPropagation();
2524 window.event.cancelBubble = true;
2525 window.event.returnValue = false;
2528 this.destroy = function(){
2530 delete this.handler;
2531 delete this.destroy;
2537 find: function( _ticket ){
2538 for( var i=0, l= tmp.list.length, _item; i<l; ++i ){
2539 _item = tmp.list[ i ];
2540 if( _item.element === _ticket.element && _item.eventType === _ticket.eventType ){
2547 tmp.TicketClass = function( _ticket ){
2549 this.element = _ticket.element;
2550 this.eventType = _ticket.eventType;
2551 this.tickets = [ _ticket ];
2552 this.onDestroy = function(){ self = null; };
2554 this.element[ 'on' + this.eventType ] = function( e ){ return self.fire( e );};
2557 tmp.TicketClass.prototype = {
2558 add: function( _ticket ){
2559 Util.getIndex( this.tickets, ticket ) === -1 && this.tickets.push( _ticket );
2561 remove: function( _ticket ){
2562 var i = Util.getIndex( this.tickets, _ticket );
2563 i !== -1 && this.tickets.splice( i, 1 );
2564 this.tickets.length === 0 && this.destroy();
2566 fire: function( e ){
2567 e = e || new wrappedEventClass( window.event, this.element );
2568 var i = this.tickets.length,
2571 if( this.tickets[ --i ].fire( e ) === false ) cancel = false;
2575 destroy: function(){
2577 this.element[ 'on' + this.eventType ] = '';
2578 tmp.list.splice( Util.getIndex( tmp.list, this ), 1 );
2579 delete this.element;
2580 delete this.eventType;
2581 delete this.tickets;
2582 delete this.onDestroy;
2589 add: function( _ticket ){
2590 if( document.addEventListener ){
2591 XBrowserEvent.add = function( _ticket ){
2592 _ticket.wrappedHandler = new wrappedHandlerClass( _ticket );
2593 _ticket.element.addEventListener( _ticket.eventType, _ticket.wrappedHandler.handler, false );
2596 if( document.attachEvent ){
2597 XBrowserEvent.add = function( _ticket ){
2598 _ticket.wrappedHandler = new wrappedHandlerClass( _ticket );
2599 _ticket.element.attachEvent( 'on' + _ticket.eventType, _ticket.wrappedHandler.handler );
2602 XBrowserEvent.add = function( _ticket ){
2603 var t = tmp.find( _ticket );
2607 tmp.list.push( new tmp.TicketClass( _ticket ) );
2612 XBrowserEvent.add( _ticket );
2614 remove: function( _ticket ){
2615 if( document.removeEventListener ){
2616 XBrowserEvent.remove = function( _ticket ){
2617 _ticket.element.removeEventListener( _ticket.eventType, _ticket.wrappedHandler.handler, false );
2618 _ticket.wrappedHandler.destroy();
2621 if( document.detachEvent ){
2622 XBrowserEvent.remove = function( _ticket ){
2623 _ticket.element.detachEvent( 'on' + _ticket.eventType, _ticket.wrappedHandler.handler );
2624 _ticket.wrappedHandler.destroy();
2627 XBrowserEvent.remove = function( _ticket ){
2628 var t = tmp.find( _ticket );
2630 t.remove( _ticket );
2635 XBrowserEvent.remove( _ticket );
2643 var EventTicketClass = function( _element, _eventType, _handler, opt_thisObject ){
2644 this.element = _element;
2645 this.eventType = _eventType;
2646 this.handler = _handler;
2647 this.wrappedHandler = null;
2648 this.thisObject = opt_thisObject;
2649 XBrowserEvent.add( this );
2651 EventTicketClass.prototype = {
2652 fire : ( function(){
2653 if( Function.prototype.call ){
2654 return function( e ){
2655 return this.handler.call( this.thisObject || this.element, e );
2658 return function( e ){
2659 var thisObj = this.thisObject || this.element,
2661 thisObj._currentHandler = this.handler;
2662 ret = thisObj._currentHandler( e );
2663 delete thisObj._currentHandler;
2667 match: function( _element, _eventType, _handler ){
2668 if( _handler && _handler !== this.handler ) return false;
2669 if( _eventType && _eventType !== this.eventType ) return false;
2670 if( _element && _element !== this.element ) return false;
2674 destroy: function( _element, _eventType, _handler ){
2675 if( this.match( _element, _eventType, _handler ) === false ) return false;
2677 XBrowserEvent.remove( this );
2679 delete this.element;
2680 delete this.eventType;
2681 delete this.handler;
2682 delete this.wrappedHandler;
2683 delete this.thisObject;
2688 var ReadyEvent = ( function(){
2692 function webkitDetect(){
2693 var state = document.readyState;
2694 if( state === 'loaded' || state === 'complete' ){
2695 SystemTimer.remove( SUPER_USER_KEY, webkitDetect );
2700 function ieDetect(){
2701 if( this.readyState === 'complete' ){ // this.readyState === 'loaded' ||
2702 this.onreadystatechange = new Function();
2703 this.onreadystatechange = null;
2704 AsyncCall.remove( SUPER_USER_KEY, ieScroll );
2708 function ieScroll(){
2710 document.documentElement.doScroll( 'left' );
2712 AsyncCall.add( SUPER_USER_KEY, ieScroll );
2716 document.onreadystatechange = new Function();
2717 document.onreadystatechange = null;
2722 ticketReady && ticketReady.destroy();
2723 ticketLoad && ticketLoad.destroy();
2724 ticketReady = ticketLoad = null;
2726 if( Page.registered() === true ){
2733 // Apple WebKit (Safari, OmniWeb, ...)
2734 if( document.readyState && !!UA.WEBKIT ){
2735 SystemTimer.add( SUPER_USER_KEY, webkitDetect, 50 );
2737 if( document.readyState && UA.isIE && UA.ieVersion < 9 ){
2739 document.onreadystatechange = ieDetect; */
2741 ticketReady = new EventTicketClass( document, 'DOMContentLoaded', onReady );
2742 ticketLoad = new EventTicketClass( window, 'load', onReady );
2749 /* =====================================================
2754 var ResizeEvent = ( function(){
2755 var _globalLock = 0;
2760 function getInnerSize(){
2762 w : root.innerWidth || root.clientWidth,
2763 h : root.innerHeight || root.clientHeight
2770 if( document.uniqueID ){
2771 _resize = function(){
2772 root = (document.compatMode || "") !== "CSS1Compat" ? document.body : document.documentElement;
2776 if( !_globalLock++ ){
2777 var size = getInnerSize();
2778 if( w !== size.w || h !== size.h ){// resized
2782 Application.onWindowResize( w, h );
2784 window.setTimeout( unlock, 0 );
2787 window.setTimeout( loop, 100 );
2792 _resize = function(){
2793 new EventTicketClass( window, 'resize', onResize );
2795 function onResize(){
2796 if( !_globalLock++ ) {
2797 var size = getInnerSize();
2798 if( w !== size.w || h !== size.h ){// resized
2802 Application.onWindowResize( w, h );
2804 window.setTimeout( unlock, 0 );
2810 AsyncCall.add( SUPER_USER_KEY, _resize );
2813 getSize: getInnerSize,
2814 onSystemShutdown: function(){
2821 /* =====================================================
2825 var MouseEvent = ( function(){
2826 var CLICK_OFFSET = 2 * 2,
2827 DRAG_OFFSET = 4 * 4;
2829 var EVENT_LIST_MAP = [],
2832 /*-------------------------------------
2834 * mousedown, mouseup, の移動距離を調べて clickハンドラ を呼ぶ
2836 var ClickEventTicketClass = function( element, clickhandler, opt_thisObject ){
2837 this.mousedownTicket = new EventTicketClass( element, 'mousedown', this.mousedownHandler, this );
2838 this.element = element;
2839 this.handler = clickhandler;
2840 this.thisObject = opt_thisObject;
2842 ClickEventTicketClass.prototype = {
2848 mousedownTicket : null,
2849 mousemoveTicket : null,
2850 mouseupTicket : null,
2851 mouseoutTicket : null,
2852 eventType : 'click',
2853 fire : EventTicketClass.prototype.fire,
2854 match : EventTicketClass.prototype.match,
2855 mousedownHandler : function( e ){
2856 this.startX = e.clientX;
2857 this.startY = e.clientY;
2859 this.mousemoveTicket = new EventTicketClass( this.element, 'mousemove', this.mousemoveHandler, this );
2860 this.mouseupTicket = new EventTicketClass( this.element, 'mouseup', this.mouseupHandler, this );
2861 this.mouseoutTicket = new EventTicketClass( this.element, 'mouseout', this.mouseoutHandler, this );
2863 mousemoveHandler : function( e ){
2864 var offsetX = e.clientX - this.startX,
2865 offsetY = e.clientY - this.startY;
2866 offsetX * offsetX + offsetY * offsetY >= CLICK_OFFSET && this.mouseoutHandler();
2868 mouseupHandler : function( e ){
2869 this.mouseoutHandler();
2870 return this.fire( ClickEventTicketClass.createEvent( e ) );
2872 mouseoutHandler : function( e ){
2873 this.mousemoveTicket && this.mousemoveTicket.destroy();
2874 this.mouseupTicket && this.mouseupTicket.destroy();
2875 this.mouseoutTicket && this.mouseoutTicket.destroy();
2876 if( this.mousemoveTicket ) delete this.mousemoveTicket;
2877 if( this.mouseupTicket ) delete this.mouseupTicket;
2878 if( this.mouseoutTicket ) delete this.mouseoutTicket;
2880 destroy : function( _element, _eventType, _handler ){
2881 if( this.match( _element, _eventType, _handler ) === false ) return false;
2883 this.mouseoutHandler();
2884 this.mousedownTicket.destroy();
2886 delete this.element;
2887 delete this.handler;
2888 delete this.thisObject;
2889 delete this.mousedownTicket;
2893 if( document.createEvent ){
2894 ClickEventTicketClass.createEvent = function( e ){
2895 var _e = document.createEvent( 'MouseEvents' );
2897 'click' , false, true, e.view,
2898 e.detail, e.screenX, e.screenY, e.clientX, e.clientY,
2899 e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
2900 e.button, e.relatedTarget
2905 if( document.attachEvent ){
2906 ClickEventTicketClass.createEvent = function( e ){
2914 /*-------------------------------------
2917 var WheelEventTicketClass = ( function(){
2919 return function( element, wheelhandler, opt_thisObject ){
2920 this.wheelTicket = new EventTicketClass( element, 'DOMMouseScroll', this.onGeckoWheel, this );
2921 this.element = element;
2922 this.handler = wheelhandler;
2923 this.thisObject = opt_thisObject;
2926 if( true || UA.isIE ){
2927 return function( element, wheelhandler, opt_thisObject ){
2928 this.wheelTicket = new EventTicketClass( element, this.eventType, wheelhandler );
2929 this.element = element;
2930 this.handler = wheelhandler;
2931 this.thisObject = opt_thisObject;
2934 TMP.wheelHandlerList = [];
2935 TMP.wheelThisObjList = [];
2936 //TMP.wheelLegacy = undefined;
2937 TMP.onWheel = function( e ){
2938 e = e || window.event;
2940 f = TMP.wheelLegacy;
2941 if( f ) cancel = f.call( this, e );
2943 for( i = TMP.wheelHandlerList.length; i; ){
2944 if( TMP.wheelHandlerList[ --i ].call( TMP.wheelThisObjList[ i ] || this, e ) === false ) cancel = false;
2948 return function( element, wheelhandler, opt_thisObject ){
2949 this.element = element;
2950 this.handler = wheelhandler;
2951 this.thisObject = opt_thisObject;
2953 if( TMP.wheelHandlerList.length === 0 ){
2954 //TMP.wheelLegacy = Type.isFunction( window.onmousewheel ) === true ? window.onmousewheel : undefined;
2955 element.onmousewheel = TMP.onWheel;
2957 TMP.wheelHandlerList.push( wheelhandler );
2958 TMP.wheelThisObjList.push( opt_thisObject )
2962 WheelEventTicketClass.prototype = {
2963 eventType : 'mousewheel',
2964 match : EventTicketClass.prototype.match,
2965 destroy : function( _element, _eventType, _handler ){
2966 if( this.match( _element, _eventType, _handler ) === false ) return false;
2968 this.wheelTicket && this.wheelTicket.destroy();
2970 delete this.wheelTicket;
2971 delete this.element;
2972 delete this.handler;
2973 delete this.thisObject;
2975 this.onDestroy && this.onDestroy();
2980 WheelEventTicketClass.prototype.onGeckoWheel = function( e ){
2981 var _e = document.createEvent( 'MouseEvents' );
2983 'mousewheel' , false, true, e.view,
2984 e.detail, e.screenX, e.screenY, e.clientX, e.clientY,
2985 e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
2986 e.button, e.relatedTarget
2988 _e.wheelDelta = e.detail * -40;
2989 return this.handler.call( this.thisObject || this.element, _e );
2992 if( true || UA.isIE ){
2995 WheelEventTicketClass.prototype.onDestroy = function(){
2996 TMP.wheelHandlerList.splice( Util.getIndex( TMP.wheelHandlerList, this.handler ), 1 );
2997 TMP.wheelThisObjList.splice( Util.getIndex( TMP.wheelThisObjList, this.handler ), 1 );
2998 if( TMP.wheelHandlerList.length === 0 ) this.element.onmousewheel = '';
3002 /*-------------------------------------
3005 var DragEventTicketClass = function( element, draghandler, opt_thisObject ){
3006 this.mousedownTicket = new EventTicketClass( element, 'mousedown', this.mousedownHandler, this );
3007 this.element = element;
3008 this.handler = draghandler;
3009 this.thisObject = opt_thisObject;
3011 DragEventTicketClass.prototype = {
3018 mousedownTicket : null,
3019 mousemoveTicket : null,
3020 mouseupTicket : null,
3021 mouseoutTicket : null,
3022 eventType : 'mousedrag',
3023 fire : EventTicketClass.prototype.fire,
3024 match : EventTicketClass.prototype.match,
3025 mousedownHandler: function( e ){
3026 this.startX = e.clientX;
3027 this.startY = e.clientY;
3029 this.mousemoveTicket = new EventTicketClass( this.element, 'mousemove', this.dragMoveHandler, this );
3030 this.mouseupTicket = new EventTicketClass( this.element, 'mouseup', this.dragEndHandler, this );
3031 this.mouseoutTicket = new EventTicketClass( this.element, 'mouseout', this.dragEndHandler, this );
3033 dragMoveHandler : function( e ){
3034 var offsetX = e.clientX - this.startX,
3035 offsetY = e.clientY - this.startY;
3036 if( this.dragging === false ){
3037 if( offsetX * offsetX + offsetY * offsetY < DRAG_OFFSET ) return;
3039 this.dragging = true;
3040 return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 0 ) );
3042 return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 1 ) );
3044 dragEndHandler : function( e ){
3045 var offsetX = e.clientX - this.startX,
3046 offsetY = e.clientY - this.startY;
3047 if( this.dragging === true ){
3048 this.removeEvents();
3050 return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 2 ) );
3052 this.removeEvents();
3054 removeEvents : function(){
3055 this.dragging = false;
3056 if( this.mousemoveTicket ){
3057 this.mousemoveTicket.destroy();
3058 delete this.mousemoveTicket;
3060 if( this.mouseupTicket ){
3061 this.mouseupTicket.destroy();
3062 delete this.mouseupTicket;
3064 if( this.mouseoutTicket ){
3065 this.mouseoutTicket.destroy();
3066 delete this.mouseoutTicket;
3069 destroy : function( _element, _eventType, _handler ){
3070 if( this.match( _element, _eventType, _handler ) === false ) return false;
3072 this.removeEvents();
3073 this.mousedownTicket.destroy();
3075 delete this.element;
3076 delete this.handler;
3077 delete this.thisObject;
3078 delete this.mousedownTicket;
3082 if( document.createEvent ){
3083 DragEventTicketClass.createEvent = function( e, offsetX, offsetY, dragPhase ){
3084 var _e = document.createEvent( 'MouseEvents' );
3086 DragEventTicketClass.prototype.eventType , false, true, e.view,
3087 e.detail, e.screenX, e.screenY, e.clientX, e.clientY,
3088 e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
3089 e.button, e.relatedTarget
3091 _e.dragPhase = dragPhase;
3092 _e.dragOffsetX = offsetX;
3093 _e.dragOffsetY = offsetY;
3097 if( document.attachEvent ){
3098 DragEventTicketClass.createEvent = function( e, offsetX, offsetY, dragPhase ){
3099 e.type = DragEventTicketClass.prototype.eventType;
3100 e.dragPhase = dragPhase;
3101 e.dragOffsetX = offsetX;
3102 e.dragOffsetY = offsetY;
3111 add: function( _apiuser, _element, _eventType, _handler, opt_thisObject ){
3112 if( isApiUser( _apiuser ) === true &&
3113 ( Type.isHTMLElement( _element ) === true || _element === window || _element === document ) &&
3114 Type.isString( _eventType ) === true &&
3115 Type.isFunction( _handler ) === true
3117 var _uid = _apiuser.getUID(),
3118 _events = EVENT_LIST_MAP[ _uid ];
3119 if( Type.isArray( _events ) === false ){
3120 _events = EVENT_LIST_MAP[ _uid ] = [];
3123 for( var i=0, l=_events.length; i<l; ++i ){
3124 if( _events[ i ].match( _element, _eventType, _handler ) === true ) return;
3127 switch( _eventType ){
3129 _events.push( new ClickEventTicketClass( _element, _handler, opt_thisObject ) );
3132 _events.push( new WheelEventTicketClass( _element, _handler, opt_thisObject ) );
3135 _events.push( new DragEventTicketClass( _element, _handler, opt_thisObject ) );
3138 _events.push( new EventTicketClass( _element, _eventType, _handler, opt_thisObject ) );
3142 remove: function( apiuser, element, eventType, handler ){
3143 if( isApiUser( apiuser ) === true ){
3144 var uid = apiuser.getUID(),
3145 list = EVENT_LIST_MAP[ uid ],
3147 if( Type.isArray( list ) === false ) return;
3148 for( ;i < list.length; ){
3149 if( list[ i ].destroy( element, eventType, handler ) === true ){
3150 list.splice( i, 1 );
3155 if( list.length === 0 ){
3156 EVENT_LIST_MAP[ uid ] = null;
3160 onCurrentApplicationChange: function(){
3163 onApplicationShutdown: function(){
3166 onSystemShutdown: function(){
3172 /* ----------------------------------------
3175 * - EDITABLE_TEXT_CONTROL
3177 * .SHIFT_DOWN_EVENT: 'shiftDown',
3178 * .SHIFT_UP_EVENT: 'shiftUp',
3179 * .CTRL_DOWN_EVENT: 'ctrlDown',
3180 * .CTRL_UP_EVENT: 'ctrlUp',
3181 * .SPACE_DOWN_EVENT: 'spaceDown',
3182 * .SPACE_UP_EVENT: 'spaceUp',
3184 * .addKeyDownEvent: function,
3185 * .keyEventDispatcher: function,
3187 * ショートカットキーの監視とテキスト入力(input, textarea)、チェックボックスを管理する。
3188 * キー入力はdocumentで受けて、テキスト編集中(input, textarea)はそちらにキーイベント流す。
3191 var KeyEvent = ( function(){
3192 var EVENT_LIST_MAP = [],
3200 var focusTicket = null,
3201 keydownTicket = null,
3204 keypressTicket = null;
3206 function unlock( lock, key ){
3207 lock.splice( Util.getIndex( lock, key ), 1 );
3210 function onKeyChange( e ){
3213 key = e.keyCode, // || e.which,
3214 shift = Type.isBoolean( e.shiftKey ) === true ? e.shiftKey : ( e.modifiers & Event.SHIFT_MASK ),
3215 ctrl = Type.isBoolean( e.ctrlKey ) === true ? e.ctrlKey : ( e.modifiers & Event.CONTROL_MASK ),
3216 lock = type === 'keyup' ? LOCK_UP : LOCK_DOWN,
3220 if( Util.getIndex( lock, key ) !== -1 ) return;
3222 AsyncCall.add( SUPER_USER_KEY, unlock, [ lock, key ] );
3224 if( key === 16 || shift === true ){
3225 KeyEvent.shiftEnabled = type !== 'keyup';
3227 if( key === 17 || ctrl === true ){
3228 KeyEvent.ctrlEnabled = type !== 'keyup';
3230 for( i = currentList.length; i; ){
3231 t = currentList[ --i ];
3232 if( Type.isFunction( t[ type ] ) === true && t.keyCode === key && ( t.shift === undefined || t.shift === shift ) && ( t.ctrl === undefined || t.ctrl === ctrl )){
3233 if( t[ type ].call( t.apiuser, e ) === false ){
3239 if( cancel === true || key === 18 || key === 9 || key === 27 || e.altKey === true ){ // 13.enter 18.esc 9.tab 27.esc || ( key === 13 && overlayEnabled === false)
3244 if( UA.isIE === true && UA.ieRenderingVersion < 9 ){
3245 keyPress = function( e ){
3246 var key = e.keyCode;
3247 if( key === 13 || key === 27 ){
3249 return onKeyChange( e );
3254 var KeyEventTicketClass = function( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ){
3255 this.apiuser = _apiuser;
3257 this.keydown = _onKeydown;
3258 this.keyup = _onKeyup;
3259 this.keyCode = _keyCode;
3260 this.shift = _shift;
3262 _apiuser = _onKeydown = _onKeyup = null;
3264 KeyEventTicketClass.prototype = {
3265 match: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3266 if( _apiuser && _apiuser !== this.apiuser ) return false;
3267 if( _type && _type !== this.type ) return false;
3269 if( this.type === 'keydown' ){
3270 if( _handler !== this.keydown ) return false;
3272 if( _handler !== this.keyup ) return false;
3275 if( _keyCode && _keyCode !== this.keyCode ) return false;
3276 if( _shift && _shift !== this.shift ) return false;
3277 if( _ctrl && _ctrl !== this.ctrl ) return false;
3280 destroy: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3281 if( this.match( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ) === false ) return false;
3283 delete this.apiuser;
3284 delete this.keydown;
3291 function registerEvent( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ){
3292 var _uid = _apiuser.getUID(),
3293 _list = EVENT_LIST_MAP[ _uid ];
3294 if( Type.isArray( _list ) === false ){
3295 _list = EVENT_LIST_MAP[ _uid ] = [];
3297 for( var i=0, l=_list.length; i<l; ++i ){
3298 if( _list[ i ].match( _apiuser, _type, _onKeydown || _onKeyup, _keyCode, _shift, _ctrl ) === true ) return;
3300 _list.push( new KeyEventTicketClass( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ));
3302 if( _apiuser === application ) KeyEvent.updateCurrentListener( _apiuser );
3306 add: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3307 if( _type === 'keydown' ){
3308 registerEvent( _apiuser, _type, _handler, null, _keyCode, _shift, _ctrl );
3310 if( _type === 'keyup' ){
3311 registerEvent( _apiuser, _type, null, _handler, _keyCode, _shift, _ctrl );
3313 if( _type === 'keychange' ){
3314 registerEvent( _apiuser, _type, _handler, _handler, _keyCode, _shift, _ctrl );
3316 if( _type === 'cursol' ){
3320 remove: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
3321 var _list = EVENT_LIST_MAP[ _apiuser.getUID() ],
3323 if( Type.isArray( _list ) === true ){
3324 while( i < _list.length ){
3325 if( _list[ i ].destroy( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ) === true ){
3326 _list.splice( i, 1 );
3332 if( _apiuser === application ) KeyEvent.updateCurrentListener( _apiuser );
3334 shiftEnabled: false,
3338 * currrentApplication ( overlay Application ) or
3341 updateCurrentListener: function( _apiuser ){
3342 application = _apiuser;
3343 var _uid = _apiuser.getUID();
3344 currentList = EVENT_LIST_MAP[ _uid ] || ( EVENT_LIST_MAP[ _uid ] = [] );
3349 for( var i=currentList.length; _ticket = currentList[ --i ]; ){
3350 if( _down === false ) _down = !!_ticket.keydown;
3351 if( _up === false ) _up = !!_ticket.keyup;
3352 if( _down && _up ) break;
3354 if( _down === true ){
3355 keydownTicket = new EventTicketClass( document, 'keydown', onKeyChange );
3356 keypressTicket = keyPress !== null ? new EventTicketClass( document, 'keypress', keyPress ) : null;
3358 keydownTicket && keydownTicket.destroy();
3359 keypressTicket && keypressTicket.destroy();
3360 keydownTicket = keypressTicket = null;
3363 keyupTicket = new EventTicketClass( document, 'keyup', onKeyChange );
3365 keyupTicket && keyupTicket.destroy();
3369 if( _down === true || _up === true ){
3370 focusTicket = new EventTicketClass( document, 'mouseenter', window.focus );
3372 focusTicket && focusTicket.destroy();
3376 onApplicationShutdown: function( _apiuser ){
3377 KeyEvent.remove( _apiuser );
3379 onSystemShutdown: function(){
3387 * http://thudjs.tumblr.com/post/637855087/stylesheet-onload-or-lack-thereof
3390 var StyleSheet = ( function(){
3391 var head = document.getElementsByTagName( 'head' )[ 0 ];
3393 var TICKET_LIST = [];
3394 var STATE_LIST = 'loaded,complete,uninitialized'.split( ',' );
3396 var cssRules, sheet;
3398 var FetchCssTicketClass = function( _apiuser, _url, _elm, _onload, _onerror, opt_thisObject ){
3399 this.apiusers = [ _apiuser ];
3402 this.onload = [ _onload ];
3403 this.onerror = [ _onerror ];
3404 this.thisObj = [ opt_thisObject ];
3407 FetchCssTicketClass.prototype = {
3408 match: function( _apiuser, _url ){
3409 if( _apiuser && Util.getIndex( this.apiusers, _apiuser ) === -1 ) return false;
3410 if( _url && _url !== this.url ) return false;
3413 destroy: function( _apiuser, _url ){
3414 if( this.match( _apiuser, _url ) === false ) return false;
3416 var i = Util.getIndex( this.apiusers, _apiuser );
3418 this.apiusers.splice( i, 1 );
3419 this.onload.splice( i, 1 );
3420 this.onerror.splice( i, 1 );
3421 this.thisObj.splice( i, 1 );
3423 if( this.apiusers.length !== 0 ) return false;
3425 head.removeChild( this.elm );
3426 this.elm.onreadystatechange = new Function();
3427 this.elm.onload = null;
3429 delete this.apiusers;
3433 delete this.onerror;
3434 delete this.thisObj;
3440 for( var i = this.onload.length, f; i; ){
3441 f = this.onload[ --i ];
3442 Type.isFunction( f ) === true && AsyncCall.add( this.apiusers[ i ], f, this.url, this.thisObj[ i ] || this.apiusers[ i ] );
3443 this.onload[ i ] = this.onerror[ i ] = null;
3447 for( var i = this.onerror.length, f; i; ){
3448 f = this.onerror[ --i ];
3449 Type.isFunction( f ) === true && AsyncCall.add( this.apiusers[ i ], f, this.url, this.thisObj[ i ] || this.apiusers[ i ] );
3450 this.onload[ i ] = this.onerror[ i ] = null;
3456 return el[ sheet ] && el[ sheet ][ cssRules ].length > 0;
3464 function getTicket( elm ){
3465 for( var i = TICKET_LIST.length, t; i; ){
3466 t = TICKET_LIST[ --i ];
3467 if( t.elm === elm ) return t;
3472 var t = getTicket( this ), rs = this.readyState, c;
3473 if( t && t.done === false && ( !rs || Util.getIndex( STATE_LIST, rs ) !== -1 ) ){
3476 this.onreadystatechange = new Function();
3481 function checkTimer(){
3482 var l = TICKET_LIST.length,
3484 for( var i = 0; i < l; ++i ){
3485 t = TICKET_LIST[ i ];
3487 if( t.check() === true ){
3497 l === n && SystemTimer.remove( SUPER_USER_KEY, checkTimer );
3501 load: function( _apiuser, _url, opt_onload, opt_onerror, opt_thisObject ){
3502 _url = Util.getAbsolutePath( _url );
3504 for( var i=TICKET_LIST.length; i; ){
3505 t = TICKET_LIST[ --i ];
3506 if( t.match( null, _url ) === true ){
3507 if( t.match( _apiuser, _url ) === false ){
3508 t.apiusers.push( _apiuser );
3509 t.onload.push( opt_onload );
3510 t.onerror.push( opt_onerror );
3511 t.thisObj.push( opt_thisObject );
3513 SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 );
3517 var elm = document.createElement( 'link' );
3518 head.appendChild( elm );
3519 elm.rel = 'stylesheet';
3520 elm.type = 'text\/css';
3521 elm.onreadystatechange = elm.onload = detect;
3524 if( !sheet ){ // only assign these once
3525 cssRules = 'cssRules';
3527 if ( !( sheet in elm ) ) { // MSIE uses non-standard property names
3529 sheet = 'styleSheet';
3533 TICKET_LIST.push( new FetchCssTicketClass( _apiuser, _url, elm, opt_onload, opt_onerror, opt_thisObject ) );
3535 SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 );
3537 unload: function( _apiuser, _url ){
3538 _url = _url ? Util.getAbsolutePath( _url ) : null;
3539 for( var i = 0; i < TICKET_LIST.length; ){
3540 t = TICKET_LIST[ i ];
3541 if( t.destroy( _apiuser, _url ) === true ){
3542 TICKET_LIST.splice( i, 1 );
3547 if( TICKET_LIST.length === 0 ){
3548 SystemTimer.remove( SUPER_USER_KEY, checkTimer );
3564 var Image = ( function(){
3567 * FetchClass original is
3570 * URL: http://d.hatena.ne.jp/uupaa/20080413/1208067631
3571 * AUTHOR: uupaa.js@gmail.com
3575 for( var i=0, t; i < TASK_LIST.length; ){
3577 if( t.complete() === true ){
3578 TASK_LIST.splice( i, 1 );
3583 TASK_LIST.length === 0 && SystemTimer.remove( SUPER_USER_KEY, detect );
3585 function getTask( img ){
3586 for( var i = TASK_LIST.length; i; ){
3587 if( TASK_LIST[ --i ].img === img ) return TASK_LIST[ i ];
3591 var task = getTask( this );
3592 if( task.finish === true ) return;
3594 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
3597 // if( finish === true ) return; // これがあると firefox3.6 で駄目、、、
3598 // if( timer ) return; // これがあると safari3.2 で駄目、、、
3599 var task = getTask( this );
3601 TASK_LIST.splice( Util.getIndex( TASK_LIST, task ), 1 );
3602 if( window.opera && !task.img.complete ){
3603 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
3606 task.size = Util.getImageSize( this );
3607 AsyncCall.add( task.apiuser, task.asyncCallback, null, task );
3611 var FetchClass = function( apiuser, abspath, onLoadCallback, onErrorCallback, timeout ){
3612 this.apiuser = apiuser;
3613 this.abspath = abspath;
3614 this.onLoadCallback = onLoadCallback;
3615 this.onErrorCallback = onErrorCallback;
3616 this.timeout = timeout;
3619 FetchClass.prototype = {
3625 var img = this.img = document.createElement( 'img' ); //var img = new Image(); ではieでimgのsizeが取れない、、、removeChildも失敗し、imgSizeGetterにimgが残る
3626 img.onabort = img.onerror = onError;
3627 img.onload = onLoad;
3628 img.src = this.abspath;
3630 complete: function(){
3631 if( this.finish === true ) return true;
3632 if( this.img.complete ){
3634 if( this.img.width ) return true;
3635 AsyncCall.add( this.apiuser, this.asyncCallback, null, this );
3638 if( ( this.tick += 250 ) > this.timeout ){
3640 AsyncCall.add( this.apiuser, this.asyncCallback, null, this );
3644 asyncCallback: function(){
3645 this.size ? this.onLoadCallback( this.abspath, this.size.width, this.size.height ) : this.onErrorCallback( this.abspath );
3648 destroy: function(){
3650 this.img.src = this.img.onload = this.img.onabort = this.img.onerror = '';
3653 delete this.onLoadCallback;
3654 delete this.onErrorCallback;
3657 timer !== null && window.clearTimeout( timer );
3663 load: function( URLorELM, onLoad, onError, opt_timeout ){
3665 if( Type.isString( URLorELM ) === true ){
3668 if( Type.isHTMLElement( URLorELM ) === true && URLorELM.tagName.toLowerCase() === 'img' ){
3674 fetch = new FetchClass(
3675 Util.getAbsolutePath( src ),
3677 Type.isFinite( opt_timeout ) === true ? opt_timeout : undefined
3679 TASK_LIST.push( fetch );
3681 SystemTimer.add( SUPER_USER_KEY, detect, 250 );
3683 unload: function( ){
3690 /* ----------------------------------------
3694 var Overlay = ( function(){
3695 var elmContainer, elmShadow, elmCloseButton,
3701 function onCloseClick( e ){
3705 function asyncInit( /* arguments */ ){
3707 elmContainer.insertBefore( application.rootElement, elmCloseButton );
3708 application.rootElement.style.display = 'none';
3710 function asyncOpen( /* arguments */ ){
3711 var _arg = Util.copyArray( arguments );
3712 _arg.unshift( windowW, windowH );
3713 application.open.apply( application, _arg );
3715 elmContainer.style.cssText = "top:" + body.scrollTop + 'px;display:none;';
3716 $( elmContainer ).stop().fadeIn( onFadeInComplete );
3718 function onFadeInComplete(){
3719 KeyEvent.add( application, Const.KEY.EVENT.KEY_DOWN, Overlay.hide, 27 ); // 27.esc
3720 MouseEvent.add( application, elmCloseButton, 'click', onCloseClick );
3722 function onFadeOutComplete(){
3723 Util.removeAllChildren( elmContainer );
3724 body.removeChild( elmContainer );
3725 elmContainer = elmShadow = elmCloseButton = null;
3728 show: function( _application, _bootParams ){
3729 if( visible === true && application === _application ) return;
3730 if( Application.isApplicationInstance( _application ) === false ) return;
3732 elmContainer = document.createElement( 'div' );
3733 body.appendChild( elmContainer );
3735 elmContainer.id = 'overlay-container';
3737 bodyOverflow = body.style.overflow;
3738 body.style.overflow = 'hidden';
3740 elmShadow = document.createElement( 'div' );
3741 elmContainer.appendChild( elmShadow );
3742 elmShadow.id = 'overlay-shadow';
3744 elmCloseButton = document.createElement( 'div' );
3745 elmContainer.appendChild( elmCloseButton );
3746 elmCloseButton.id = 'overlay-close-button';
3747 elmCloseButton.appendChild( document.createTextNode( 'x' ) );
3749 elmContainer.style.display = 'none'; // hide for fadeIn
3752 application = _application;
3756 _application.addAsyncCall( asyncInit );
3757 _application.addAsyncCall( asyncOpen, _bootParams );
3760 if( visible === false ) return;
3761 if( application.close() === false ) return false;
3763 body.style.overflow = bodyOverflow;
3765 $( elmContainer ).stop().css( {
3768 }).fadeOut( onFadeOutComplete );
3773 onWindowResize: function( _windowW, _windowH ){
3777 if( application === null ) return;
3779 elmContainer.style.height = _windowH + 'px';
3780 elmContainer.style.top = body.scrollTop + 'px';
3782 elmShadow.style.height = _windowH + 'px';
3784 AsyncCall.add( application, application.resize, [ _windowW, _windowH ] );
3789 /* ----------------------------------------
3793 * form -> overlay -> view
3797 var UI = ( function(){
3806 var CLASSNAME_COMBOBOX_OPTION = 'combobox-option',
3807 CLASSNAME_COMBOBOX_OPTION_CURRENT = CLASSNAME_COMBOBOX_OPTION + ' combobox-option-current',
3808 ELM_COMBOBOX = ( function(){
3809 var ret = document.createElement( 'a' ),
3810 elmToggle = document.createElement( 'span' ),
3811 elmValue = document.createElement( 'span' );
3813 ret.appendChild( elmToggle );
3814 ret.appendChild( elmValue );
3815 elmToggle.className = 'combobox-toggle';
3816 elmValue.className = 'combobox-value';
3818 elmToggle.appendChild( document.createTextNode( '▼' ));
3819 elmValue.appendChild( document.createTextNode( 'null' ));
3823 var UIItemPrivateData = function(){};
3824 UIItemPrivateData.prototype = {
3842 init : function( groupData, item, elm, value, onUpdate, validator, focus, visible, enabled ){
3843 this.groupData = groupData;
3847 this.onUpdate = onUpdate;
3848 this.validator = validator;
3849 this.focus = !!focus;
3850 this.visible = !!visible;
3851 this.enabled = !!enabled;
3852 UIItemPrivateData.list.push( this );
3854 destroy : function(){
3855 var list = UIItemPrivateData.list;
3856 list.splice( Util.getIndex( list, this ), 1 );
3858 this.node && this.node.remove();
3861 UIItemPrivateData.list = [];
3862 UIItemPrivateData.get = function( item ){
3863 var list = UIItemPrivateData.list;
3864 for( i = list.length; i; ){
3865 if( list[ --i ].item === item ) return list[ i ];
3870 /* --------------------------------
3873 var TextInputManager = ( function(){
3874 var elmInput = ( function(){
3875 var ret = document.createElement( 'input' );
3877 ret.id = 'ui-textinput';
3882 function updateWrapperPosition(){
3883 var p = Position.cumulativeOffset( currentData.elmValue ),
3884 w = currentData.elmValue.offsetWidth - 2,
3886 elmInput.style.cssText = [
3887 'left:', p[ 0 ], 'px;',
3888 'top:', p[ 1 ], 'px;',//,
3889 'width:', w, 'px;'//,
3890 //'height:', data.elmValue.offsetHeight, 'px;',
3891 //'position:absolute;'
3894 //_w = elmInput.offsetWidth;
3895 //if( w !== _w ) elmInput.style.width = ( w - ( _w - w ) ) + 'px;';
3899 show: function( data ){
3900 // this.groupData.node.addEventListener( 'mouseout' );
3903 body.appendChild( elmInput );
3904 elmInput.value = data.value;
3905 updateWrapperPosition();
3910 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
3912 hide : function( data ){
3913 if( currentData !== data ) return;
3915 body.removeChild( elmInput );
3916 var ret = elmInput.value;
3917 elmInput.value = '';
3918 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition );
3921 update : function( data ){
3922 elmInput.value = data.value;
3924 onWindowResize: function( _w, _h ){
3925 AsyncCall.add( currentData.apiuser, updateWrapperPosition );
3930 var TextInputClass = function( groupData, elmWrapper, elmValue, onUpdate, validater ){
3931 var data = new UIItemPrivateData();
3932 data.init( groupData, this, elmWrapper, elmValue.innerHTML, onUpdate, validater, false, true, true );
3933 Util.addClass( elmValue, 'editable-text' );
3934 data.elmValue = elmValue;
3935 this.value( data.value );
3936 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-inpittext-hover', 'pointer' );
3937 data.node.addEventListener( 'click', this.focus, this );
3938 //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', instance.focus );
3940 TextInputClass.prototype = {
3941 value : function( value ){
3942 var data = UIItemPrivateData.get( this );
3943 if( Type.isString( value ) === true || Type.isNumber( value ) === true ){
3944 data.elmValue.innerHTML = data.value = '' + value;
3945 data.focus === true && TextInputManager.update( data );
3947 data.focus === true && this.blur();
3950 focus : function( e ){
3951 var data = UIItemPrivateData.get( this );
3954 TextInputManager.show( data );
3957 blur : function( keep ){
3958 var data = UIItemPrivateData.get( this ),
3960 if( data.focus === false ) return;
3961 newValue = TextInputManager.hide( data );
3962 newValue = keep !== 27 ? ( data.validater ? '' + data.validater( newValue ) : newValue ) : data.value; // 27:ESC
3964 data.elmValue.innerHTML = newValue;
3966 data.onUpdate && newValue !== data.value && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ newValue, data.value ], this );
3968 data.value = newValue;
3972 enabled : function( v ){
3973 var data = UIItemPrivateData.get( this );
3974 if( Type.isBoolean( v ) === true && data.enabled !== v ){
3975 Util.toggleClass( data.elm, 'ui-textinput-disabled', !v );
3976 if( data.focus === true && v === false ) this.blur();
3978 data.node.disabled( !( data.visible && v ) );
3980 return data.enabled;
3982 visible : function( v ){
3983 var data = UIItemPrivateData.get( this );
3984 if( Type.isBoolean( v ) === true && data.visible !== v ){
3985 data.elm.style.display = v ? '' : 'none';
3986 if( data.focus === true && v === false ) this.blur();
3988 data.node.disabled( !( data.enabled && v ) );
3990 return data.visible;
3992 destroy : function(){
3993 var data = UIItemPrivateData.get( this );
3994 data.focus === true && TextInputManager.hide( data );
3999 /* --------------------------------
4002 var FileInputManager = ( function(){
4007 function updateWrapperPosition(){
4008 var p = Position.cumulativeOffset( currentData.elmValue ),
4009 w = currentData.elmValue.offsetWidth - 2,
4011 elmInput.style.cssText = [
4012 'left:', p[ 0 ], 'px;',
4013 'top:', p[ 1 ], 'px;',//,
4014 'width:', w, 'px;'//,
4015 //'height:', data.elmValue.offsetHeight, 'px;',
4016 //'position:absolute;'
4019 _w = elmInput.offsetWidth;
4020 if( w !== _w ) elmInput.style.width = ( w - ( _w - w ) ) + 'px;';
4023 function change( e ){
4024 var data = currentData,
4025 file = data.elmFileInputReal.value;
4026 if( data.value !== file ){
4027 data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ file, data.value ], this );
4028 data.elmValue.innerHTML = data.value = value;
4034 show : function( data ){
4036 updateWrapperPosition();
4038 elmInput = data.elmFileInputReal;
4040 data.node.addEventListener( 'change', change, data );
4042 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4044 hide : function( data ){
4045 if( currentData !== data ) return;
4046 data.node.removeEventListener( 'change', change );
4048 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition );
4050 onWindowResize: function( _w, _h ){
4051 AsyncCall.add( currentData.apiuser, updateWrapperPosition );
4056 var FileInputClass = function( groupData, elmWrapper, onUpdate, elmFileInputReal, elmValue ){
4057 var data = new UIItemPrivateData();
4058 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4059 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-fileinput-hover', 'pointer' );
4060 data.elmValue = elmValue;
4061 data.elmFileInputReal = elmFileInputReal;
4062 data.node.addEventListener( 'mouseover', this.focus, this );
4064 FileInputClass.prototype = {
4069 var data = UIItemPrivateData.get( this );
4071 Util.addClass( data.elm, 'fileinput-has-focus' );
4073 FileInputManager.show( data );
4075 blur : function( keyCode ){
4076 var data = UIItemPrivateData.get( this );
4077 Util.removeClass( data.elm, 'fileinput-has-focus' );
4079 FileInputManager.hide( data );
4082 enabled : function( v ){
4083 var data = UIItemPrivateData.get( this );
4084 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4085 if( data.focus === true && v === false ) this.blur();
4086 Util.toggleClass( data.elm, 'fileinput-disabled', !v );
4088 data.node.disabled( !( data.visible && v ) );
4090 return data.enabled;
4092 visible : function( v ){
4093 var data = UIItemPrivateData.get( this );
4094 if( Type.isBoolean( v ) === true && data.visible !== v ){
4095 if( data.focus === true && v === false ) this.blur();
4096 data.elm.style.display = v ? '' : 'none';
4098 data.node.disabled( !( data.enabled && v ) );
4100 return data.visible;
4102 destroy : function(){
4103 var data = UIItemPrivateData.get( this );
4104 data.focus === true && FileInputManager.hide( data );
4109 var ButtonClass = function( groupData, elmWrapper, onUpdate ){
4110 var data = new UIItemPrivateData();
4111 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4112 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-button-hover', 'pointer' );
4113 data.node.addEventListener( 'click', onUpdate );
4114 //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', onUpdate );
4116 ButtonClass.prototype = {
4118 var data = UIItemPrivateData.get( this );
4120 Util.addClass( data.elm, 'button-has-focus' );
4123 blur : function( keyCode ){
4124 var data = UIItemPrivateData.get( this );
4125 keyCode === 13 && data.onUpdate && data.onUpdate();
4126 Util.removeClass( data.elm, 'button-has-focus' );
4130 enabled : function( v ){
4131 var data = UIItemPrivateData.get( this );
4132 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4133 Util.toggleClass( data.elm, 'button-disabled', !v );
4135 data.node.disabled( !( data.visible && v ) );
4137 return data.enabled;
4139 visible : function( v ){
4140 var data = UIItemPrivateData.get( this );
4141 if( Type.isBoolean( v ) === true && data.visible !== v ){
4142 data.elm.style.display = v ? '' : 'none';
4144 data.node.disabled( !( data.enabled && v ) );
4146 return data.visible;
4148 destroy : function(){
4149 var data = UIItemPrivateData.get( this );
4150 // MouseEvent.remove( data.groupData.apiuser, data.elm );
4155 var ComboBoxClass = function( groupData, elmWrapper, onUpdate ){
4156 var elmA = ELM_COMBOBOX.cloneNode( true ),
4157 data = new UIItemPrivateData();
4158 data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true );
4160 data.elmBox = Util.getElementsByClassName( elmWrapper, 'combobox' )[ 0 ];
4161 data.elmBox.appendChild( elmA );
4163 data.elmToggle = Util.getElementsByClassName( elmA, 'combobox-toggle' )[ 0 ];
4164 data.elmValue = Util.getElementsByClassName( elmA, 'combobox-value' )[ 0 ].firstChild;
4165 data.selectIndex = 0;
4166 data.optionList = [];
4168 data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-combobox-hover', 'pointer' );
4169 data.node.addEventListener( 'click', this.focus, this );
4171 ComboBoxClass.prototype = {
4172 focus : function( e ){
4173 var data = UIItemPrivateData.get( this );
4174 data.node.removeEventListener( 'click', this.focus );
4176 data.elmA.className = 'combobox-has-focus';
4178 OptionControl.show( data );
4181 blur : function( keyCode ){
4182 var data = UIItemPrivateData.get( this );
4183 OptionControl.hide( this );
4185 data.elmA.className = '';
4187 data.node.addEventListener( 'click', this.focus, this );
4189 enabled : function( v ){
4190 var data = UIItemPrivateData.get( this );
4191 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4192 Util.toggleClass( data.elm, 'ui-combobox-disabled', !v );
4193 if( data.focus === true && v === false ) this.blur();
4195 data.node.disabled( !( data.visible && v ) );
4197 return data.enabled;
4199 visible : function( v ){
4200 var data = UIItemPrivateData.get( this );
4201 if( Type.isBoolean( v ) === true && data.visible !== v ){
4202 data.elm.style.display = v ? '' : 'none';
4203 if( data.focus === true && v === false ) this.blur();
4205 data.node.disabled( !( data.enabled && v ) );
4207 return data.visible;
4209 value : function( _value ){
4210 var data = UIItemPrivateData.get( this ),
4212 list = data.optionList,
4215 if( Type.isString( _value ) === true && data.value !== _value ){
4216 for( ; i < l; ++i ){
4217 _option = list[ i ];
4218 if( _value === _option.value ){
4219 data.value = _value;
4221 data.elmValue.data = _option.displayValue;
4222 if( data.focus === true ){
4223 OptionControl.update( this, _value );
4225 data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, _value, this );
4232 selectIndex : function(){
4233 var data = UIItemPrivateData.get( this );
4234 return data.selectIndex;
4236 createOption : function( _displayValue, _value, _isSelected ){
4237 var data = UIItemPrivateData.get( this ),
4239 list = data.optionList,
4242 _value = _value || _displayValue;
4243 _isSelected = !!_isSelected;
4245 _option = list[ --i ];
4246 if( _value === _option.value ){
4251 if( _isSelected === true ){
4252 data.selectIndex = list.length;
4253 data.elmValue.data = _displayValue;
4255 option === null && list.push( new OptionDataClass( _displayValue, _value, _isSelected ) );
4257 destroy : function(){
4258 var data = UIItemPrivateData.get( this );
4259 data.focus === true && OptionControl.hide( this );
4261 // MouseEvent.remove( data.groupData.apiuser, data.elm );
4262 data.optionList.length = 0;
4266 var OptionDataClass = function( displayValue, value, isCurrent ){
4267 this.displayValue = displayValue;
4268 this.value = value || displayValue;
4269 this.current = isCurrent;
4270 displayValue = value = null;
4273 var OptionControl = ( function(){
4274 var ELM_OPTION_WRAPPER = ( function(){
4275 var ret = document.createElement( 'div' );
4276 ret.className = 'option-container';
4279 ELM_OPTION_ORIGIN = ( function(){
4280 var ret = document.createElement( 'a' );
4281 ret.appendChild( document.createTextNode( 'option' ) );
4286 var OptionClass = function( option ){
4287 this.elm = ELM_OPTION_ORIGIN.cloneNode( true );
4291 OptionClass.prototype = {
4293 ELM_OPTION_WRAPPER.appendChild( this.elm );
4294 this.elm.firstChild.data = this.data.displayValue;
4295 this.current( this.data.current );
4296 MouseEvent.add( SUPER_USER_KEY, this.elm, 'mousedown', onOptionSelect );// onclick では 選択ボックス 隠すように body に設定した onmouseup が先に動いてしまう!
4298 current: function( _current ){
4299 this.elm.className = _current === true ? CLASSNAME_COMBOBOX_OPTION_CURRENT : CLASSNAME_COMBOBOX_OPTION;
4300 this.data.current = _current;
4301 currentOption = _current === true ? this : currentOption;
4303 destroy: function(){
4304 MouseEvent.remove( SUPER_USER_KEY, this.elm );
4305 Util.removeAllChildren( this.elm );
4306 ELM_OPTION_WRAPPER.removeChild( this.elm );
4312 function onOptionSelect( e ){
4314 l = OPTION_LIST.length,
4316 for( ; i < l; ++i ){
4317 _option = OPTION_LIST[ i ];
4318 if( this === _option.elm ){
4319 updateCurrrentOption( _option.data.value, true );
4320 currentCombobox.blur();
4327 var OPTION_LIST = [],
4328 currentCombobox = null,
4334 function updateCurrrentOption( _value, _updateCombobox ){
4336 i = OPTION_LIST.length;
4338 _option = OPTION_LIST[ --i ];
4339 if( _value === _option.data.value ){
4340 currentOption && currentOption.current( false );
4341 _option.current( true );
4342 currentOption = _option;
4344 _updateCombobox === true && currentCombobox.value( _value );
4349 function bodyMouseupHandler(){
4350 currentCombobox.blur();
4351 OptionControl.hide( currentCombobox );
4353 function updateWrapperPosition(){
4354 var position = Util.getAbsolutePosition( elm );
4356 ELM_OPTION_WRAPPER.style.cssText = [
4357 'width:', elm.offsetWidth - 2, 'px;',
4358 'left:', position.x, 'px;',
4359 'top:', position.y + elm.offsetHeight, 'px;'
4362 function change( e ){
4363 var l = OPTION_LIST.length,
4364 i = currentIndex + ( e.keyCode === 40 ? -1 : 1 );
4365 if( currentCombobox === null || l < 2 ) return;
4369 updateCurrrentOption( OPTION_LIST[ i ].data.value, true );
4373 show: function( data ){
4374 var combobox = data.item,
4375 list = data.optionList,
4378 if( currentItem !== combobox || currentCombobox === combobox ) return;
4379 currentCombobox && currentCombobox.blur();
4381 apiuser = data.groupData.apiuser;
4382 currentCombobox = combobox;
4385 for( ; i < l; ++i ){
4386 OPTION_LIST.unshift( new OptionClass( list[ i ] ) );
4388 MouseEvent.add( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler );
4389 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 38 );
4390 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 40 );
4391 //KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter, 13 );
4392 //KeyEvent.updateCurrentListener( SUPER_USER_KEY );
4394 body.appendChild( ELM_OPTION_WRAPPER );
4396 updateCurrrentOption( combobox.value(), false );
4397 updateWrapperPosition();
4399 SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 );
4401 hide: function( _combobox ){
4402 if( currentCombobox !== _combobox || currentCombobox === null ) return;
4405 while( _option = OPTION_LIST.shift() ){
4409 body.removeChild( ELM_OPTION_WRAPPER );
4411 MouseEvent.remove( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler );
4412 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change );
4413 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change );
4414 //KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter );
4415 //KeyEvent.updateCurrentListener( apiuser );
4417 SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition, 500 );
4420 currentCombobox = null;
4421 currentOption = null;
4424 onEnter: function(){
4425 currentCombobox.value( currentOption.data.value );
4426 //currentCombobox.blur();
4427 //OptionControl.hide( currentCombobox );
4429 update: function( data, _value ){
4430 if( currentCombobox !== data.item || currentItem !== data.item ) return;
4431 if( currentOption.data.value === _value ) return;
4432 updateCurrrentOption( _value, true );
4434 onWindowResize: function( _w, _h ){
4435 currentCombobox && AsyncCall.add( apiuser, updateWrapperPosition );
4440 var UIGroupPrivateData = function(){};
4441 UIGroupPrivateData.prototype = {
4448 init : function( apiuser, node, uigroup ){
4449 this.apiuser = apiuser;
4451 this.uigroup = uigroup;
4453 UIGroupPrivateData.list.push( this );
4455 destroy : function(){
4459 UIGroupPrivateData.list = [];
4460 UIGroupPrivateData.get = function( uigroup ){
4461 var list = UIGroupPrivateData.list,
4464 if( list[ --i ].uigroup === uigroup ) return list[ i ];
4469 var UIGroupClass = function( apiuser, node ){
4470 ( new UIGroupPrivateData() ).init( apiuser, node, this );
4472 UIGroupClass.prototype = {
4473 focus : function( _value ){
4474 var data = UIGroupPrivateData.get( this );
4476 if( _value === true ){
4478 start( apiuser, self, currentItem );
4480 if( itemList.length > 0 ){
4481 start( apiuser, self, itemList[ 0 ] );
4484 if( _value === false ){
4485 finish( apiuser, self, currentItem );
4488 if( _value && Util.getIndex( data.itemList, _value ) !== -1 ){
4489 // currentItem = _value;
4490 currentList = data.itemList;
4492 return currentUi === this;
4495 var data = UIGroupPrivateData.get( this );
4496 if( currentList === data.itemList ){
4500 createInputText : function( elmWrapper, onUpdate, validater ){
4501 var data = UIGroupPrivateData.get( this ),
4502 elmValue = Util.getElementsByClassName( elmWrapper, 'editable-value' )[ 0 ],
4505 ret = new TextInputClass( data, elmWrapper, elmValue, onUpdate, validater );
4506 data.itemList.push( ret );
4509 alert( 'error createInputText' );
4511 createButton : function( elm, onClick ){
4512 var data = UIGroupPrivateData.get( this ),
4513 ret = new ButtonClass( data, elm, onClick );
4514 data.itemList.push( ret );
4517 createFileInput : function( elm, onUpdate, validater, elmFileInputReal ){
4518 var data = UIGroupPrivateData.get( this ),
4519 elmValue = Util.getElementsByClassName( elmWrapper, 'fileinput-value' )[ 0 ],
4522 ret = new FileInputClass( data, elm, onUpdate, validater, elmFileInputReal, elmValue );
4523 data.itemList.push( ret );
4528 createCombobox : function( elm, onUpdate, optionList ){
4529 var data = UIGroupPrivateData.get( this ),
4530 ret = new ComboBoxClass( data, elm, onUpdate, optionList );
4531 data.itemList.push( ret );
4534 createCheckBox : function(){
4537 createRadio : function(){
4540 createSlider : function(){
4543 visible : function( v ){
4544 var data = UIGroupPrivateData.get( this );
4545 if( Type.isBoolean( v ) === true && data.visible !== v ){
4546 for( var i = data.itemList.length; i; ){
4547 data.itemList[ --i ].visible( v );
4550 data.node.disabled( !( data.enabled && v ) );
4552 return data.visible;
4554 enabled : function( v ){
4555 var data = UIGroupPrivateData.get( this );
4556 if( Type.isBoolean( v ) === true && data.enabled !== v ){
4557 for( var i = data.itemList.length; i; ){
4558 data.itemList[ --i ].enabled( v );
4561 data.node.disabled( !( data.visible && v ) );
4563 return data.enabled;
4565 destroy : function(){
4566 var data = UIGroupPrivateData.get( this ),
4568 if( currentUi === this ){
4570 // finish( UIItemPrivateData.get( currentItem ) );
4572 while( _item = data.itemList.shift() ){
4579 function start( data ){
4580 if( currentItem !== data.item ){
4581 currentUi !== data.groupData.uigroup && currentUi && currentUi.blur();
4583 currentItem !== null && currentItem.blur();
4585 currentUser = data.groupData.apiuser;
4586 currentUi = data.groupData.uigroup;
4587 currentItem = data.item;
4589 currentUi.focus( currentItem );
4591 // if( currentUser !== _apiuser ) {
4592 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 );
4593 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 );
4594 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 9 );
4595 KeyEvent.updateCurrentListener( SUPER_USER_KEY );
4599 function finish( data ){
4600 if( currentItem === data.item ){
4608 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 );
4609 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 );
4610 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 9 );
4611 KeyEvent.updateCurrentListener( data.groupData.apiuser );
4615 function onKeyDown( e ){
4616 if( currentItem === null ) return true;
4617 var keyCode = e.keyCode,
4618 index = Util.getIndex( currentList, currentItem );
4619 if( keyCode === 13 || keyCode === 27 || keyCode === 9 || keyCode === 18 || e.altKey === true ){ // 13.return 27.esc 9.tab 18.alt
4620 keyCode === 9 && tabShift( index, e.shiftKey === true ? -1 : 1 );
4621 keyCode === 13 && currentItem instanceof ComboBoxClass && OptionControl.onEnter();
4622 keyCode === 13 && tabShift( index, 1 );
4623 currentItem && currentItem.blur( keyCode );
4628 function tabShift( index, way ){
4629 var l = currentList.length,
4633 while( i !== index ){
4636 i < l ? i : 0; // 0 < i < l
4637 item = currentList[ i ];
4638 if( item.enabled() === true && item.visible() === true ){
4639 AsyncCall.add( currentUser, item.focus, null, item );
4647 createUIGroup: function( apiuser, node ){
4648 var uid = apiuser.getUID(),
4649 list = UI_LIST[ uid ],
4650 ui = new UIGroupClass( apiuser, node );
4651 if( Type.isArray( list ) === false ){
4652 list = UI_LIST[ uid ] = [];
4657 onWindowResize: function( w, h ){
4660 currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h );
4661 currentItem instanceof TextInputClass && TextInputManager.onWindowResize( w, h );
4662 currentItem instanceof FileInputClass && FileInputManager.onWindowResize( w, h );
4664 onCurrentApplicationChange: function( _apiuser ){
4665 currentList = UI_LIST[ _apiuser.getUID() ];
4667 onApplicationShutdown: function( _apiuser ){
4668 KeyEvent.remove( _apiuser );
4670 onSystemShutdown: function(){
4677 var Finder = ( function(){
4678 var HTML_FINDER_ICON = ( function(){
4679 return ( UA.isIE === true && UA.ieVersion < 8 ?
4681 '<div class="finder-icon fnder-icon-ie7">',
4682 '<span class="finder-icon-handle"></span>',
4683 '<span class="finder-icon-thumbnail"></span>',
4684 '<span class="finder-icon-cell finder-icon-ie-filename">',
4685 '<span class="finder-icon-vertical-middle-outer">',
4686 '<span class="finder-icon-vertical-middle-inner">',
4687 '<span class="finder-icon-filename break-word">file name</span>',
4691 '<span class="finder-icon-cell finder-icon-ie-summary">',
4692 '<span class="finder-icon-vertical-middle-outer">',
4693 '<span class="finder-icon-vertical-middle-inner">',
4694 '<span class="finder-icon-summary break-word">file descriptiion</span>',
4701 '<div class="finder-icon fnder-icon-modern">',
4702 '<span class="finder-icon-handle"></span>',
4703 '<span class="finder-icon-thumbnail"></span>',
4704 '<span class="finder-icon-filename break-word">file name</span>',
4705 '<span class="finder-icon-summary break-word">file descriptiion</span>',
4711 var FINDER_LIST = [],
4712 ELM_ORIGIN_LOCATION_ITEM = Util.pullHtmlAsTemplete( '<div class="finder-location-item"></div>' ),
4713 ELM_ORIGIN_FINDER_ICON = Util.pullHtmlAsTemplete( HTML_FINDER_ICON ),
4714 ELM_ORIGIN_CONTAINER = Util.pullHtmlAsTemplete( '<div class="finder-body"></div>' ),
4715 ICON_HEIGHT = Util.getElementSize( ELM_ORIGIN_FINDER_ICON ).height,
4716 ICON_CLASSNAME = 'finder-icon-thumbnail',
4717 elmConsole = Util.pullHtmlAsTemplete( [
4718 '<div class="finder-icon-console">',
4719 '<a href="#" class="finder-icon-console-action"></a>',
4720 '<a href="#" class="finder-icon-console-editor-apps"></a>',
4721 '<a href="#" class="finder-icon-console-viewer-apps"></a>',
4728 var FinderIconClass = function(){};
4729 FinderIconClass.prototype = {
4736 init : function( finderData, file, w, index, style ){
4737 if( !this.elm ) this.elm = ELM_ORIGIN_FINDER_ICON.cloneNode( true );
4739 if( this.finderData !== finderData ){
4740 this.finderData = finderData;
4741 finderData.elmScroll.appendChild( this.elm );
4742 this.node && this.node.remove();
4743 this.node = finderData.nodeRoot.createNode( this.elm, false, true, 'finder-icon-hover', '' );
4745 if( this.file !== file ){
4746 this.file && this.file.destroy();
4748 this._index = index;
4752 if( this._index !== index ){
4753 this._index = index;
4757 index : function( _index ){
4760 style : function( _style ){
4763 draw : function( w ){
4764 var file = this.file,
4766 thumb = file.getThumbnail(),
4767 elmThumb = Util.getElementsByClassName( elm, ICON_CLASSNAME )[ 0 ],
4768 elmName = Util.getElementsByClassName( elm, 'finder-icon-filename' )[ 0 ],
4769 elmDesc = Util.getElementsByClassName( elm, 'finder-icon-summary' )[ 0 ];
4771 elmThumb.className = ICON_CLASSNAME + ' has-thumbnail';
4772 elmThumb.style.backgroundImage = [ 'url(', thumb.image, ')' ].join( '' );
4774 elmThumb.className = ICON_CLASSNAME + ' ' + thumb.className;
4775 elmThumb.style.backgroundImage = '';
4778 elmName.firstChild.data = file.getName();
4779 elmDesc.firstChild.data = file.getSummary();
4783 resize : function( w ){
4784 this.node.update( 0, this._index * ICON_HEIGHT, w );
4786 onEditorClick : function( e ){
4787 this.onEditorCallback && this.onEditorCallback( this.file, this.file.editorApplicationList()[ 0 ] );
4790 onViwerClick : function( e ){
4791 this.onViewerCallback && this.onViewerCallback( this.file, this.file.viewerApplicationList()[ 0 ] );
4794 onActionClick : function( e ){
4795 this.onActionCallback && this.onActionCallback( this.file );
4798 destroy : function(){
4799 this.elm && this.elm.parentNode.removeChild( this.elm );
4800 this.file && this.file.destroy();
4801 this.node && this.node.remove();
4802 delete this.finderData;
4807 FinderIconClass.pool.push( this );
4810 FinderIconClass.pool = [];
4811 FinderIconClass.get = function( finderData, file, w, index, style ){
4812 var _icon = FinderIconClass.pool.length > 0 ? FinderIconClass.pool.shift() : new FinderIconClass();
4813 _icon.init( finderData, file, w, index, style );
4820 var PathClass = function(){};
4821 PathClass.prototype = {
4828 init : function( finderData, file, index ){
4829 if( !this.elm ) this.elm = ELM_ORIGIN_LOCATION_ITEM.cloneNode( true );
4831 if( this.finderData !== finderData ){
4832 this.finderData = finderData;
4833 finderData.elmPath.appendChild( this.elm );
4834 this.node && this.node.remove();
4837 if( this.file !== file ){
4841 if( this._index !== index ){
4842 this._index = index;
4843 this.resize( index );
4845 if( !this.node ) this.node = finderData.nodePath.createNode( this.elm, false, true, 'finder-path-hover', 'pointer' );
4848 this.elm.className = 'file-icon-' + this.file.getType();
4849 this.elm.innerHTML = this.file.getName();
4851 resize : function(){
4852 this.elm.style.left = ( this._index * 90 ) + 'px';
4854 index : function( _index ){
4857 destroy : function(){
4858 this.finderData.elmPath.removeChild( this.elm );
4859 this.node && this.node.remove();
4861 delete this.finderData;
4866 PathClass.pool.push( this );
4869 PathClass.pool = [];
4870 PathClass.get = function( finderData, file, index ){
4871 var _bread = PathClass.pool.length > 0 ? PathClass.pool.shift() : new PathClass();
4872 _bread.init( finderData, file, index );
4879 var FinderPrivateData = function(){};
4880 FinderPrivateData.prototype = {
4890 viewerOption : null,
4891 editorOption : null,
4898 init : function( finder, apiuser, elm, tree, onSelect, viewerOption, editorOption ){
4899 this.finder = finder;
4900 this.apiuser = apiuser;
4901 if( PointingDeviceEventTree.isNodeInstance( elm ) === true ){
4902 this.nodeRoot = elm;
4903 this.elmRoot = PointingDeviceEventTree._getNodePrivateData( elm ).elm;
4905 // App が eventTree を持っている?
4906 // App が eventTree を持っていない
4909 this.nodeRoot.addEventListener( 'click', this.onIconClick, this );
4911 this.elmScroll = document.createElement( 'div' );
4912 this.elmRoot.appendChild( this.elmScroll );
4913 this.elmScroll.style.cssText = 'width:100%;';
4916 this.onSelect = onSelect;
4917 this.viewerOption = viewerOption;
4918 this.editorOption = editorOption;
4922 var size = Util.getElementSize( ELM_ORIGIN_FINDER_ICON );
4923 this.iconW = size.width;
4924 this.iconH = size.height;
4926 tree.addTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw, this );
4927 Util.addClass( this.elmRoot, 'finder-body' );
4929 FinderPrivateData.LIST.push( this );
4931 onIconClick : function( e ){
4932 var target = e.target,
4933 i = target.nodeIndex(),
4935 if( target === this.nodeRoot ) return;
4936 var file = this.tree.getCurrentFile().getChildFileByIndex( i );
4937 if( file !== null && ( file.getChildFileLength() !== -1 || file.getType() === Const.FILE.TYPE.FOLDER )){
4938 this.tree.down( i );
4941 Type.isFunction( this.onSelect ) === true && this.onSelect( file );
4945 onPathClick : function( e ){
4946 var target = e.target,
4947 i = target.nodeIndex();
4948 if( target === this.nodePath || this.nodePath.numNode() - 1 === i ) return;
4952 draw : function( _w, _h ){
4954 data.w = _w = Type.isFinite( _w ) === true ? _w : data.w;
4955 data.h = _h = Type.isFinite( _h ) === true ? _h : data.h;
4956 data.elmPath && data.drawPath( _w );
4957 data.drawBody( _w, _h );
4959 drawPath : function( _w ){
4960 if( !this.elmPath.parentNode ) return;
4964 apiuser = data.apiuser,
4965 pathList = data.pathList,
4967 l = tree.hierarchy() + 1,
4968 m = pathList.length,
4971 for( ; i < l; ++i ){
4972 file = i !== l - 1 ? tree.getParentFileAt( i ) : tree.getCurrentFile();
4974 pathList[ i ].init( this, file, i );
4976 pathList.push( PathClass.get( this, file, i ) );
4979 while( l < pathList.length ) pathList.pop().destroy();
4981 drawBody : function( _w, _h ){
4983 apiuser = data.apiuser,
4984 iconList = data.iconList,
4985 file = data.tree.getCurrentFile(),
4987 l = file.getChildFileLength(),
4988 m = iconList.length;
4990 for( ; i < l; ++i ){
4992 iconList[ i ].init( this, file.getChildFileByIndex( i ), _w, i, data.style );
4994 iconList.push( FinderIconClass.get( this, file.getChildFileByIndex( i ), _w, i, data.style ) );
4997 data.elmRoot.className = file.getState() === Const.FILE.STATE.LOADING ? 'finder-body loading' : 'finder-body';
4998 // data.elmRoot.style.height = ( data.h - data.headH ) + 'px';
5000 while( l < iconList.length ) iconList.pop().destroy();
5002 this.nodeRoot.invalidateScrollbar();
5004 createPath : function( node ){
5005 if( this.elmPath ) return;
5007 if( PointingDeviceEventTree.isNodeInstance( node ) === true ){
5008 this.nodePath = node;
5009 this.elmPath = PointingDeviceEventTree._getNodePrivateData( node ).elm;
5011 node.addEventListener( 'click', this.onPathClick, this );
5012 Util.addClass( this.elmPath, 'finder-path' );
5013 // this.elmPath = document.createElement( 'div' );
5014 // this.elmPath.className = ;
5017 AsyncCall.add( this.apiuser, this.draw, null, this );
5020 destroy : function(){
5021 this.tree.removeTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw );
5023 if( this.pathList ){
5024 while( this.pathList.length > 0 ) this.pathList.shift().destroy();
5026 while( this.iconList.length > 0 ) this.iconList.shift().destroy();
5028 this.nodeRoot.remove();
5029 // this.nodePath && this.nodePath.remove();
5031 // this.elmRoot.removeChild( this.elmRoot );
5033 FINDER_LIST.splice( Util.getIndex( FINDER_LIST, this.finder ), 1 );
5034 var data = ApplicationPrivateData.get( this.apiuser ),
5035 list = data.finderList,
5036 i = Util.getIndex( list, this.finder );
5037 i !== -1 && list.splice( i, 1 );
5040 FinderPrivateData.LIST = [];
5041 FinderPrivateData.get = function( finderOrTree ){
5042 var list = FinderPrivateData.LIST,
5047 if( data === finderOrTree || data.finder === finderOrTree || data.tree === finderOrTree ) return data;
5055 var FinderClass = function( application, elmRoot, tree, onSelect, viewerOption, editorOption ){
5056 ( new FinderPrivateData() ).init( this, application, elmRoot, tree, onSelect, viewerOption, editorOption );
5058 FinderClass.prototype = {
5062 var data = FinderPrivateData.get( this );
5063 // var position = Util.getAbsolutePosition( elmPath );
5064 // data.headX = position.x;
5065 // data.headY = position.y;
5066 // data.bodyY = Util.getAbsolutePosition( data.elmBody ).y;
5067 data.apiuser.addEventListener( data.elmRoot, 'mousemove', data.mousemove, data );
5068 data.apiuser.addEventListener( data.elmRoot, 'click', data.click, data );
5069 data.apiuser.addEventListener( data.elmRoot, 'mousewheel', data.mousewheel, data );
5071 resize : function( w, h ){
5072 var data = FinderPrivateData.get( this ),
5073 i = data.iconList.length;
5074 //data.draw( _w, _h );
5076 //data.elmRoot.style.height = ( _h - data.headH ) + 'px';
5078 for( ; i; ) data.iconList[ --i ].resize( w );
5080 createPath : function( node ){
5081 return FinderPrivateData.get( this ).createPath( node );
5083 destroy : function(){
5084 FinderPrivateData.get( this ).destroy();
5092 create: function( application, elmTarget, tree, onSelect, viewerOption, editorOption ){
5093 //if( Application.isApplicationInstance( _application ) === false ) return;
5095 var finder = new FinderClass( application, elmTarget, tree, onSelect, viewerOption, editorOption );
5097 FINDER_LIST.push( finder );
5100 registerFinderHead: function(){
5103 registerFinderPane: function( _finderPane ){
5106 isFinderInstance: function( _finder ){
5107 return _finder instanceof FinderClass;
5109 isFinderPaneInstance: function(){
5112 isFinderHeadInstance: function(){
5120 * marginBottom, marginLeft, marginRight, marginTop, margin
5121 * padding, paddingBottom, paddingLeft, paddingRight, paddingTop
5122 * fontSize, textIndent
5124 * bottom, left, right, top (len, %)
5127 * borderBottomWidth, borderLeftWidth, borderRightWidth, borderTopWidth, borderWidth,
5132 * borderBottomColor, borderLeftColor, borderRightColor, borderTopColor, borderColor
5136 * clip rect(0px, 40px, 40px, 0px);
5137 * backgroundPosition (len, %)
5139 * lineHeight (len, %, num)
5143 var DHTML = ( function(){
5145 var TICKET_ARRAY = [],
5148 cround = function( v ){ return round( v * 100 ) / 100 };
5150 function startAnimation( _elm, _cssObject, _onComplete, _onEnterFrame, _numFrames ){
5151 var _ticket, i = TICKET_ARRAY.length;
5153 _ticket = TICKET_ARRAY[ --i ];
5154 if( _ticket.elm === _elm ){
5159 var _currentValues = [],
5162 _targetProperties = [],
5164 var target, current,
5165 inlineStyle = CSS.getInlineStyle( _elm ),
5166 currentStyle = CSS.getWrappedStyle( _elm ),
5167 targetStyle = CSS.getWrappedStyle( _elm, _cssObject );
5168 targetStyle.pxPerEm = currentStyle.get( 'fontSize' )._toPx();
5169 for( var p in _cssObject ){
5170 p = Util.camelize( p );
5171 target = targetStyle.get( p );
5172 current = currentStyle.get( p );
5174 if( target.isValid() === false || current.isValid() === false || current.equal( target ) !== false ){
5180 current.convert( target );
5181 // alert( current.getValue() + ' , ' + target.getValue() )
5182 _currentValues.push( current.getValue() );
5183 _offsetValues.push( current.getOffset( target ) );
5184 _endValues.push( target.getValue() );
5185 _targetProperties.push( p );
5186 _units.push( target.getUnit() );
5188 // IE has trouble with opacity if it does not have layout
5189 // Force it by setting the zoom level
5190 if( p === 'opacity' && SPECIAL.hasLayout ){
5191 if( SPECIAL.hasLayout( _elm ) === false ) inlineStyle.zoom = 1;
5192 inlineStyle.filter = current.getValueText();
5194 inlineStyle[ p ] = current.getValueText();
5201 var i, cssTexts = [];
5202 for( i = 0; i < _numFrames; ++i ){
5203 if( i < _numFrames - 1 ){
5204 tickValue( _currentValues, _offsetValues, _numFrames );
5205 cssTexts.push( createCssText( _currentValues, _targetProperties, targetStyle, inlineStyle ) );
5207 cssTexts.push( createCssText( _endValues, _targetProperties, targetStyle, inlineStyle ) );
5211 TICKET_ARRAY.push( new AnimationTaskClass(
5213 Type.isFunction( _onComplete ) === true ? _onComplete : null,
5214 Type.isFunction( _onEnterFrame ) === true ? _onEnterFrame : null,
5218 currentStyle.clear();
5219 targetStyle.clear();
5220 SystemTimer.add( SUPER_USER_KEY, onEnterFrame, 1000 / fpms );
5223 function tickValue( current, offset, numFrames ){
5224 if( Type.isArray( current ) === true ){
5225 var ret, i = current.length;
5228 ret = tickValue( current[ i ], offset[ i ], numFrames );
5229 if( Type.isNumber( ret ) === true ) current[ i ] = ret;
5232 return current + offset / numFrames;
5235 function createCssText( update, props, style, inline ){
5237 for( var i = props.length; i; ){
5238 prop = style.get( props[ --i ] );
5239 prop.setValue( update[ i ] );
5240 inline[ Util.uncamelize( prop.name ) ] = prop.getValueText();
5241 //if( prop.name === 'backgroundColor' ) alert( prop.getValueText() + '|' + update[ i ].join( ',') )
5244 return CSS.toCssText( inline );
5247 function onEnterFrame(){
5250 while( i < TICKET_ARRAY.length ){
5251 _ticket = TICKET_ARRAY[ i ];
5252 l = _ticket.cssTexts.length;
5253 _ticket.elm.style.cssText = _ticket.cssTexts.shift();
5255 _ticket.onComplete && _ticket.onComplete();
5257 delete _ticket.cssTexts;
5258 delete _ticket.onComplete;
5259 delete _ticket.onEnterFrame;
5260 delete _ticket.numFrame;
5261 TICKET_ARRAY.splice( i, 1 );
5263 _ticket.onEnterFrame && _ticket.onEnterFrame( l / _ticket.numFrame );
5267 if( TICKET_ARRAY.length === 0 ){
5268 SystemTimer.remove( SUPER_USER_KEY, onEnterFrame );
5272 var AnimationTaskClass = function( elm, cssTexts, onEnterFrame, onComplete, numFrame ){
5274 this.cssTexts = cssTexts;
5275 this.onEnterFrame = onEnterFrame;
5276 this.onComplete = onComplete;
5277 this.numFrame = numFrame;
5280 var VisualEffectClass = function( elm ){
5283 VisualEffectClass.prototype = {
5284 anime : function( _cssObject, _onComplete, _onEnterFrame, _time ){
5285 var _numFrames = Math.floor( _time / fpms );
5286 startAnimation( this.elm, _cssObject, _onComplete, _onEnterFrame, _numFrames );
5288 fadeIn : function(){
5291 fadeOut : function(){
5294 update : function( x, y, w, h ){
5295 var _cssText = this.elm.style.cssText;
5300 create: function( application, _elm ){
5301 return new VisualEffectClass( _elm );
5303 isInstanceOfVisualEffect: function( _instance){
5304 return _instance instanceof VisualEffectClass;
5310 /* --------------------------------------------
5314 Application.onCurrentApplicationChange( SUPER_USER_KEY );
5316 SERVICE_LIST.push( MouseEvent );
5318 new EventTicketClass( window, 'unload', function(){
5320 while( SERVICE_LIST.length > 0 ){
5321 _service = SERVICE_LIST.shift();
5322 Type.isFunction( _service.onSystemShutdown ) === true && _service.onSystemShutdown();
5328 /* ---------------------------------------------
5329 * broadcast to global
5333 gOS.registerApplication = Application.register;
5334 gOS.registerDriver = File.registerDriver;
5336 })( window, document );