X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=0.5.x%2Fjavascripts%2Fsystem.js;h=364938cecf7fb5b8b222f49b89cce491e27b571a;hb=2621070c032954702155d4a315535b8b1aafd616;hp=0e68aaddd175d4d1da3d4e8af8598cc75fa08683;hpb=5dab36539b331a9d4141dd9f04829f6c8df0b291;p=pettanr%2FclientJs.git diff --git a/0.5.x/javascripts/system.js b/0.5.x/javascripts/system.js index 0e68aad..364938c 100644 --- a/0.5.x/javascripts/system.js +++ b/0.5.x/javascripts/system.js @@ -1,5608 +1,6345 @@ -/* - * pettanR system.js - * version 0.5.31 - * - * gadgetOS - * author: - * itozyun - * licence: - * 3-clause BSD - */ - -( function( window, document, undefined ){ - - var body = document.getElementsByTagName( 'body' )[ 0 ]; //( document.compatMode || '' ) !== 'CSS1Compat' ? document.body : document.documentElement;// - var SERVICE_LIST = []; - var SUPER_USER_KEY = { getUID: function(){ return 0; }}; - var API_USER_LIST = [ SUPER_USER_KEY ]; - var numApiUser = 1; - - function EMPTY_FUNCTION(){}; - - function isApiUser( _user ){ - return _user === SUPER_USER_KEY || - File.isDriver( _user ) === true || - Application.isApplicationInstance( _user ) === true; - }; - - var Const = { - FILE: { - TYPE: { - UNKNOWN: 0, - FOLDER: 1, - IMAGE: 2, - TEXT: 3, - HTML: 4, - CSV: 5, - JSON: 6, - XML: 7 - }, - STATE: { - UNKNOWN: 0, - OK: 1, - LOADING: 2, - ERROR: 3, - BROKEN: 4 - }, - UPDATE_POLICY: { - _____: parseInt( '00000', 2 ), - ____C: parseInt( '00001', 2 ), // hasCreateMenu - ___W_: parseInt( '00010', 2 ), // isWritable - ___WC: parseInt( '00011', 2 ), // isWritable - __R__: parseInt( '00100', 2 ), // isRenamable - __R_C: parseInt( '00101', 2 ), // hasCreateMenu - __RW_: parseInt( '00110', 2 ), // isWritable - __RWC: parseInt( '00111', 2 ), // isWritable - _S___: parseInt( '01000', 2 ), // childrenIsSortable - _S__C: parseInt( '01001', 2 ), - _S_W_: parseInt( '01010', 2 ), - _S_WC: parseInt( '01011', 2 ), - _SR__: parseInt( '01100', 2 ), - _SR_C: parseInt( '01101', 2 ), - _SRW_: parseInt( '01110', 2 ), - _SRWC: parseInt( '01111', 2 ), - D____: parseInt( '10000', 2 ), - D___C: parseInt( '10001', 2 ), // hasCreateMenu - D__W_: parseInt( '10010', 2 ), // isWritable - D__WC: parseInt( '10011', 2 ), // isWritable - D_R__: parseInt( '10100', 2 ), // isRenamable - D_R_C: parseInt( '10101', 2 ), // hasCreateMenu - D_RW_: parseInt( '10110', 2 ), // isWritable - D_RWC: parseInt( '10111', 2 ), // isWritable - DS___: parseInt( '11000', 2 ), // childrenIsSortable - DS__C: parseInt( '11001', 2 ), - DS_W_: parseInt( '11010', 2 ), - DS_WC: parseInt( '11011', 2 ), - DSR__: parseInt( '11100', 2 ), - DSR_C: parseInt( '11101', 2 ), - DSRW_: parseInt( '11110', 2 ), - DSRWC: parseInt( '11111', 2 ), - CREATE: 1, - WRAITE: 2, - RENAME: 4, - SORT: 8, - DELETE: 16 - }, - EVENT: { - UPDATE_ATTRIVUTE: 'onFileUpdate', - GET_SEQENTIAL_FILES:'gotSeqentilFiles' - }, - DATA_PROPERTY_RESERVED: [ - 'children', 'driver', 'state', 'type' - ] - }, - TREE: { - EVENT: { - UPDATE: 'onTreeUpdate' - } - }, - KEY: { - EVENT: { - KEY_DOWN: 'keydown', - KEY_UP: 'keyup', - KEY_CHANGE: 'keychange', - CURSOL: 'cursol' - } - }, - APP: { - TYPE: { - GENERAL : 0, - OVERLAY : 1, - PAGE : 2 - } - } - }; - -var Class = ( function(){ - var CLASS_LIST = []; - - function getClass( instance ){ - var list = CLASS_LIST, - l = list.length, - getIndex = Util.getIndex, - klass, live, pool; - for( ; i; ){ - klass = list[ --i ] - live = klass.live; - if( live && getIndex( live, instance ) !== -1 ) return klass; - pool = klass.pool; - if( pool && getIndex( pool, instance ) !== -1 ) return klass; - if( instance instanceof klass ) return klass; - }; - return null; - }; - - function clone( src ){ - var ret, key; - if( Type.isArray( src ) === true ){ - ret = []; - } else - if( Type.isObject( src ) === true ){ - ret = {}; - } else - if( Type.isNumber( src ) === true || Type.isString( src ) === true || Type.isBoolean( src ) === true ){ - return src; - } else { - return null; - }; - for( key in src ){ - ret[ key ] = clone( src[ key ]); - }; - return ret; - }; - - function copy( base, extend ){ - for( var key in extend ){ - base[ key ] = extend[ key ]; - }; - return base; - }; - - function extend(){ - - }; - - var basic = { - clear : function(){ - var o = this, - p, v, - klass = getClass( o ); - for( p in o ){ - if( o.hasOwnProperty && !o.hasOwnProperty( p ) ) continue; - v = o[ p ]; - delete o[ p ]; - }; - if( klass && klass.pool ){ - klass.live.splice( Util.getIndex( klass.live, o ), 1 ); - klass.pool.push( o ); - }; - } - }; - - var f = true; - var c = Util.copyArray; - var a; - function I(){ - var klass = this, - instance; - if( klass.abstract === true ){ - throw new Error( 'AbstractClass!' ); - }; - if( klass.pool && klass.pool.length > 0 ){ - instance = klass.pool.shift(); - } else { - f = false; - instance = new klass(); - f = true; - }; - if( klass._super ){ - instance._super = klass._super.prototype; - }; - instance.init && instance.init.apply( instance, c( arguments ) ); - klass.live && klass.live.push( instance ); - return instance; - }; - - return { - create : function( def, final, pool, abstract ){ - var klass = function(){ - a = arguments; - if( f ) return I.apply( a.collee, c( a ) ); - }; - klass.prototype = copy( copy( {}, basic ), def ); - if( final !== true ){ - klass.extend = extend; - }; - if( pool === true ){ - klass.pool = []; - klass.live = []; - }; - if( abstract === true ){ - klass.abstract = true; - }; - return klass; - } - }; -})(); - -var TicketBase = function(){ - this.kill = function(){ - var t = this, v, p; - for( p in t ){ - if( t.hasOwnProperty && !t.hasOwnProperty( p ) ) continue; - v = t[ p ]; - v && v instanceof TicketBase && v.kill(); - delete t[ p ]; - }; - }; -}; - - - -/* -------------------------------------------------------------- - * System Timer - * - */ - -var SystemTimer = ( function(){ - var setTimeout = window.setTimeout; - var clearTimeout = window.clearTimeout; - var INTERVAL_TIME = 16; - var TICKET_LIST = []; - var timerId = undefined; - var next = 0; - - function loop(){ - for( var i = 0; i < TICKET_LIST.length; ) { - if( TICKET_LIST[ i ].call( next ) !== false ) ++i; - }; - timerId = undefined; - update(); - }; - function update(){ - var l = TICKET_LIST.length, - n = 99999999, - c; - if( l === 0 ){ - timerId !== undefined && clearTimeout( timerId ); - timerId = undefined; - return; - }; - for( var i = 0; i c ) n = c; - }; - if( next > n || timerId === undefined ){ - timerId !== undefined && clearTimeout( timerId ); - timerId = setTimeout( loop, INTERVAL_TIME * n ); - next = n; - }; - }; - - var TimerTicketClass = function( _apiuser, _callback, _time, _once, opt_thisObject ){ - this.apiuser = _apiuser; - this.callback = _callback; - this.time = _time; - this.count = _time; - this.once = _once; - this.thisObj = opt_thisObject; - }; - TimerTicketClass.prototype = new TicketBase(); - TimerTicketClass.prototype.call = function( c ){ - this.count -= c; - if( this.count <= 0 ){ - this.callback.call( this.thisObj || this.apiuser ); - if( this.once === true ){ - this.destroy(); - TICKET_LIST.splice( Util.getIndex( TICKET_LIST, this ), 1 ); - return false; - } else { - this.count = this.time; - }; - }; - }; - TimerTicketClass.prototype.destroy = function( _apiuser, _callback ){ - if( _apiuser && _apiuser !== this.apiuser ) return false; - if( _callback && _callback !== this.callback ) return false; - - this.kill(); - return true; - }; - - return { - add: function( _apiuser, _handler, _time, _once, opt_thisObject ){ - if( Type.isNumber( _time ) === false || _time < INTERVAL_TIME ) _time = INTERVAL_TIME; - - var _ticket = new TimerTicketClass( _apiuser, _handler, Math.ceil( _time / INTERVAL_TIME ), _once, opt_thisObject ); - TICKET_LIST.push( _ticket ); - - update(); - }, - remove: function( _apiuser, _handler ){ - var _ticket, - i = 0; - while( _ticket = TICKET_LIST[ i ] ){ - if( _ticket.destroy( _apiuser, _handler ) === true ){ - TICKET_LIST.splice( i, 1 ); - } else { - ++i; - }; - }; - update(); - } - } -})(); - -/* -------------------------------------------------------------- - * Async Callback - * - */ -var AsyncCall = ( function(){ - var CALLBACK_LIST = []; - - var CallbackTicketClass = function( _apiuser, _callback, _argments, _thisObject ){ - this.apiuser = _apiuser; - this.callback = _callback; - this.argments = _argments; - this.thisObject = _thisObject; - }; - CallbackTicketClass.prototype = new TicketBase(); - CallbackTicketClass.prototype.call = function(){ - var f = this.callback, - a = this.argments, - t = this.thisObject; - this.destroy(); - if( Type.isArray( a ) === true ){ - f.apply( t, a ); - } else { - f.call( t, a ); - }; - }; - CallbackTicketClass.prototype.destroy = function( _apiuser, _callback ){ - if( _apiuser && _apiuser !== this.apiuser ) return false; - if( _callback && _callback !== this.callback ) return false; - - this.kill(); - return true; - }; - - function dispatch(){ - var _ticket = CALLBACK_LIST.shift(); - if( _ticket ){ - _ticket.call(); - CALLBACK_LIST.length !== 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true ); - }; - }; - - return { - add: function( _apiuser, _callback, _argments, _thisObject ){ - CALLBACK_LIST.length === 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true ); - CALLBACK_LIST.push( new CallbackTicketClass( _apiuser, _callback, _argments, _thisObject || _apiuser ) ); - }, - remove: function( _apiuser, _callback ){ - var _ticket, - i = 0; - while( _ticket = CALLBACK_LIST[ i ] ){ - if( _ticket.destroy( _apiuser, _callback ) === true ){ - CALLBACK_LIST.splice( i, 1 ); - } else { - ++i; - }; - }; - } - }; -})(); - -/* ----------------------------------------------------------- - * 画像一覧は - * お気に入り画像一覧 > tag:ペン次郎 > ペン次郎:笑う - * 最近アップロードされた画像 > images - * 最近使われた画像 > images - * キャラクター画像庫 > アニマル系 > tag:ペン次郎 > ペン次郎:笑う - * 風景画像庫 > - * 効果画像庫 > - * アイテム画像庫 > - * - * 画像一覧を読み込むタイミング - */ -var File = ( function(){ - var DRIVER_LIST = []; - - var FILE_TYPE_IS_FOLDER = Const.FILE.TYPE.FOLDER, - numFileType = Const.FILE.TYPE.XML, - FILEDATA_RESITER = [], // store all of fileData( json object ) - FILEDATA_ACCESS = [], // file operations for Kernel only ! hide from Out of File - FILE_OBJECT_POOL = [], - EVENT_LISTENER_REGISTER = [], - TREE_ARRAY = [], - TREE_ACCESS_ARRAY = []; - - var REQUEST_CONTROLER = ( function(){ - var REQUEST_TICKET_RESISTER = [], - currentTicket = null, - currentData = null, - DATA_TYPE_ARRAY = 'json,xml,html,text'.split( ','), - DATA_IS_JSON = 0, - DATA_IS_XML = 1, - DATA_IS_HTML = 2, - DATA_IS_TEXT = 3, - numError = 0; - - var RequestTicketClass = function( _apiuser, _type, _data, _url, _onLoad, _onError ){ - this.apiuser = _apiuser; - this.type = _type; - this.data = _data; - this.url = _url; - this.onLoad = _onLoad; - this.onError = _onError; - this.state = 0; - _apiuser = _type = _data = _onLoad = _onError = null; - }; - RequestTicketClass.prototype = new TicketBase(); - RequestTicketClass.prototype.load = function( _data ){ - AsyncCall.add( this.apiuser, this.onLoad, [ this.data, _data ] ); - }; - RequestTicketClass.prototype.error = function(){ - AsyncCall.add( this.apiuser, this.onError, this.data ); - }; - - function request(){ - if( currentTicket !== null || REQUEST_TICKET_RESISTER.length === 0 ) return; - currentTicket = REQUEST_TICKET_RESISTER.shift(); - $.ajax({ - url: currentTicket.url, - dataType: DATA_TYPE_ARRAY[ currentTicket.type ], - success: onSuccess, - error: onError - }); - }; - function onSuccess( _data ){ - currentTicket.load( _data ); - currentTicket.kill(); - currentTicket = null; - request(); - }; - function onError(){ - ++numError; - currentTicket.error(); - currentTicket.kill(); // retry - currentTicket = null; - request(); - }; - - return { - getNumTask: function(){ - return REQUEST_TICKET_RESISTER.length; - }, - getNumError: function(){ - return numError; - }, - getJson: function( _apiuser, _data, _url, _onLoad, _onError ){ - REQUEST_TICKET_RESISTER.push( new RequestTicketClass( _apiuser, DATA_IS_JSON, _data, _url, _onLoad, _onError )); - currentTicket === null && request(); - } - }; - })(); - - var FILE_CONTROLER = { - createTree: function( _apiuser, _rootFileData ){ - var _tree = new TreeClass( _apiuser, _rootFileData ); - TREE_ARRAY.push( _tree ); - return _tree; - }, - getFileUID: function( FILEDATAorFILE ){ - if( FILEDATAorFILE instanceof FileClass ){ - return FILEDATAorFILE.getUID(); - }; - - var uid = Util.getIndex( FILEDATA_RESITER, FILEDATAorFILE ); - if( uid === -1 ){ - uid = FILEDATA_RESITER.length; - FILEDATA_RESITER.push( FILEDATAorFILE ); - }; - return uid; - }, - getFileDataAccess: function( UIDorFILEorFILEDATA ){ - var _uid, _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA ), _access; - - if( _data === null || typeof _data !== 'object' ) return null; - for( var i=0, l = FILEDATA_ACCESS.length; i= _bit; - }, - move: function( _prentUID, _targetfile, _newFolder, _newIndex, _opt_callback ){ - var _parentData = FILE_CONTROLER.getFileDataAccess( _prentUID ), - _parentType = _parentData.TYPE, - _targetData = FILE_CONTROLER.getFileDataAccess( _targetfile ), - _targetType = _targetData.TYPE; - }, - replace: function( _uid, _file, _newIndex ){ - - }, - addEventListener: function( FILEorNULL, _eventType, _callback, opt_thisObject ){ - var _uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL; - EVENT_LISTENER_REGISTER.push( new FileEventTicketClass( _uid, _eventType, _callback, opt_thisObject )); - }, - removeEventListener: function( FILEorNULL, _eventType, _callback ){ - var _uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL, - _ticket; - for(var i=0, l = EVENT_LISTENER_REGISTER.length; i= l ) return null; - return PARENT_FILE_RESITER[ l -1 -_index ]; - }; - this.down = function( _index ){ - if( typeof _index !== 'number' || _index < 0 || _index >= currentFile.getChildFileLength()) return; - PARENT_FILE_RESITER.unshift( currentFile ); - currentFile = currentFile.getChildFileByIndex( _index ); - currentFile.getSeqentialFiles(); - return currentFile; - }; - this.up = function( _index ){ - var l = PARENT_FILE_RESITER.length; - if( l === 0 ) return null; - - if( currentFile ){ - var _currentFile = currentFile; - currentFile = null; - _currentFile.destroy(); - }; - if( typeof _index === 'number' ){ - if( _index >= l ) return null; - currentFile = this.getParentFileAt( _index ); - PARENT_FILE_RESITER.splice( 0, l -_index); - } else { - currentFile = PARENT_FILE_RESITER.shift(); - }; - currentFile.getSeqentialFiles(); - return currentFile; - }; - this.addTreeEventListener = function( _eventType, _callback, opt_thisObject ){ - FILE_CONTROLER.addEventListener( null, _eventType, _callback, opt_thisObject ); - }; - this.removeTreeEventListener = function( _eventType, _callback ){ - FILE_CONTROLER.removeEventListener( null, _eventType, _callback ); - }; - this.destroy = function( _apiuser ){ - if( _apiuser && apiuser !== _apiuser ) return false; - // removeEvent - var _currentFile = currentFile; - currentFile = rootFile = rootFileData = null; - // currentFile, rootFile を null にしないと .File.destroy() ができない. - _currentFile.destroy(); - while( PARENT_FILE_RESITER.length > 0 ){ - _currentFile = PARENT_FILE_RESITER.shift(); - _currentFile.destroy(); - }; - - AsyncCall.remove( apiuser ); - instance = apiuser = null; - return true; - }; - }; - - var FileEventTicketClass = function( uid, eventType, callback, opt_thisObject ){ - this.fileUID = uid; - this.eventType = eventType; - this.callBack = callback; - this.thisObject = opt_thisObject; - }; - FileEventTicketClass.prototype = new TicketBase(); - - var FileEventClass = function( eventType, file, key, value ){ - this.eventType = eventType; - this.targetFile = file; - this.updatedAttribute = key; - this.updatedValue = value; - }; - -/* - * file の data は object で保持している。 - * File の外からファイルをみるときは、FileClassを通して操作する。 - * fileの変更、それに付随して追加されたイベントは、TreeClassで管理される。 - * treeがdestryされると、fileのイベントリスナーも全て削除される。 - * 他の tree も data の共通する currentFile に対してのみは、file の変更イベントを受け取って流す. - * - */ - - var FileClass = function( tree, parentData, data ){ - var uid = FILE_CONTROLER.getFileUID( data ); - - FILEDATA_ACCESS.push( { - TREE: tree, - parentData: parentData, - DATA: data - } ); - - tree = parentData = data = null; - - this.getUID = function(){ - return uid; - } - }; - - FileClass.prototype = { - isChildFile: function( _FILEorFILEDATA ){ - return this.getChildFileIndex( _FILEorFILEDATA) !== -1; - }, - getSeqentialFiles: function(){ - var _driver = FILE_CONTROLER.getDriver( this ); - if( _driver !== null && typeof _driver.getSeqentialFiles === 'function' ){ - _driver.getSeqentialFiles( this ); - } - }, - addEventListener: function( _eventType, _callback ){ - FILE_CONTROLER.addEventListener( this, _eventType, _callback ); - }, - removeEventListener: function( _eventType, _callback ){ - FILE_CONTROLER.removeEventListener( this, _eventType, _callback ); - }, - dispatchEvent: function( e ){ - e instanceof FileEventClass && FILE_CONTROLER.fileEventRellay( this.getUID(), e ); - }, - getChildFileLength: function(){ - var children = FILE_CONTROLER.getChildren( this ); - return Type.isArray( children ) === true ? children.length : -1; - }, - getChildFileIndex: function( _FILEorFILEDATA ){ - var children = FILE_CONTROLER.getChildren( this ); - if( Type.isArray( children ) === false ) return -1; - var l = children.length, - _fileData = FILE_CONTROLER.getFileData( _FILEorFILEDATA ); - if( _fileData === null ) return -1; - for( var i=0; i= _children.length) return null; - var _file = new FileClass( _access.TREE, _access.DATA, _children[ _index ]); - // _file.init(); - return _file; - }, - getName: function(){ - var driver = FILE_CONTROLER.getDriver( this ); - if( typeof driver.getName === 'function'){ - return driver.getName( this ); - } - return BASE_DRIVER.getName( this); - }, - getThumbnail: function(){ - var driver = FILE_CONTROLER.getDriver( this ); - if( typeof driver.getThumbnail === 'function'){ - return driver.getThumbnail( this ); - } - return BASE_DRIVER.getThumbnail( this ); - }, - getType: function(){ - var _data = FILE_CONTROLER.getFileData( this ); - return typeof _data.type === 'number' ? _data.type : Const.FILE.TYPE.UNKNOWN; - }, - getState: function(){ - var _data = FILE_CONTROLER.getFileData( this ); - return typeof _data.state === 'number' ? _data.state : Const.FILE.STATE.OK; - }, - getSummary: function(){ - var driver = FILE_CONTROLER.getDriver( this ); - if( typeof driver.getSummary === 'function'){ - return driver.getSummary( this ); - } - return BASE_DRIVER.getSummary( this ); - }, - isWritable: function(){ - return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.WRITE ); - }, - isSortable: function(){ - return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.SORT ); - }, - isCreatable: function(){ - return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.CREATE ); - }, - isRenamable: function(){ - return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.RENAME ); - }, - isDeletable: function(){ - return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.DELETE ); - }, - read: function(){ - // simpleDeepCopy - var driver = FILE_CONTROLER.getDriver( this ), - data; - if( typeof driver.read === 'function'){ - data = driver.read( this ); - } - return BASE_DRIVER.read( data || this ); - }, - write: function( _newData, _onUpdateFunction ){ - var driver = FILE_CONTROLER.getDriver( this ); - if( typeof driver.write === 'function'){ - return driver.write( this, _newData, _onUpdateFunction ); - } - return BASE_DRIVER.write( this, _newData, _onUpdateFunction ); - }, - viewerApplicationList: function(){ - var driver = FILE_CONTROLER.getDriver( this ); - if( typeof driver.viewerApplicationList === 'function'){ - return driver.viewerApplicationList( this ); - } - return BASE_DRIVER.viewerApplicationList( this ); - }, - editorApplicationList: function(){ - var driver = FILE_CONTROLER.getDriver( this ); - if( typeof driver.editorApplicationList === 'function'){ - return driver.editorApplicationList( this ); - } - return BASE_DRIVER.viwerApps( this ); - }, - create: function(){ - - }, - sort: function(){ - - }, - onCopy: function(){ - - }, - onDelete: function(){ - - }, - move: function( _newFolder, _newIndex, opt_callback ){ - var _access = FILE_CONTROLER.getFileDataAccess( this ); - _access.TREE.move( _access.parentData, this.getUID(), _newFolder, _newIndex, opt_callback ); - }, - replace: function( _newIndex, opt_callback ){ - var _access = FILE_CONTROLER.getFileDataAccess( this ); - _access.TREE.replace( _access.parentData, this.getUID(), _newIndex, opt_callback); - }, - /** - * サーチ - * 探しているファイルの属性と値を指定.一致する child の index を配列で返す. - */ - search: function( obj, rule ){ - var _children = FILE_CONTROLER.getChildren( this ), - _child, - ret = [], k, c; - for( var i=0, l=_children.length; i this.w || this.application.MIN_HEIGHT > this.h ){ - if( Type.isHTMLElement( this.rootElement ) === true ){ - // 小さすぎる!、と表示 - }; - }; - if( this.bootParams.length > 2 ){ - this.application.onOpen.apply( this.application, this.bootParams ); - } else { - this.application.onOpen( this.w, this.h ); - }; - this.phase = 4; - }, - fetchResourceComplete : function(){ - --this.fetchResource; - } -}; -ApplicationPrivateData.list = []; -ApplicationPrivateData.get = function( app ){ - var list = ApplicationPrivateData.list, - i = list.length; - for( ; i; ){ - if( app instanceof list[ --i ].appClass ) return list[ i ]; - }; - return null; -}; - -var AbstractApplication = function( appClass, displayName, isOverlay ){ - ( new ApplicationPrivateData() ).init( appClass, displayName, isOverlay ); -}; -AbstractApplication.prototype = { - getUID : function(){ - var data = ApplicationPrivateData.get( this ); - return Util.getIndex( API_USER_LIST, data.appClass ); - }, - init : function(){ - var data = ApplicationPrivateData.get( this ); - // this.rootElement = data.rootElement; - // data.application = this; - data.phase = 1; - data.appClass === Page.appClass && Page.show(); - this.onInit(); - data.phase = 2; - }, - open : function( w, h /*, _option */ ){ - var data = ApplicationPrivateData.get( this ); - data.phase = 3; - data.bootParams = Util.copyArray( arguments ); - data.w = w; - data.h = h; - if( data.rootElement.innerHTML && data.rootElement.innerHTML.length > 0 ){ - SystemTimer.add( this, data.detect, 16, false, data ); - } else { - data.onOpen(); - }; - }, - resize : function( w, h ){ - var data = ApplicationPrivateData.get( this ); - if( data.phase !== 4 ) return; - if( this.MIN_WIDTH > w || this.MIN_HEIGHT > h ){ - if( Type.isHTMLElement( this.rootElement ) === true ){ - // 小さすぎる!、と表示 - }; - return; - }; - this.onPaneResize( w, h ); - }, - close : function(){ - var data = ApplicationPrivateData.get( this ); - data.phase = 5; - if( this.onClose() === false ){ - return false; - }; - if( data.uiList ){ - while( data.uiList.length > 0 ) data.uiList.shift().destroy(); - }; - if( data.finderList ){ - while( data.finderList.length > 0 ) data.finderList.shift().destroy(); - }; - - data.eventRoot && PointingDeviceEventTree.destroyTree( data.eventRoot ); - MouseEvent.remove( this ); - KeyEvent.remove( this ); - SystemTimer.remove( this ); - AsyncCall.remove( this ); - StyleSheet.unload( this ); - - var elm = this.rootElement; - Util.removeAllChildren( elm ); - elm.parentNode.removeChild( elm ); - - Application.shutdown( this, data.isOverlay ); - - data.appClass === Page.appClass && Page.hide(); - - data.phase = 6; - - var list = ApplicationPrivateData.list; - list.splice( Util.getIndex( list, data ), 1 ); - }, - createUIGroup : function( node ){ - var data = ApplicationPrivateData.get( this ), - ui = UI.createUIGroup( this, node ); - if( data.uiList === null ) data.uiList = []; - data.uiList.push( ui ); - return ui; - }, - createUIForm : function( nodeOrElm, opt_elmForm ){ - var data = ApplicationPrivateData.get( this ), - form = UIForm.createForm( this, nodeOrElm, opt_elmForm ); - if( data.formList === null ) data.formList = []; - data.formList.push( form ); - return form; - }, - createFinder : function( _elmTarget, _tree, _onSelect, _viewerOption, _editorOption ){ - var data = ApplicationPrivateData.get( this ), - finder = Finder.create( this, _elmTarget, _tree, _onSelect, _viewerOption, _editorOption ); - if( data.finderList === null ) data.finderList = []; - data.finderList.push( finder ); - return finder; - }, - createDHTML : function( _elm ){ - return DHTML.create( this, _elm ); - }, - addEventListener : function( element, eventType, handler, opt_thisObject ){ - MouseEvent.add( this, element, eventType, handler, opt_thisObject ); - }, - removeEventListener : function( element, eventType, handler ){ - MouseEvent.remove( this, element, eventType, handler ); - }, - getPointingDeviceEventTreeRoot : function(){ - var data = ApplicationPrivateData.get( this ); - if( data.phase === 1 ){ - data.eventRoot = PointingDeviceEventTree.create( this ); - data.styleCursor = PointingDeviceEventTree._getNodePrivateData( data.eventRoot ).elmMouseCatch.style; - }; - return data.eventRoot; - }, - updateCoursor : function( _cursor ){ - var data = ApplicationPrivateData.get( this ); - if( data.cursor !== _cursor ){ - data.styleCursor.cursor = data.cursor = _cursor; - }; - }, - fetchCSS : function( url, opt_onload, opt_onerror ){ - var data = ApplicationPrivateData.get( this ); - if( data.phase === 1 ){ - ++data.fetchResource; - StyleSheet.load( this, url, data.fetchResourceComplete, data.fetchResourceComplete, data ); - }; - }, - onInit : function(){}, - onOpen : function(){}, - onClose : function(){ return true; }, - onPaneResize : function( w, h ){}, - addKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){ - KeyEvent.add( this, _eventType, _handler, _keyCode, _shift, _ctrl ); - }, - removeKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){ - KeyEvent.remove( this, _eventType, _handler, _keyCode, _shift, _ctrl ); - }, - shiftEnabled : function(){ - return KeyEvent.shiftEnabled; - }, - ctrlEnabled : function(){ - return KeyEvent.ctrlEnabled; - }, - addTimer : function( handler, time, once ){ - SystemTimer.add( this, handler, time, !!once ); - }, - removeTimer : function( handler ){ - SystemTimer.remove( this, handler ); - }, - addAsyncCall : function( _callback, _argments, _thisObject ){ - AsyncCall.add( this, _callback, _argments, _thisObject ); - }, - removeAsyncCall : function( _callback ){ - AsyncCall.remove( this, _callback ); - }, - fetchHTMLElement : function( id ){ - var elm = document.getElementById( id ); - if( elm ){ - elm.removeAttribute( 'id' ); - elm.parentNode.removeChild( elm ); - return elm; - }; - } -}; - -var PointingDeviceEventTree = ( function(){ - var ROOT_LIST = [], - currentRootData = null, - targetNodeData = null, - forceNodeData = null, - hoverList = [], - c = 0; - - function eventRellay( e ){ - var data = forceNodeData, // || targetNodeData, - x = e.clientX, - y = e.clientY, - type = e.type, - list = hoverList, - i = 0, - ret, systemOnly = false, addClass, removeClass, - parent; - if( data && data.dispatchEvent( e, type, true ) === true ) return false; - if( currentRootData === null ) return; - targetNodeData = currentRootData; - currentRootData._capcher( x, y ); - targetNodeData.apiuser.updateCoursor( targetNodeData._cursor ); - data = targetNodeData; - while( data ){ - ret = data.dispatchEvent( e, type, true, systemOnly ); - if( ret === true || ret === false ) break; // systemOnly = true; - data = data.parentData; - }; - - addClass = Util.addClass; - removeClass = Util.removeClass; - for( ; i < list.length; ){ - parent = data = list[ i ]; - while( parent.parentData && parent === parent.parentData.hitChild ){ - parent = parent.parentData; - }; - if( parent !== currentRootData ){ - data.hover === true && removeClass( data.elm, data.hoverClass ); - delete data.isHover; - data.events && data.events.mouseout && data.fire( e, 'mouseout', false ); - delete data.hitSelf; - list.splice( i, 1 ); - continue; - }; - if( data.hover === true && data.isHover === false ){ - addClass( data.elm, data.hoverClass ); - data.isHover = true; - }; - if( data.hitSelf === false ){ - data.events && data.events.mouseover && data.fire( e, 'mouseover', true ); - data.hitSelf = true; - }; - ++i; - }; - return false; - }; - - var NodeClass = function( apiuser, rootData, /*parentLayer,*/ parentData, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){ - ( new NodePrivateData() ).init( apiuser, rootData, /*parentLayer,*/ parentData, this, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ); - }; - NodeClass.prototype = { - createNode : function( rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ){ - var data = NodePrivateData.get( this ), - elm; - if( Type.isHTMLElement( rangeOrElmData ) === true ){ - elm = rangeOrElmData; - } else - if( Type.isString( rangeOrElmData ) === true ){ - elm = document.getElementById( rangeOrElmData ); - if( !elm ){ - elm = Util.pullHtmlAsTemplete( rangeOrElmData ); - }; - if( !elm || Type.isHTMLElement( elm ) === false || elm.nodeType !== 1 ){ - throw new Error( "invalid HTMLElement." ); - }; - } else - if( Type.isObject( rangeOrElmData ) === false || Type.isFinite( rangeOrElmData.x ) === false || Type.isFinite( rangeOrElmData.y ) === false ){ - throw new Error( "No range" ); - }; - - if( elm && data.elm === null ){ - throw new Error( "MetaLayer don't containe HTMLElement-Layer." ); - }; - if( data.elm && data.elm.style.hasLayout === false ){ - throw new Error( "[ie] OffsetParent is hasLayout === false." ); - }; - - var newNode = new NodeClass( data.apiuser, data.rootData, data, elm || rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ), - newData = NodePrivateData.get( newNode ); - - if( data.childData === null ) data.childData = []; - data.childData.push( newData ); - return newNode; - }, - createNodeAt : function(){ - }, - remove : function(){ - NodePrivateData.get( this ).remove(); - }, - nodeIndex : function( v ){ - return NodePrivateData.get( this ).nodeIndex( v ); - }, - numNode : function(){ - return NodePrivateData.get( this ).numNode(); - }, - disabled : function( v ){ - return NodePrivateData.get( this ).disabled( v ); - }, - childrenDisabled : function( v ){ - return NodePrivateData.get( this ).disabled( v ); - }, - mesure : function(){ - NodePrivateData.get( this ).mesure(); - }, - mesureChildren : function(){ - NodePrivateData.get( this ).mesureChildren(); - }, - update : function( x, y, w, h ){ - NodePrivateData.get( this ).update( x, y, w, h ); - }, - setPosition : function( x, y ){ - NodePrivateData.get( this ).setPosition( x, y ); - }, - setSize : function( w, h ){ - NodePrivateData.get( this ).setSize( w, h ); - }, - cursor : function( v ){ - return NodePrivateData.get( this ).cursor( v ); - }, - x : function( x ){ - return NodePrivateData.get( this ).positionX( x ); - }, - y : function( y ){ - return NodePrivateData.get( this ).positionY( y ); - }, - width : function( w ){ - return NodePrivateData.get( this ).width( w ); - }, - height : function( h ){ - return NodePrivateData.get( this ).height( h ); - }, - getAbsolutePositionX : function(){ - return NodePrivateData.get( this ).getAbsolutePositionX(); - }, - getAbsolutePositionY : function(){ - return NodePrivateData.get( this ).getAbsolutePositionY(); - }, - addEventListener : function( type, handler, opt_thisObject ){ - NodePrivateData.get( this ).addEventListener( type, handler, opt_thisObject ); - }, - removeEventListener : function( type, handler ){ - NodePrivateData.get( this ).removeEventListener( type, handler ); - }, - scrollTo : function( x, y ){ - NodePrivateData.get( this ).scrollTo( x, y ); - }, - scrollX : function( v ){ - return NodePrivateData.get( this ).scrollX( v ); - }, - scrollY : function( v ){ - return NodePrivateData.get( this ).scrollY( v ); - }, - invalidateScrollbar : function(){ - ScrollBarManager.update( NodePrivateData.get( this ) ); - } - }; - - /** - * clip : true の場合、子ノードの変更によってヒットエリアを変化させない.elm には overflow:hidden としておくのが通常. - */ - var NodePrivateData = function(){}; - NodePrivateData.prototype = { - elmMouseCatch : null, // rootData only - eventCounter : null, // rootData only - cursorStyle : null, // rootData only - node : null, - apiuser : null, - rootData : null, - elm : null, // resizeTarget - elmScroll : null, - elmScroller : null, - elmScrollbar : null, - x : 0, - y : 0, - w : 0, - h : 0, - t : 0, // top - l : 0, // left - b : 0, // bottom - r : 0, // right - absoluteX : 0, - absoluteY : 0, - _scrollX : 0, - _scrollY : 0, - scrollingX : 0, - scrollingY : 0, - scrollStartX : 0, - scrollStartY : 0, - _cursor : '', - // parentLayer : null, - parentData : null, - childData : null, - events : null, - hitChild : null, - hitSelf : false, - _disabled : false, - _childDisabled: false, - layoutManager : null, - through : false, - clip : false, - hover : false, - hoverClass : null, - isHover : false, - scroll : false, - dragdrop : false, - tooltip : null, - init: function( apiuser, rootData, /*parentLayer,*/ parentData, node, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){ - this.apiuser = apiuser; - this.rootData = rootData || this; - // this.parentLayer = parentLayer; - this.parentData = parentData; - this.node = node; - this.through = through; - this.clip = !!clip; - if( cursor ) this._cursor = cursor; - - if( Type.isHTMLElement( rangeOrElm ) === true ){ - this.elm = rangeOrElm; - this.hover = !!hover; - this.hoverClass = hover; - this.scroll = clip && scroll; - this.mesure(); - this.scroll === true && ScrollBarManager.register( this ); - } else { - this.update( rangeOrElm.x, rangeOrElm.y, rangeOrElm.w, rangeOrElm.h ); - }; - - NodePrivateData.dataList.push( this ); - }, - mesure : function(){ - var x, y, w, h, parent, _this, _parent; - if( this.elm ){ - w = this.elm.offsetWidth; - h = this.elm.offsetHeight; - _this = Position.cumulativeOffset( this.elm ); - _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ]; - x = _this[ 0 ] - _parent[ 0 ]; - y = _this[ 1 ] - _parent[ 1 ]; - if( this.x !== x || this.y !== y || this.w !== w || this.h !== h ){ - this.x = x; - this.y = y; - this.w = w; - this.h = h; - parent = this.parentData; - parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY ); - this._updateRectangle(); - }; - } else { - this._updateRectangle(); - }; - }, - mesureChildren : function(){ - var nodes, i; - if( nodes = this.childData ){ - for( i = nodes.length; i; ){ - nodes[ --i ].mesure(); - }; - }; - }, - update : function( x, y, w, h ){ - var updateXY = false, - _this, _parent, - parent; - - if( this.elm ){ - // width - if( Type.isFinite( w ) === true ){ - this.elm.style.width = w + 'px'; - } else - if( Type.isString( w ) === true ){ - this.elm.style.width = w; - w = this.elm.offsetWidth; - }; - //update = this.w !== w; - - // height - if( Type.isFinite( h ) === true ){ - this.elm.style.height = h + 'px'; - } else - if( Type.isString( h ) === true ){ - this.elm.style.height = w; - h = this.elm.offsetHeight; - }; - //update = update || this.h !== h; - - // x - if( Type.isFinite( x ) === true ){ - this.elm.style.left = x + 'px'; - } else - if( Type.isString( x ) === true ){ - this.elm.style.left = x; - updateXY = true; - } else { - updateXY = true; - }; - - // y - if( Type.isFinite( y ) === true ){ - this.elm.style.top = y + 'px'; - } else - if( Type.isString( y ) === true ){ - this.elm.style.top = y; - updateXY = true; - } else { - updateXY = true; - }; - if( updateXY === true ){ - _this = Position.cumulativeOffset( this.elm ); - _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ]; - x = _this[ 0 ] - _parent[ 0 ]; - y = _this[ 1 ] - _parent[ 1 ]; - }; - //update = update || this.x !== x; - //update = update || this.y !== y; - - //update === true && this._updateRectangle(); - // return; - }; - x = Type.isFinite( x ) === true ? x : this.x; - y = Type.isFinite( y ) === true ? y : this.y; - w = Type.isFinite( w ) === true ? w : this.w; - h = Type.isFinite( h ) === true ? h : this.h; - if( this.x !== x || this.y !== y ){ - this.x = x; - this.y = y; - console.log( 'xy ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h + ' absX:' + this.parentData.absoluteX ) - parent = this.parentData; - parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY ); - this.w === w && this.h === h && this._updateRectangle(); - }; - if( this.w !== w || this.h !== h ){ - this.w = w; - this.h = h; - console.log( 'wh ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h ) - this._updateRectangle(); - }; - - ScrollBarManager.update( this ); - }, - _updateAbsoluteXY : function( x, y, sX, sY ){ - var nodes, i; - this.absoluteX = x = this.x + x; - this.absoluteY = y = this.y + y; - if( nodes = this.childData ){ - for( i = nodes.length; i; ){ - nodes[ --i ]._updateAbsoluteXY( x, y, this.scrollingX, this.scrollingY ); - }; - }; - }, - _updateRectangle : function(){ - var w = this.w, - h = this.h, - x = this.x, - y = this.y, - l = x, - t = y, - r = x + w, - b = y + h, - nodes = this.childData, - i, node; - // self; - // childnodes - if( this.clip === false && nodes ){ - for( i = nodes.length; i; ){ - node = nodes[ --i ]; - if( node.l + x < l ) l = x + node.l; - if( node.t + y < t ) t = y + node.t; - if( r < node.r + x ) r = x + node.r; - if( b < node.b + y ) b = y + node.b; - }; - }; - // update - if( b !== this.b || r !== this.r || t !== this.t || l !== this.l ){ - this.l = l; - this.t = t; - this.r = r; - this.b = b; - // this.w = r - x; - // this.h = b - y; - this.parentData && this.parentData.clip === false && this.parentData._updateRectangle(); - return true; - }; - }, - setPosition : function( x, y ){ - this.update( x, y ); - }, - setSize : function( w, h ){ - this.update( undefined, undefined, w, h ); - }, - positionX : function( x ){ - x !== undefined && this.update( x ); - return this.x; - }, - positionY : function( y ){ - y !== undefined && this.update( undefined, y ); - return this.y; - }, - width : function( w ){ - w !== undefined && this.update( undefined, undefined, w ); - return this.w; - }, - height : function( h ){ - h !== undefined && this.update( undefined, undefined, undefined, h ); - return this.h; - }, - getAbsolutePositionX : function(){ - return this.absoluteX; - }, - getAbsolutePositionY : function(){ - return this.absoluteY; - }, - cursor : function( v ){ - if( Type.isString( v ) === true ){ - this._cursor = v; - this === targetNodeData && this.apiuser.updateCoursor( v ); - }; - return this._cursor; - }, - addEventListener : function( eventType, handler, opt_thisObject ){ - var node = this.node, - counter = this.rootData.eventCounter, - list, i; - if( this.events === null ) this.events = {}; - list = this.events[ eventType ]; - if( !list ){ - list = this.events[ eventType ] = []; - } else { - for( i = list.length; i; ){ - if( list[ --i ].match( eventType, handler ) === true ){ - return; - }; - }; - }; - list.push( new EventTicketClass( this.node, eventType, handler, opt_thisObject ) ); - if( eventType !== 'mouseout' && eventType !== 'mouseover' ){ - if( counter[ eventType ] ){ - ++counter[ eventType ]; - } else { - console.log( eventType ); - counter[ eventType ] = 1; - MouseEvent.add( this.apiuser, this.rootData.elmMouseCatch, eventType, eventRellay ); - }; - }; - }, - removeEventListener : function( eventType, handler ){ - var events = this.events, - counter = this.rootData.eventCounter, - type, list, i = 0; - if( events === null ) return; - console.log( ' *** remove ' + eventType ); - for( type in events ){ - list = events[ type ]; - if( eventType && eventType !== type ) continue; - for( ; i < list.length; ){ - if( list[ i ].destroy( type, handler ) === true ){ - console.log( ' *** removed! ' + type ); - list.splice( i, 1 ); - } else { - ++i; - }; - }; - if( list.length === 0 ){ - // delete this[ type ]; - delete events[ type ]; - }; - if( counter[ type ] ){ - --counter[ type ]; - if( counter[ type ] === 0 ){ - MouseEvent.remove( this.apiuser, this.rootData.elmMouseCatch, type, eventRellay ); - delete counter[ type ]; - }; - }; - }; - }, - _capcher : function( x, y ){ - var t = this, nodes, child, _x, _y, hit, i; - if( t._disabled === true ) return false; - delete t.hitChild; - x -= t.x; - y -= t.y; - if( nodes = t.childData ){ - _x = x - t._scrollX; - _y = y - t._scrollY; - for( i = nodes.length; i; ){ - child = nodes[ --i ]; - if( child._disabled === false && child.l <= _x && _x < child.r && child.t <= _y && _y < child.b && child._capcher( _x, _y ) === true ){ - t.hitChild = child; - break; - }; - }; - }; - if( t.through === true ){ - t.hitChild && t.hitSelf === false && hoverList.push( t ); - return !!t.hitChild; - }; - hit = 0 <= x && x < t.w && 0 <= y && y < t.h; - ( t.hitChild || hit ) && t.hitSelf === false && hoverList.push( t ); - if( hit === true && t.hitChild === null ) targetNodeData = t; - return hit || !!t.hitChild; - }, - fire : function( e, eventType, hit ){ - var list = this.events[ eventType ], - i = list.length; - e = NodePrivateData.createEvent( e, eventType, this, hit ); - for( ; i; ) list[ --i ].fire( e ); - // console.log( eventType + ' x:' + x + ' y:' + y ); - }, - dispatchEvent : function( e, eventType, hit ){ - var ret, list, i, p, child; - if( !this.events || !( list = this.events[ eventType ] ) ) return; - - child = !!this.hitChild; - e = NodePrivateData.createEvent( e, eventType, this, hit ); - for( i = list.length; i; ){ - ret = list[ --i ].fire( e ); - if( ret === true && child === false ){ - forceNodeData = this; - return true; - }; - if( ret === false ) return false; - }; - forceNodeData = null; - }, - scrollTo : function( x, y ){ - this._scrollX = x; - this._scrollY = y; - ScrollBarManager.update( this ); - }, - scrollX : function( v ){ - if( Type.isFinite( v ) === true ){ - this._scrillX = v; - ScrollBarManager.update( this ); - }; - return this._scrollX; - }, - scrollY : function( v ){ - if( Type.isFinite( v ) === true ){ - this._scrillY = v; - ScrollBarManager.update( this ); - }; - return this._scrollY; - }, - nodeIndex : function( v ){ - var list, i; - if( !this.parentData ) return 0; - - list = this.parentData.childData; - i = Util.getIndex( list, this ); - if( Type.isFinite( v ) === false || i === v && v < 0 && list.length <= v ) return i; - - list.splice( i, 1 ); - list.length === v ? list.push( this ) : list.splice( v, 0, this ); - this._free(); - return v; - }, - _free : function(){ - if( this.parentData.hitChild === this ){ - this.parentData.hitChild = null; - this.isHover === true && hoverList.splice( Util.getIndex( hoverList, this ), 1 ) && Util.removeClass( this.elm, this.hoverClass ); - this.isHover = false; - if( forceNodeData === this ) forceNodeData = null; - if( targetNodeData === this ) targetNodeData = null; - }; - }, - numNode : function(){ - return this.childData ? this.childData.length : 0; - }, - disabled : function( v ){ - if( Type.isBoolean( v ) === true ){ - this._disabled = v; - if( v === false ){ - this._free(); - }; - }; - return this._disabled; - }, - childrenDisabled : function( v ){ - if( Type.isBoolean( v ) === true ){ - this._childDisabled = v; - }; - return this._childDisabled; - }, - remove : function(){ - if( this === this.rootData ) return; - var parent = this.parentData, - nodes = parent.childData; - this._destroy(); - if( parent.hitChild === this ) delete parent.hitChild; - nodes.splice( Util.getIndex( nodes, this ), 1 ); - if( nodes.length === 0 ) delete parent.childData; - parent.clip === false && parent._updateRectangle(); - }, - _destroy : function(){ - var nodes = this.childData, - list = NodePrivateData.dataList, - node; - this.removeEventListener(); - if( nodes ){ - while( node = nodes.shift() ) node._destroy(); - delete this.childData; - }; - list.splice( Util.getIndex( list, this ), 1 ); - } - }; - NodePrivateData.dataList = []; - NodePrivateData.get = function( node ){ - // if( node instanceof NodePrivateData ) return node; - // return NodePrivateData.dataList[ layer._getUID() ]; - var list = NodePrivateData.dataList; - for( var i = list.length; i; ){ - if( list[ --i ].node === node ) return list[ i ]; - }; - return null; - }; - NodePrivateData.createEvent = function( e, eventType, data, hit ){ - var _e = { - layerX : e.clientX - data.absoluteX, - layerY : e.clientY - data.absoluteY, - clientX : e.clientX, - clientY : e.clientY, - dragOffsetX : e.dragOffsetX, - dragOffsetY : e.dragOffsetY, - eventType : eventType, - hit : hit, - node : data.node, - wheelDelta : e.wheelDelta, - target : forceNodeData ? forceNodeData.node : targetNodeData ? targetNodeData.node : null - }; - return _e; - }; - - var EventTicketClass = function( node, eventType, handler, opt_thisObject ){ - this.node = node; - this.type = eventType; - this.handler = handler; - this.thisObj = opt_thisObject || node; - }; - EventTicketClass.prototype = { - match : function( eventType, handler ){ - if( handler && this.handler !== handler ) return false; - if( eventType && this.type !== eventType ) return false; - return true; - }, - destroy : function( eventType, handler ){ - if( this.match( eventType, handler ) === false ) return false; - delete this.node; - delete this.type; - delete this.handler; - delete this.thisObj; - return true; - }, - fire : ( function(){ - if( Function.prototype.call ){ - return function( e ){ - return this.handler.call( this.thisObj, e ); - }; - }; - return function( e ){ - var ret; - this.thisObj._currentHandler = this.handler; - ret = this.thisObj._currentHandler( e ); - delete this.thisObj._currentHandler; - return ret; - }; - })() - }; - -/*------------------------------------- - * StayHelper - */ - var StayEventTicketClass = function( node, data, stayhandler, opt_thisObject ){ - node.addEventListener( 'mouseover', this.mouseoverHandler, this ); - this.node = node; - this.data = data; - this.handler = stayhandler; - this.thisObject = opt_thisObject; - }; - StayEventTicketClass.prototype = Util.extend( new EventTicketClass( null, 'mousestay' ), { - // type : 'mousestay', - e : null, - mouseoverHandler : function( e ){ - this.e = NodePrivateData.createEvent( e, this.type, this.data, true ); - this.node.addEventListener( 'mouseout', this.mousestayHandler, this ); - this.node.addEventListener( 'mousemove', this.mousemoveHandler, this ); - SystemTimer.add( this.data.apiuser, this.timeoutHandler, null, this ); - }, - timeoutHandler : function(){ - this.mouseoutHandler(); - return this.fire( this.e ); - }, - mousemoveHandler : function( e ){ - this.e = NodePrivateData.createEvent( e, this.type, this.data, true ); - SystemTimer.remove( this.data.apiuser, this.timeoutHandler ); - SystemTimer.add( this.data.apiuser, this.timeoutHandler, null, this ); - }, - mouseoutHandler : function( e ){ - this.node.removeEventListener( 'mouseout', this.mousestayHandler ); - this.node.removeEventListener( 'mousemove', this.mousemoveHandler ); - SystemTimer.remove( this.data.apiuser, this.timeoutHandler ); - delete this.e; - } - }); - - var ScrollBarManager = ( function(){ - var elmScroller = document.createElement( 'div' ), - elmBar = document.createElement( 'div' ), - smoothList = [], - currentNodeData = null; - - function tick(){ - var list = smoothList, - i, data, y; - for( i = 0; i < list.length; ){ - data = list[ i ]; - if( data.scrollingY !== data._scrollY ){ - y = data.scrollingY += data.smoothY; - if( data.smoothY < 0 ){ - y = y < data._scrollY ? data._scrollY : y; - } else { - y = data._scrollY < y ? data._scrollY : y; - }; - data.scrollingY = y; - data.elm.scrollTop = -y; - }; - if( data.scrollingY === data._scrollY ){ - list.splice( i, 1 ); - } else { - ++i; - }; - }; - list.length === 0 && SystemTimer.remove( SUPER_USER_KEY, tick ); - }; - - function onScrollStart( e ){ - var data = this; - if( data === currentNodeData ) return; - currentNodeData && onScrollComplete(); - - data.elm.parentNode.appendChild( elmScroller ); - elmScroller.appendChild( data.elm ); - - elmScroller.style.cssText = 'position:absolute;left:0;top:0;'; - elmScroller.appendChild( elmBar ); - - data.scrollStartX = data.scrollingX; - data.scrollStartY = data.scrollingY; - data.elm.scrollTop = -data.scrollingY; - data.addEventListener( 'mousewheel', onMouseWheelScroll, data ); - data.addEventListener( 'mousedrag', onMouseDragScroll, data ); - data.addEventListener( 'mouseout', onScrollComplete, data ); - currentNodeData = data; - ScrollBarManager.update( data ); - }; - function onScrollComplete( e ){ - if( currentNodeData === null ) return; - - var data = currentNodeData; - var parent = elmScroller.parentNode; - parent.appendChild( currentNodeData.elm ); - parent.removeChild( elmScroller ); - currentNodeData.elm.scrollTop = -data.scrollingY; - - data.removeEventListener( 'mousewheel', onMouseWheelScroll, data ); - data.removeEventListener( 'mousedrag', onMouseDragScroll, data ); - data.removeEventListener( 'mouseout', onScrollComplete, data ); - currentNodeData = null; - }; - function onMouseWheelScroll( e ){ - var data = this; - this._scrollY += e.wheelDelta; - ScrollBarManager.update( this ); - return true; - }; - function onMouseDragScroll( e ){ - var data = this; - //e.dragOffsetY; - this._scrollY = this.scrollStartY + e.dragOffsetY; - ScrollBarManager.update( this ); - this.scrollStartY = this._scrollY; - return true; - }; - - return { - register : function( data ){ - data.addEventListener( 'mouseover', onScrollStart, data ); - }, - update : function( data ){ - if( data !== currentNodeData ) return; - - var contentH = data._scrollH = data.elm.scrollHeight, - clipH = data.h, - offsetH = contentH - clipH, - scrollY = data._scrollY = 0 < data._scrollY ? 0 : ( data._scrollY < -offsetH ? -offsetH : data._scrollY ), - barH, barY; - elmScroller.style.width = data.w + 'px'; - elmScroller.style.height = clipH + 'px'; - if( offsetH < 1 ){ - data._scrollY = scrollY = 0; - elmBar.style.display = 'none'; - } else { - barH = Math.floor( clipH * ( clipH / contentH ) ); - barY = Math.floor( ( clipH - barH ) * - scrollY / offsetH ); - elmBar.style.cssText = [ - 'position:absolute;', - 'width:10px;', - 'background-color:#333;', - 'right:2px;', - 'font-size:0;line-height:0;', - 'height:', barH, 'px;', - 'top:', data.y + barY, 'px;' - ].join( '' ); - }; - data.smoothY = ( scrollY - data.scrollingY ) / 10; - if( data.scrollingY !== scrollY && Util.getIndex( smoothList, data ) === -1 ){ - smoothList.length === 0 && SystemTimer.add( SUPER_USER_KEY, tick, 16 ); - smoothList.push( data ); - }; - } - }; - })(); - - return { - create : function( apiuser ){ - var elm = document.createElement( 'div' ), - root, data; - body.appendChild( elm ); - - root = new NodeClass( apiuser, null, null, elm ); - data = NodePrivateData.get( root ); - - // elm.style.cssText = 'position:absolute;top:0;left:0;height:100%;'; - elm.className = 'mouse-operation-catcher'; - elm.unselectable = 'on'; - data.elmMouseCatch = elm; - - data.eventCounter = {}; - ROOT_LIST.push( data ); - currentRootData = data; - targetNodeData = null; - forceNodeData = null; - - MouseEvent.add( apiuser, elm, 'mousemove', eventRellay ); - return root; - }, - onCurrentApplicationChange : function( _application ){ - currentRootData = null; - targetNodeData = null; - forceNodeData = null; - for( var i = ROOT_LIST.length; i; ){ - if( ROOT_LIST[ --i ].apiuser === _application ){ - currentRootData = ROOT_LIST[ i ]; - return; - }; - }; - }, - destroyTree : function( root ){ - var data = NodePrivateData.get( root ); - MouseEvent.remove( data.apiuser, data.elmMouseCatch, 'mousemove', eventRellay ); - body.removeChild( data.elmMouseCatch ); - data._destroy(); - ROOT_LIST.splice( Util.getIndex( ROOT_LIST, data ), 1 ); - if( currentRootData === data ){ - currentRootData = null; - targetNodeData = null; - forceNodeData = null; - }; - }, - onSystemShutdown : function(){ - - }, - isNodeInstance : function( node ){ - return node instanceof NodeClass; - }, - _getNodePrivateData : function( node ){ // system only - return NodePrivateData.get( node ); - } - }; -})(); - -var Application = ( function(){ - - var LIVE_APPLICATION_LIST = []; - - var currentApplication = null, - coveredApplication = null, - winW = 0, - winH = 0; - - var ApplicationReference = function( appClass, isOverlay, displayName, id, thumbnailUrl, tailColor ){ - var self = this; - var application = null; - this.id = id; - this.displayName = displayName; - this.thumbnailUrl = thumbnailUrl; - this.tailColor = tailColor; - - function asyncBoot(){ - application = Application.boot( appClass, displayName, self.getUID(), isOverlay, Util.copyArray( arguments ) ); - }; - - this.getUID = function(){ - return Util.getIndex( API_USER_LIST, appClass ); - }; - this.boot = function( /* _option */ ){ - AsyncCall.add( this, asyncBoot, Util.copyArray( arguments ) ); - }; - this.shutdown = function(){ - if( !application ) return false; - - AsyncCall.add( application, ( isOverlay === true ? Overlay.hide : application.close ) ); - }; - }; - - function asyncBootHome(){ - currentApplication === null && Home.boot(); - }; - function asyncOpen( /* arguments */ ){ - var _arg = Util.copyArray( arguments ); - _arg.unshift( winW, winH ); - currentApplication.open.apply( currentApplication, _arg ); - }; - return { - register: function( _class, _overlay, _tail, _displayName, _id, _thumbnailUrl, _tailColor ){ - APPLICATION_LIST.push( _class ); - API_USER_LIST.push( _class ); - var _ref = new ApplicationReference( _class, _overlay, _displayName, _id, _thumbnailUrl, _tailColor ); - _tail === true && Home.add( _ref ); - return _ref; - }, - isApplicationInstance: function( app ){ - return ApplicationPrivateData.get( app ) !== null; - }, - isApplicationReference: function( _reference ){ - return _reference instanceof ApplicationReference; - }, - isCurrentAppplication: function( app ){ - return app === currentApplication; - }, - boot: function( appClass, displayName, uid, isOverlay, arg ){ - if( currentApplication ){ - if( currentApplication.getUID() === uid ) return null; - if( isOverlay === false && currentApplication.close() === false ) return null; - }; - - appClass.prototype = new AbstractApplication( appClass, displayName, isOverlay ); - - var application = new appClass(), - data = ApplicationPrivateData.get( application ); - - application.rootElement = data.rootElement; - data.application = application; - - coveredApplication = isOverlay === true ? currentApplication : null; - - Application.onCurrentApplicationChange( application ); - - if( isOverlay === false ){ - body.style.backgroundColor = application.bgColor; - - body.appendChild( data.rootElement ); - data.rootElement.style.display = 'none'; - application.init(); - - application.addAsyncCall( asyncOpen, arg ); - } else { - Overlay.show( application, arg ); - }; - - return application; - }, - shutdown: function( _application, isOverlay ){ - if( isOverlay === false ){ - currentApplication = null; - AsyncCall.add( SUPER_USER_KEY, asyncBootHome ); - } else { - Application.onCurrentApplicationChange( coveredApplication ); - coveredApplication = null; - }; - }, - onCurrentApplicationChange: function( _application ){ - if( Application.isApplicationInstance( _application ) === false ) return; - if( currentApplication === _application ) return; - currentApplication = _application; - MouseEvent.onCurrentApplicationChange( _application ); - PointingDeviceEventTree.onCurrentApplicationChange( _application ); - KeyEvent.updateCurrentListener( _application ); - // InteractiveLayer.onCurrentApplicationChange( _application ); - }, - onApplicationShutdown: function( _application ){ - LIVE_APPLICATION_LIST.splice( Util.getIndex( LIVE_APPLICATION_LIST, _application ) ); - }, - onWindowResize: function( w, h ){ - winW = w; - winH = h; - currentApplication && currentApplication.resize( w, h ); - Overlay.onWindowResize( w, h ); - UI.onWindowResize( w, h ); - }, - onSystemShutdown: function(){ - - } - } -})(); - -/* -------------------------------------------------------------- - * Home - * - */ - var Home = ( function(){ - var APP_REF_LIST = []; - var ELM_TAIL_ORIGIN = ( function(){ - var ret = document.createElement( 'div' ), - h2 = document.createElement( 'h2' ); - ret.className = 'tail-wrapper'; - ret.appendChild( h2 ); - h2.appendChild( document.createTextNode( 'appName' ) ); - return ret; - })(); - - var TailClass = function( appRef ){ - this.elm = ELM_TAIL_ORIGIN.cloneNode( true ); - this.destroy = function(){ - appRef = self = elmName = null; - }; - - var self = this, - elmName = this.elm.getElementsByTagName( 'h2' )[ 0 ].firstChild; - - this.elm.style.backgroundColor = appRef.tailColor; - elmName.data = appRef.displayName; - }; - - var ref = Application.register( function(){ - var self = this, - winW = 0, - winH = 0, - tailList = [], - elmContainer, elmHeader; - - function draw(){ - var tail, elm; - for( var i=0, l=APP_REF_LIST.length; i 0 ){ - tailList.shift().destroy(); - } - self = tailList = elmContainer = null; - }; - }, false, false, 'home', 'home', null ); - - return { - add: function( _appRef ){ - if( Application.isApplicationReference( _appRef ) === false ) return; - Util.getIndex( APP_REF_LIST, _appRef ) === -1 && APP_REF_LIST.push( _appRef ); - }, - boot: function(){ - ref.boot(); - } - } - })(); - - var Page = ( function(){ - var pageNodes = [], - appClass, ref, - ignoreTagList = [ 'script', 'noscript', 'style' ]; - - var MemoryClass = function( node ){ - this.node = node; - }; - MemoryClass.prototype = { - init: function(){ - var node = this.node, - _nodeType = node.nodeType; - if( _nodeType === 1 && Util.getIndex( ignoreTagList, node.tagName.toLowerCase() ) === -1 ){ - this.type = _nodeType; - this.display = node.style.display; - } else - if( _nodeType === 3 ){ - if( node.data.replace( /\s/g, '' ).length !== 0 ){ - this.type = _nodeType; - this.before = pageNodes.length === 0 ? null : pageNodes[ pageNodes.length - 1 ].node; - } else { - body.removeChild( node ); - return false; - } - } else { - // body.removeChild( node ); - return false; - }; - }, - show: function(){ - if( this.type === 1 ){ - if( this.display ){ - this.node.style.display = this.display; - } else { - this.node.style.display = ''; - } - } else { - if( this.before ){ - body.insertBefore( this.node, this.before ); - } else { - body.appendChild( this.node ); - }; - }; - }, - hide: function(){ - if( !this.node.parentNode ){ - return; - }; - if( this.type === 1 ){ - this.node.style.display = 'none'; - } else { - body.removeChild( this.node ); - }; - } - }; - - return { - onReady: function(){ - var _children = Util.copyArray( body.childNodes ), - _mem; - for( var i = 0, l = _children.length; i= CLICK_OFFSET && this.mouseoutHandler(); - }, - mouseupHandler : function( e ){ - this.mouseoutHandler(); - return this.fire( ClickEventTicketClass.createEvent( e ) ); - }, - mouseoutHandler : function( e ){ - this.mousemoveTicket && this.mousemoveTicket.destroy(); - this.mouseupTicket && this.mouseupTicket.destroy(); - this.mouseoutTicket && this.mouseoutTicket.destroy(); - if( this.mousemoveTicket ) delete this.mousemoveTicket; - if( this.mouseupTicket ) delete this.mouseupTicket; - if( this.mouseoutTicket ) delete this.mouseoutTicket; - }, - destroy : function( _element, _eventType, _handler ){ - if( this.match( _element, _eventType, _handler ) === false ) return false; - - this.mouseoutHandler(); - this.mousedownTicket.destroy(); - - delete this.element; - delete this.handler; - delete this.thisObject; - delete this.mousedownTicket; - return true; - } - }; - if( document.createEvent ){ - ClickEventTicketClass.createEvent = function( e ){ - var _e = document.createEvent( 'MouseEvents' ); - _e.initMouseEvent( - 'click' , false, true, e.view, - e.detail, e.screenX, e.screenY, e.clientX, e.clientY, - e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, - e.button, e.relatedTarget - ); - return _e; - }; - } else - if( document.attachEvent ){ - ClickEventTicketClass.createEvent = function( e ){ - e.type = 'click'; - return e; - }; - } else { - - }; - - /*------------------------------------- - * WheelHelper - */ - var WheelEventTicketClass = ( function(){ - if( UA.GECKO ){ - return function( element, wheelhandler, opt_thisObject ){ - this.wheelTicket = new EventTicketClass( element, 'DOMMouseScroll', this.onGeckoWheel, this ); - this.element = element; - this.handler = wheelhandler; - this.thisObject = opt_thisObject; - }; - } else - if( true || UA.isIE ){ - return function( element, wheelhandler, opt_thisObject ){ - this.wheelTicket = new EventTicketClass( element, this.eventType, wheelhandler ); - this.element = element; - this.handler = wheelhandler; - this.thisObject = opt_thisObject; - }; - } else { - TMP.wheelHandlerList = []; - TMP.wheelThisObjList = []; - //TMP.wheelLegacy = undefined; - TMP.onWheel = function( e ){ - e = e || window.event; - var cancel = true, - f = TMP.wheelLegacy; - if( f ) cancel = f.call( this, e ); - - for( i = TMP.wheelHandlerList.length; i; ){ - if( TMP.wheelHandlerList[ --i ].call( TMP.wheelThisObjList[ i ] || this, e ) === false ) cancel = false; - }; - return cancel; - }; - return function( element, wheelhandler, opt_thisObject ){ - this.element = element; - this.handler = wheelhandler; - this.thisObject = opt_thisObject; - - if( TMP.wheelHandlerList.length === 0 ){ - //TMP.wheelLegacy = Type.isFunction( window.onmousewheel ) === true ? window.onmousewheel : undefined; - element.onmousewheel = TMP.onWheel; - }; - TMP.wheelHandlerList.push( wheelhandler ); - TMP.wheelThisObjList.push( opt_thisObject ) - }; - }; - })(); - WheelEventTicketClass.prototype = { - eventType : 'mousewheel', - match : EventTicketClass.prototype.match, - destroy : function( _element, _eventType, _handler ){ - if( this.match( _element, _eventType, _handler ) === false ) return false; - - this.wheelTicket && this.wheelTicket.destroy(); - - delete this.wheelTicket; - delete this.element; - delete this.handler; - delete this.thisObject; - - this.onDestroy && this.onDestroy(); - return true; - } - }; - if( UA.GECKO ){ - WheelEventTicketClass.prototype.onGeckoWheel = function( e ){ - var _e = document.createEvent( 'MouseEvents' ); - _e.initMouseEvent( - 'mousewheel' , false, true, e.view, - e.detail, e.screenX, e.screenY, e.clientX, e.clientY, - e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, - e.button, e.relatedTarget - ); - _e.wheelDelta = e.detail * -40; - return this.handler.call( this.thisObject || this.element, _e ); - }; - } else - if( true || UA.isIE ){ - - } else { - WheelEventTicketClass.prototype.onDestroy = function(){ - TMP.wheelHandlerList.splice( Util.getIndex( TMP.wheelHandlerList, this.handler ), 1 ); - TMP.wheelThisObjList.splice( Util.getIndex( TMP.wheelThisObjList, this.handler ), 1 ); - if( TMP.wheelHandlerList.length === 0 ) this.element.onmousewheel = ''; - }; - }; - - /*------------------------------------- - * DragHelper - */ - var DragEventTicketClass = function( element, draghandler, opt_thisObject ){ - this.mousedownTicket = new EventTicketClass( element, 'mousedown', this.mousedownHandler, this ); - this.element = element; - this.handler = draghandler; - this.thisObject = opt_thisObject; - }; - DragEventTicketClass.prototype = { - element : null, - handler : null, - thisObject : null, - startX : 0, - startY : 0, - dragging : false, - mousedownTicket : null, - mousemoveTicket : null, - mouseupTicket : null, - mouseoutTicket : null, - eventType : 'mousedrag', - fire : EventTicketClass.prototype.fire, - match : EventTicketClass.prototype.match, - mousedownHandler: function( e ){ - this.startX = e.clientX; - this.startY = e.clientY; - - this.mousemoveTicket = new EventTicketClass( this.element, 'mousemove', this.dragMoveHandler, this ); - this.mouseupTicket = new EventTicketClass( this.element, 'mouseup', this.dragEndHandler, this ); - this.mouseoutTicket = new EventTicketClass( this.element, 'mouseout', this.dragEndHandler, this ); - }, - dragMoveHandler : function( e ){ - var offsetX = e.clientX - this.startX, - offsetY = e.clientY - this.startY; - if( this.dragging === false ){ - if( offsetX * offsetX + offsetY * offsetY < DRAG_OFFSET ) return; - // dragStart - this.dragging = true; - return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 0 ) ); - }; - return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 1 ) ); - }, - dragEndHandler : function( e ){ - var offsetX = e.clientX - this.startX, - offsetY = e.clientY - this.startY; - if( this.dragging === true ){ - this.removeEvents(); - // dragEnd - return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 2 ) ); - }; - this.removeEvents(); - }, - removeEvents : function(){ - this.dragging = false; - if( this.mousemoveTicket ){ - this.mousemoveTicket.destroy(); - delete this.mousemoveTicket; - }; - if( this.mouseupTicket ){ - this.mouseupTicket.destroy(); - delete this.mouseupTicket; - }; - if( this.mouseoutTicket ){ - this.mouseoutTicket.destroy(); - delete this.mouseoutTicket; - }; - }, - destroy : function( _element, _eventType, _handler ){ - if( this.match( _element, _eventType, _handler ) === false ) return false; - - this.removeEvents(); - this.mousedownTicket.destroy(); - - delete this.element; - delete this.handler; - delete this.thisObject; - delete this.mousedownTicket; - return true; - } - }; - if( document.createEvent ){ - DragEventTicketClass.createEvent = function( e, offsetX, offsetY, dragPhase ){ - var _e = document.createEvent( 'MouseEvents' ); - _e.initMouseEvent( - DragEventTicketClass.prototype.eventType , false, true, e.view, - e.detail, e.screenX, e.screenY, e.clientX, e.clientY, - e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, - e.button, e.relatedTarget - ); - _e.dragPhase = dragPhase; - _e.dragOffsetX = offsetX; - _e.dragOffsetY = offsetY; - return _e; - }; - } else - if( document.attachEvent ){ - DragEventTicketClass.createEvent = function( e, offsetX, offsetY, dragPhase ){ - e.type = DragEventTicketClass.prototype.eventType; - e.dragPhase = dragPhase; - e.dragOffsetX = offsetX; - e.dragOffsetY = offsetY; - return e; - }; - } else { - - }; - - return { - add: function( _apiuser, _element, _eventType, _handler, opt_thisObject ){ - if( isApiUser( _apiuser ) === true && - ( Type.isHTMLElement( _element ) === true || _element === window || _element === document ) && - Type.isString( _eventType ) === true && - Type.isFunction( _handler ) === true - ){ - var _uid = _apiuser.getUID(), - _events = EVENT_LIST_MAP[ _uid ]; - if( Type.isArray( _events ) === false ){ - _events = EVENT_LIST_MAP[ _uid ] = []; - } else { - // 2重登録の禁止 - for( var i=0, l=_events.length; i 0; - } catch( e ){ - return false; - }; - }, - done: false - }; - - function getTicket( elm ){ - for( var i = TICKET_LIST.length, t; i; ){ - t = TICKET_LIST[ --i ]; - if( t.elm === elm ) return t; - }; - }; - - function detect(){ - var t = getTicket( this ), rs = this.readyState, c; - if( t && t.done === false && ( !rs || Util.getIndex( STATE_LIST, rs ) !== -1 ) ){ - t.done = true; - t.loaded(); - this.onreadystatechange = new Function(); - this.onload = null; - }; - }; - - function checkTimer(){ - var l = TICKET_LIST.length, - n = 0; - for( var i = 0; i < l; ++i ){ - t = TICKET_LIST[ i ]; - ++t.time; - if( t.check() === true ){ - t.loaded(); - ++n; - } else - if( t.time > 99 ){ - t.error(); - } else { - - }; - }; - l === n && SystemTimer.remove( SUPER_USER_KEY, checkTimer ); - }; - - return { - load: function( _apiuser, _url, opt_onload, opt_onerror, opt_thisObject ){ - _url = Util.getAbsolutePath( _url ); - var t; - for( var i=TICKET_LIST.length; i; ){ - t = TICKET_LIST[ --i ]; - if( t.match( null, _url ) === true ){ - if( t.match( _apiuser, _url ) === false ){ - t.apiusers.push( _apiuser ); - t.onload.push( opt_onload ); - t.onerror.push( opt_onerror ); - t.thisObj.push( opt_thisObject ); - }; - SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 ); - return; - }; - }; - var elm = document.createElement( 'link' ); - head.appendChild( elm ); - elm.rel = 'stylesheet'; - elm.type = 'text\/css'; - elm.onreadystatechange = elm.onload = detect; - elm.href = _url; - - if( !sheet ){ // only assign these once - cssRules = 'cssRules'; - sheet = 'sheet'; - if ( !( sheet in elm ) ) { // MSIE uses non-standard property names - cssRules = 'rules'; - sheet = 'styleSheet'; - }; - }; - - TICKET_LIST.push( new FetchCssTicketClass( _apiuser, _url, elm, opt_onload, opt_onerror, opt_thisObject ) ); - - SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 ); - }, - unload: function( _apiuser, _url ){ - _url = _url ? Util.getAbsolutePath( _url ) : null; - for( var i = 0; i < TICKET_LIST.length; ){ - t = TICKET_LIST[ i ]; - if( t.destroy( _apiuser, _url ) === true ){ - TICKET_LIST.splice( i, 1 ); - } else { - ++i; - } - }; - if( TICKET_LIST.length === 0 ){ - SystemTimer.remove( SUPER_USER_KEY, checkTimer ); - } - } - } -})(); - -/* - * AssetLoader - * fetchCSS - * fetchJson - * fetchHtml - * fetchImage - * fetchLocalFile - * fetchLocalStorage - */ - -var Image = ( function(){ - var TASK_LIST = []; - /* - * FetchClass original is - * - * LICENSE: MIT? - * URL: http://d.hatena.ne.jp/uupaa/20080413/1208067631 - * AUTHOR: uupaa.js@gmail.com - * - */ - function detect(){ - for( var i=0, t; i < TASK_LIST.length; ){ - t = TASK_LIST[ i ]; - if( t.complete() === true ){ - TASK_LIST.splice( i, 1 ); - } else { - ++i; - }; - }; - TASK_LIST.length === 0 && SystemTimer.remove( SUPER_USER_KEY, detect ); - }; - function getTask( img ){ - for( var i = TASK_LIST.length; i; ){ - if( TASK_LIST[ --i ].img === img ) return TASK_LIST[ i ]; - }; - }; - function onError(){ - var task = getTask( this ); - if( task.finish === true ) return; - task.finish = true; - AsyncCall.add( task.apiuser, task.asyncCallback, null, task ); - }; - function onLoad(){ - // if( finish === true ) return; // これがあると firefox3.6 で駄目、、、 - // if( timer ) return; // これがあると safari3.2 で駄目、、、 - var task = getTask( this ); - task.finish = true; - TASK_LIST.splice( Util.getIndex( TASK_LIST, task ), 1 ); - if( window.opera && !task.img.complete ){ - AsyncCall.add( task.apiuser, task.asyncCallback, null, task ); - return; - }; - task.size = Util.getImageSize( this ); - AsyncCall.add( task.apiuser, task.asyncCallback, null, task ); - }; - - - var FetchClass = function( apiuser, abspath, onLoadCallback, onErrorCallback, timeout ){ - this.apiuser = apiuser; - this.abspath = abspath; - this.onLoadCallback = onLoadCallback; - this.onErrorCallback = onErrorCallback; - this.timeout = timeout; - this.tick = 0; - }; - FetchClass.prototype = { - img: null, - size: null, - tick: 0, - finish: false, - load: function(){ - var img = this.img = document.createElement( 'img' ); //var img = new Image(); ではieでimgのsizeが取れない、、、removeChildも失敗し、imgSizeGetterにimgが残る - img.onabort = img.onerror = onError; - img.onload = onLoad; - img.src = this.abspath; - }, - complete: function(){ - if( this.finish === true ) return true; - if( this.img.complete ){ - this.finish = true; - if( this.img.width ) return true; - AsyncCall.add( this.apiuser, this.asyncCallback, null, this ); - return true; - }; - if( ( this.tick += 250 ) > this.timeout ){ - this.finish = true; - AsyncCall.add( this.apiuser, this.asyncCallback, null, this ); - return true; - }; - }, - asyncCallback: function(){ - this.size ? this.onLoadCallback( this.abspath, this.size.width, this.size.height ) : this.onErrorCallback( this.abspath ); - this.destroy(); - }, - destroy: function(){ - this.finish = true; - this.img.src = this.img.onload = this.img.onabort = this.img.onerror = ''; - delete this.img; - delete this.size; - delete this.onLoadCallback; - delete this.onErrorCallback; - }, - stop: function(){ - timer !== null && window.clearTimeout( timer ); - destroy(); - } - }; - - return { - load: function( URLorELM, onLoad, onError, opt_timeout ){ - var src, fetch; - if( Type.isString( URLorELM ) === true ){ - src = URLorELM; - } else - if( Type.isHTMLElement( URLorELM ) === true && URLorELM.tagName.toLowerCase() === 'img' ){ - src = URLorELM.src; - } else { - return; - }; - - fetch = new FetchClass( - Util.getAbsolutePath( src ), - onLoad, onError, - Type.isFinite( opt_timeout ) === true ? opt_timeout : undefined - ); - TASK_LIST.push( fetch ); - - SystemTimer.add( SUPER_USER_KEY, detect, 250 ); - }, - unload: function( ){ - - } - }; -})(); - - -/* ---------------------------------------- - * - */ - -var Overlay = ( function(){ - var elmContainer, elmShadow, elmCloseButton, - application = null, - visible = false, - bodyOverflow = '', - windowW, windowH; - - function onCloseClick( e ){ - Overlay.hide(); - return false; - }; - function asyncInit( /* arguments */ ){ - application.init(); - //application.rootElement.style.display = 'none'; - }; - function asyncOpen( /* arguments */ ){ - var _arg = Util.copyArray( arguments ); - _arg.unshift( windowW, windowH ); - application.open.apply( application, _arg ); - - elmContainer.style.cssText = "top:" + body.scrollTop + 'px;display:none;'; - $( elmContainer ).stop().fadeIn( onFadeInComplete ); - }; - function onFadeInComplete(){ - KeyEvent.add( application, Const.KEY.EVENT.KEY_DOWN, Overlay.hide, 27 ); // 27.esc - MouseEvent.add( application, elmCloseButton, 'click', onCloseClick ); - }; - function onFadeOutComplete(){ - Util.removeAllChildren( elmContainer ); - body.removeChild( elmContainer ); - elmContainer = elmShadow = elmCloseButton = null; - }; - return { - show: function( _application, _bootParams ){ - if( visible === true && application === _application ) return; - if( Application.isApplicationInstance( _application ) === false ) return; - - elmContainer = document.createElement( 'div' ); - body.appendChild( elmContainer ); - - elmContainer.id = 'overlay-container'; - - bodyOverflow = body.style.overflow; - body.style.overflow = 'hidden'; - - elmShadow = document.createElement( 'div' ); - elmContainer.appendChild( elmShadow ); - elmShadow.id = 'overlay-shadow'; - - elmCloseButton = document.createElement( 'div' ); - elmContainer.appendChild( elmCloseButton ); - elmCloseButton.id = 'overlay-close-button'; - elmCloseButton.appendChild( document.createTextNode( 'x' ) ); - - elmContainer.style.display = 'none'; // hide for fadeIn - - visible = true; - application = _application; - - //asyncInit(); - elmContainer.insertBefore( application.rootElement, elmCloseButton ); - _application.addAsyncCall( asyncInit ); - _application.addAsyncCall( asyncOpen, _bootParams ); - }, - hide: function(){ - if( visible === false ) return; - if( application.close() === false ) return false; - - body.style.overflow = bodyOverflow; - - $( elmContainer ).stop().css( { - filter: '', - opacity: '' - }).fadeOut( onFadeOutComplete ); - visible = false; - - application = null; - }, - onWindowResize: function( _windowW, _windowH ){ - windowW = _windowW; - windowH = _windowH; - - if( application === null ) return; - - elmContainer.style.height = _windowH + 'px'; - elmContainer.style.top = body.scrollTop + 'px'; - - elmShadow.style.height = _windowH + 'px'; - - AsyncCall.add( application, application.resize, [ _windowW, _windowH ] ); - } - } -})(); - -/* ---------------------------------------- - * UI - * - * keyEventRellay - * form -> overlay -> view - * - */ - -var UI = ( function(){ - var UI_LIST = [], - currentUser = null, - currentList = null, - currentUi = null, - currentItem = null, - windowW = 0, - windowH = 0; - - var CLASSNAME_COMBOBOX_OPTION = 'combobox-option', - CLASSNAME_COMBOBOX_OPTION_CURRENT = CLASSNAME_COMBOBOX_OPTION + ' combobox-option-current', - ELM_COMBOBOX = ( function(){ - var ret = document.createElement( 'a' ), - elmToggle = document.createElement( 'span' ), - elmValue = document.createElement( 'span' ); - ret.href = '#'; - ret.appendChild( elmToggle ); - ret.appendChild( elmValue ); - elmToggle.className = 'combobox-toggle'; - elmValue.className = 'combobox-value'; - - elmToggle.appendChild( document.createTextNode( '▼' )); - elmValue.appendChild( document.createTextNode( 'null' )); - return ret; - })(); - - var UIItemPrivateData = function(){}; - UIItemPrivateData.prototype = { - groupData : null, - item : null, - elm : null, - node : null, - focus : false, - visible : true, - enabled : true, - value : null, - onUpdate : null, - validator : null, - elmValue : null, - elmBox : null, - elmA : null, - elmToggle : null, - elmValue : null, - selectIndex : 0, - optionList : null, - init : function( groupData, item, elm, value, onUpdate, validator, focus, visible, enabled ){ - this.groupData = groupData; - this.item = item; - this.elm = elm; - this.value = value; - this.onUpdate = onUpdate; - this.validator = validator; - this.focus = !!focus; - this.visible = !!visible; - this.enabled = !!enabled; - UIItemPrivateData.list.push( this ); - }, - destroy : function(){ - var list = UIItemPrivateData.list; - list.splice( Util.getIndex( list, this ), 1 ); - - this.node && this.node.remove(); - } - }; - UIItemPrivateData.list = []; - UIItemPrivateData.get = function( item ){ - var list = UIItemPrivateData.list; - for( i = list.length; i; ){ - if( list[ --i ].item === item ) return list[ i ]; - }; - return null; - }; - -/* -------------------------------- - * TextInputManager - */ - var TextInputManager = ( function(){ - var elmInput = ( function(){ - var ret = document.createElement( 'input' ); - ret.type = 'text'; - ret.id = 'ui-textinput'; - return ret; - })(); - var currentData; - - function updateWrapperPosition(){ - var p = Position.cumulativeOffset( currentData.elmValue ), - w = currentData.elmValue.offsetWidth - 2, - _w; - elmInput.style.cssText = [ - 'left:', p[ 0 ], 'px;', - 'top:', p[ 1 ], 'px;',//, - 'width:', w, 'px;'//, - //'height:', data.elmValue.offsetHeight, 'px;', - //'position:absolute;' - ].join( '' ); - - //_w = elmInput.offsetWidth; - //if( w !== _w ) elmInput.style.width = ( w - ( _w - w ) ) + 'px;'; - }; - - return { - show: function( data ){ - // this.groupData.node.addEventListener( 'mouseout' ); - currentData = data; - - body.appendChild( elmInput ); - elmInput.value = data.value; - updateWrapperPosition(); - - elmInput.focus(); - elmInput.select(); - - SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 ); - }, - hide : function( data ){ - if( currentData !== data ) return; - currentData = null; - body.removeChild( elmInput ); - var ret = elmInput.value; - elmInput.value = ''; - SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition ); - return ret; - }, - update : function( data ){ - elmInput.value = data.value; - }, - onWindowResize: function( _w, _h ){ - AsyncCall.add( currentUser, updateWrapperPosition ); - } - }; - })(); - - var TextInputClass = function( groupData, elmWrapper, elmValue, onUpdate, validater ){ - var data = new UIItemPrivateData(); - data.init( groupData, this, elmWrapper, elmValue.innerHTML, onUpdate, validater, false, true, true ); - Util.addClass( elmValue, 'editable-text' ); - data.elmValue = elmValue; - this.value( data.value ); - data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-inpittext-hover', 'pointer' ); - data.node.addEventListener( 'click', this.focus, this ); - //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', instance.focus ); - }; - TextInputClass.prototype = { - value : function( value ){ - var data = UIItemPrivateData.get( this ); - if( Type.isString( value ) === true || Type.isNumber( value ) === true ){ - data.elmValue.innerHTML = data.value = '' + value; - data.focus === true && TextInputManager.update( data ); - }; - data.focus === true && this.blur(); - return data.value; - }, - focus : function( e ){ - var data = UIItemPrivateData.get( this ); - data.focus = true; - start( data ); - TextInputManager.show( data ); - return false; - }, - blur : function( keep ){ - var data = UIItemPrivateData.get( this ), - newValue; - if( data.focus === false ) return; - newValue = TextInputManager.hide( data ); - newValue = keep !== 27 ? ( data.validater ? '' + data.validater( newValue ) : newValue ) : data.value; // 27:ESC - - data.elmValue.innerHTML = newValue; - - data.onUpdate && newValue !== data.value && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ newValue, data.value ], this ); - - data.value = newValue; - data.focus = false; - finish( data ); - }, - enabled : function( v ){ - var data = UIItemPrivateData.get( this ); - if( Type.isBoolean( v ) === true && data.enabled !== v ){ - Util.toggleClass( data.elm, 'ui-textinput-disabled', !v ); - if( data.focus === true && v === false ) this.blur(); - data.enabled = v; - data.node.disabled( !( data.visible && v ) ); - }; - return data.enabled; - }, - visible : function( v ){ - var data = UIItemPrivateData.get( this ); - if( Type.isBoolean( v ) === true && data.visible !== v ){ - data.elm.style.display = v ? '' : 'none'; - if( data.focus === true && v === false ) this.blur(); - data.visible = v; - data.node.disabled( !( data.enabled && v ) ); - }; - return data.visible; - }, - destroy : function(){ - var data = UIItemPrivateData.get( this ); - data.focus === true && TextInputManager.hide( data ); - data.destroy(); - } - }; - -/* -------------------------------- - * TextInputManager - */ - var FileInputManager = ( function(){ - var currentData, - elmForm, - elmWrap, - evt; - - function updateWrapperPosition(){ - var p = Position.cumulativeOffset( currentData.elmValue ), - w = currentData.elmValue.offsetWidth, - _w; - elmWrap.style.cssText = [ - 'left:', p[ 0 ], 'px;', - 'top:', p[ 1 ], 'px;',//, - 'width:', w, 'px;'//, - //'height:', data.elmValue.offsetHeight, 'px;', - //'position:absolute;' - ].join( '' ); - - _w = elmWrap.offsetWidth; - if( w !== _w ) elmWrap.style.width = ( w - ( _w - w ) ) + 'px'; - }; - - function change( e ){ - var data = currentData, - file = data.elmFileInputReal.value; - file = file.split( '\\' ); - file = file[ file.length - 1 ]; - if( data.value !== file ){ - data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ file, data.value ], this ); - data.elmValue.innerHTML = data.value = file; - }; - currentData.item.blur(); - }; - function asyncMouseout(){ - currentData && currentData.item.blur(); - }; - - return { - show : function( data ){ - currentData = data; - - elmWrap = data.elmFileInputReal.parentNode; - // - - updateWrapperPosition(); - data.elmFileInputReal.focus(); - //data.node.addEventListener( 'change', change, data ); - evt = new EventTicketClass( data.elmFileInputReal, 'change', change ); - // MouseEvent.add( currentUser, data.elmFileInputReal, 'mouseout', asyncMouseout ); - // MouseEvent.add( elmWrap, 'click', data.elmFileInputReal.focus, data.elmFileInputReal ); - currentData.elmFileInputReal.onchange = change; - SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 ); - }, - hide : function( data ){ - if( currentData !== data ) return; - // data.node.removeEventListener( 'change', change ); - evt.destroy(); - MouseEvent.remove( currentUser, currentData.elmFileInputReal, 'mouseout', asyncMouseout ); - currentData.elmFileInputReal.onchange = null; - elmWrap.style.display = 'none'; - currentData = null; - SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition ); - }, - onWindowResize: function( _w, _h ){ - AsyncCall.add( currentUser, updateWrapperPosition ); - } - }; - })(); - - var FileInputClass = function( groupData, elmWrapper, onUpdate, validater, elmFileInputReal, elmValue ){ - var data = new UIItemPrivateData(); - data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true ); - data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-fileinput-hover', 'pointer' ); - data.elmValue = elmValue; - data.elmFileInputReal = elmFileInputReal; - data.node.addEventListener( 'mouseover', this.focus, this ); - }; - FileInputClass.prototype = { - value : function(){ - return data.value; - }, - focus : function(){ - var data = UIItemPrivateData.get( this ); - data.focus = true; - Util.addClass( data.elm, 'fileinput-has-focus' ); - start( data ); - FileInputManager.show( data ); - }, - blur : function( keyCode ){ - var data = UIItemPrivateData.get( this ); - Util.removeClass( data.elm, 'fileinput-has-focus' ); - data.focus = false; - FileInputManager.hide( data ); - finish( data ); - }, - enabled : function( v ){ - var data = UIItemPrivateData.get( this ); - if( Type.isBoolean( v ) === true && data.enabled !== v ){ - if( data.focus === true && v === false ) this.blur(); - Util.toggleClass( data.elm, 'fileinput-disabled', !v ); - data.enabled = v; - data.node.disabled( !( data.visible && v ) ); - }; - return data.enabled; - }, - visible : function( v ){ - var data = UIItemPrivateData.get( this ); - if( Type.isBoolean( v ) === true && data.visible !== v ){ - if( data.focus === true && v === false ) this.blur(); - data.elm.style.display = v ? '' : 'none'; - data.visible = v; - data.node.disabled( !( data.enabled && v ) ); - }; - return data.visible; - }, - destroy : function(){ - var data = UIItemPrivateData.get( this ); - data.focus === true && FileInputManager.hide( data ); - data.destroy(); - } - }; - - var ButtonClass = function( groupData, elmWrapper, onUpdate ){ - var data = new UIItemPrivateData(); - data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true ); - data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-button-hover', 'pointer' ); - data.node.addEventListener( 'click', onUpdate ); - //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', onUpdate ); - }; - ButtonClass.prototype = { - focus : function(){ - var data = UIItemPrivateData.get( this ); - data.focus = true; - Util.addClass( data.elm, 'button-has-focus' ); - start( data ); - }, - blur : function( keyCode ){ - var data = UIItemPrivateData.get( this ); - keyCode === 13 && data.onUpdate && data.onUpdate(); - Util.removeClass( data.elm, 'button-has-focus' ); - data.focus = false; - finish( data ); - }, - enabled : function( v ){ - var data = UIItemPrivateData.get( this ); - if( Type.isBoolean( v ) === true && data.enabled !== v ){ - Util.toggleClass( data.elm, 'button-disabled', !v ); - data.enabled = v; - data.node.disabled( !( data.visible && v ) ); - }; - return data.enabled; - }, - visible : function( v ){ - var data = UIItemPrivateData.get( this ); - if( Type.isBoolean( v ) === true && data.visible !== v ){ - data.elm.style.display = v ? '' : 'none'; - data.visible = v; - data.node.disabled( !( data.enabled && v ) ); - }; - return data.visible; - }, - destroy : function(){ - var data = UIItemPrivateData.get( this ); - // MouseEvent.remove( data.groupData.apiuser, data.elm ); - data.destroy(); - } - }; - - var ComboBoxClass = function( groupData, elmWrapper, onUpdate ){ - var elmA = ELM_COMBOBOX.cloneNode( true ), - data = new UIItemPrivateData(); - data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true ); - - data.elmBox = Util.getElementsByClassName( elmWrapper, 'combobox' )[ 0 ]; - data.elmBox.appendChild( elmA ); - data.elmA = elmA; - data.elmToggle = Util.getElementsByClassName( elmA, 'combobox-toggle' )[ 0 ]; - data.elmValue = Util.getElementsByClassName( elmA, 'combobox-value' )[ 0 ].firstChild; - data.selectIndex = 0; - data.optionList = []; - - data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-combobox-hover', 'pointer' ); - data.node.addEventListener( 'click', this.focus, this ); - }; - ComboBoxClass.prototype = { - focus : function( e ){ - var data = UIItemPrivateData.get( this ); - data.node.removeEventListener( 'click', this.focus ); - data.focus = true; - data.elmA.className = 'combobox-has-focus'; - start( data ); - OptionControl.show( data ); - return false; - }, - blur : function( keyCode ){ - var data = UIItemPrivateData.get( this ); - OptionControl.hide( this ); - data.focus = false; - data.elmA.className = ''; - finish( data ); - data.node.addEventListener( 'click', this.focus, this ); - }, - enabled : function( v ){ - var data = UIItemPrivateData.get( this ); - if( Type.isBoolean( v ) === true && data.enabled !== v ){ - Util.toggleClass( data.elm, 'ui-combobox-disabled', !v ); - if( data.focus === true && v === false ) this.blur(); - data.enabled = v; - data.node.disabled( !( data.visible && v ) ); - }; - return data.enabled; - }, - visible : function( v ){ - var data = UIItemPrivateData.get( this ); - if( Type.isBoolean( v ) === true && data.visible !== v ){ - data.elm.style.display = v ? '' : 'none'; - if( data.focus === true && v === false ) this.blur(); - data.visible = v; - data.node.disabled( !( data.enabled && v ) ); - }; - return data.visible; - }, - value : function( _value ){ - var data = UIItemPrivateData.get( this ), - i = 0, - list = data.optionList, - l = list.length, - _option; - if( Type.isString( _value ) === true && data.value !== _value ){ - for( ; i < l; ++i ){ - _option = list[ i ]; - if( _value === _option.value ){ - data.value = _value; - data.index = i; - data.elmValue.data = _option.displayValue; - if( data.focus === true ){ - OptionControl.update( this, _value ); - }; - data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, _value, this ); - break; - }; - }; - }; - return data.value; - }, - selectIndex : function(){ - var data = UIItemPrivateData.get( this ); - return data.selectIndex; - }, - createOption : function( _displayValue, _value, _isSelected ){ - var data = UIItemPrivateData.get( this ), - option = null, - list = data.optionList, - i = list.length, - _option, i; - _value = _value || _displayValue; - _isSelected = !!_isSelected; - for( ; i; ){ - _option = list[ --i ]; - if( _value === _option.value ){ - option = _option; - break; - }; - }; - if( _isSelected === true ){ - data.selectIndex = list.length; - data.elmValue.data = _displayValue; - }; - option === null && list.push( new OptionDataClass( _displayValue, _value, _isSelected ) ); - }, - destroy : function(){ - var data = UIItemPrivateData.get( this ); - data.focus === true && OptionControl.hide( this ); - // this.blur(); - // MouseEvent.remove( data.groupData.apiuser, data.elm ); - data.optionList.length = 0; - data.destroy(); - } - }; - var OptionDataClass = function( displayValue, value, isCurrent ){ - this.displayValue = displayValue; - this.value = value || displayValue; - this.current = isCurrent; - displayValue = value = null; - }; - - var OptionControl = ( function(){ - var ELM_OPTION_WRAPPER = ( function(){ - var ret = document.createElement( 'div' ); - ret.className = 'option-container'; - return ret; - })(), - ELM_OPTION_ORIGIN = ( function(){ - var ret = document.createElement( 'a' ); - ret.appendChild( document.createTextNode( 'option' ) ); - ret.href = '#'; - return ret; - })(); - - var OptionClass = function( option ){ - this.elm = ELM_OPTION_ORIGIN.cloneNode( true ); - this.data = option; - this.init(); - }; - OptionClass.prototype = { - init: function(){ - ELM_OPTION_WRAPPER.appendChild( this.elm ); - this.elm.firstChild.data = this.data.displayValue; - this.current( this.data.current ); - MouseEvent.add( SUPER_USER_KEY, this.elm, 'mousedown', onOptionSelect );// onclick では 選択ボックス 隠すように body に設定した onmouseup が先に動いてしまう! - }, - current: function( _current ){ - this.elm.className = _current === true ? CLASSNAME_COMBOBOX_OPTION_CURRENT : CLASSNAME_COMBOBOX_OPTION; - this.data.current = _current; - currentOption = _current === true ? this : currentOption; - }, - destroy: function(){ - MouseEvent.remove( SUPER_USER_KEY, this.elm ); - Util.removeAllChildren( this.elm ); - ELM_OPTION_WRAPPER.removeChild( this.elm ); - delete this.elm; - delete this.data; - } - }; - - function onOptionSelect( e ){ - var i = 0, - l = OPTION_LIST.length, - _option; - for( ; i < l; ++i ){ - _option = OPTION_LIST[ i ]; - if( this === _option.elm ){ - updateCurrrentOption( _option.data.value, true ); - currentCombobox.blur(); - break; - }; - }; - return false; - }; - - var OPTION_LIST = [], - currentCombobox = null, - apiuser, - elm, - currentOption, - currentIndex; - - function updateCurrrentOption( _value, _updateCombobox ){ - var _option, - i = OPTION_LIST.length; - for( ; i; ){ - _option = OPTION_LIST[ --i ]; - if( _value === _option.data.value ){ - currentOption && currentOption.current( false ); - _option.current( true ); - currentOption = _option; - currentIndex = i; - _updateCombobox === true && currentCombobox.value( _value ); - break; - }; - }; - }; - function bodyMouseupHandler(){ - currentCombobox.blur(); - OptionControl.hide( currentCombobox ); - }; - function updateWrapperPosition(){ - var position = Util.getAbsolutePosition( elm ); - - ELM_OPTION_WRAPPER.style.cssText = [ - 'width:', elm.offsetWidth - 2, 'px;', - 'left:', position.x, 'px;', - 'top:', position.y + elm.offsetHeight, 'px;' - ].join( '' ); - }; - function change( e ){ - var l = OPTION_LIST.length, - i = currentIndex + ( e.keyCode === 40 ? -1 : 1 ); - if( currentCombobox === null || l < 2 ) return; - i = i < 0 ? - l - 1 : - i < l ? i : 0; - updateCurrrentOption( OPTION_LIST[ i ].data.value, true ); - return false; - }; - return { - show: function( data ){ - var combobox = data.item, - list = data.optionList, - i = 0, - l = list.length; - if( currentItem !== combobox || currentCombobox === combobox ) return; - currentCombobox && currentCombobox.blur(); - - apiuser = data.groupData.apiuser; - currentCombobox = combobox; - elm = data.elmBox; - - for( ; i < l; ++i ){ - OPTION_LIST.unshift( new OptionClass( list[ i ] ) ); - }; - MouseEvent.add( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler ); - KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 38 ); - KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 40 ); - //KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter, 13 ); - //KeyEvent.updateCurrentListener( SUPER_USER_KEY ); - - body.appendChild( ELM_OPTION_WRAPPER ); - - updateCurrrentOption( combobox.value(), false ); - updateWrapperPosition(); - - SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 ); - }, - hide: function( _combobox ){ - if( currentCombobox !== _combobox || currentCombobox === null ) return; - - var _option; - while( _option = OPTION_LIST.shift() ){ - _option.destroy(); - }; - - body.removeChild( ELM_OPTION_WRAPPER ); - - MouseEvent.remove( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler ); - KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change ); - KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change ); - //KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter ); - //KeyEvent.updateCurrentListener( apiuser ); - - SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition, 500 ); - - apiuser = null; - currentCombobox = null; - currentOption = null; - currentIndex = 0; - }, - onEnter: function(){ - currentCombobox.value( currentOption.data.value ); - //currentCombobox.blur(); - //OptionControl.hide( currentCombobox ); - }, - update: function( data, _value ){ - if( currentCombobox !== data.item || currentItem !== data.item ) return; - if( currentOption.data.value === _value ) return; - updateCurrrentOption( _value, true ); - }, - onWindowResize: function( _w, _h ){ - currentCombobox && AsyncCall.add( apiuser, updateWrapperPosition ); - } - }; - })(); - - var UIGroupPrivateData = function(){}; - UIGroupPrivateData.prototype = { - apiuser : null, - node : null, - uigroup : null, - itemList : null, - visible : true, - enabled : true, - init : function( apiuser, node, uigroup ){ - this.apiuser = apiuser; - this.node = node; - this.uigroup = uigroup; - this.itemList = []; - UIGroupPrivateData.list.push( this ); - }, - destroy : function(){ - - } - }; - UIGroupPrivateData.list = []; - UIGroupPrivateData.get = function( uigroup ){ - var list = UIGroupPrivateData.list, - i = list.length; - for( ; i; ){ - if( list[ --i ].uigroup === uigroup ) return list[ i ]; - }; - return null; - }; - - var UIGroupClass = function( apiuser, node ){ - ( new UIGroupPrivateData() ).init( apiuser, node, this ); - }; - UIGroupClass.prototype = { - focus : function( _value ){ - var data = UIGroupPrivateData.get( this ); - /* - if( _value === true ){ - if( currentItem ){ - start( apiuser, self, currentItem ); - } else - if( itemList.length > 0 ){ - start( apiuser, self, itemList[ 0 ] ); - }; - } else - if( _value === false ){ - finish( apiuser, self, currentItem ); - } else - */ - if( _value && Util.getIndex( data.itemList, _value ) !== -1 ){ - // currentItem = _value; - currentList = data.itemList; - }; - return currentUi === this; - }, - blur : function(){ - var data = UIGroupPrivateData.get( this ); - if( currentList === data.itemList ){ - currentList = null; - }; - }, - createInputText : function( elmWrapper, onUpdate, validater ){ - var data = UIGroupPrivateData.get( this ), - elmValue = Util.getElementsByClassName( elmWrapper, 'editable-value' )[ 0 ], - ret; - if( elmValue ){ - ret = new TextInputClass( data, elmWrapper, elmValue, onUpdate, validater ); - data.itemList.push( ret ); - return ret; - }; - alert( 'error createInputText' ); - }, - createButton : function( elm, onClick ){ - var data = UIGroupPrivateData.get( this ), - ret = new ButtonClass( data, elm, onClick ); - data.itemList.push( ret ); - return ret; - }, - createFileInput : function( elm, onUpdate, validater, elmFileInputReal ){ - var data = UIGroupPrivateData.get( this ), - elmValue = Util.getElementsByClassName( elm, 'fileinput-value' )[ 0 ], - ret; - if( elmValue ){ - ret = new FileInputClass( data, elm, onUpdate, validater, elmFileInputReal, elmValue ); - data.itemList.push( ret ); - return ret; - }; - return ret; - }, - createCombobox : function( elm, onUpdate, optionList ){ - var data = UIGroupPrivateData.get( this ), - ret = new ComboBoxClass( data, elm, onUpdate, optionList ); - data.itemList.push( ret ); - return ret; - }, - createCheckBox : function(){ - - }, - createRadio : function(){ - - }, - createSlider : function(){ - - }, - visible : function( v ){ - var data = UIGroupPrivateData.get( this ); - if( Type.isBoolean( v ) === true && data.visible !== v ){ - for( var i = data.itemList.length; i; ){ - data.itemList[ --i ].visible( v ); - }; - data.visible = v; - data.node.disabled( !( data.enabled && v ) ); - }; - return data.visible; - }, - enabled : function( v ){ - var data = UIGroupPrivateData.get( this ); - if( Type.isBoolean( v ) === true && data.enabled !== v ){ - for( var i = data.itemList.length; i; ){ - data.itemList[ --i ].enabled( v ); - }; - data.enabled = v; - data.node.disabled( !( data.visible && v ) ); - }; - return data.enabled; - }, - destroy : function(){ - var data = UIGroupPrivateData.get( this ), - _item; - if( currentUi === this ){ - currentItem.blur(); - // finish( UIItemPrivateData.get( currentItem ) ); - }; - while( _item = data.itemList.shift() ){ - _item.destroy(); - }; - data.destroy(); - } - }; - - function start( data ){ - if( currentItem !== data.item ){ - currentUi !== data.groupData.uigroup && currentUi && currentUi.blur(); - - currentItem !== null && currentItem.blur(); - - currentUser = data.groupData.apiuser; - currentUi = data.groupData.uigroup; - currentItem = data.item; - - currentUi.focus( currentItem ); - - // if( currentUser !== _apiuser ) { - KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 ); - KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 ); - KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 9 ); - KeyEvent.updateCurrentListener( SUPER_USER_KEY ); - // }; - }; - } - function finish( data ){ - if( currentItem === data.item ){ - currentUi.blur(); - - currentUser = null; - currentUi = null; - currentItem = null; - currentList = null; - - KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 ); - KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 ); - KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 9 ); - KeyEvent.updateCurrentListener( data.groupData.apiuser ); - }; - }; - - function onKeyDown( e ){ - if( currentItem === null ) return true; - var keyCode = e.keyCode, - index = Util.getIndex( currentList, currentItem ); - if( keyCode === 13 || keyCode === 27 || keyCode === 9 || keyCode === 18 || e.altKey === true ){ // 13.return 27.esc 9.tab 18.alt - keyCode === 9 && tabShift( index, e.shiftKey === true ? -1 : 1 ); - keyCode === 13 && currentItem instanceof ComboBoxClass && OptionControl.onEnter(); - keyCode === 13 && tabShift( index, 1 ); - currentItem && currentItem.blur( keyCode ); - return false; - }; - }; - - function tabShift( index, way ){ - var l = currentList.length, - i = index + way, - item; - if( l < 2 ) return; - while( i !== index ){ - i = i < 0 ? - l - 1 : - i < l ? i : 0; // 0 < i < l - item = currentList[ i ]; - if( item.enabled() === true && item.visible() === true ){ - AsyncCall.add( currentUser, item.focus, null, item ); - return; - }; - i += way; - }; - }; - - return { - createUIGroup: function( apiuser, node ){ - var uid = apiuser.getUID(), - list = UI_LIST[ uid ], - ui = new UIGroupClass( apiuser, node ); - if( Type.isArray( list ) === false ){ - list = UI_LIST[ uid ] = []; - }; - list.push( ui ); - return ui; - }, - onWindowResize: function( w, h ){ - windowW = w; - windowH = h; - currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h ); - currentItem instanceof TextInputClass && TextInputManager.onWindowResize( w, h ); - currentItem instanceof FileInputClass && FileInputManager.onWindowResize( w, h ); - }, - onCurrentApplicationChange: function( _apiuser ){ - currentList = UI_LIST[ _apiuser.getUID() ]; - }, - onApplicationShutdown: function( _apiuser ){ - KeyEvent.remove( _apiuser ); - }, - onSystemShutdown: function(){ - - } - }; -})(); - -var UIForm = ( function(){ - var FORM_LIST = []; - var CLASSNAME_FORM = 'uiform-invisible'; - var CLASSNAME_FILE_WRAP = 'ui-fileinput-wrapper'; - var FormItemData = function(){}; - FormItemData.prototype = { - formData : null, - uiItem : null, - init: function( formData, uiItem ){ - this.formData = formData; - this.uiItem = uiItem; - } - }; - - var FormPrivateData = function(){}; - FormPrivateData.prototype = { - apiuser : null, - node : null, - form : null, - elmForm : null, - itemList : null, - visible : true, - enabled : true, - init : function( apiuser, from, node, elm, elmForm ){ - this.apiuser = apiuser; - this.form = form; - this.ui = apiuser.createUIGroup( node ); - this.node = node; - this.elm = elm; - this.elmForm = elmForm; - this.itemList = []; - elmForm.className = CLASSNAME_FORM; - FormPrivateData.list.push( this ); - - var forms = Util.copyArray( elmForm.getElementsByTagName( '*' ) ), - l = forms.length, - i = 0, - items = 'input,select,textarea,button', - form, data, el, wrap; - for( ; i
' ); - elm.appendChild( el ); - data = new FormItemData(); - wrap = document.createElement( 'div' ); - form.parentNode.insertBefore( wrap, form ); - wrap.className = CLASSNAME_FILE_WRAP; - wrap.appendChild( form ); - data.init( this, this.ui.createFileInput( el, null, null, form ) ); - this.itemList.push( data ); - // alert( i ) - break; - case 'button': - break; - default: - continue; - }; - break; - case 'select': - break; - case 'button': - break; - case 'textarea': - break; - default: - continue; - }; - }; - }, - destroy : function(){ - - } - }; - FormPrivateData.list = []; - FormPrivateData.get = function( from ){ - var list = FormPrivateData.list, - i = list.length; - for( ; i; ){ - if( list[ --i ].form === form ) return list[ i ]; - }; - return null; - }; - - var FormClass = function( apiuser, node, elm, elmForm ){ - ( new FormPrivateData() ).init( apiuser, this, node, elm, elmForm ); - }; - FormClass.prototype = { - createTextInput : function(){ - - }, - createMultiLineInput : function(){ - - }, - createFileInput : function(){ - - }, - createButton : function(){ - - }, - createComboBox : function(){ - - }, - submit : function(){ - - } - }; - - return { - createForm: function( apiuser, nodeOrElm, opt_elmForm ){ - var uid = apiuser.getUID(), - list = FORM_LIST[ uid ], - node, elm, form; - if( PointingDeviceEventTree.isNodeInstance( nodeOrElm ) === true ){ - node = nodeOrElm; - elm = PointingDeviceEventTree._getNodePrivateData( nodeOrElm ).elm; - } else { - // App が eventTree を持っている? - // App が eventTree を持っていない - elm = nodeOrElm; - }; - form = new FormClass( apiuser, node, elm, opt_elmForm ); - if( Type.isArray( list ) === false ){ - list = FORM_LIST[ uid ] = []; - }; - list.push( form ); - return form; - }, - onWindowResize: function( w, h ){ - windowW = w; - windowH = h; - currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h ); - currentItem instanceof TextInputClass && TextInputManager.onWindowResize( w, h ); - currentItem instanceof FileInputClass && FileInputManager.onWindowResize( w, h ); - }, - onCurrentApplicationChange: function( _apiuser ){ - }, - onApplicationShutdown: function( _apiuser ){ - }, - onSystemShutdown: function(){ - - } - }; -})(); - -var Finder = ( function(){ - var HTML_FINDER_ICON = ( function(){ - return ( UA.isIE === true && UA.ieVersion < 8 ? - [ - '
', - '', - '', - '', - '', - '', - 'file name', - '', - '', - '', - '', - '', - '', - 'file descriptiion', - '', - '', - '', - '
' - ] : - [ - '
', - '', - '', - 'file name', - 'file descriptiion', - '
' - ] ).join( '' ); - })(); - - - var FINDER_LIST = [], - ELM_ORIGIN_LOCATION_ITEM = Util.pullHtmlAsTemplete( '
' ), - ELM_ORIGIN_FINDER_ICON = Util.pullHtmlAsTemplete( HTML_FINDER_ICON ), - ELM_ORIGIN_CONTAINER = Util.pullHtmlAsTemplete( '
' ), - ICON_HEIGHT = Util.getElementSize( ELM_ORIGIN_FINDER_ICON ).height, - ICON_CLASSNAME = 'finder-icon-thumbnail', - elmConsole = Util.pullHtmlAsTemplete( [ - '
', - '', - '', - '', - '
' - ].join( '' ) ); - -/** - * FinderIconClass - */ - var FinderIconClass = function(){}; - FinderIconClass.prototype = { - finderData : null, - file : null, - elm : null, - node : null, - _index : -1, - _style : -1, - init : function( finderData, file, w, index, style ){ - if( !this.elm ) this.elm = ELM_ORIGIN_FINDER_ICON.cloneNode( true ); - - if( this.finderData !== finderData ){ - this.finderData = finderData; - finderData.elmScroll.appendChild( this.elm ); - this.node && this.node.remove(); - this.node = finderData.nodeRoot.createNode( this.elm, false, true, 'finder-icon-hover', '' ); - }; - if( this.file !== file ){ - this.file && this.file.destroy(); - this.file = file; - this._index = index; - this.draw( w ); - return; - }; - if( this._index !== index ){ - this._index = index; - this.resize( w ); - }; - }, - index : function( _index ){ - return this._index; - }, - style : function( _style ){ - return this._style; - }, - draw : function( w ){ - var file = this.file, - elm = this.elm, - thumb = file.getThumbnail(), - elmThumb = Util.getElementsByClassName( elm, ICON_CLASSNAME )[ 0 ], - elmName = Util.getElementsByClassName( elm, 'finder-icon-filename' )[ 0 ], - elmDesc = Util.getElementsByClassName( elm, 'finder-icon-summary' )[ 0 ]; - if( thumb.image ){ - elmThumb.className = ICON_CLASSNAME + ' has-thumbnail'; - elmThumb.style.backgroundImage = [ 'url(', thumb.image, ')' ].join( '' ); - } else { - elmThumb.className = ICON_CLASSNAME + ' ' + thumb.className; - elmThumb.style.backgroundImage = ''; - }; - - elmName.firstChild.data = file.getName(); - elmDesc.firstChild.data = file.getSummary(); - - this.resize( w ); - }, - resize : function( w ){ - this.node.update( 0, this._index * ICON_HEIGHT, w ); - }, - onEditorClick : function( e ){ - this.onEditorCallback && this.onEditorCallback( this.file, this.file.editorApplicationList()[ 0 ] ); - return false; - }, - onViwerClick : function( e ){ - this.onViewerCallback && this.onViewerCallback( this.file, this.file.viewerApplicationList()[ 0 ] ); - return false; - }, - onActionClick : function( e ){ - this.onActionCallback && this.onActionCallback( this.file ); - return false; - }, - destroy : function(){ - this.elm && this.elm.parentNode.removeChild( this.elm ); - this.file && this.file.destroy(); - this.node && this.node.remove(); - delete this.finderData; - delete this.file; - delete this.node; - delete this._index; - delete this._style; - FinderIconClass.pool.push( this ); - } - }; - FinderIconClass.pool = []; - FinderIconClass.get = function( finderData, file, w, index, style ){ - var _icon = FinderIconClass.pool.length > 0 ? FinderIconClass.pool.shift() : new FinderIconClass(); - _icon.init( finderData, file, w, index, style ); - return _icon; - }; - -/** - * PathClass - */ - var PathClass = function(){}; - PathClass.prototype = { - finderData : null, - elm : null, - node : null, - file : null, - _index : null, - w : 0, - init : function( finderData, file, index ){ - if( !this.elm ) this.elm = ELM_ORIGIN_LOCATION_ITEM.cloneNode( true ); - - if( this.finderData !== finderData ){ - this.finderData = finderData; - finderData.elmPath.appendChild( this.elm ); - this.node && this.node.remove(); - delete this.node; - }; - if( this.file !== file ){ - this.file = file; - this.draw(); - }; - if( this._index !== index ){ - this._index = index; - this.resize( index ); - }; - if( !this.node ) this.node = finderData.nodePath.createNode( this.elm, false, true, 'finder-path-hover', 'pointer' ); - }, - draw : function(){ - this.elm.className = 'file-icon-' + this.file.getType(); - this.elm.innerHTML = this.file.getName(); - }, - resize : function(){ - this.elm.style.left = ( this._index * 90 ) + 'px'; - }, - index : function( _index ){ - return this._index; - }, - destroy : function(){ - this.finderData.elmPath.removeChild( this.elm ); - this.node && this.node.remove(); - - delete this.finderData; - delete this.elm; - delete this.node; - delete this.file; - delete this._index; - PathClass.pool.push( this ); - } - }; - PathClass.pool = []; - PathClass.get = function( finderData, file, index ){ - var _bread = PathClass.pool.length > 0 ? PathClass.pool.shift() : new PathClass(); - _bread.init( finderData, file, index ); - return _bread; - }; - -/** - * FinderPrivateData - */ - var FinderPrivateData = function(){}; - FinderPrivateData.prototype = { - finder : null, - apiuser : null, - elmRoot : null, - nodeRoot : null, - elmScroll : null, - elmPath : null, - nodePath : null, - tree : null, - onSelect : null, - viewerOption : null, - editorOption : null, - iconList : null, - pathList : null, - headH : 0, - iconW : 0, - iconH : 0, - style : 0, - init : function( finder, apiuser, elm, tree, onSelect, viewerOption, editorOption ){ - this.finder = finder; - this.apiuser = apiuser; - if( PointingDeviceEventTree.isNodeInstance( elm ) === true ){ - this.nodeRoot = elm; - this.elmRoot = PointingDeviceEventTree._getNodePrivateData( elm ).elm; - } else { - // App が eventTree を持っている? - // App が eventTree を持っていない - this.elmRoot = elm; - }; - this.nodeRoot.addEventListener( 'click', this.onIconClick, this ); - - this.elmScroll = document.createElement( 'div' ); - this.elmRoot.appendChild( this.elmScroll ); - this.elmScroll.style.cssText = 'width:100%;'; - - this.tree = tree; - this.onSelect = onSelect; - this.viewerOption = viewerOption; - this.editorOption = editorOption; - - this.iconList = []; - - var size = Util.getElementSize( ELM_ORIGIN_FINDER_ICON ); - this.iconW = size.width; - this.iconH = size.height; - - tree.addTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw, this ); - Util.addClass( this.elmRoot, 'finder-body' ); - - FinderPrivateData.LIST.push( this ); - }, - onIconClick : function( e ){ - var target = e.target, - i = target.nodeIndex(), - file; - if( target === this.nodeRoot ) return; - var file = this.tree.getCurrentFile().getChildFileByIndex( i ); - if( file !== null && ( file.getChildFileLength() !== -1 || file.getType() === Const.FILE.TYPE.FOLDER )){ - this.tree.down( i ); - this.draw(); - } else { - Type.isFunction( this.onSelect ) === true && this.onSelect( file ); - }; - file.destroy(); - }, - onPathClick : function( e ){ - var target = e.target, - i = target.nodeIndex(); - if( target === this.nodePath || this.nodePath.numNode() - 1 === i ) return; - this.tree.up( i ); - this.draw(); - }, - draw : function( _w, _h ){ - var data = this; - data.w = _w = Type.isFinite( _w ) === true ? _w : data.w; - data.h = _h = Type.isFinite( _h ) === true ? _h : data.h; - data.elmPath && data.drawPath( _w ); - data.drawBody( _w, _h ); - }, - drawPath : function( _w ){ - if( !this.elmPath.parentNode ) return; - - var data = this, - tree = data.tree, - apiuser = data.apiuser, - pathList = data.pathList, - i = 0, - l = tree.hierarchy() + 1, - m = pathList.length, - file; - - for( ; i < l; ++i ){ - file = i !== l - 1 ? tree.getParentFileAt( i ) : tree.getCurrentFile(); - if( i < m ){ - pathList[ i ].init( this, file, i ); - } else { - pathList.push( PathClass.get( this, file, i ) ); - }; - }; - while( l < pathList.length ) pathList.pop().destroy(); - }, - drawBody : function( _w, _h ){ - var data = this, - apiuser = data.apiuser, - iconList = data.iconList, - file = data.tree.getCurrentFile(), - i = 0, - l = file.getChildFileLength(), - m = iconList.length; - - for( ; i < l; ++i ){ - if( i < m ){ - iconList[ i ].init( this, file.getChildFileByIndex( i ), _w, i, data.style ); - } else { - iconList.push( FinderIconClass.get( this, file.getChildFileByIndex( i ), _w, i, data.style ) ); - }; - }; - data.elmRoot.className = file.getState() === Const.FILE.STATE.LOADING ? 'finder-body loading' : 'finder-body'; - // data.elmRoot.style.height = ( data.h - data.headH ) + 'px'; - - while( l < iconList.length ) iconList.pop().destroy(); - - this.nodeRoot.invalidateScrollbar(); - }, - createPath : function( node ){ - if( this.elmPath ) return; - - if( PointingDeviceEventTree.isNodeInstance( node ) === true ){ - this.nodePath = node; - this.elmPath = PointingDeviceEventTree._getNodePrivateData( node ).elm; - - node.addEventListener( 'click', this.onPathClick, this ); - Util.addClass( this.elmPath, 'finder-path' ); - // this.elmPath = document.createElement( 'div' ); - // this.elmPath.className = ; - this.pathList = []; - // this.headH = 0; - AsyncCall.add( this.apiuser, this.draw, null, this ); - }; - }, - destroy : function(){ - this.tree.removeTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw ); - - if( this.pathList ){ - while( this.pathList.length > 0 ) this.pathList.shift().destroy(); - }; - while( this.iconList.length > 0 ) this.iconList.shift().destroy(); - - this.nodeRoot.remove(); - // this.nodePath && this.nodePath.remove(); - - // this.elmRoot.removeChild( this.elmRoot ); - - FINDER_LIST.splice( Util.getIndex( FINDER_LIST, this.finder ), 1 ); - var data = ApplicationPrivateData.get( this.apiuser ), - list = data.finderList, - i = Util.getIndex( list, this.finder ); - i !== -1 && list.splice( i, 1 ); - } - }; - FinderPrivateData.LIST = []; - FinderPrivateData.get = function( finderOrTree ){ - var list = FinderPrivateData.LIST, - i = list.length, - data; - for( ; i; ){ - data = list[ --i ]; - if( data === finderOrTree || data.finder === finderOrTree || data.tree === finderOrTree ) return data; - }; - return null; - }; - -/** - * FinderClass - */ - var FinderClass = function( application, elmRoot, tree, onSelect, viewerOption, editorOption ){ - ( new FinderPrivateData() ).init( this, application, elmRoot, tree, onSelect, viewerOption, editorOption ); - }; - FinderClass.prototype = { - MIN_WIDTH : 200, - MIN_HEIGHT : 200, - init : function(){ - var data = FinderPrivateData.get( this ); - // var position = Util.getAbsolutePosition( elmPath ); - // data.headX = position.x; - // data.headY = position.y; - // data.bodyY = Util.getAbsolutePosition( data.elmBody ).y; - data.apiuser.addEventListener( data.elmRoot, 'mousemove', data.mousemove, data ); - data.apiuser.addEventListener( data.elmRoot, 'click', data.click, data ); - data.apiuser.addEventListener( data.elmRoot, 'mousewheel', data.mousewheel, data ); - }, - resize : function( w, h ){ - var data = FinderPrivateData.get( this ), - i = data.iconList.length; - //data.draw( _w, _h ); - - //data.elmRoot.style.height = ( _h - data.headH ) + 'px'; - - for( ; i; ) data.iconList[ --i ].resize( w ); - }, - createPath : function( node ){ - return FinderPrivateData.get( this ).createPath( node ); - }, - destroy : function(){ - FinderPrivateData.get( this ).destroy(); - } - }; - - return { - init: function(){ - - }, - create: function( application, elmTarget, tree, onSelect, viewerOption, editorOption ){ - //if( Application.isApplicationInstance( _application ) === false ) return; - - var finder = new FinderClass( application, elmTarget, tree, onSelect, viewerOption, editorOption ); - finder.init(); - FINDER_LIST.push( finder ); - return finder; - }, - registerFinderHead: function(){ - - }, - registerFinderPane: function( _finderPane ){ - - }, - isFinderInstance: function( _finder ){ - return _finder instanceof FinderClass; - }, - isFinderPaneInstance: function(){ - - }, - isFinderHeadInstance: function(){ - } - }; -})(); - - -/* - * -- len, % - * marginBottom, marginLeft, marginRight, marginTop, margin - * padding, paddingBottom, paddingLeft, paddingRight, paddingTop - * fontSize, textIndent - * height, width - * bottom, left, right, top (len, %) - * - * -- len - * borderBottomWidth, borderLeftWidth, borderRightWidth, borderTopWidth, borderWidth, - * letterSpacing - * - * -- color - * backgroundColor - * borderBottomColor, borderLeftColor, borderRightColor, borderTopColor, borderColor - * color - * - * -- special - * clip rect(0px, 40px, 40px, 0px); - * backgroundPosition (len, %) - * opacity - * lineHeight (len, %, num) - * zIndex ( order ) - */ - -var DHTML = ( function(){ - - var TICKET_ARRAY = [], - fpms = 50, - round = Math.round, - cround = function( v ){ return round( v * 100 ) / 100 }; - - function startAnimation( _elm, _cssObject, _onComplete, _onEnterFrame, _numFrames ){ - var _ticket, i = TICKET_ARRAY.length; - for( ; i; ){ - _ticket = TICKET_ARRAY[ --i ]; - if( _ticket.elm === _elm ){ - return; - }; - }; - - var _currentValues = [], - _offsetValues = [], - _endValues = [], - _targetProperties = [], - _units = []; - var target, current, - inlineStyle = CSS.getInlineStyle( _elm ), - currentStyle = CSS.getWrappedStyle( _elm ), - targetStyle = CSS.getWrappedStyle( _elm, _cssObject ); - targetStyle.pxPerEm = currentStyle.get( 'fontSize' )._toPx(); - for( var p in _cssObject ){ - p = Util.camelize( p ); - target = targetStyle.get( p ); - current = currentStyle.get( p ); - - if( target.isValid() === false || current.isValid() === false || current.equal( target ) !== false ){ - target.clear(); - current.clear(); - continue; - }; - - current.convert( target ); - // alert( current.getValue() + ' , ' + target.getValue() ) - _currentValues.push( current.getValue() ); - _offsetValues.push( current.getOffset( target ) ); - _endValues.push( target.getValue() ); - _targetProperties.push( p ); - _units.push( target.getUnit() ); - - // IE has trouble with opacity if it does not have layout - // Force it by setting the zoom level - if( p === 'opacity' && SPECIAL.hasLayout ){ - if( SPECIAL.hasLayout( _elm ) === false ) inlineStyle.zoom = 1; - inlineStyle.filter = current.getValueText(); - } else { - inlineStyle[ p ] = current.getValueText(); - }; - - target.clear(); - current.clear(); - }; - - var i, cssTexts = []; - for( i = 0; i < _numFrames; ++i ){ - if( i < _numFrames - 1 ){ - tickValue( _currentValues, _offsetValues, _numFrames ); - cssTexts.push( createCssText( _currentValues, _targetProperties, targetStyle, inlineStyle ) ); - } else { - cssTexts.push( createCssText( _endValues, _targetProperties, targetStyle, inlineStyle ) ); - }; - }; - - TICKET_ARRAY.push( new AnimationTaskClass( - _elm, cssTexts, - Type.isFunction( _onComplete ) === true ? _onComplete : null, - Type.isFunction( _onEnterFrame ) === true ? _onEnterFrame : null, - _numFrames - ) ); - - currentStyle.clear(); - targetStyle.clear(); - SystemTimer.add( SUPER_USER_KEY, onEnterFrame, 1000 / fpms ); - }; - - function tickValue( current, offset, numFrames ){ - if( Type.isArray( current ) === true ){ - var ret, i = current.length; - for( ; i; ){ - --i; - ret = tickValue( current[ i ], offset[ i ], numFrames ); - if( Type.isNumber( ret ) === true ) current[ i ] = ret; - }; - } else { - return current + offset / numFrames; - }; - }; - function createCssText( update, props, style, inline ){ - var prop; - for( var i = props.length; i; ){ - prop = style.get( props[ --i ] ); - prop.setValue( update[ i ] ); - inline[ Util.uncamelize( prop.name ) ] = prop.getValueText(); - //if( prop.name === 'backgroundColor' ) alert( prop.getValueText() + '|' + update[ i ].join( ',') ) - prop.clear(); - }; - return CSS.toCssText( inline ); - }; - - function onEnterFrame(){ - var _ticket, l, - i = 0; - while( i < TICKET_ARRAY.length ){ - _ticket = TICKET_ARRAY[ i ]; - l = _ticket.cssTexts.length; - _ticket.elm.style.cssText = _ticket.cssTexts.shift(); - if( l === 1 ){ - _ticket.onComplete && _ticket.onComplete(); - delete _ticket.elm; - delete _ticket.cssTexts; - delete _ticket.onComplete; - delete _ticket.onEnterFrame; - delete _ticket.numFrame; - TICKET_ARRAY.splice( i, 1 ); - } else { - _ticket.onEnterFrame && _ticket.onEnterFrame( l / _ticket.numFrame ); - ++i; - }; - }; - if( TICKET_ARRAY.length === 0 ){ - SystemTimer.remove( SUPER_USER_KEY, onEnterFrame ); - }; - }; - - var AnimationTaskClass = function( elm, cssTexts, onEnterFrame, onComplete, numFrame ){ - this.elm = elm; - this.cssTexts = cssTexts; - this.onEnterFrame = onEnterFrame; - this.onComplete = onComplete; - this.numFrame = numFrame; - }; - - var VisualEffectClass = function( elm ){ - this.elm = elm; - }; - VisualEffectClass.prototype = { - anime : function( _cssObject, _onComplete, _onEnterFrame, _time ){ - var _numFrames = Math.floor( _time / fpms ); - startAnimation( this.elm, _cssObject, _onComplete, _onEnterFrame, _numFrames ); - }, - fadeIn : function(){ - - }, - fadeOut : function(){ - - }, - update : function( x, y, w, h ){ - var _cssText = this.elm.style.cssText; - } - }; - - return { - create: function( application, _elm ){ - return new VisualEffectClass( _elm ); - }, - isInstanceOfVisualEffect: function( _instance){ - return _instance instanceof VisualEffectClass; - } - } -})(); - - -/* -------------------------------------------- - * - */ - - Application.onCurrentApplicationChange( SUPER_USER_KEY ); - - SERVICE_LIST.push( MouseEvent ); - - new EventTicketClass( window, 'unload', function(){ - var _service; - while( SERVICE_LIST.length > 0 ){ - _service = SERVICE_LIST.shift(); - Type.isFunction( _service.onSystemShutdown ) === true && _service.onSystemShutdown(); - } - }); - // beforeunload - - -/* --------------------------------------------- - * broadcast to global - */ - window.gOS = {}; - - gOS.registerApplication = Application.register; - gOS.registerDriver = File.registerDriver; - -})( window, document ); +/* + * pettanR system.js + * version 0.5.48 + * + * gadgetOS + * author: + * itozyun + * licence: + * 3-clause BSD + */ + +( function( window, document, undefined ){ + + var body = document.getElementsByTagName( 'body' )[ 0 ]; //( document.compatMode || '' ) !== 'CSS1Compat' ? document.body : document.documentElement;// + var SERVICE_LIST = []; + var SUPER_USER_KEY = { getUID: function(){ return 0; }}; + var API_USER_LIST = [ SUPER_USER_KEY ]; + var numApiUser = 1; + + function EMPTY_FUNCTION(){}; + + function isApiUser( _user ){ + return _user === SUPER_USER_KEY || + File.isDriver( _user ) === true || + Application.isApplicationInstance( _user ) === true; + }; + + var Const = { + FILE: { + TYPE: { + UNKNOWN: 0, + FOLDER: 1, + IMAGE: 2, + TEXT: 3, + HTML: 4, + CSV: 5, + JSON: 6, + XML: 7 + }, + STATE: { + UNKNOWN: 0, + OK: 1, + LOADING: 2, + ERROR: 3, + BROKEN: 4 + }, + UPDATE_POLICY: { + _____: parseInt( '00000', 2 ), + ____C: parseInt( '00001', 2 ), // hasCreateMenu + ___W_: parseInt( '00010', 2 ), // isWritable + ___WC: parseInt( '00011', 2 ), // isWritable + __R__: parseInt( '00100', 2 ), // isRenamable + __R_C: parseInt( '00101', 2 ), // hasCreateMenu + __RW_: parseInt( '00110', 2 ), // isWritable + __RWC: parseInt( '00111', 2 ), // isWritable + _S___: parseInt( '01000', 2 ), // childrenIsSortable + _S__C: parseInt( '01001', 2 ), + _S_W_: parseInt( '01010', 2 ), + _S_WC: parseInt( '01011', 2 ), + _SR__: parseInt( '01100', 2 ), + _SR_C: parseInt( '01101', 2 ), + _SRW_: parseInt( '01110', 2 ), + _SRWC: parseInt( '01111', 2 ), + D____: parseInt( '10000', 2 ), + D___C: parseInt( '10001', 2 ), // hasCreateMenu + D__W_: parseInt( '10010', 2 ), // isWritable + D__WC: parseInt( '10011', 2 ), // isWritable + D_R__: parseInt( '10100', 2 ), // isRenamable + D_R_C: parseInt( '10101', 2 ), // hasCreateMenu + D_RW_: parseInt( '10110', 2 ), // isWritable + D_RWC: parseInt( '10111', 2 ), // isWritable + DS___: parseInt( '11000', 2 ), // childrenIsSortable + DS__C: parseInt( '11001', 2 ), + DS_W_: parseInt( '11010', 2 ), + DS_WC: parseInt( '11011', 2 ), + DSR__: parseInt( '11100', 2 ), + DSR_C: parseInt( '11101', 2 ), + DSRW_: parseInt( '11110', 2 ), + DSRWC: parseInt( '11111', 2 ), + CREATE: 1, + WRAITE: 2, + RENAME: 4, + SORT: 8, + DELETE: 16 + }, + EVENT: { + UPDATE_ATTRIVUTE: 'onFileUpdate', + GET_SEQENTIAL_FILES:'gotSeqentilFiles' + }, + DATA_PROPERTY_RESERVED: [ + 'children', 'driver', 'state', 'type' + ] + }, + TREE: { + EVENT: { + UPDATE: 'onTreeUpdate' + } + }, + KEY: { + EVENT: { + KEY_DOWN: 'keydown', + KEY_UP: 'keyup', + KEY_CHANGE: 'keychange', + CURSOL: 'cursol' + } + }, + APP: { + TYPE: { + GENERAL : 0, + OVERLAY : 1, + PAGE : 2 + } + } + }; + +/** + * Class を定義し システムの管理下に置く. + * 全てのクラスと pool が有効の場合インスタンスへの参照が保持される. + * 1. Class.create( def, opt_final, opt_pool, opt_abstract ) でクラスを登録. + * 2. コンストラクタ となるメソッドは、Constructor : function( arg ){ ... }, に書く. + * 3. 通常通り new で インスタンス生成 + * 4. kill() でオブジェクトをクリーンして削除、pool が有効の場合は pool される. + * 5. pool が有効の場合、new で pool されたインスタンスが返される. + * 6. + * + */ +var Class = ( function(){ + var CLASS_LIST = [], + DEF_LIST = [], + PRIVATE_CLASS_LIST = [], + PRIVATE_DEF_LIST = [], + CONSTRUCTOR = 'Constructor', + GET_INDEX = Util.getIndex, + killPrivateFlag = false, + dataUser = null, + traits = null, + f = true, + copyArray = Util.copyArray; + + function getClass( instance ){ + var cList = CLASS_LIST, + i = cList.length, + klass; + for( ; i; ){ + klass = cList[ --i ]; + if( instance instanceof klass ) return klass; + }; + cList = PRIVATE_CLASS_LIST; + i = cList.length; + for( ; i; ){ + klass = cList[ --i ]; + if( instance instanceof klass ) return klass; + }; + + if( GET_INDEX( cList, instance ) !== -1 ) return instance; + if( GET_INDEX( CLASS_LIST, instance ) !== -1 ) return instance; + }; + + function getClassDef( KlassOrInstance ){ + var getIndex = GET_INDEX, + i = getIndex( CLASS_LIST, KlassOrInstance ); + if( i === -1 ) i = getIndex( CLASS_LIST, getClass( KlassOrInstance ) ); + if( i !== -1 ) return DEF_LIST[ i ]; + + i = getIndex( PRIVATE_CLASS_LIST, KlassOrInstance ); + if( i === -1 ) i = getIndex( PRIVATE_CLASS_LIST, getClass( KlassOrInstance ) ); + if( i !== -1 ) return PRIVATE_DEF_LIST[ i ]; + + if( GET_INDEX( DEF_LIST, KlassOrInstance ) !== -1 ) return KlassOrInstance; + if( GET_INDEX( PRIVATE_DEF_LIST, KlassOrInstance ) !== -1 ) return KlassOrInstance; + }; + + /* over のプロパティを target にコピーする.ただし target の プロパティが優先, force で解除 */ + function override( target, over, force ){ + for( var p in over ){ + if( force === true || typeof target[ p ] === 'undefined' ){ + target[ p ] = over[ p ]; + }; + }; + return target; + }; + + /* サブクラスを作るメソッド + * var subClass = superClass.inherits( ... ) + * http://d.hatena.ne.jp/m-hiyama/20051018/1129605002 + */ + function inherits( /* displayName, classSetting, opt_PrivateClass, props */ ){ + var args = copyArray( arguments ), + params = [], + Super = this, + superDef = getClassDef( Super ), + displayName = args[ 0 ], + classSetting, + opt_super, + klass; + if( superDef.Final === true ) throw new Error( 'Class is final!' ); + + if( Type.isString( displayName ) === true ){ + args.shift(); + } else { + displayName = 'SubClass of ' + superDef.displayName; + }; + params.push( displayName ); + + classSetting = args[ 0 ]; + if( Type.isNumber( classSetting ) === true ){ + if( superDef.isPrivate === true ) classSetting = classSetting | Class.PRIVATE_DATA; + opt_super = !!( classSetting & Class.SUPER_ACCESS ); + params.push( classSetting ); + args.shift(); + }; + if( getClass( args[ 0 ] ) ){ + params.push( args.shift() ); + } else + if( superDef.privateClass ){ + params.push( superDef.privateClass ); + }; + params.push( args[ 0 ] ); /* props */ + f = false; + traits = new Super(); + f = true; + klass = Class.create.apply( Class, params ); + traits = null; + if( opt_super === true ) getClassDef( klass ).Super = Super.prototype; + return klass; + }; + + /* Class.create で作られたクラスのインスタンスが共通で備えるメソッド */ + var CommonProps = { + kill : function(){ + var instance = this, + klass = getClass( instance ), + def = getClassDef( klass ), + data, p, i; + if( def.isPrivate === true && killPrivateFlag === false ){ + throw new Error( 'PrivateInstance.kill() work in PrivateUser.kill().' ); + }; + Type.isFunction( instance.onKill ) === true && instance.onKill(); + for( p in instance ){ + if( instance.hasOwnProperty && !instance.hasOwnProperty( p ) ) continue; + delete instance[ p ]; + }; + if( def.pool ){ + def.live && def.live.splice( GET_INDEX( def.live, instance ), 1 ); + def.pool.push( instance ); + }; + if( def.privateClass ){ + i = GET_INDEX( def.userList, instance ); + if( i !== -1 ){ + data = klass.getPrivateData( instance ); + killPrivateFlag = true; + data.kill(); + killPrivateFlag = false; + def.dataList.splice( i, 1 ); + def.userList.splice( i, 1 ); + }; + }; + // myCallback の削除 + // myCallback を受け取った API への通知 + }, + getMyCallback : function( callback ){ + var def = getClassDef( this ), + iList = def.callbackInstanceList, + rList = def.callbackRegisterList, + i, cList, myCallback; + if( !iList ){ + iList = def.callbackInstanceList = []; + rList = def.callbackRegisterList = []; + }; + i = GET_INDEX( iList, this ); + if( i === -1 ){ + cList = []; + iList.push( this ); + rList.push( cList ); + } else { + cList = rList[ i ]; + for( i = cList.length; i; ){ + if( cList[ --i ].callback === callback ) return cList[ i ]; + }; + }; + myCallback = new Callback( this, callback ); + cList.push( myCallback ); + return myCallback; + }, + releaseMyCallback : function( callback ){ + var def = getClassDef( this ), + iList = def.callbackInstanceList, + rList = def.callbackRegisterList, + i, _i, cList; + if( !iList ) return; + i = GET_INDEX( iList, this ); + if( i === -1 ) return; + cList = rList[ i ]; + _i = GET_INDEX( cList, callback ); + if( _i === -1 ) return; + cList.splice( _i, 1 ); + callback.kill(); + if( cList.length !== 0 ) return; + iList.splice( i, 1 ); + rList.splice( i, 1 ); + if( iList.length !== 0 ) return; + delete def.callbackInstanceList; + delete def.callbackRegisterList; + }, + listenTo : function( eventDispatcher, eventType, callback ){ + //if( eventDispatcher instanceof EventDsipatcher ){ + eventDispatcher.addEventListener( eventType, callback, this ); + //} + }, + unlistenTo : function( eventDispatcher, eventType, callback ){ + + } + }; + + /* privateDataclass をもつクラスに追加されるメソッド */ + function newPrivateData( /* instance, args */ ){ + var args = copyArray( arguments ), + user = args.shift(), + def = getClassDef( user ), + privateClass = def.privateClass, + privateDef = getClassDef( privateClass ), + i = -1, + data; + if( def.userList ){ + i = GET_INDEX( def.userList, user ); + } else { + def.userList = []; + def.dataList = []; + }; + if( i !== -1 ){ + throw new Error( 'PrivateData already exist!' ); + }; + dataUser = user; + data = new privateClass( args ); + data.User = user; + dataUser = null; + return data; + }; + function getPrivateData( instance ){ + var def = getClassDef( instance ), + i = GET_INDEX( def.userList, instance ); + if( i !== -1 ) return def.dataList[ i ]; + }; + + /* + * new の実体.コンストラクタの機能は instance.Constructor に書く. + * これにより pool された オブジェクト(破棄されたインスタンス) を再利用できる + */ + /* Constructor Real for GeneralClass */ + function C( args ){ + var klass = this, + def = getClassDef( klass ), + instance, + userDef; + if( def.Abstract === true ){ + throw new Error( 'AbstractClass!' ); + }; + if( def.isPrivate === true && dataUser === null ){ + throw new Error( 'use myClass.newPrivateData( instance, ...args )!' ); + }; + f = false; + instance = def.pool && def.pool.length > 0 ? def.pool.shift() : instance = new klass(); + f = true; + if( def.Super && !instance.Super ) instance.Super = def.Super; + if( def.isPrivate === true ){ + userDef = getClassDef( dataUser ); + userDef.dataList.push( instance ); + userDef.userList.push( dataUser ); + } else { + def.live && def.live.push( instance ); + args = copyArray( arguments ); + }; + def[ CONSTRUCTOR ] && def[ CONSTRUCTOR ].apply( instance, args ); + return instance; + }; + + return { + POOL_OBJECT : 1, + ABSTRACT : 2, + FINAL : 4, + SUPER_ACCESS : 8, + PRIVATE_DATA : 16, + create : function( /* displayName, classSetting, opt_PrivateClass, props */ ){ + var args = copyArray( arguments ), + displayName = args[ 0 ], + classSetting, + opt_pool, opt_abstract, opt_final, opt_private, + privateDef, + props, + klass, + classDef = {}; + if( Type.isString( displayName ) === true ){ + classDef.displayName = displayName; + args.shift(); + }; + classSetting = args[ 0 ]; + if( Type.isNumber( classSetting ) === true ){ + opt_pool = !!( classSetting & Class.POOL_OBJECT ); + opt_abstract = !!( classSetting & Class.ABSTRACT ); + opt_final = !!( classSetting & Class.FINAL ); + opt_private = !!( classSetting & Class.PRIVATE_DATA ); + if( opt_final === true && opt_abstract === true ){ + throw new Error( 'final & Abstract!' ); + }; + args.shift(); + }; + + if( GET_INDEX( PRIVATE_CLASS_LIST, args[ 0 ] ) !== -1 ){ + privateDef = getClassDef( args[ 0 ] ); + if( privateDef.isPrivate !== true ){ + throw new Error( 'PrivateClass not found! please, Class.create( Class.PRIVATE, {...} ).' ); + } else + if( privateDef.Abstract === true ){ + throw new Error( 'PrivateClass is Abstract!' ); + }; + classDef.privateClass = args.shift(); + }; + props = args[ 0 ]; + if( props === null || Type.isObject( props ) === false ){ + throw new Error( 'No Class Def!' ); + }; + + if( Type.isFunction( props[ CONSTRUCTOR ] ) === true ){ + classDef[ CONSTRUCTOR ] = props[ CONSTRUCTOR ]; + }; + + klass = function(){ var a = arguments; if( f ) return C.apply( a.callee, a )}; + klass.prototype = override( override( traits || {}, props, true ), CommonProps, false ); + + if( opt_abstract === true ){ + classDef.Abstract = true; + } else + if( opt_pool === true ){ + classDef.pool = []; + if( opt_private === false )classDef.live = []; + }; + if( opt_final === true ){ + classDef.Final = true; + } else { + klass.inherits = inherits; + }; + if( opt_private === true ){ + if( classDef.privateClass ){ + throw new Error( 'Private Data Class has no PrivateClass!' ); + }; + classDef.isPrivate = true; + PRIVATE_CLASS_LIST.push( klass ); + PRIVATE_DEF_LIST.push( classDef ); + } else { + if( classDef.privateClass ){ + klass.newPrivateData = newPrivateData; + klass.getPrivateData = getPrivateData; + }; + CLASS_LIST.push( klass ); + DEF_LIST.push( classDef ); + }; + return klass; + }, + onShutdown : function(){ + + }, + getClass : function( instance ){ + return getClass( instance ); + }, + getClassDef : function(){ + + } + }; +})(); + +/** + * Callback 時に thisObject や args を指定したい場合に使用. + */ +var Callback = Class.create( + Class.POOL_OBJECT | Class.FINAL, { + Constructor : function( thisObject, callback, opt_args ){ + if( Type.isFunction( callback ) === false ){ + throw new Error( 'Not function!' ); + }; + this.callback = callback; + if( thisObject ) this.thisObject = thisObject; + if( Type.isArray( opt_args ) === true ){ + this.args = opt_args; + } else + if( opt_args !== undefined ){ + this.arg = opt_args; + }; + }, + fire : function( /* args */ ){ + var thisObject = this.thisObject || window, + args = Util.copyArray( arguments ); + if( 0 < args.length ){ + if( this.args !== undefined ){ + args.push.apply( args, this.args ); + } else + if( this.arg !== undefined ){ + args.push( this.arg ); + }; + this.callback.apply( thisObject, args ); + } else { + if( this.args !== undefined ){ + this.callback.apply( thisObject, this.args ); + } else + if( this.arg !== undefined ){ + this.callback.call( thisObject, this.arg ); + } else { + this.callback.call( thisObject ); + }; + }; + }, + registerUser : function( user ){ + if( !this.userList ){ + this.userList = [ user ]; + } else { + Util.getIndex( this.userList, user ) === -1 && this.userList.push( user ); + }; + }, + onKill : function(){ + var instance = this.thisObject; + this.userList && Class.getClass( instance ) && instance.releaseMyCalllback( this ); + } +}); + + +/* -------------------------------------------------------------- + * System Timer + * + */ + +var SystemTimer = ( function(){ + var setTimeout = window.setTimeout; + var clearTimeout = window.clearTimeout; + var INTERVAL_TIME = 16; + var TICKET_LIST = []; + var timerId = undefined; + var next = 0; + + function loop(){ + var i = 0, + list = TICKET_LIST; + for( i = 0; i < list.length; ){ + if( list[ i ].fire( next ) !== false ) ++i; + }; + timerId = undefined; + update(); + }; + function update(){ + var list = TICKET_LIST, + l = list.length, + n = 99999999, + c; + if( l === 0 ){ + timerId !== undefined && clearTimeout( timerId ); + timerId = undefined; + return; + }; + for( ; l; ){ + c = list[ --l ].count; + if( n > c ) n = c; + }; + if( next > n || timerId === undefined ){ + timerId !== undefined && clearTimeout( timerId ); + timerId = setTimeout( loop, INTERVAL_TIME * n ); + next = n; + }; + }; + + var TimerTicket = Class.create( + Class.POOL_OBJECT, { + Constructor : function( apiuser, callback, time, once, opt_thisObject ){ + this.apiuser = apiuser; + this.callback = callback; + this.time = time; + this.count = time; + if( once ) this.once = once; + this.thisObj = opt_thisObject || apiuser; + }, + fire : function( c ){ + this.count -= c; + if( 0 < this.count ) return; + this.callback.call( this.thisObj ); + if( this.once === true ){ + this.destroy(); + TICKET_LIST.splice( Util.getIndex( TICKET_LIST, this ), 1 ); + return false; + } else { + this.count = this.time; + }; + }, + destroy : function( apiuser, callback ){ + if( apiuser && apiuser !== this.apiuser ) return false; + if( callback && callback !== this.callback ) return false; + + this.kill(); + return true; + } + } + ); + + return { + add: function( _apiuser, _handler, _time, _once, opt_thisObject ){ + if( Type.isNumber( _time ) === false || _time < INTERVAL_TIME ) _time = INTERVAL_TIME; + + var _ticket = new TimerTicket( _apiuser, _handler, Math.ceil( _time / INTERVAL_TIME ), _once, opt_thisObject ); + TICKET_LIST.push( _ticket ); + + update(); + }, + remove: function( _apiuser, _handler ){ + var _ticket, + i = 0; + while( _ticket = TICKET_LIST[ i ] ){ + if( _ticket.destroy( _apiuser, _handler ) === true ){ + TICKET_LIST.splice( i, 1 ); + } else { + ++i; + }; + }; + update(); + } + }; +})(); + +/* -------------------------------------------------------------- + * Async Callback + * + */ +var AsyncCall = ( function(){ + var CALLBACK_LIST = []; + + var CallbackTicket = Class.create( + Class.POOL_OBJECT, { + Constructor : function( apiuser, callback, args, thisObject ){ + this.apiuser = apiuser; + this.callback = callback; + this.args = args; + this.thisObj = thisObject || apiuser; + }, + fire : function(){ + var f = this.callback, + a = this.args, + t = this.thisObj; + this.destroy(); + if( Type.isArray( a ) === true ){ + f.apply( t, a ); + } else { + f.call( t, a ); + }; + }, + destroy : function( apiuser, callback ){ + if( apiuser && apiuser !== this.apiuser ) return false; + if( callback && callback !== this.callback ) return false; + + this.kill(); + return true; + } + }); + + function dispatch(){ + var _ticket = CALLBACK_LIST.shift(); + if( _ticket ){ + _ticket.fire(); + CALLBACK_LIST.length !== 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true ); + }; + }; + + return { + add: function( _apiuser, _callback, _argments, _thisObject ){ + CALLBACK_LIST.length === 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true ); + CALLBACK_LIST.push( new CallbackTicket( _apiuser, _callback, _argments, _thisObject ) ); + }, + remove: function( _apiuser, _callback ){ + var _ticket, + i = 0; + while( _ticket = CALLBACK_LIST[ i ] ){ + if( _ticket.destroy( _apiuser, _callback ) === true ){ + CALLBACK_LIST.splice( i, 1 ); + } else { + ++i; + }; + }; + } + }; +})(); + +/* ----------------------------------------------------------- + * 画像一覧は + * お気に入り画像一覧 > tag:ペン次郎 > ペン次郎:笑う + * 最近アップロードされた画像 > images + * 最近使われた画像 > images + * キャラクター画像庫 > アニマル系 > tag:ペン次郎 > ペン次郎:笑う + * 風景画像庫 > + * 効果画像庫 > + * アイテム画像庫 > + * + * 画像一覧を読み込むタイミング + */ +var File = ( function(){ + var DRIVER_LIST = []; + + var FILE_TYPE_IS_FOLDER = Const.FILE.TYPE.FOLDER, + numFileType = Const.FILE.TYPE.XML, + FILEDATA_RESITER = [], // store all of fileData( json object ) + FILEDATA_ACCESS = [], // file operations for Kernel only ! hide from Out of File + FILE_OBJECT_POOL = [], + EVENT_LISTENER_REGISTER = [], + TREE_ARRAY = [], + TREE_ACCESS_ARRAY = []; + + var REQUEST_CONTROLER = ( function(){ + var REQUEST_TICKET_RESISTER = [], + currentTicket = null, + currentData = null, + DATA_TYPE_ARRAY = 'json,xml,html,text'.split( ',' ), + DATA_IS_JSON = 0, + DATA_IS_XML = 1, + DATA_IS_HTML = 2, + DATA_IS_TEXT = 3, + numError = 0; + + var RequestTicket = Class.create( + Class.POOL_OBJECT, { + Constructor : function( apiuser, type, data, url, onLoad, onError ){ + this.apiuser = apiuser; + this.type = type; + this.data = data; + this.url = url; + this.onLoad = onLoad; + this.onError = onError; + this.state = 0; + }, + load : function( data ){ + AsyncCall.add( this.apiuser, this.onLoad, [ this.data, data ] ); + }, + error : function(){ + AsyncCall.add( this.apiuser, this.onError, this.data ); + } + }); + + function request(){ + if( currentTicket !== null || REQUEST_TICKET_RESISTER.length === 0 ) return; + currentTicket = REQUEST_TICKET_RESISTER.shift(); + $.ajax({ + url: currentTicket.url, + dataType: DATA_TYPE_ARRAY[ currentTicket.type ], + success: onSuccess, + error: onError + }); + }; + function onSuccess( _data ){ + currentTicket.load( _data ); + currentTicket.kill(); + currentTicket = null; + request(); + }; + function onError(){ + ++numError; + currentTicket.error(); + currentTicket.kill(); // retry + currentTicket = null; + request(); + }; + + return { + getNumTask: function(){ + return REQUEST_TICKET_RESISTER.length; + }, + getNumError: function(){ + return numError; + }, + getJson: function( _apiuser, _data, _url, _onLoad, _onError ){ + REQUEST_TICKET_RESISTER.push( new RequestTicket( _apiuser, DATA_IS_JSON, _data, _url, _onLoad, _onError )); + currentTicket === null && request(); + } + }; + })(); + + var FILE_CONTROLER = { + createTree: function( _apiuser, _rootFileData ){ + var _tree = new TreeClass( _apiuser, _rootFileData ); + TREE_ARRAY.push( _tree ); + return _tree; + }, + getFileUID: function( FILEDATAorFILE ){ + if( FILEDATAorFILE instanceof FileClass ){ + return FILEDATAorFILE.getUID(); + }; + + var uid = Util.getIndex( FILEDATA_RESITER, FILEDATAorFILE ); + if( uid === -1 ){ + uid = FILEDATA_RESITER.length; + FILEDATA_RESITER.push( FILEDATAorFILE ); + }; + return uid; + }, + getFileDataAccess: function( UIDorFILEorFILEDATA ){ + var _uid, _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA ), _access; + + if( _data === null || typeof _data !== 'object' ) return null; + for( var i=0, l = FILEDATA_ACCESS.length; i= _bit; + }, + move: function( _prentUID, _targetfile, _newFolder, _newIndex, _opt_callback ){ + var _parentData = FILE_CONTROLER.getFileDataAccess( _prentUID ), + _parentType = _parentData.TYPE, + _targetData = FILE_CONTROLER.getFileDataAccess( _targetfile ), + _targetType = _targetData.TYPE; + }, + replace: function( _uid, _file, _newIndex ){ + + }, + addEventListener: function( FILEorNULL, _eventType, _callback, opt_thisObject ){ + var _uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL; + EVENT_LISTENER_REGISTER.push( new FileEventTicket( _uid, _eventType, _callback, opt_thisObject )); + }, + removeEventListener: function( FILEorNULL, eventType, callback ){ + var uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL, + list = EVENT_LISTENER_REGISTER, + i = 0, + ticket; + for( ; i < list.length; ){ + ticket = list[ i ]; + if( ticket.fileUID === uid && ticket.eventType === eventType && ticket.callBack === callback ){ + list.splice( i, 1 ); + ticket.kill(); + } else { + ++i; + }; + }; + }, + getTreeAccess: function(){ + + }, + fileEventRellay: function( _uid, _event ){ + var _fileAccess = FILE_CONTROLER.getFileDataAccess( _uid ); + if( _fileAccess === null ) return; + var _treeUID = _fileAccess.TREE.getUID(), + _treeAccess = TREE_ACCESS_ARRAY[ _treeUID ], + _data = _fileAccess.DATA, + _tree; + if( !_treeAccess ) return; + _treeAccess.dispatchFileEvent( _event ); + for( var i=0, l = TREE_ARRAY.length; i= l ) return null; + return PARENT_FILE_RESITER[ l -1 -_index ]; + }; + this.down = function( _index ){ + if( typeof _index !== 'number' || _index < 0 || _index >= currentFile.getChildFileLength()) return; + PARENT_FILE_RESITER.unshift( currentFile ); + currentFile = currentFile.getChildFileAt( _index ); + currentFile.getSeqentialFiles(); + return currentFile; + }; + this.up = function( _index ){ + var l = PARENT_FILE_RESITER.length; + if( l === 0 ) return null; + + if( currentFile ){ + var _currentFile = currentFile; + currentFile = null; + _currentFile.destroy(); + }; + if( typeof _index === 'number' ){ + if( _index >= l ) return null; + currentFile = this.getParentFileAt( _index ); + PARENT_FILE_RESITER.splice( 0, l -_index); + } else { + currentFile = PARENT_FILE_RESITER.shift(); + }; + currentFile.getSeqentialFiles(); + return currentFile; + }; + this.addTreeEventListener = function( _eventType, _callback, opt_thisObject ){ + FILE_CONTROLER.addEventListener( null, _eventType, _callback, opt_thisObject ); + }; + this.removeTreeEventListener = function( _eventType, _callback ){ + FILE_CONTROLER.removeEventListener( null, _eventType, _callback ); + }; + this.destroy = function( _apiuser ){ + if( _apiuser && apiuser !== _apiuser ) return false; + // removeEvent + var _currentFile = currentFile; + currentFile = rootFile = rootFileData = null; + // currentFile, rootFile を null にしないと .File.destroy() ができない. + _currentFile.destroy(); + while( PARENT_FILE_RESITER.length > 0 ){ + _currentFile = PARENT_FILE_RESITER.shift(); + _currentFile.destroy(); + }; + + AsyncCall.remove( apiuser ); + instance = apiuser = null; + return true; + }; + }; + + var FileEventTicket = Class.create( + Class.POOL_OBJECT, { + Constructor : function( uid, eventType, callback, opt_thisObject ){ + this.fileUID = uid; + this.eventType = eventType; + this.callBack = callback; + this.thisObject = opt_thisObject; + } + }); + + var FileEventClass = function( eventType, file, key, value ){ + this.eventType = eventType; + this.targetFile = file; + this.updatedAttribute = key; + this.updatedValue = value; + }; + +/* + * file の data は object で保持している。 + * File の外からファイルをみるときは、FileClassを通して操作する。 + * fileの変更、それに付随して追加されたイベントは、TreeClassで管理される。 + * treeがdestryされると、fileのイベントリスナーも全て削除される。 + * 他の tree も data の共通する currentFile に対してのみは、file の変更イベントを受け取って流す. + * + */ + + var FileClass = function( tree, parentData, data ){ + var uid = FILE_CONTROLER.getFileUID( data ); + + FILEDATA_ACCESS.push( { + TREE: tree, + parentData: parentData, + DATA: data + } ); + + tree = parentData = data = null; + + this.getUID = function(){ + return uid; + }; + }; + + FileClass.prototype = { + isChildFile: function( _FILEorFILEDATA ){ + return this.getChildFileIndex( _FILEorFILEDATA) !== -1; + }, + getSeqentialFiles: function(){ + var _driver = FILE_CONTROLER.getDriver( this ); + if( _driver !== null && typeof _driver.getSeqentialFiles === 'function' ){ + _driver.getSeqentialFiles( this ); + } + }, + addEventListener: function( _eventType, _callback ){ + FILE_CONTROLER.addEventListener( this, _eventType, _callback ); + }, + removeEventListener: function( _eventType, _callback ){ + FILE_CONTROLER.removeEventListener( this, _eventType, _callback ); + }, + dispatchEvent: function( e ){ + e instanceof FileEventClass && FILE_CONTROLER.fileEventRellay( this.getUID(), e ); + }, + getChildFileLength: function(){ + var children = FILE_CONTROLER.getChildren( this ); + return Type.isArray( children ) === true ? children.length : -1; + }, + getChildFileIndex: function( _FILEorFILEDATA ){ + var children = FILE_CONTROLER.getChildren( this ); + if( Type.isArray( children ) === false ) return -1; + var l = children.length, + _fileData = FILE_CONTROLER.getFileData( _FILEorFILEDATA ); + if( _fileData === null ) return -1; + for( var i=0; i= _children.length ) return null; + var _file = new FileClass( _access.TREE, _access.DATA, _children[ _index ]); + // _file.init(); + return _file; + }, + getName: function(){ + var driver = FILE_CONTROLER.getDriver( this ); + if( typeof driver.getName === 'function'){ + return driver.getName( this ); + } + return BASE_DRIVER.getName( this ); + }, + getThumbnail: function(){ + var driver = FILE_CONTROLER.getDriver( this ); + if( typeof driver.getThumbnail === 'function'){ + return driver.getThumbnail( this ); + } + return BASE_DRIVER.getThumbnail( this ); + }, + getType: function(){ + var _data = FILE_CONTROLER.getFileData( this ); + return typeof _data.type === 'number' ? _data.type : Const.FILE.TYPE.UNKNOWN; + }, + getState: function(){ + var _data = FILE_CONTROLER.getFileData( this ); + return typeof _data.state === 'number' ? _data.state : Const.FILE.STATE.OK; + }, + getSummary: function(){ + var driver = FILE_CONTROLER.getDriver( this ); + if( typeof driver.getSummary === 'function'){ + return driver.getSummary( this ); + } + return BASE_DRIVER.getSummary( this ); + }, + isWritable: function(){ + return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.WRITE ); + }, + isSortable: function(){ + return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.SORT ); + }, + isCreatable: function(){ + return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.CREATE ); + }, + isRenamable: function(){ + return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.RENAME ); + }, + isDeletable: function(){ + return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.DELETE ); + }, + read: function(){ + // simpleDeepCopy + var driver = FILE_CONTROLER.getDriver( this ), + data; + if( Type.isFunction( driver.read ) === true ){ + data = driver.read( this ); + }; + return BASE_DRIVER.read( data || this ); + }, + write: function( _newData, _onUpdateFunction ){ + var driver = FILE_CONTROLER.getDriver( this ); + if( typeof driver.write === 'function' ){ + return driver.write( this, _newData, _onUpdateFunction ); + }; + return BASE_DRIVER.write( this, _newData, _onUpdateFunction ); + }, + viewerApplicationList: function(){ + var driver = FILE_CONTROLER.getDriver( this ); + if( typeof driver.viewerApplicationList === 'function' ){ + return driver.viewerApplicationList( this ); + }; + return BASE_DRIVER.viewerApplicationList( this ); + }, + editorApplicationList: function(){ + var driver = FILE_CONTROLER.getDriver( this ); + if( typeof driver.editorApplicationList === 'function' ){ + return driver.editorApplicationList( this ); + }; + return BASE_DRIVER.viwerApps( this ); + }, + create: function(){ + + }, + sort: function(){ + + }, + onCopy: function(){ + + }, + onDelete: function(){ + + }, + move: function( _newFolder, _newIndex, opt_callback ){ + var _access = FILE_CONTROLER.getFileDataAccess( this ); + _access.TREE.move( _access.parentData, this.getUID(), _newFolder, _newIndex, opt_callback ); + }, + replace: function( _newIndex, opt_callback ){ + var _access = FILE_CONTROLER.getFileDataAccess( this ); + _access.TREE.replace( _access.parentData, this.getUID(), _newIndex, opt_callback); + }, + /** + * サーチ + * 探しているファイルの属性と値を指定.一致する child の index を配列で返す. + */ + search: function( obj, rule ){ + var _children = FILE_CONTROLER.getChildren( this ), + _child, + ret = [], k, c; + for( var i=0, l=_children.length; i this.w || this.application.MIN_HEIGHT > this.h ){ + if( Type.isHTMLElement( this.rootElement ) === true ){ + // 小さすぎる!、と表示 + }; + }; + if( this.bootParams.length > 2 ){ + this.application.onOpen.apply( this.application, this.bootParams ); + } else { + this.application.onOpen( this.w, this.h ); + }; + this.phase = 4; + }, + fetchResourceComplete : function(){ + --this.fetchResource; + } +}; +ApplicationPrivateData.list = []; +ApplicationPrivateData.get = function( app ){ + var list = ApplicationPrivateData.list, + i = list.length; + for( ; i; ){ + if( app instanceof list[ --i ].appClass ) return list[ i ]; + }; + return null; +}; + +var AbstractApplication = function( appClass, displayName, isOverlay ){ + ( new ApplicationPrivateData() ).init( appClass, displayName, isOverlay ); +}; +AbstractApplication.prototype = { + getUID : function(){ + var data = ApplicationPrivateData.get( this ); + return Util.getIndex( API_USER_LIST, data.appClass ); + }, + init : function(){ + var data = ApplicationPrivateData.get( this ); + // this.rootElement = data.rootElement; + // data.application = this; + data.phase = 1; + data.appClass === Page.appClass && Page.show(); + this.onInit(); + data.phase = 2; + }, + open : function( w, h /*, _option */ ){ + var data = ApplicationPrivateData.get( this ); + data.phase = 3; + data.bootParams = Util.copyArray( arguments ); + data.w = w; + data.h = h; + if( data.rootElement.innerHTML && data.rootElement.innerHTML.length > 0 ){ + SystemTimer.add( this, data.detect, 16, false, data ); + } else { + data.onOpen(); + }; + }, + resize : function( w, h ){ + var data = ApplicationPrivateData.get( this ); + if( data.phase !== 4 ) return; + if( this.MIN_WIDTH > w || this.MIN_HEIGHT > h ){ + if( Type.isHTMLElement( this.rootElement ) === true ){ + // 小さすぎる!、と表示 + }; + return; + }; + this.onPaneResize( w, h ); + }, + close : function(){ + var data = ApplicationPrivateData.get( this ); + data.phase = 5; + if( this.onClose() === false ){ + return false; + }; + if( data.uiList ){ + while( data.uiList.length > 0 ) data.uiList.shift().destroy(); + }; + if( data.finderList ){ + while( data.finderList.length > 0 ) data.finderList.shift().destroy(); + }; + + data.eventRoot && PointingDeviceEventTree.destroyTree( data.eventRoot ); + MouseEvent.remove( this ); + KeyEvent.remove( this ); + SystemTimer.remove( this ); + AsyncCall.remove( this ); + StyleSheet.unload( this ); + + var elm = this.rootElement; + Util.removeAllChildren( elm ); + elm.parentNode.removeChild( elm ); + + Application.shutdown( this, data.isOverlay ); + + data.appClass === Page.appClass && Page.hide(); + + data.phase = 6; + + var list = ApplicationPrivateData.list; + list.splice( Util.getIndex( list, data ), 1 ); + }, + createUIGroup : function( node ){ + var data = ApplicationPrivateData.get( this ), + ui = UI.createUIGroup( this, node ); + if( data.uiList === null ) data.uiList = []; + data.uiList.push( ui ); + return ui; + }, + createUIForm : function( nodeOrElm, opt_elmForm ){ + var data = ApplicationPrivateData.get( this ), + form = UIForm.createForm( this, nodeOrElm, opt_elmForm ); + if( data.formList === null ) data.formList = []; + data.formList.push( form ); + return form; + }, + createFinder : function( _elmTarget, _tree, _onSelect, _viewerOption, _editorOption ){ + var data = ApplicationPrivateData.get( this ), + finder = Finder.create( this, _elmTarget, _tree, _onSelect, _viewerOption, _editorOption ); + if( data.finderList === null ) data.finderList = []; + data.finderList.push( finder ); + return finder; + }, + createDHTML : function( _elm ){ + return DHTML.create( this, _elm ); + }, + addEventListener : function( element, eventType, handler, opt_thisObject ){ + MouseEvent.add( this, element, eventType, handler, opt_thisObject ); + }, + removeEventListener : function( element, eventType, handler ){ + MouseEvent.remove( this, element, eventType, handler ); + }, + getPointingDeviceEventTreeRoot : function(){ + var data = ApplicationPrivateData.get( this ); + if( data.phase === 1 ){ + data.eventRoot = PointingDeviceEventTree.create( this ); + data.styleCursor = PointingDeviceEventTree._getNodePrivateData( data.eventRoot ).elmMouseCatch.style; + }; + return data.eventRoot; + }, + updateCoursor : function( _cursor ){ + var data = ApplicationPrivateData.get( this ); + if( data.cursor !== _cursor ){ + data.styleCursor.cursor = data.cursor = _cursor; + }; + }, + fetchCSS : function( url, opt_onload, opt_onerror ){ + var data = ApplicationPrivateData.get( this ); + if( data.phase === 1 ){ + ++data.fetchResource; + StyleSheet.load( this, url, data.fetchResourceComplete, data.fetchResourceComplete, data ); + }; + }, + onInit : function(){}, + onOpen : function(){}, + onClose : function(){ return true; }, + onPaneResize : function( w, h ){}, + addKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){ + KeyEvent.add( this, _eventType, _handler, _keyCode, _shift, _ctrl ); + }, + removeKeyEventListener : function( _eventType, _handler, _keyCode, _shift, _ctrl ){ + KeyEvent.remove( this, _eventType, _handler, _keyCode, _shift, _ctrl ); + }, + shiftEnabled : function(){ + return KeyEvent.shiftEnabled; + }, + ctrlEnabled : function(){ + return KeyEvent.ctrlEnabled; + }, + addTimer : function( handler, time, once ){ + SystemTimer.add( this, handler, time, !!once ); + }, + removeTimer : function( handler ){ + SystemTimer.remove( this, handler ); + }, + addAsyncCall : function( _callback, _argments, _thisObject ){ + AsyncCall.add( this, _callback, _argments, _thisObject ); + }, + removeAsyncCall : function( _callback ){ + AsyncCall.remove( this, _callback ); + }, + fetchHTMLElement : function( id ){ + var elm = document.getElementById( id ); + if( elm ){ + elm.removeAttribute( 'id' ); + elm.parentNode.removeChild( elm ); + return elm; + }; + } +}; + +var PointingDeviceEventTree = ( function(){ + var ROOT_LIST = [], + currentRootData = null, + targetNodeData = null, + forceNodeData = null, + hoverList = []; + + function eventRellay( e ){ + var data = forceNodeData, // || targetNodeData, + x = e.clientX, + y = e.clientY, + type = e.type, + list = hoverList, + i = 0, + ret, systemOnly = false, addClass, removeClass, + parent; + if( data && data.dispatchEvent( e, type, true ) === true ) return false; + if( currentRootData === null ) return; + targetNodeData = currentRootData; + currentRootData._capcher( x, y ); + targetNodeData.apiuser.updateCoursor( targetNodeData._cursor ); + data = targetNodeData; + while( data ){ + ret = data.dispatchEvent( e, type, true, systemOnly ); + if( ret === true || ret === false ) break; // systemOnly = true; + data = data.parentData; + }; + + addClass = Util.addClass; + removeClass = Util.removeClass; + for( ; i < list.length; ){ + parent = data = list[ i ]; + while( parent.parentData && parent === parent.parentData.hitChild ){ + parent = parent.parentData; + }; + if( parent !== currentRootData ){ + data.hover === true && removeClass( data.elm, data.hoverClass ); + delete data.isHover; + data.events && data.events.mouseout && data.fire( e, 'mouseout', false ); + delete data.hitSelf; + list.splice( i, 1 ); + continue; + }; + if( data.hover === true && data.isHover === false ){ + addClass( data.elm, data.hoverClass ); + data.isHover = true; + }; + if( data.hitSelf === false ){ + data.events && data.events.mouseover && data.fire( e, 'mouseover', true ); + data.hitSelf = true; + }; + ++i; + }; + return false; + }; + + var NodeClass = function( apiuser, rootData, /*parentLayer,*/ parentData, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){ + ( new NodePrivateData() ).init( apiuser, rootData, /*parentLayer,*/ parentData, this, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ); + }; + NodeClass.prototype = { + createNode : function( rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ){ + var data = NodePrivateData.get( this ), + elm; + if( Type.isHTMLElement( rangeOrElmData ) === true ){ + elm = rangeOrElmData; + } else + if( Type.isString( rangeOrElmData ) === true ){ + elm = document.getElementById( rangeOrElmData ); + if( !elm ){ + elm = Util.pullHtmlAsTemplete( rangeOrElmData ); + }; + if( !elm || Type.isHTMLElement( elm ) === false || elm.nodeType !== 1 ){ + throw new Error( "invalid HTMLElement." ); + }; + } else + if( Type.isObject( rangeOrElmData ) === false || Type.isFinite( rangeOrElmData.x ) === false || Type.isFinite( rangeOrElmData.y ) === false ){ + throw new Error( "No range" ); + }; + + if( elm && data.elm === null ){ + throw new Error( "MetaLayer don't containe HTMLElement-Layer." ); + }; + if( data.elm && data.elm.style.hasLayout === false ){ + throw new Error( "[ie] OffsetParent is hasLayout === false." ); + }; + + var newNode = new NodeClass( data.apiuser, data.rootData, data, elm || rangeOrElmData, through, clip, hover, cursor, scroll, dragdrop ), + newData = NodePrivateData.get( newNode ); + + if( data.childData === null ) data.childData = []; + data.childData.push( newData ); + return newNode; + }, + createNodeAt : function(){ + }, + remove : function(){ + NodePrivateData.get( this ).remove(); + }, + nodeIndex : function( v ){ + return NodePrivateData.get( this ).nodeIndex( v ); + }, + numNode : function(){ + return NodePrivateData.get( this ).numNode(); + }, + disabled : function( v ){ + return NodePrivateData.get( this ).disabled( v ); + }, + childrenDisabled : function( v ){ + return NodePrivateData.get( this ).disabled( v ); + }, + mesure : function(){ + NodePrivateData.get( this ).mesure(); + }, + mesureChildren : function(){ + NodePrivateData.get( this ).mesureChildren(); + }, + update : function( x, y, w, h ){ + NodePrivateData.get( this ).update( x, y, w, h ); + }, + setPosition : function( x, y ){ + NodePrivateData.get( this ).setPosition( x, y ); + }, + setSize : function( w, h ){ + NodePrivateData.get( this ).setSize( w, h ); + }, + cursor : function( v ){ + return NodePrivateData.get( this ).cursor( v ); + }, + x : function( x ){ + return NodePrivateData.get( this ).positionX( x ); + }, + y : function( y ){ + return NodePrivateData.get( this ).positionY( y ); + }, + width : function( w ){ + return NodePrivateData.get( this ).width( w ); + }, + height : function( h ){ + return NodePrivateData.get( this ).height( h ); + }, + getAbsolutePositionX : function(){ + return NodePrivateData.get( this ).getAbsolutePositionX(); + }, + getAbsolutePositionY : function(){ + return NodePrivateData.get( this ).getAbsolutePositionY(); + }, + addEventListener : function( type, handler, opt_thisObject ){ + NodePrivateData.get( this ).addEventListener( type, handler, opt_thisObject ); + }, + removeEventListener : function( type, handler ){ + NodePrivateData.get( this ).removeEventListener( type, handler ); + }, + scrollTo : function( x, y ){ + NodePrivateData.get( this ).scrollTo( x, y ); + }, + scrollX : function( v ){ + return NodePrivateData.get( this ).scrollX( v ); + }, + scrollY : function( v ){ + return NodePrivateData.get( this ).scrollY( v ); + }, + invalidateScrollbar : function(){ + ScrollBarManager.update( NodePrivateData.get( this ) ); + } + }; + + /** + * clip : true の場合、子ノードの変更によってヒットエリアを変化させない.elm には overflow:hidden としておくのが通常. + */ + var NodePrivateData = function(){}; + NodePrivateData.prototype = { + elmMouseCatch : null, // rootData only + eventCounter : null, // rootData only + cursorStyle : null, // rootData only + node : null, + apiuser : null, + rootData : null, + elm : null, // resizeTarget + elmScroll : null, + elmScroller : null, + elmScrollbar : null, + x : 0, + y : 0, + w : 0, + h : 0, + t : 0, // top + l : 0, // left + b : 0, // bottom + r : 0, // right + absoluteX : 0, + absoluteY : 0, + _scrollX : 0, + _scrollY : 0, + scrollingX : 0, + scrollingY : 0, + _cursor : '', + // parentLayer : null, + parentData : null, + childData : null, + events : null, + hitChild : null, + hitSelf : false, + _disabled : false, + _childDisabled: false, + layoutManager : null, + through : false, + clip : false, + hover : false, + hoverClass : null, + isHover : false, + scroll : false, + dragdrop : false, + tooltip : null, + init: function( apiuser, rootData, /*parentLayer,*/ parentData, node, rangeOrElm, through, clip, hover, cursor, scroll, dragdrop ){ + this.apiuser = apiuser; + this.rootData = rootData || this; + // this.parentLayer = parentLayer; + this.parentData = parentData; + this.node = node; + this.through = through; + this.clip = !!clip; + if( cursor ) this._cursor = cursor; + + if( Type.isHTMLElement( rangeOrElm ) === true ){ + this.elm = rangeOrElm; + this.hover = !!hover; + this.hoverClass = hover; + this.scroll = clip && scroll; + this.mesure(); + this.scroll === true && ScrollBarManager.register( this ); + } else { + this.update( rangeOrElm.x, rangeOrElm.y, rangeOrElm.w, rangeOrElm.h ); + }; + + NodePrivateData.dataList.push( this ); + }, + mesure : function(){ + var x, y, w, h, parent, _this, _parent; + if( this.elm ){ + w = this.elm.offsetWidth; + h = this.elm.offsetHeight; + _this = Position.cumulativeOffset( this.elm ); + _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ]; + x = _this[ 0 ] - _parent[ 0 ]; + y = _this[ 1 ] - _parent[ 1 ]; + if( this.x !== x || this.y !== y || this.w !== w || this.h !== h ){ + this.x = x; + this.y = y; + this.w = w; + this.h = h; + parent = this.parentData; + parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY ); + this._updateRectangle(); + }; + } else { + this._updateRectangle(); + }; + }, + mesureChildren : function(){ + var nodes, i; + if( nodes = this.childData ){ + for( i = nodes.length; i; ){ + nodes[ --i ].mesure(); + }; + }; + }, + update : function( x, y, w, h ){ + var updateXY = false, + _this, _parent, + parent; + + if( this.elm ){ + // width + if( Type.isFinite( w ) === true ){ + this.elm.style.width = w + 'px'; + } else + if( Type.isString( w ) === true ){ + this.elm.style.width = w; + w = this.elm.offsetWidth; + }; + //update = this.w !== w; + + // height + if( Type.isFinite( h ) === true ){ + this.elm.style.height = h + 'px'; + } else + if( Type.isString( h ) === true ){ + this.elm.style.height = w; + h = this.elm.offsetHeight; + }; + //update = update || this.h !== h; + + // x + if( Type.isFinite( x ) === true ){ + this.elm.style.left = x + 'px'; + } else + if( Type.isString( x ) === true ){ + this.elm.style.left = x; + updateXY = true; + } else { + updateXY = true; + }; + + // y + if( Type.isFinite( y ) === true ){ + this.elm.style.top = y + 'px'; + } else + if( Type.isString( y ) === true ){ + this.elm.style.top = y; + updateXY = true; + } else { + updateXY = true; + }; + if( updateXY === true ){ + _this = Position.cumulativeOffset( this.elm ); + _parent = this.parentData ? Position.cumulativeOffset( this.parentData.elm ) : [ 0, 0 ]; + x = _this[ 0 ] - _parent[ 0 ]; + y = _this[ 1 ] - _parent[ 1 ]; + }; + //update = update || this.x !== x; + //update = update || this.y !== y; + + //update === true && this._updateRectangle(); + // return; + }; + x = Type.isFinite( x ) === true ? x : this.x; + y = Type.isFinite( y ) === true ? y : this.y; + w = Type.isFinite( w ) === true ? w : this.w; + h = Type.isFinite( h ) === true ? h : this.h; + if( this.x !== x || this.y !== y ){ + this.x = x; + this.y = y; + //console.log( 'xy ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h + ' absX:' + this.parentData.absoluteX ) + parent = this.parentData; + parent && this._updateAbsoluteXY( parent.absoluteX, parent.absoluteY, parent.scrollingX, parent.scrollingY ); + this.w === w && this.h === h && this._updateRectangle(); + }; + if( this.w !== w || this.h !== h ){ + this.w = w; + this.h = h; + //console.log( 'wh ' + ( this.elm ? this.elm.id : '' ) + ' x:' + x + ' y:' + y + ' w:' + w + ' h:' + h ) + this._updateRectangle(); + }; + + ScrollBarManager.update( this ); + }, + _updateAbsoluteXY : function( x, y, sX, sY ){ + var nodes, i; + this.absoluteX = x = this.x + x; + this.absoluteY = y = this.y + y; + if( nodes = this.childData ){ + for( i = nodes.length; i; ){ + nodes[ --i ]._updateAbsoluteXY( x, y, this.scrollingX, this.scrollingY ); + }; + }; + }, + _updateRectangle : function(){ + var w = this.w, + h = this.h, + x = this.x, + y = this.y, + l = x, + t = y, + r = x + w, + b = y + h, + nodes = this.childData, + i, node; + // self; + // childnodes + if( this.clip === false && nodes ){ + for( i = nodes.length; i; ){ + node = nodes[ --i ]; + if( node.l + x < l ) l = x + node.l; + if( node.t + y < t ) t = y + node.t; + if( r < node.r + x ) r = x + node.r; + if( b < node.b + y ) b = y + node.b; + }; + }; + // update + if( b !== this.b || r !== this.r || t !== this.t || l !== this.l ){ + this.l = l; + this.t = t; + this.r = r; + this.b = b; + // this.w = r - x; + // this.h = b - y; + this.parentData && this.parentData.clip === false && this.parentData._updateRectangle(); + return true; + }; + }, + setPosition : function( x, y ){ + this.update( x, y ); + }, + setSize : function( w, h ){ + this.update( undefined, undefined, w, h ); + }, + positionX : function( x ){ + x !== undefined && this.update( x ); + return this.x; + }, + positionY : function( y ){ + y !== undefined && this.update( undefined, y ); + return this.y; + }, + width : function( w ){ + w !== undefined && this.update( undefined, undefined, w ); + return this.w; + }, + height : function( h ){ + h !== undefined && this.update( undefined, undefined, undefined, h ); + return this.h; + }, + getAbsolutePositionX : function(){ + return this.absoluteX; + }, + getAbsolutePositionY : function(){ + return this.absoluteY; + }, + cursor : function( v ){ + if( Type.isString( v ) === true ){ + this._cursor = v; + this === targetNodeData && this.apiuser.updateCoursor( v ); + }; + return this._cursor; + }, + addEventListener : function( eventType, handler, opt_thisObject ){ + var node = this.node, + counter = this.rootData.eventCounter, + list, i; + if( this.events === null ) this.events = {}; + list = this.events[ eventType ]; + if( !list ){ + list = this.events[ eventType ] = []; + } else { + for( i = list.length; i; ){ + if( list[ --i ].match( eventType, handler ) === true ){ + return; + }; + }; + }; + list.push( new EventTicketClass( this.node, eventType, handler, opt_thisObject ) ); + if( eventType !== 'mouseout' && eventType !== 'mouseover' ){ + if( counter[ eventType ] ){ + ++counter[ eventType ]; + } else { + //console.log( eventType ); + counter[ eventType ] = 1; + MouseEvent.add( this.apiuser, this.rootData.elmMouseCatch, eventType, eventRellay ); + }; + }; + }, + removeEventListener : function( eventType, handler ){ + var events = this.events, + counter = this.rootData.eventCounter, + type, list, i = 0; + if( events === null ) return; + console.log( ' *** remove ' + eventType ); + for( type in events ){ + list = events[ type ]; + if( eventType && eventType !== type ) continue; + for( ; i < list.length; ){ + if( list[ i ].destroy( type, handler ) === true ){ + console.log( ' *** removed! ' + type ); + list.splice( i, 1 ); + } else { + ++i; + }; + }; + if( list.length === 0 ){ + // delete this[ type ]; + delete events[ type ]; + }; + if( counter[ type ] ){ + --counter[ type ]; + if( counter[ type ] === 0 ){ + MouseEvent.remove( this.apiuser, this.rootData.elmMouseCatch, type, eventRellay ); + delete counter[ type ]; + }; + }; + }; + }, + _capcher : function( x, y ){ + var t = this, nodes, child, _x, _y, hit, i; + if( t._disabled === true ) return false; + delete t.hitChild; + x -= t.x; + y -= t.y; + if( nodes = t.childData ){ + _x = x - t.scrollingX; + _y = y - t.scrollingY; + for( i = nodes.length; i; ){ + child = nodes[ --i ]; + if( child._disabled === false && child.l <= _x && _x < child.r && child.t <= _y && _y < child.b && child._capcher( _x, _y ) === true ){ + t.hitChild = child; + break; + }; + }; + }; + if( t.through === true ){ + t.hitChild && t.hitSelf === false && hoverList.push( t ); + return !!t.hitChild; + }; + hit = 0 <= x && x < t.w && 0 <= y && y < t.h; + ( t.hitChild || hit ) && t.hitSelf === false && hoverList.push( t ); + if( hit === true && t.hitChild === null ) targetNodeData = t; + return hit || !!t.hitChild; + }, + fire : function( e, eventType, hit ){ + var list = this.events[ eventType ], + i = list.length; + e = NodePrivateData.createEvent( e, eventType, this, hit ); + for( ; i; ) list[ --i ].fire( e ); + // console.log( eventType + ' x:' + x + ' y:' + y ); + }, + dispatchEvent : function( e, eventType, hit ){ + var ret, list, i, p, child; + if( !this.events || !( list = this.events[ eventType ] ) ) return; + + child = !!this.hitChild; + e = NodePrivateData.createEvent( e, eventType, this, hit ); + for( i = list.length; i; ){ + ret = list[ --i ].fire( e ); + if( ret === true && child === false ){ + forceNodeData = this; + return true; + }; + if( ret === false ) return false; + }; + forceNodeData = null; + }, + scrollTo : function( x, y ){ + this._scrollX = x; + this._scrollY = y; + ScrollBarManager.update( this ); + }, + scrollX : function( v ){ + if( Type.isFinite( v ) === true ){ + this._scrillX = v; + ScrollBarManager.update( this ); + }; + return this.scrollingX; // this._scrollX; + }, + scrollY : function( v ){ + if( Type.isFinite( v ) === true ){ + this._scrillY = v; + ScrollBarManager.update( this ); + }; + return this.scrollingY; // this._scrollY; + }, + nodeIndex : function( v ){ + var list, i; + if( !this.parentData ) return 0; + + list = this.parentData.childData; + i = Util.getIndex( list, this ); + if( Type.isFinite( v ) === false || i === v && v < 0 && list.length <= v ) return i; + + list.splice( i, 1 ); + list.length === v ? list.push( this ) : list.splice( v, 0, this ); + this._free(); + return v; + }, + _free : function(){ + if( this.parentData.hitChild === this ){ + this.parentData.hitChild = null; + this.isHover === true && hoverList.splice( Util.getIndex( hoverList, this ), 1 ) && Util.removeClass( this.elm, this.hoverClass ); + this.isHover = false; + if( forceNodeData === this ) forceNodeData = null; + if( targetNodeData === this ) targetNodeData = null; + }; + }, + numNode : function(){ + return this.childData ? this.childData.length : 0; + }, + disabled : function( v ){ + if( Type.isBoolean( v ) === true ){ + this._disabled = v; + if( v === false ){ + this._free(); + }; + }; + return this._disabled; + }, + childrenDisabled : function( v ){ + if( Type.isBoolean( v ) === true ){ + this._childDisabled = v; + }; + return this._childDisabled; + }, + remove : function(){ + if( this === this.rootData ) return; + var parent = this.parentData, + nodes = parent.childData; + this._destroy(); + if( parent.hitChild === this ) delete parent.hitChild; + nodes.splice( Util.getIndex( nodes, this ), 1 ); + if( nodes.length === 0 ) delete parent.childData; + parent.clip === false && parent._updateRectangle(); + }, + _destroy : function(){ + var nodes = this.childData, + list = NodePrivateData.dataList, + node; + this.removeEventListener(); + ScrollBarManager.remove( this ); + if( nodes ){ + while( node = nodes.shift() ) node._destroy(); + delete this.childData; + }; + list.splice( Util.getIndex( list, this ), 1 ); + } + }; + NodePrivateData.dataList = []; + NodePrivateData.get = function( node ){ + // if( node instanceof NodePrivateData ) return node; + // return NodePrivateData.dataList[ layer._getUID() ]; + var list = NodePrivateData.dataList; + for( var i = list.length; i; ){ + if( list[ --i ].node === node ) return list[ i ]; + }; + return null; + }; + NodePrivateData.createEvent = function( e, eventType, data, hit ){ + var _e = { + layerX : e.clientX - data.absoluteX, + layerY : e.clientY - data.absoluteY, + clientX : e.clientX, + clientY : e.clientY, + dragOffsetX : e.dragOffsetX, + dragOffsetY : e.dragOffsetY, + dragPhase : e.dragPhase, + eventType : eventType, + hit : hit, + node : data.node, + wheelDelta : e.wheelDelta, + target : forceNodeData ? forceNodeData.node : targetNodeData ? targetNodeData.node : null + }; + return _e; + }; + + var EventTicketClass = function( node, eventType, handler, opt_thisObject ){ + this.node = node; + this.type = eventType; + this.handler = handler; + this.thisObj = opt_thisObject || node; + }; + EventTicketClass.prototype = { + match : function( eventType, handler ){ + if( handler && this.handler !== handler ) return false; + if( eventType && this.type !== eventType ) return false; + return true; + }, + destroy : function( eventType, handler ){ + if( this.match( eventType, handler ) === false ) return false; + delete this.node; + delete this.type; + delete this.handler; + delete this.thisObj; + return true; + }, + fire : ( function(){ + if( Function.prototype.call ){ + return function( e ){ + return this.handler.call( this.thisObj, e ); + }; + }; + return function( e ){ + var ret; + this.thisObj._currentHandler = this.handler; + ret = this.thisObj._currentHandler( e ); + delete this.thisObj._currentHandler; + return ret; + }; + })() + }; + +/*------------------------------------- + * StayHelper + */ + var StayEventTicketClass = function( node, data, stayhandler, opt_thisObject ){ + node.addEventListener( 'mouseover', this.mouseoverHandler, this ); + this.node = node; + this.data = data; + this.handler = stayhandler; + this.thisObject = opt_thisObject; + }; + StayEventTicketClass.prototype = Util.extend( new EventTicketClass( null, 'mousestay' ), { + // type : 'mousestay', + e : null, + mouseoverHandler : function( e ){ + this.e = NodePrivateData.createEvent( e, this.type, this.data, true ); + this.node.addEventListener( 'mouseout', this.mousestayHandler, this ); + this.node.addEventListener( 'mousemove', this.mousemoveHandler, this ); + SystemTimer.add( this.data.apiuser, this.timeoutHandler, null, this ); + }, + timeoutHandler : function(){ + this.mouseoutHandler(); + return this.fire( this.e ); + }, + mousemoveHandler : function( e ){ + this.e = NodePrivateData.createEvent( e, this.type, this.data, true ); + SystemTimer.remove( this.data.apiuser, this.timeoutHandler ); + SystemTimer.add( this.data.apiuser, this.timeoutHandler, null, this ); + }, + mouseoutHandler : function( e ){ + this.node.removeEventListener( 'mouseout', this.mousestayHandler ); + this.node.removeEventListener( 'mousemove', this.mousemoveHandler ); + SystemTimer.remove( this.data.apiuser, this.timeoutHandler ); + delete this.e; + } + }); + + var ScrollBarManager = ( function(){ + var elmScroller = document.createElement( 'div' ), + elmBar = document.createElement( 'div' ), + smoothList = [], + dragPhase = 2, + dragOut = false, + currentNodeData = null, + dragStartY = 0, + currentEvent; + + function tick(){ + var list = smoothList, + i, data, y; + for( i = 0; i < list.length; ){ + data = list[ i ]; + if( data.scrollingY !== data._scrollY ){ + y = data.scrollingY += data.smoothY; + if( data.smoothY < 0 ){ + y = y < data._scrollY ? data._scrollY : y; + } else { + y = data._scrollY < y ? data._scrollY : y; + }; + data.scrollingY = y; + data.elm.scrollTop = -y; + data.events && data.events.scroll && data.fire( currentEvent, 'scroll', true ); + }; + if( data.scrollingY === data._scrollY ){ + list.splice( i, 1 ); + // data.events && data.events.scroll && data.fire( currentEvent, 'scroll', true ); + } else { + ++i; + }; + }; + list.length === 0 && SystemTimer.remove( SUPER_USER_KEY, tick ); + currentEvent.type = 'updateAfterScroll'; + AsyncCall.add( data.apiuser, eventRellay, currentEvent ); // スクロール後の更新 + }; + + function scrollReady( e ){ + var data = this; + + dragOut = false; + if( data === currentNodeData || dragPhase !== 2 ) return; // Drag中の場合は 他にスクロールを作らない + currentNodeData && scrollRelease(); + + dragPhase = 2; + data.elm.parentNode.appendChild( elmScroller ); + elmScroller.appendChild( data.elm ); + + elmScroller.style.cssText = 'position:absolute;left:0;top:0;'; + elmScroller.appendChild( elmBar ); + + data.elm.scrollTop = -data.scrollingY; + data.rootData.addEventListener( 'mousewheel', onMouseWheelScroll, data ); + data.rootData.addEventListener( 'mousedrag', onMouseDragScroll, data ); + data.addEventListener( 'mouseout', onMouseOut, data ); + currentNodeData = data; + ScrollBarManager.update( data ); + }; + function scrollRelease(){ + var data = currentNodeData; + var parent = elmScroller.parentNode; + parent.appendChild( currentNodeData.elm ); + parent.removeChild( elmScroller ); + currentNodeData.elm.scrollTop = -data.scrollingY; + + data.rootData.removeEventListener( 'mousewheel', onMouseWheelScroll, data ); + data.rootData.removeEventListener( 'mousedrag', onMouseDragScroll, data ); + data.removeEventListener( 'mouseout', onMouseOut, data ); + currentNodeData = null; + }; + function onMouseOut( e ){ + dragOut = true; + console.log( 'mouseOut ' + dragPhase ); + dragPhase === 2 && scrollRelease(); // Dragしてのアウトの場合, scroll をリリースしない + }; + function onMouseWheelScroll( e ){ + var data = this; + this._scrollY += e.wheelDelta; + ScrollBarManager.update( this ); + currentEvent = e; + return true; + }; + function onMouseDragScroll( e ){ + var data = this; + //e.dragOffsetY; + currentEvent = e; + dragPhase = e.dragPhase; + switch( dragPhase ){ + case 0: + dragStartY = this.scrollingY; + data.rootData.removeEventListener( 'mousewheel', onMouseWheelScroll, data ); + case 1: + this._scrollY = dragStartY + e.dragOffsetY; + ScrollBarManager.update( this ); + return true; + case 2: + dragOut === true ? scrollRelease() : data.rootData.addEventListener( 'mousewheel', onMouseWheelScroll, data ); + return false; + }; + }; + + return { + register : function( data ){ + data.addEventListener( 'mouseover', scrollReady, data ); + }, + update : function( data ){ + // if( data !== currentNodeData ) return; + var isCurrent = data === currentNodeData; + + var contentH = data._scrollH = data.elm.scrollHeight, + clipH = data.h, + offsetH = contentH - clipH, + scrollY = data._scrollY = 0 < data._scrollY ? 0 : ( data._scrollY < -offsetH ? -offsetH : data._scrollY ), + barH, barY; + if( isCurrent === true ){ + elmScroller.style.width = data.w + 'px'; + elmScroller.style.height = clipH + 'px'; + }; + + if( offsetH < 1 ){ + data._scrollY = scrollY = 0; + if( isCurrent === true ) elmBar.style.display = 'none'; + } else + if( isCurrent === true ){ + barH = Math.floor( clipH * ( clipH / contentH ) ); + barY = Math.floor( ( clipH - barH ) * - scrollY / offsetH ); + elmBar.style.cssText = [ + 'position:absolute;', + 'width:10px;', + 'background-color:#333;', + 'right:2px;', + 'font-size:0;line-height:0;', + 'height:', barH, 'px;', + 'top:', data.y + barY, 'px;' + ].join( '' ); + }; + data.smoothY = ( scrollY - data.scrollingY ) / 10; + if( data.scrollingY !== scrollY && Util.getIndex( smoothList, data ) === -1 ){ + smoothList.length === 0 && SystemTimer.add( SUPER_USER_KEY, tick, 16 ); + smoothList.push( data ); + }; + }, + remove : function( data ){ + var list = smoothList, + i = Util.getIndex( list, data ); + data === currentNodeData && scrollRelease(); + i !== -1 && list.splice( i, 1 ); + } + }; + })(); + + return { + create : function( apiuser ){ + var elm = document.createElement( 'div' ), + root, data; + body.appendChild( elm ); + + root = new NodeClass( apiuser, null, null, elm ); + data = NodePrivateData.get( root ); + + // elm.style.cssText = 'position:absolute;top:0;left:0;height:100%;'; + elm.className = 'mouse-operation-catcher'; + elm.unselectable = 'on'; + data.elmMouseCatch = elm; + + data.eventCounter = {}; + ROOT_LIST.push( data ); + currentRootData = data; + targetNodeData = null; + forceNodeData = null; + + MouseEvent.add( apiuser, elm, 'mousemove', eventRellay ); + return root; + }, + onCurrentApplicationChange : function( _application ){ + currentRootData = null; + targetNodeData = null; + forceNodeData = null; + for( var i = ROOT_LIST.length; i; ){ + if( ROOT_LIST[ --i ].apiuser === _application ){ + currentRootData = ROOT_LIST[ i ]; + return; + }; + }; + }, + destroyTree : function( root ){ + var data = NodePrivateData.get( root ); + MouseEvent.remove( data.apiuser, data.elmMouseCatch, 'mousemove', eventRellay ); + body.removeChild( data.elmMouseCatch ); + data._destroy(); + ROOT_LIST.splice( Util.getIndex( ROOT_LIST, data ), 1 ); + if( currentRootData === data ){ + currentRootData = null; + targetNodeData = null; + forceNodeData = null; + }; + }, + onSystemShutdown : function(){ + + }, + isNodeInstance : function( node ){ + return node instanceof NodeClass; + }, + _getNodePrivateData : function( node ){ // system only + return NodePrivateData.get( node ); + } + }; +})(); + +var Application = ( function(){ + + var LIVE_APPLICATION_LIST = []; + + var currentApplication = null, + coveredApplication = null, + winW = 0, + winH = 0; + + var ApplicationReference = function( appClass, isOverlay, displayName, id, thumbnailUrl, tailColor ){ + var self = this; + var application = null; + this.id = id; + this.displayName = displayName; + this.thumbnailUrl = thumbnailUrl; + this.tailColor = tailColor; + + function asyncBoot(){ + application = Application.boot( appClass, displayName, self.getUID(), isOverlay, Util.copyArray( arguments ) ); + }; + this.getUID = function(){ + return Util.getIndex( API_USER_LIST, appClass ); + }; + this.getDisplayName = function(){ + return this.displayName; + }; + this.boot = function( /* _option */ ){ + AsyncCall.add( this, asyncBoot, Util.copyArray( arguments ) ); + }; + this.shutdown = function(){ + if( !application ) return false; + + AsyncCall.add( application, ( isOverlay === true ? Overlay.hide : application.close ) ); + }; + }; + + function asyncBootHome(){ + currentApplication === null && Home.boot(); + }; + function asyncOpen( /* arguments */ ){ + var _arg = Util.copyArray( arguments ); + _arg.unshift( winW, winH ); + currentApplication.open.apply( currentApplication, _arg ); + }; + return { + register: function( _class, _overlay, _tail, _displayName, _id, _thumbnailUrl, _tailColor ){ + APPLICATION_LIST.push( _class ); + API_USER_LIST.push( _class ); + var _ref = new ApplicationReference( _class, _overlay, _displayName, _id, _thumbnailUrl, _tailColor ); + _tail === true && Home.add( _ref ); + return _ref; + }, + isApplicationInstance: function( app ){ + return ApplicationPrivateData.get( app ) !== null; + }, + isApplicationReference: function( _reference ){ + return _reference instanceof ApplicationReference; + }, + isCurrentAppplication: function( app ){ + return app === currentApplication; + }, + boot: function( appClass, displayName, uid, isOverlay, arg ){ + if( currentApplication ){ + if( currentApplication.getUID() === uid ) return null; + if( isOverlay === false && currentApplication.close() === false ) return null; + }; + + appClass.prototype = new AbstractApplication( appClass, displayName, isOverlay ); + + var application = new appClass(), + data = ApplicationPrivateData.get( application ); + + application.rootElement = data.rootElement; + data.application = application; + + coveredApplication = isOverlay === true ? currentApplication : null; + + Application.onCurrentApplicationChange( application ); + + if( isOverlay === false ){ + body.style.backgroundColor = application.bgColor; + + body.appendChild( data.rootElement ); + data.rootElement.style.display = 'none'; + application.init(); + + application.addAsyncCall( asyncOpen, arg ); + } else { + Overlay.show( application, arg ); + }; + + return application; + }, + shutdown: function( _application, isOverlay ){ + if( isOverlay === false ){ + currentApplication = null; + AsyncCall.add( SUPER_USER_KEY, asyncBootHome ); + } else { + Application.onCurrentApplicationChange( coveredApplication ); + coveredApplication = null; + }; + }, + onCurrentApplicationChange: function( _application ){ + if( Application.isApplicationInstance( _application ) === false ) return; + if( currentApplication === _application ) return; + currentApplication = _application; + MouseEvent.onCurrentApplicationChange( _application ); + PointingDeviceEventTree.onCurrentApplicationChange( _application ); + KeyEvent.updateCurrentListener( _application ); + // InteractiveLayer.onCurrentApplicationChange( _application ); + }, + onApplicationShutdown: function( _application ){ + LIVE_APPLICATION_LIST.splice( Util.getIndex( LIVE_APPLICATION_LIST, _application ) ); + }, + onWindowResize: function( w, h ){ + winW = w; + winH = h; + currentApplication && currentApplication.resize( w, h ); + Overlay.onWindowResize( w, h ); + UI.onWindowResize( w, h ); + }, + onSystemShutdown: function(){ + + } + } +})(); + +/* -------------------------------------------------------------- + * Home + * + */ + var Home = ( function(){ + var APP_REF_LIST = []; + var ELM_TAIL_ORIGIN = ( function(){ + var ret = document.createElement( 'div' ), + h2 = document.createElement( 'h2' ); + ret.className = 'tail-wrapper'; + ret.appendChild( h2 ); + h2.appendChild( document.createTextNode( 'appName' ) ); + return ret; + })(); + + var TailClass = function( appRef ){ + this.elm = ELM_TAIL_ORIGIN.cloneNode( true ); + this.destroy = function(){ + appRef = self = elmName = null; + }; + + var self = this, + elmName = this.elm.getElementsByTagName( 'h2' )[ 0 ].firstChild; + + this.elm.style.backgroundColor = appRef.tailColor; + elmName.data = appRef.displayName; + }; + + var ref = Application.register( function(){ + var self = this, + winW = 0, + winH = 0, + tailList = [], + elmContainer, elmHeader; + + function draw(){ + var tail, elm; + for( var i=0, l=APP_REF_LIST.length; i 0 ){ + tailList.shift().destroy(); + } + self = tailList = elmContainer = null; + }; + }, false, false, 'home', 'home', null ); + + return { + add: function( _appRef ){ + if( Application.isApplicationReference( _appRef ) === false ) return; + Util.getIndex( APP_REF_LIST, _appRef ) === -1 && APP_REF_LIST.push( _appRef ); + }, + boot: function(){ + ref.boot(); + } + } + })(); + + var Page = ( function(){ + var pageNodes = [], + appClass, ref, + ignoreTagList = [ 'script', 'noscript', 'style' ]; + + var MemoryClass = function( node ){ + this.node = node; + }; + MemoryClass.prototype = { + init: function(){ + var node = this.node, + _nodeType = node.nodeType; + if( _nodeType === 1 && Util.getIndex( ignoreTagList, node.tagName.toLowerCase() ) === -1 ){ + this.type = _nodeType; + this.display = node.style.display; + } else + if( _nodeType === 3 ){ + if( node.data.replace( /\s/g, '' ).length !== 0 ){ + this.type = _nodeType; + this.before = pageNodes.length === 0 ? null : pageNodes[ pageNodes.length - 1 ].node; + } else { + body.removeChild( node ); + return false; + } + } else { + // body.removeChild( node ); + return false; + }; + }, + show: function(){ + if( this.type === 1 ){ + if( this.display ){ + this.node.style.display = this.display; + } else { + this.node.style.display = ''; + } + } else { + if( this.before ){ + body.insertBefore( this.node, this.before ); + } else { + body.appendChild( this.node ); + }; + }; + }, + hide: function(){ + if( !this.node.parentNode ){ + return; + }; + if( this.type === 1 ){ + this.node.style.display = 'none'; + } else { + body.removeChild( this.node ); + }; + } + }; + + return { + onReady: function(){ + var _children = Util.copyArray( body.childNodes ), + _mem; + for( var i = 0, l = _children.length; i= CLICK_OFFSET && this.mouseoutHandler(); + return false; + }, + mouseupHandler : function( e ){ + this.mouseoutHandler(); + return this.fire( ClickEventTicketClass.createEvent( e ) ); + }, + mouseoutHandler : function( e ){ + this.mousemoveTicket && this.mousemoveTicket.destroy(); + this.mouseupTicket && this.mouseupTicket.destroy(); + this.mouseoutTicket && this.mouseoutTicket.destroy(); + if( this.mousemoveTicket ) delete this.mousemoveTicket; + if( this.mouseupTicket ) delete this.mouseupTicket; + if( this.mouseoutTicket ) delete this.mouseoutTicket; + return false; + }, + destroy : function( _element, _eventType, _handler ){ + if( this.match( _element, _eventType, _handler ) === false ) return false; + + this.mouseoutHandler(); + this.mousedownTicket.destroy(); + + delete this.element; + delete this.handler; + delete this.thisObject; + delete this.mousedownTicket; + return true; + } + }; + if( document.createEvent ){ + ClickEventTicketClass.createEvent = function( e ){ + var _e = document.createEvent( 'MouseEvents' ); + _e.initMouseEvent( + 'click' , false, true, e.view, + e.detail, e.screenX, e.screenY, e.clientX, e.clientY, + e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, + e.button, e.relatedTarget + ); + return _e; + }; + } else + if( document.attachEvent ){ + ClickEventTicketClass.createEvent = function( e ){ + e.type = 'click'; + return e; + }; + } else { + + }; + + /*------------------------------------- + * WheelHelper + */ + var WheelEventTicketClass = ( function(){ + if( UA.GECKO ){ + return function( element, wheelhandler, opt_thisObject ){ + this.wheelTicket = new EventTicketClass( element, 'DOMMouseScroll', this.onGeckoWheel, this ); + this.element = element; + this.handler = wheelhandler; + this.thisObject = opt_thisObject; + }; + } else + if( true || UA.isIE ){ + return function( element, wheelhandler, opt_thisObject ){ + this.wheelTicket = new EventTicketClass( element, this.eventType, wheelhandler ); + this.element = element; + this.handler = wheelhandler; + this.thisObject = opt_thisObject; + }; + } else { + TMP.wheelHandlerList = []; + TMP.wheelThisObjList = []; + //TMP.wheelLegacy = undefined; + TMP.onWheel = function( e ){ + e = e || window.event; + var cancel = true, + f = TMP.wheelLegacy, i; + if( f ) cancel = f.call( this, e ); + + for( i = TMP.wheelHandlerList.length; i; ){ + if( TMP.wheelHandlerList[ --i ].call( TMP.wheelThisObjList[ i ] || this, e ) === false ) cancel = false; + }; + return cancel; + }; + return function( element, wheelhandler, opt_thisObject ){ + this.element = element; + this.handler = wheelhandler; + this.thisObject = opt_thisObject; + + if( TMP.wheelHandlerList.length === 0 ){ + //TMP.wheelLegacy = Type.isFunction( window.onmousewheel ) === true ? window.onmousewheel : undefined; + element.onmousewheel = TMP.onWheel; + }; + TMP.wheelHandlerList.push( wheelhandler ); + TMP.wheelThisObjList.push( opt_thisObject ) + }; + }; + })(); + WheelEventTicketClass.prototype = { + eventType : 'mousewheel', + match : EventTicketClass.prototype.match, + destroy : function( _element, _eventType, _handler ){ + if( this.match( _element, _eventType, _handler ) === false ) return false; + + this.wheelTicket && this.wheelTicket.destroy(); + + delete this.wheelTicket; + delete this.element; + delete this.handler; + delete this.thisObject; + + this.onDestroy && this.onDestroy(); + return true; + } + }; + if( UA.GECKO ){ + WheelEventTicketClass.prototype.onGeckoWheel = function( e ){ + var _e = document.createEvent( 'MouseEvents' ); + _e.initMouseEvent( + 'mousewheel' , false, true, e.view, + e.detail, e.screenX, e.screenY, e.clientX, e.clientY, + e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, + e.button, e.relatedTarget + ); + _e.wheelDelta = e.detail * -40; + return this.handler.call( this.thisObject || this.element, _e ); + }; + } else + if( true || UA.isIE ){ + + } else { + WheelEventTicketClass.prototype.onDestroy = function(){ + TMP.wheelHandlerList.splice( Util.getIndex( TMP.wheelHandlerList, this.handler ), 1 ); + TMP.wheelThisObjList.splice( Util.getIndex( TMP.wheelThisObjList, this.handler ), 1 ); + if( TMP.wheelHandlerList.length === 0 ) this.element.onmousewheel = ''; + }; + }; + + /*------------------------------------- + * DragHelper + */ + var DragEventTicketClass = function( element, draghandler, opt_thisObject ){ + this.mousedownTicket = new EventTicketClass( element, 'mousedown', this.mousedownHandler, this ); + this.element = element; + this.handler = draghandler; + this.thisObject = opt_thisObject; + }; + DragEventTicketClass.prototype = { + element : null, + handler : null, + thisObject : null, + startX : 0, + startY : 0, + dragging : false, + mousedownTicket : null, + mousemoveTicket : null, + mouseupTicket : null, + mouseoutTicket : null, + eventType : 'mousedrag', + fire : EventTicketClass.prototype.fire, + match : EventTicketClass.prototype.match, + mousedownHandler: function( e ){ + this.startX = e.clientX; + this.startY = e.clientY; + + this.mousemoveTicket = new EventTicketClass( this.element, 'mousemove', this.dragMoveHandler, this ); + this.mouseupTicket = new EventTicketClass( this.element, 'mouseup', this.dragEndHandler, this ); + this.mouseoutTicket = new EventTicketClass( this.element, 'mouseout', this.dragEndHandler, this ); + + return false; + }, + dragMoveHandler : function( e ){ + var offsetX = e.clientX - this.startX, + offsetY = e.clientY - this.startY; + if( this.dragging === false ){ + if( offsetX * offsetX + offsetY * offsetY < DRAG_OFFSET ) return; + console.log( 'Drag start' ); + // dragStart + this.dragging = true; + return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 0 ) ); + }; + return this.fire( DragEventTicketClass.createEvent( e, offsetX, offsetY, 1 ) ); + }, + dragEndHandler : function( e ){ + if( this.dragging === true ){ + console.log( 'Drag End ' + e.type ); + this.removeEvents(); + // dragEnd + return this.fire( DragEventTicketClass.createEvent( e, e.clientX - this.startX, e.clientY - this.startY, 2 ) ); + }; + this.removeEvents(); + return false; + }, + removeEvents : function(){ + this.dragging = false; + if( this.mousemoveTicket ){ + this.mousemoveTicket.destroy(); + delete this.mousemoveTicket; + }; + if( this.mouseupTicket ){ + this.mouseupTicket.destroy(); + delete this.mouseupTicket; + }; + if( this.mouseoutTicke ){ + this.mouseoutTicket.destroy(); + delete this.mouseoutTicket; + }; + }, + destroy : function( _element, _eventType, _handler ){ + if( this.match( _element, _eventType, _handler ) === false ) return false; + + this.removeEvents(); + this.mousedownTicket.destroy(); + + delete this.element; + delete this.handler; + delete this.thisObject; + delete this.mousedownTicket; + return true; + } + }; + if( document.createEvent ){ + DragEventTicketClass.createEvent = function( e, offsetX, offsetY, dragPhase ){ + var _e = document.createEvent( 'MouseEvents' ); + _e.initMouseEvent( + DragEventTicketClass.prototype.eventType , false, true, e.view, + e.detail, e.screenX, e.screenY, e.clientX, e.clientY, + e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, + e.button, e.relatedTarget + ); + _e.dragPhase = dragPhase; + _e.dragOffsetX = offsetX; + _e.dragOffsetY = offsetY; + return _e; + }; + } else + if( document.attachEvent ){ + DragEventTicketClass.createEvent = function( e, offsetX, offsetY, dragPhase ){ + e.type = DragEventTicketClass.prototype.eventType; + e.dragPhase = dragPhase; + e.dragOffsetX = offsetX; + e.dragOffsetY = offsetY; + return e; + }; + } else { + + }; + + return { + add: function( _apiuser, _element, _eventType, _handler, opt_thisObject ){ + if( isApiUser( _apiuser ) === true && + ( Type.isHTMLElement( _element ) === true || _element === window || _element === document ) && + Type.isString( _eventType ) === true && + Type.isFunction( _handler ) === true + ){ + var _uid = _apiuser.getUID(), + _events = EVENT_LIST_MAP[ _uid ]; + if( Type.isArray( _events ) === false ){ + _events = EVENT_LIST_MAP[ _uid ] = []; + } else { + // 2重登録の禁止 + for( var i=0, l=_events.length; i 0; + } catch( e ){ + return false; + }; + }, + done: false + }; + + function getTicket( elm ){ + for( var i = TICKET_LIST.length, t; i; ){ + t = TICKET_LIST[ --i ]; + if( t.elm === elm ) return t; + }; + }; + + function detect(){ + var t = getTicket( this ), rs = this.readyState, c; + if( t && t.done === false && ( !rs || Util.getIndex( STATE_LIST, rs ) !== -1 ) ){ + t.done = true; + t.loaded(); + this.onreadystatechange = new Function(); + this.onload = null; + }; + }; + + function checkTimer(){ + var l = TICKET_LIST.length, + n = 0, t; + for( var i = 0; i < l; ++i ){ + t = TICKET_LIST[ i ]; + ++t.time; + if( t.check() === true ){ + t.loaded(); + ++n; + } else + if( t.time > 99 ){ + t.error(); + } else { + + }; + }; + l === n && SystemTimer.remove( SUPER_USER_KEY, checkTimer ); + }; + + return { + load: function( _apiuser, _url, opt_onload, opt_onerror, opt_thisObject ){ + _url = Util.getAbsolutePath( _url ); + var t; + for( var i=TICKET_LIST.length; i; ){ + t = TICKET_LIST[ --i ]; + if( t.match( null, _url ) === true ){ + if( t.match( _apiuser, _url ) === false ){ + t.apiusers.push( _apiuser ); + t.onload.push( opt_onload ); + t.onerror.push( opt_onerror ); + t.thisObj.push( opt_thisObject ); + }; + SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 ); + return; + }; + }; + var elm = document.createElement( 'link' ); + head.appendChild( elm ); + elm.rel = 'stylesheet'; + elm.type = 'text\/css'; + elm.onreadystatechange = elm.onload = detect; + elm.href = _url; + + if( !sheet ){ // only assign these once + cssRules = 'cssRules'; + sheet = 'sheet'; + if ( !( sheet in elm ) ) { // MSIE uses non-standard property names + cssRules = 'rules'; + sheet = 'styleSheet'; + }; + }; + + TICKET_LIST.push( new FetchCssTicketClass( _apiuser, _url, elm, opt_onload, opt_onerror, opt_thisObject ) ); + + SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 ); + }, + unload: function( _apiuser, _url ){ + _url = _url ? Util.getAbsolutePath( _url ) : null; + var t; + for( var i = 0; i < TICKET_LIST.length; ){ + t = TICKET_LIST[ i ]; + if( t.destroy( _apiuser, _url ) === true ){ + TICKET_LIST.splice( i, 1 ); + } else { + ++i; + } + }; + if( TICKET_LIST.length === 0 ){ + SystemTimer.remove( SUPER_USER_KEY, checkTimer ); + } + } + } +})(); + +/* + * AssetLoader + * fetchCSS + * fetchJson + * fetchHtml + * fetchImage + * fetchLocalFile + * fetchLocalStorage + */ + +var Image = ( function(){ + var TASK_LIST = []; + /* + * FetchClass original is + * + * LICENSE: MIT? + * URL: http://d.hatena.ne.jp/uupaa/20080413/1208067631 + * AUTHOR: uupaa.js@gmail.com + * + */ + function detect(){ + for( var i=0, t; i < TASK_LIST.length; ){ + t = TASK_LIST[ i ]; + if( t.complete() === true ){ + TASK_LIST.splice( i, 1 ); + } else { + ++i; + }; + }; + TASK_LIST.length === 0 && SystemTimer.remove( SUPER_USER_KEY, detect ); + }; + function getTask( img ){ + for( var i = TASK_LIST.length; i; ){ + if( TASK_LIST[ --i ].img === img ) return TASK_LIST[ i ]; + }; + }; + function onError(){ + var task = getTask( this ); + if( task.finish === true ) return; + task.finish = true; + AsyncCall.add( task.apiuser, task.asyncCallback, null, task ); + }; + function onLoad(){ + // if( finish === true ) return; // これがあると firefox3.6 で駄目、、、 + // if( timer ) return; // これがあると safari3.2 で駄目、、、 + var task = getTask( this ); + task.finish = true; + TASK_LIST.splice( Util.getIndex( TASK_LIST, task ), 1 ); + if( window.opera && !task.img.complete ){ + AsyncCall.add( task.apiuser, task.asyncCallback, null, task ); + return; + }; + task.size = Util.getImageSize( this ); + AsyncCall.add( task.apiuser, task.asyncCallback, null, task ); + }; + + + var FetchClass = function( apiuser, abspath, onLoadCallback, onErrorCallback, timeout ){ + this.apiuser = apiuser; + this.abspath = abspath; + this.onLoadCallback = onLoadCallback; + this.onErrorCallback = onErrorCallback; + this.timeout = timeout; + this.tick = 0; + }; + FetchClass.prototype = { + img: null, + size: null, + tick: 0, + finish: false, + load: function(){ + var img = this.img = document.createElement( 'img' ); //var img = new Image(); ではieでimgのsizeが取れない、、、removeChildも失敗し、imgSizeGetterにimgが残る + img.onabort = img.onerror = onError; + img.onload = onLoad; + img.src = this.abspath; + }, + complete: function(){ + if( this.finish === true ) return true; + if( this.img.complete ){ + this.finish = true; + if( this.img.width ) return true; + AsyncCall.add( this.apiuser, this.asyncCallback, null, this ); + return true; + }; + if( ( this.tick += 250 ) > this.timeout ){ + this.finish = true; + AsyncCall.add( this.apiuser, this.asyncCallback, null, this ); + return true; + }; + }, + asyncCallback: function(){ + this.size ? this.onLoadCallback( this.abspath, this.size.width, this.size.height ) : this.onErrorCallback( this.abspath ); + this.destroy(); + }, + destroy: function(){ + this.finish = true; + this.img.src = this.img.onload = this.img.onabort = this.img.onerror = ''; + delete this.img; + delete this.size; + delete this.onLoadCallback; + delete this.onErrorCallback; + }, + stop: function(){ + timer !== null && window.clearTimeout( timer ); + destroy(); + } + }; + + return { + load: function( URLorELM, onLoad, onError, opt_timeout ){ + var src, fetch; + if( Type.isString( URLorELM ) === true ){ + src = URLorELM; + } else + if( Type.isHTMLElement( URLorELM ) === true && URLorELM.tagName.toLowerCase() === 'img' ){ + src = URLorELM.src; + } else { + return; + }; + + fetch = new FetchClass( + Util.getAbsolutePath( src ), + onLoad, onError, + Type.isFinite( opt_timeout ) === true ? opt_timeout : undefined + ); + TASK_LIST.push( fetch ); + + SystemTimer.add( SUPER_USER_KEY, detect, 250 ); + }, + unload: function( ){ + + } + }; +})(); + + +/* ---------------------------------------- + * + */ + +var Overlay = ( function(){ + var elmContainer, elmShadow, elmCloseButton, + bootParams, + application = null, + visible = false, + bodyOverflow = '', + windowW, windowH; + + function onCloseClick( e ){ + Overlay.hide(); + return false; + }; + function asyncInit( /* arguments */ ){ + application.init(); + //application.rootElement.style.display = 'none'; + + elmContainer.style.cssText = "top:" + body.scrollTop + 'px;display:none;'; + $( elmContainer ).stop().fadeIn( onFadeInComplete ); + }; + function asyncOpen( /* arguments */ ){ + + + + }; + function onFadeInComplete(){ + KeyEvent.add( application, Const.KEY.EVENT.KEY_DOWN, Overlay.hide, 27 ); // 27.esc + MouseEvent.add( application, elmCloseButton, 'click', onCloseClick ); + + var _arg = bootParams; //Util.copyArray( arguments ); + _arg.unshift( windowW, windowH ); + application.open.apply( application, _arg ); + }; + function onFadeOutComplete(){ + Util.removeAllChildren( elmContainer ); + body.removeChild( elmContainer ); + elmContainer = elmShadow = elmCloseButton = null; + }; + return { + show: function( _application, _bootParams ){ + if( visible === true && application === _application ) return; + if( Application.isApplicationInstance( _application ) === false ) return; + + elmContainer = document.createElement( 'div' ); + body.appendChild( elmContainer ); + + elmContainer.id = 'overlay-container'; + + bodyOverflow = body.style.overflow; + body.style.overflow = 'hidden'; + + elmShadow = document.createElement( 'div' ); + elmContainer.appendChild( elmShadow ); + elmShadow.id = 'overlay-shadow'; + + elmCloseButton = document.createElement( 'div' ); + elmContainer.appendChild( elmCloseButton ); + elmCloseButton.id = 'overlay-close-button'; + elmCloseButton.appendChild( document.createTextNode( 'x' ) ); + + elmContainer.style.display = 'none'; // hide for fadeIn + + visible = true; + application = _application; + + //asyncInit(); + elmContainer.insertBefore( application.rootElement, elmCloseButton ); + _application.addAsyncCall( asyncInit ); + // _application.addAsyncCall( asyncOpen, ); + + bootParams = _bootParams; + }, + hide: function(){ + if( visible === false ) return; + if( application.close() === false ) return false; + + body.style.overflow = bodyOverflow; + + $( elmContainer ).stop().css( { + filter: '', + opacity: '' + }).fadeOut( onFadeOutComplete ); + visible = false; + + application = null; + }, + onWindowResize: function( _windowW, _windowH ){ + windowW = _windowW; + windowH = _windowH; + + if( application === null ) return; + + elmContainer.style.height = _windowH + 'px'; + elmContainer.style.top = body.scrollTop + 'px'; + + elmShadow.style.height = _windowH + 'px'; + + AsyncCall.add( application, application.resize, [ _windowW, _windowH ] ); + } + } +})(); + +/* ---------------------------------------- + * UI + * + * keyEventRellay + * form -> overlay -> view + * + */ + +var UI = ( function(){ + var UI_LIST = [], + currentUser = null, + currentList = null, + currentUi = null, + currentItem = null, + windowW = 0, + windowH = 0; + + var CLASSNAME_COMBOBOX_OPTION = 'combobox-option', + CLASSNAME_COMBOBOX_OPTION_CURRENT = CLASSNAME_COMBOBOX_OPTION + ' combobox-option-current', + ELM_COMBOBOX = ( function(){ + var ret = document.createElement( 'a' ), + elmToggle = document.createElement( 'span' ), + elmValue = document.createElement( 'span' ); + ret.href = '#'; + ret.appendChild( elmToggle ); + ret.appendChild( elmValue ); + elmToggle.className = 'combobox-toggle'; + elmValue.className = 'combobox-value'; + + elmToggle.appendChild( document.createTextNode( '▼' )); + elmValue.appendChild( document.createTextNode( 'null' )); + return ret; + })(); + + var UIItemPrivateData = function(){}; + UIItemPrivateData.prototype = { + groupData : null, + item : null, + elm : null, + node : null, + focus : false, + visible : true, + enabled : true, + value : null, + onUpdate : null, + validator : null, + elmValue : null, + elmBox : null, + elmA : null, + elmToggle : null, + elmValue : null, + selectIndex : 0, + optionList : null, + init : function( groupData, item, elm, value, onUpdate, validator, focus, visible, enabled ){ + this.groupData = groupData; + this.item = item; + this.elm = elm; + this.value = value; + this.onUpdate = onUpdate; + this.validator = validator; + this.focus = !!focus; + this.visible = !!visible; + this.enabled = !!enabled; + UIItemPrivateData.list.push( this ); + }, + destroy : function(){ + var list = UIItemPrivateData.list; + list.splice( Util.getIndex( list, this ), 1 ); + + list = this.groupData.itemList; + var i = Util.getIndex( list, this.item ); + i !== -1 && list.splice( i, 1 ); + + this.node && this.node.remove(); + } + }; + UIItemPrivateData.list = []; + UIItemPrivateData.get = function( item ){ + var list = UIItemPrivateData.list; + for( i = list.length; i; ){ + if( list[ --i ].item === item ) return list[ i ]; + }; + return null; + }; + +/* -------------------------------- + * TextInputManager + */ + var TextInputManager = ( function(){ + var elmInput = ( function(){ + var ret = document.createElement( 'input' ); + ret.type = 'text'; + ret.id = 'ui-textinput'; + return ret; + })(); + var currentData; + + function updateWrapperPosition(){ + var p = Position.cumulativeOffset( currentData.elmValue ), + w = currentData.elmValue.offsetWidth - 2, + _w; + elmInput.style.cssText = [ + 'left:', p[ 0 ], 'px;', + 'top:', p[ 1 ], 'px;',//, + 'width:', w, 'px;'//, + //'height:', data.elmValue.offsetHeight, 'px;', + //'position:absolute;' + ].join( '' ); + + //_w = elmInput.offsetWidth; + //if( w !== _w ) elmInput.style.width = ( w - ( _w - w ) ) + 'px;'; + }; + + return { + show: function( data ){ + // this.groupData.node.addEventListener( 'mouseout' ); + currentData = data; + + body.appendChild( elmInput ); + elmInput.value = data.value; + updateWrapperPosition(); + + elmInput.focus(); + elmInput.select(); + + SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 ); + }, + hide : function( data ){ + if( currentData !== data ) return; + currentData = null; + body.removeChild( elmInput ); + var ret = elmInput.value; + elmInput.value = ''; + SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition ); + return ret; + }, + update : function( data ){ + elmInput.value = data.value; + }, + onWindowResize: function( _w, _h ){ + AsyncCall.add( currentUser, updateWrapperPosition ); + } + }; + })(); + + var TextInputClass = function( groupData, elmWrapper, elmValue, onUpdate, validater ){ + var data = new UIItemPrivateData(); + data.init( groupData, this, elmWrapper, elmValue.innerHTML, onUpdate, validater, false, true, true ); + Util.addClass( elmValue, 'editable-text' ); + data.elmValue = elmValue; + this.value( data.value ); + data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-inpittext-hover', 'pointer' ); + data.node.addEventListener( 'click', this.focus, this ); + //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', instance.focus ); + }; + TextInputClass.prototype = { + value : function( value ){ + var data = UIItemPrivateData.get( this ); + if( Type.isString( value ) === true || Type.isNumber( value ) === true ){ + data.elmValue.innerHTML = data.value = '' + value; + data.focus === true && TextInputManager.update( data ); + }; + data.focus === true && this.blur(); + return data.value; + }, + focus : function( e ){ + var data = UIItemPrivateData.get( this ); + data.focus = true; + start( data ); + TextInputManager.show( data ); + return false; + }, + blur : function( keep ){ + var data = UIItemPrivateData.get( this ), + newValue; + if( data.focus === false ) return; + newValue = TextInputManager.hide( data ); + newValue = keep !== 27 ? ( data.validater ? '' + data.validater( newValue ) : newValue ) : data.value; // 27:ESC + + data.elmValue.innerHTML = newValue; + + data.onUpdate && newValue !== data.value && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ newValue, data.value ], this ); + + data.value = newValue; + data.focus = false; + finish( data ); + }, + enabled : function( v ){ + var data = UIItemPrivateData.get( this ); + if( Type.isBoolean( v ) === true && data.enabled !== v ){ + Util.toggleClass( data.elm, 'ui-textinput-disabled', !v ); + if( data.focus === true && v === false ) this.blur(); + data.enabled = v; + data.node.disabled( !( data.visible && v ) ); + }; + return data.enabled; + }, + visible : function( v ){ + var data = UIItemPrivateData.get( this ); + if( Type.isBoolean( v ) === true && data.visible !== v ){ + data.elm.style.display = v ? '' : 'none'; + if( data.focus === true && v === false ) this.blur(); + data.visible = v; + data.node.disabled( !( data.enabled && v ) ); + }; + return data.visible; + }, + destroy : function(){ + var data = UIItemPrivateData.get( this ); + data.focus === true && TextInputManager.hide( data ); + data.destroy(); + } + }; + +/* -------------------------------- + * TextInputManager + */ + var FileInputManager = ( function(){ + var currentData, + elmForm, + elmFileInput, + elmWrap, + evt; + + function updateWrapperPosition(){ + var p = Position.cumulativeOffset( currentData.elmValue ), + w = currentData.elmValue.offsetWidth, + _w; + elmWrap.style.cssText = [ + 'left:', p[ 0 ], 'px;', + 'top:', p[ 1 ], 'px;',//, + 'width:', w, 'px;'//, + //'height:', data.elmValue.offsetHeight, 'px;', + //'position:absolute;' + ].join( '' ); + + _w = elmWrap.offsetWidth; + if( w !== _w ) elmWrap.style.width = ( w - ( _w - w ) ) + 'px'; + }; + + function change( e ){ + var data = currentData, + file = data.elmFileInputReal.value; + file = file.split( '\\' ); + file = file[ file.length - 1 ]; + if( data.value !== file ){ + data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, [ file, data.value ], this ); + data.elmValue.innerHTML = data.value = file; + }; + currentData.item.blur(); + }; + function asyncMouseout(){ + currentData && currentData.item.blur(); + }; + function onClick(){ + MouseEvent.remove( currentUser, elmFileInput, 'mouseout', asyncMouseout ); + MouseEvent.remove( currentUser, elmFileInput, 'click', onClick ); + }; + return { + show : function( data ){ + currentData = data; + + elmFileInput = data.elmFileInputReal; + elmWrap = elmFileInput.parentNode; + // + + updateWrapperPosition(); + elmFileInput.focus(); + //data.node.addEventListener( 'change', change, data ); + evt = new EventTicketClass( elmFileInput, 'change', change ); + MouseEvent.add( currentUser, elmFileInput, 'mouseout', asyncMouseout ); + MouseEvent.add( currentUser, elmFileInput, 'click', onClick ); + // currentData.elmFileInputReal.onchange = change; + SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 ); + }, + hide : function( data ){ + if( currentData !== data ) return; + // data.node.removeEventListener( 'change', change ); + evt.destroy(); + // MouseEvent.remove( currentUser, elmFileInput, 'mouseout', asyncMouseout ); + onClick(); + //currentData.elmFileInputReal.onchange = null; + elmWrap.style.display = 'none'; + currentData = elmFileInput = null; + SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition ); + }, + onWindowResize: function( _w, _h ){ + AsyncCall.add( currentUser, updateWrapperPosition ); + } + }; + })(); + + var FileInputClass = function( groupData, elmWrapper, onUpdate, validater, elmFileInputReal, elmValue ){ + var data = new UIItemPrivateData(); + data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true ); + data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-fileinput-hover', 'pointer' ); + data.elmValue = elmValue; + data.elmFileInputReal = elmFileInputReal; + data.node.addEventListener( 'mouseover', this.focus, this ); + }; + FileInputClass.prototype = { + value : function(){ + return data.value; + }, + focus : function(){ + var data = UIItemPrivateData.get( this ); + data.focus = true; + Util.addClass( data.elm, 'fileinput-has-focus' ); + start( data ); + FileInputManager.show( data ); + }, + blur : function( keyCode ){ + var data = UIItemPrivateData.get( this ); + Util.removeClass( data.elm, 'fileinput-has-focus' ); + data.focus = false; + FileInputManager.hide( data ); + finish( data ); + }, + enabled : function( v ){ + var data = UIItemPrivateData.get( this ); + if( Type.isBoolean( v ) === true && data.enabled !== v ){ + if( data.focus === true && v === false ) this.blur(); + Util.toggleClass( data.elm, 'fileinput-disabled', !v ); + data.enabled = v; + data.node.disabled( !( data.visible && v ) ); + }; + return data.enabled; + }, + visible : function( v ){ + var data = UIItemPrivateData.get( this ); + if( Type.isBoolean( v ) === true && data.visible !== v ){ + if( data.focus === true && v === false ) this.blur(); + data.elm.style.display = v ? '' : 'none'; + data.visible = v; + data.node.disabled( !( data.enabled && v ) ); + }; + return data.visible; + }, + destroy : function(){ + var data = UIItemPrivateData.get( this ); + data.focus === true && FileInputManager.hide( data ); + data.destroy(); + } + }; + + var ButtonClass = function( groupData, elmWrapper, onUpdate ){ + var data = new UIItemPrivateData(); + data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true ); + data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-button-hover', 'pointer' ); + data.node.addEventListener( 'click', onUpdate ); + //MouseEvent.add( groupData.apiuser, elmWrapper, 'click', onUpdate ); + }; + ButtonClass.prototype = { + focus : function(){ + var data = UIItemPrivateData.get( this ); + data.focus = true; + Util.addClass( data.elm, 'button-has-focus' ); + start( data ); + }, + blur : function( keyCode ){ + var data = UIItemPrivateData.get( this ); + keyCode === 13 && data.onUpdate && data.onUpdate(); + Util.removeClass( data.elm, 'button-has-focus' ); + data.focus = false; + finish( data ); + }, + enabled : function( v ){ + var data = UIItemPrivateData.get( this ); + if( Type.isBoolean( v ) === true && data.enabled !== v ){ + Util.toggleClass( data.elm, 'button-disabled', !v ); + data.enabled = v; + data.node.disabled( !( data.visible && v ) ); + }; + return data.enabled; + }, + visible : function( v ){ + var data = UIItemPrivateData.get( this ); + if( Type.isBoolean( v ) === true && data.visible !== v ){ + data.elm.style.display = v ? '' : 'none'; + data.visible = v; + data.node.disabled( !( data.enabled && v ) ); + }; + return data.visible; + }, + destroy : function(){ + var data = UIItemPrivateData.get( this ); + // MouseEvent.remove( data.groupData.apiuser, data.elm ); + data.destroy(); + } + }; + + var ComboBoxClass = function( groupData, elmWrapper, onUpdate ){ + var elmA = ELM_COMBOBOX.cloneNode( true ), + data = new UIItemPrivateData(); + data.init( groupData, this, elmWrapper, null, onUpdate, null, false, true, true ); + + data.elmBox = Util.getElementsByClassName( elmWrapper, 'combobox' )[ 0 ]; + data.elmBox.appendChild( elmA ); + data.elmA = elmA; + data.elmToggle = Util.getElementsByClassName( elmA, 'combobox-toggle' )[ 0 ]; + data.elmValue = Util.getElementsByClassName( elmA, 'combobox-value' )[ 0 ].firstChild; + data.selectIndex = 0; + data.optionList = []; + + data.node = groupData.node.createNode( elmWrapper, false, true, 'ui-combobox-hover', 'pointer' ); + data.node.addEventListener( 'click', this.focus, this ); + }; + ComboBoxClass.prototype = { + focus : function( e ){ + var data = UIItemPrivateData.get( this ); + data.node.removeEventListener( 'click', this.focus ); + data.focus = true; + data.elmA.className = 'combobox-has-focus'; + start( data ); + OptionControl.show( data ); + return false; + }, + blur : function( keyCode ){ + var data = UIItemPrivateData.get( this ); + OptionControl.hide( this ); + data.focus = false; + data.elmA.className = ''; + finish( data ); + data.node.addEventListener( 'click', this.focus, this ); + }, + enabled : function( v ){ + var data = UIItemPrivateData.get( this ); + if( Type.isBoolean( v ) === true && data.enabled !== v ){ + Util.toggleClass( data.elm, 'ui-combobox-disabled', !v ); + if( data.focus === true && v === false ) this.blur(); + data.enabled = v; + data.node.disabled( !( data.visible && v ) ); + }; + return data.enabled; + }, + visible : function( v ){ + var data = UIItemPrivateData.get( this ); + if( Type.isBoolean( v ) === true && data.visible !== v ){ + data.elm.style.display = v ? '' : 'none'; + if( data.focus === true && v === false ) this.blur(); + data.visible = v; + data.node.disabled( !( data.enabled && v ) ); + }; + return data.visible; + }, + value : function( _value ){ + var data = UIItemPrivateData.get( this ), + i = 0, + list = data.optionList, + l = list.length, + _option; + if( Type.isString( _value ) === true && data.value !== _value ){ + for( ; i < l; ++i ){ + _option = list[ i ]; + if( _value === _option.value ){ + data.value = _value; + data.index = i; + data.elmValue.data = _option.displayValue; + if( data.focus === true ){ + OptionControl.update( this, _value ); + }; + data.onUpdate && AsyncCall.add( data.groupData.apiuser, data.onUpdate, _value, this ); + break; + }; + }; + }; + return data.value; + }, + selectIndex : function(){ + var data = UIItemPrivateData.get( this ); + return data.selectIndex; + }, + createOption : function( _displayValue, _value, _isSelected ){ + var data = UIItemPrivateData.get( this ), + option = null, + list = data.optionList, + i = list.length, + _option, i; + _value = _value || _displayValue; + _isSelected = !!_isSelected; + for( ; i; ){ + _option = list[ --i ]; + if( _value === _option.value ){ + option = _option; + break; + }; + }; + if( _isSelected === true ){ + data.selectIndex = list.length; + data.elmValue.data = _displayValue; + }; + option === null && list.push( new OptionDataClass( _displayValue, _value, _isSelected ) ); + }, + destroy : function(){ + var data = UIItemPrivateData.get( this ); + data.focus === true && OptionControl.hide( this ); + // this.blur(); + // MouseEvent.remove( data.groupData.apiuser, data.elm ); + data.optionList.length = 0; + data.destroy(); + } + }; + var OptionDataClass = function( displayValue, value, isCurrent ){ + this.displayValue = displayValue; + this.value = value || displayValue; + this.current = isCurrent; + displayValue = value = null; + }; + + var OptionControl = ( function(){ + var ELM_OPTION_WRAPPER = ( function(){ + var ret = document.createElement( 'div' ); + ret.className = 'option-container'; + return ret; + })(), + ELM_OPTION_ORIGIN = ( function(){ + var ret = document.createElement( 'a' ); + ret.appendChild( document.createTextNode( 'option' ) ); + ret.href = '#'; + return ret; + })(); + + var OptionClass = function( option ){ + this.elm = ELM_OPTION_ORIGIN.cloneNode( true ); + this.data = option; + this.init(); + }; + OptionClass.prototype = { + init: function(){ + ELM_OPTION_WRAPPER.appendChild( this.elm ); + this.elm.firstChild.data = this.data.displayValue; + this.current( this.data.current ); + MouseEvent.add( SUPER_USER_KEY, this.elm, 'mousedown', onOptionSelect );// onclick では 選択ボックス 隠すように body に設定した onmouseup が先に動いてしまう! + }, + current: function( _current ){ + this.elm.className = _current === true ? CLASSNAME_COMBOBOX_OPTION_CURRENT : CLASSNAME_COMBOBOX_OPTION; + this.data.current = _current; + currentOption = _current === true ? this : currentOption; + }, + destroy: function(){ + MouseEvent.remove( SUPER_USER_KEY, this.elm ); + Util.removeAllChildren( this.elm ); + ELM_OPTION_WRAPPER.removeChild( this.elm ); + delete this.elm; + delete this.data; + } + }; + + function onOptionSelect( e ){ + var i = 0, + l = OPTION_LIST.length, + _option; + for( ; i < l; ++i ){ + _option = OPTION_LIST[ i ]; + if( this === _option.elm ){ + updateCurrrentOption( _option.data.value, true ); + currentCombobox.blur(); + break; + }; + }; + return false; + }; + + var OPTION_LIST = [], + currentCombobox = null, + apiuser, + elm, + currentOption, + currentIndex; + + function updateCurrrentOption( _value, _updateCombobox ){ + var _option, + i = OPTION_LIST.length; + for( ; i; ){ + _option = OPTION_LIST[ --i ]; + if( _value === _option.data.value ){ + currentOption && currentOption.current( false ); + _option.current( true ); + currentOption = _option; + currentIndex = i; + _updateCombobox === true && currentCombobox.value( _value ); + break; + }; + }; + }; + function bodyMouseupHandler(){ + currentCombobox.blur(); + OptionControl.hide( currentCombobox ); + }; + function updateWrapperPosition(){ + var position = Util.getAbsolutePosition( elm ); + + ELM_OPTION_WRAPPER.style.cssText = [ + 'width:', elm.offsetWidth - 2, 'px;', + 'left:', position.x, 'px;', + 'top:', position.y + elm.offsetHeight, 'px;' + ].join( '' ); + }; + function change( e ){ + var l = OPTION_LIST.length, + i = currentIndex + ( e.keyCode === 40 ? -1 : 1 ); + if( currentCombobox === null || l < 2 ) return; + i = i < 0 ? + l - 1 : + i < l ? i : 0; + updateCurrrentOption( OPTION_LIST[ i ].data.value, true ); + return false; + }; + return { + show: function( data ){ + var combobox = data.item, + list = data.optionList, + i = 0, + l = list.length; + if( currentItem !== combobox || currentCombobox === combobox ) return; + currentCombobox && currentCombobox.blur(); + + apiuser = data.groupData.apiuser; + currentCombobox = combobox; + elm = data.elmBox; + + for( ; i < l; ++i ){ + OPTION_LIST.unshift( new OptionClass( list[ i ] ) ); + }; + MouseEvent.add( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler ); + KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 38 ); + KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 40 ); + //KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter, 13 ); + //KeyEvent.updateCurrentListener( SUPER_USER_KEY ); + + body.appendChild( ELM_OPTION_WRAPPER ); + + updateCurrrentOption( combobox.value(), false ); + updateWrapperPosition(); + + SystemTimer.add( SUPER_USER_KEY, updateWrapperPosition, 500 ); + }, + hide: function( _combobox ){ + if( currentCombobox !== _combobox || currentCombobox === null ) return; + + var _option; + while( _option = OPTION_LIST.shift() ){ + _option.destroy(); + }; + + body.removeChild( ELM_OPTION_WRAPPER ); + + MouseEvent.remove( SUPER_USER_KEY, document, 'mouseup', bodyMouseupHandler ); + KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change ); + KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change ); + //KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter ); + //KeyEvent.updateCurrentListener( apiuser ); + + SystemTimer.remove( SUPER_USER_KEY, updateWrapperPosition, 500 ); + + apiuser = null; + currentCombobox = null; + currentOption = null; + currentIndex = 0; + }, + onEnter: function(){ + currentCombobox.value( currentOption.data.value ); + //currentCombobox.blur(); + //OptionControl.hide( currentCombobox ); + }, + update: function( data, _value ){ + if( currentCombobox !== data.item || currentItem !== data.item ) return; + if( currentOption.data.value === _value ) return; + updateCurrrentOption( _value, true ); + }, + onWindowResize: function( _w, _h ){ + currentCombobox && AsyncCall.add( apiuser, updateWrapperPosition ); + } + }; + })(); + + var UIGroupPrivateData = function(){}; + UIGroupPrivateData.prototype = { + apiuser : null, + node : null, + uigroup : null, + itemList : null, + visible : true, + enabled : true, + init : function( apiuser, node, uigroup ){ + this.apiuser = apiuser; + this.node = node; + this.uigroup = uigroup; + this.itemList = []; + UIGroupPrivateData.list.push( this ); + }, + destroy : function(){ + + } + }; + UIGroupPrivateData.list = []; + UIGroupPrivateData.get = function( uigroup ){ + var list = UIGroupPrivateData.list, + i = list.length; + for( ; i; ){ + if( list[ --i ].uigroup === uigroup ) return list[ i ]; + }; + return null; + }; + + var UIGroupClass = function( apiuser, node ){ + ( new UIGroupPrivateData() ).init( apiuser, node, this ); + }; + UIGroupClass.prototype = { + focus : function( _value ){ + var data = UIGroupPrivateData.get( this ); + /* + if( _value === true ){ + if( currentItem ){ + start( apiuser, self, currentItem ); + } else + if( itemList.length > 0 ){ + start( apiuser, self, itemList[ 0 ] ); + }; + } else + if( _value === false ){ + finish( apiuser, self, currentItem ); + } else + */ + if( _value && Util.getIndex( data.itemList, _value ) !== -1 ){ + // currentItem = _value; + currentList = data.itemList; + }; + return currentUi === this; + }, + blur : function(){ + var data = UIGroupPrivateData.get( this ); + if( currentList === data.itemList ){ + currentList = null; + }; + }, + createInputText : function( elmWrapper, onUpdate, validater ){ + var data = UIGroupPrivateData.get( this ), + elmValue = Util.getElementsByClassName( elmWrapper, 'editable-value' )[ 0 ], + ret; + if( elmValue ){ + ret = new TextInputClass( data, elmWrapper, elmValue, onUpdate, validater ); + data.itemList.push( ret ); + return ret; + }; + alert( 'error createInputText' ); + }, + createButton : function( elm, onClick ){ + var data = UIGroupPrivateData.get( this ), + ret = new ButtonClass( data, elm, onClick ); + data.itemList.push( ret ); + return ret; + }, + createFileInput : function( elm, onUpdate, validater, elmFileInputReal ){ + var data = UIGroupPrivateData.get( this ), + elmValue = Util.getElementsByClassName( elm, 'fileinput-value' )[ 0 ], + ret; + if( elmValue ){ + ret = new FileInputClass( data, elm, onUpdate, validater, elmFileInputReal, elmValue ); + data.itemList.push( ret ); + return ret; + }; + return ret; + }, + createCombobox : function( elm, onUpdate, optionList ){ + var data = UIGroupPrivateData.get( this ), + ret = new ComboBoxClass( data, elm, onUpdate, optionList ); + data.itemList.push( ret ); + return ret; + }, + createCheckBox : function(){ + + }, + createRadio : function(){ + + }, + createSlider : function(){ + + }, + visible : function( v ){ + var data = UIGroupPrivateData.get( this ); + if( Type.isBoolean( v ) === true && data.visible !== v ){ + for( var i = data.itemList.length; i; ){ + data.itemList[ --i ].visible( v ); + }; + data.visible = v; + data.node.disabled( !( data.enabled && v ) ); + }; + return data.visible; + }, + enabled : function( v ){ + var data = UIGroupPrivateData.get( this ); + if( Type.isBoolean( v ) === true && data.enabled !== v ){ + for( var i = data.itemList.length; i; ){ + data.itemList[ --i ].enabled( v ); + }; + data.enabled = v; + data.node.disabled( !( data.visible && v ) ); + }; + return data.enabled; + }, + destroy : function(){ + var data = UIGroupPrivateData.get( this ), + _item; + if( currentUi === this ){ + currentItem.blur(); + // finish( UIItemPrivateData.get( currentItem ) ); + }; + while( _item = data.itemList.shift() ){ + _item.destroy(); + }; + data.destroy(); + } + }; + + function start( data ){ + if( currentItem !== data.item ){ + currentUi !== data.groupData.uigroup && currentUi && currentUi.blur(); + + currentItem !== null && currentItem.blur(); + + currentUser = data.groupData.apiuser; + currentUi = data.groupData.uigroup; + currentItem = data.item; + + currentUi.focus( currentItem ); + + // if( currentUser !== _apiuser ) { + KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 ); + KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 ); + KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 9 ); + KeyEvent.updateCurrentListener( SUPER_USER_KEY ); + // }; + }; + } + function finish( data ){ + if( currentItem === data.item ){ + currentUi.blur(); + + currentUser = null; + currentUi = null; + currentItem = null; + currentList = null; + + KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 ); + KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 ); + KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 9 ); + KeyEvent.updateCurrentListener( data.groupData.apiuser ); + }; + }; + + function onKeyDown( e ){ + if( currentItem === null ) return true; + var keyCode = e.keyCode, + index = Util.getIndex( currentList, currentItem ); + if( keyCode === 13 || keyCode === 27 || keyCode === 9 || keyCode === 18 || e.altKey === true ){ // 13.return 27.esc 9.tab 18.alt + keyCode === 9 && tabShift( index, e.shiftKey === true ? -1 : 1 ); + keyCode === 13 && currentItem instanceof ComboBoxClass && OptionControl.onEnter(); + keyCode === 13 && tabShift( index, 1 ); + currentItem && currentItem.blur( keyCode ); + return false; + }; + }; + + function tabShift( index, way ){ + var l = currentList.length, + i = index + way, + item; + if( l < 2 ) return; + while( i !== index ){ + i = i < 0 ? + l - 1 : + i < l ? i : 0; // 0 < i < l + item = currentList[ i ]; + if( item.enabled() === true && item.visible() === true ){ + AsyncCall.add( currentUser, item.focus, null, item ); + return; + }; + i += way; + }; + }; + + return { + createUIGroup: function( apiuser, node ){ + var uid = apiuser.getUID(), + list = UI_LIST[ uid ], + ui = new UIGroupClass( apiuser, node ); + if( Type.isArray( list ) === false ){ + list = UI_LIST[ uid ] = []; + }; + list.push( ui ); + return ui; + }, + onWindowResize: function( w, h ){ + windowW = w; + windowH = h; + currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h ); + currentItem instanceof TextInputClass && TextInputManager.onWindowResize( w, h ); + currentItem instanceof FileInputClass && FileInputManager.onWindowResize( w, h ); + }, + onCurrentApplicationChange: function( _apiuser ){ + currentList = UI_LIST[ _apiuser.getUID() ]; + }, + onApplicationShutdown: function( _apiuser ){ + KeyEvent.remove( _apiuser ); + }, + onSystemShutdown: function(){ + + } + }; +})(); + +var UIForm = ( function(){ + var FORM_LIST = []; + var CLASSNAME_FORM = 'uiform-invisible'; + var CLASSNAME_FILE_WRAP = 'ui-fileinput-wrapper'; + var FormItemData = function(){}; + var windowW, windowH; + FormItemData.prototype = { + formData : null, + uiItem : null, + init : function( formData, uiItem ){ + this.formData = formData; + this.uiItem = uiItem; + }, + onUpdate : function( v ){ + // var index = Util.getIndex( this.formData.itemList, this ); + } + }; + + var FormPrivateData = function(){}; + FormPrivateData.prototype = { + apiuser : null, + node : null, + form : null, + elmForm : null, + itemList : null, + visible : true, + enabled : true, + init : function( apiuser, from, node, elm, elmForm ){ + this.apiuser = apiuser; + this.form = form; + this.ui = apiuser.createUIGroup( node ); + this.node = node; + this.elm = elm; + this.elmForm = elmForm; + this.itemList = []; + elmForm.className = CLASSNAME_FORM; + FormPrivateData.list.push( this ); + + var forms = Util.copyArray( elmForm.getElementsByTagName( '*' ) ), + l = forms.length, + i = 0, + items = 'input,select,textarea,button', + form, data, el, wrap; + for( ; i
' ); + elm.appendChild( el ); + data = new FormItemData(); + wrap = document.createElement( 'div' ); + form.parentNode.insertBefore( wrap, form ); + wrap.className = CLASSNAME_FILE_WRAP; + wrap.appendChild( form ); + data.init( this, this.ui.createFileInput( el, data.onUpdate, null, form ) ); + this.itemList.push( data ); + break; + case 'button': + break; + default: + continue; + }; + break; + case 'select': + break; + case 'button': + break; + case 'textarea': + break; + default: + continue; + }; + }; + }, + destroy : function(){ + + } + }; + FormPrivateData.list = []; + FormPrivateData.get = function( from ){ + var list = FormPrivateData.list, + i = list.length; + for( ; i; ){ + if( list[ --i ].form === form ) return list[ i ]; + }; + return null; + }; + + var FormClass = function( apiuser, node, elm, elmForm ){ + ( new FormPrivateData() ).init( apiuser, this, node, elm, elmForm ); + }; + FormClass.prototype = { + createTextInput : function(){ + + }, + createMultiLineInput : function(){ + + }, + createFileInput : function(){ + + }, + createButton : function(){ + + }, + createComboBox : function(){ + + }, + submit : function(){ + + } + }; + + return { + createForm: function( apiuser, nodeOrElm, opt_elmForm ){ + var uid = apiuser.getUID(), + list = FORM_LIST[ uid ], + node, elm, form; + if( PointingDeviceEventTree.isNodeInstance( nodeOrElm ) === true ){ + node = nodeOrElm; + elm = PointingDeviceEventTree._getNodePrivateData( nodeOrElm ).elm; + } else { + // App が eventTree を持っている? + // App が eventTree を持っていない + elm = nodeOrElm; + }; + form = new FormClass( apiuser, node, elm, opt_elmForm ); + if( Type.isArray( list ) === false ){ + list = FORM_LIST[ uid ] = []; + }; + list.push( form ); + return form; + }, + onWindowResize: function( w, h ){ + windowW = w; + windowH = h; + currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h ); + currentItem instanceof TextInputClass && TextInputManager.onWindowResize( w, h ); + currentItem instanceof FileInputClass && FileInputManager.onWindowResize( w, h ); + }, + onCurrentApplicationChange: function( _apiuser ){ + }, + onApplicationShutdown: function( _apiuser ){ + }, + onSystemShutdown: function(){ + + } + }; +})(); + +var Finder = ( function(){ + var FINDER_LIST = [], + ELM_ORIGIN_LOCATION_ITEM = Util.pullHtmlAsTemplete( '
' ), + HTML_FINDER_ICON = ( function(){ + return ( UA.isIE === true && UA.ieVersion < 8 ? + [ + '
', + '
', + '
', + '', + '', + '', + 'file name', + '', + '', + '', + '', + '', + '', + 'file descriptiion', + '', + '', + '', + '
', + '
' + ] : + [ + '
', + '
', + '
', + '
file name
', + '
file descriptiion
', + '
>
', + '
' + ] ).join( '' ); + })(), + ELM_ORIGIN_FINDER_ICON = Util.pullHtmlAsTemplete( HTML_FINDER_ICON ), + ICON_HEIGHT = Util.getElementSize( ELM_ORIGIN_FINDER_ICON ).height; + + // t : 時間 + // b : 開始の値(開始時の座標やスケールなど) + // c : 開始と終了の値の差分 + // d : Tween(トゥイーン)の合計時間 + + function easeOutQuad( t, b, c, d ){ + t /= d; + return -c * t*( t-2 ) + b; + }; + +/** + * FinderIconClass + */ + var FinderIconClass = function(){}; + FinderIconClass.prototype = { + finderData : null, + file : null, + elm : null, + node : null, + _index : -1, + _style : -1, + init : function( page, file, w, index, style ){ + if( !this.elm ) this.elm = ELM_ORIGIN_FINDER_ICON.cloneNode( true ); + + if( this.page !== page ){ + this.page = page; + page.elm.appendChild( this.elm ); + this.node && this.node.remove(); + this.node = page.node.createNode( this.elm, false, true, 'finder-icon-hover', '' ); + }; + if( this.file !== file ){ + this.file && this.file.destroy(); + this.file = file; + this._index = index; + this.draw( w ); + return; + }; + if( this._index !== index ){ + this._index = index; + this.resize( w ); + }; + }, + index : function( _index ){ + return this._index; + }, + style : function( _style ){ + return this._style; + }, + draw : function( w ){ + var file = this.file, + elm = this.elm, + thumb = file.getThumbnail(), + elmThumb = Util.getElementsByClassName( elm, 'file-icon' )[ 0 ].firstChild, + elmName = Util.getElementsByClassName( elm, 'finder-icon-filename' )[ 0 ], + elmDesc = Util.getElementsByClassName( elm, 'finder-icon-summary' )[ 0 ]; + if( thumb.image ){ + elmThumb.className = 'has-thumbnail'; + elmThumb.style.backgroundImage = [ 'url(', thumb.image, ')' ].join( '' ); + } else { + elmThumb.className = thumb.className; + elmThumb.style.backgroundImage = ''; + }; + + elmName.firstChild.data = file.getName(); + elmDesc.firstChild.data = file.getSummary(); + + this.resize( w ); + }, + resize : function( w ){ + this.node.update( 0, this._index * ICON_HEIGHT, w ); + }, + onEditorClick : function( e ){ + this.onEditorCallback && this.onEditorCallback( this.file, this.file.editorApplicationList()[ 0 ] ); + return false; + }, + onViwerClick : function( e ){ + this.onViewerCallback && this.onViewerCallback( this.file, this.file.viewerApplicationList()[ 0 ] ); + return false; + }, + onActionClick : function( e ){ + this.onActionCallback && this.onActionCallback( this.file ); + return false; + }, + destroy : function(){ + this.elm && this.elm.parentNode.removeChild( this.elm ); + this.file && this.file.destroy(); + this.node && this.node.remove(); + delete this.page; + delete this.file; + delete this.node; + delete this._index; + delete this._style; + FinderIconClass.pool.push( this ); + } + }; + FinderIconClass.pool = []; + FinderIconClass.get = function( page, file, w, index, style ){ + var _icon = FinderIconClass.pool.length > 0 ? FinderIconClass.pool.shift() : new FinderIconClass(); + _icon.init( page, file, w, index, style ); + return _icon; + }; + +/** + * PathClass + */ + var PathClass = function(){}; + PathClass.prototype = { + finderData : null, + elm : null, + node : null, + file : null, + _index : null, + w : 0, + init : function( finderData, file, index ){ + if( !this.elm ) this.elm = ELM_ORIGIN_LOCATION_ITEM.cloneNode( true ); + + if( this.finderData !== finderData ){ + this.finderData = finderData; + finderData.elmPath.appendChild( this.elm ); + this.node && this.node.remove(); + delete this.node; + }; + if( this.file !== file ){ + this.file = file; + this.draw(); + }; + this._index = index; + if( !this.node ) this.node = finderData.nodePath.createNode( this.elm, false, true, 'finder-path-hover', 'pointer' ); + }, + draw : function(){ + this.elm.className = 'file-icon-' + this.file.getType(); + this.elm.innerHTML = this.file.getName(); + }, + textWidth : function(){ + this.elm.style.width = 'auto'; + var ret = this.elm.offsetWidth; + this.elm.style.width = ''; + return ret + 15; + }, + update : function( x, w ){ + this.node.update( x - 15, undefined, w ); + }, + index : function( _index ){ + return this._index; + }, + destroy : function(){ + this.finderData.elmPath.removeChild( this.elm ); + this.node && this.node.remove(); + + delete this.finderData; + delete this.elm; + delete this.node; + delete this.file; + delete this._index; + PathClass.pool.push( this ); + } + }; + PathClass.pool = []; + PathClass.get = function( finderData, file, index ){ + var _bread = PathClass.pool.length > 0 ? PathClass.pool.shift() : new PathClass(); + _bread.init( finderData, file, index ); + return _bread; + }; + + + /** + * Page + */ + var PageClass = function(){}; + PageClass.prototype = { + nodeRoot : null, + elmRoot : null, + elmScroll : null, + elm : null, + node : null, + folder : null, + iconList : null, + sliding : false, + currentX : 0, + panTime : 0, + startX : 0, + offsetX : 0, + panTotalTime : 0, + isPanOut : false, + init : function( nodeRoot, elmRoot, elmScroll ){ + this.nodeRoot = nodeRoot; + this.elmRoot = elmRoot; + this.elmScroll = elmScroll; + + if( this.elm === null ){ + this.elm = document.createElement( 'div' ); + }; + elmScroll.appendChild( this.elm ); + this.elm.style.cssText = 'position:absolute;top:0;'; + // this.elm.style.display = 'none'; + this.node = this.nodeRoot.createNode( this.elm, true, false ); + if( this.iconList === null ){ + this.iconList = []; + }; + }, + panInReady : function( way ){ + this.elm.style.display = ''; + var x = this.sliding === true ? this.currentX : way * this.nodeRoot.width(); + this.startX = this.currentX = x; + this.targetX = 0; + this.offsetX = -x; + this.panTime = 0; + this.panTotalTime = 20; + this.sliding = true; + this.isPanOut = false; + // this.elm.style.left = x + 'px'; + this.node.x( x ); + }, + panOutReady : function( way ){ + var x = -way * this.nodeRoot.width(); + this.startX = this.currentX || 0; + this.targetX = x; + this.offsetX = x - this.startX; + this.panTime = 0; + this.panTotalTime = 20; + this.sliding = true; + this.isPanOut = true; + }, + pan : function(){ + var page = this, + x = page.currentX = easeOutQuad( page.panTime, page.startX, page.offsetX, page.panTotalTime ); + // page.elm.style.left = x + 'px'; + this.node.x( x ); + if( page.panTotalTime < ++page.panTime ){ + delete page.panTime; + delete page.startX; + delete page.offsetX; + delete page.panTotalTime; + delete page.sliding; + if( this.isPanOut === true ) this.elm.style.display = 'none'; + }; + }, + draw : function( folder ){ + var _w = this.nodeRoot.width(); + this.folder = folder; + var data = this, + iconList = data.iconList, + i = 0, + j = 0, + l = folder.getChildFileLength(), + m = iconList.length, + scrollY = -this.nodeRoot.scrollY(), + rootH = scrollY + this.nodeRoot.height(), + icon; + + for( ; i < l; ++i ){ + if( ( i + 1 ) * ICON_HEIGHT < scrollY || rootH < i * ICON_HEIGHT ) continue; + if( j < m ){ + iconList[ j ].init( this, folder.getChildFileAt( i ), _w, i, data.style ); + } else { + iconList.push( FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) ); + }; + j++; + }; + data.elmRoot.className = folder.getState() === Const.FILE.STATE.LOADING ? 'finder-body loading' : 'finder-body'; + // data.elmRoot.style.height = ( data.h - data.headH ) + 'px'; + + while( j < iconList.length ) iconList.pop().destroy(); + data.elmScroll.style.height = ( l * ICON_HEIGHT ) + 'px'; + }, + onScroll : function(){ + var _w = this.nodeRoot.width(); + + var data = this, + iconList = data.iconList, + folder = this.folder, + i = 0, + j = 0, + l = folder.getChildFileLength(), + scrollY = -this.nodeRoot.scrollY(), + rootH = scrollY + this.nodeRoot.height(), + startIndex = 0 < iconList.length ? iconList[ 0 ]._index : 0, + icon; + + // console.log( ' > ' + scrollY + ' , ' + rootH ) + for( ; i < l; ++i ){ + if( ( i + 1 ) * ICON_HEIGHT < scrollY || rootH < i * ICON_HEIGHT ){ + if( iconList.length <= j ) continue; + icon = iconList[ j ]; + if( icon._index !== i ) continue; + icon.destroy(); + iconList.splice( j, 1 ); + continue; + }; + if( iconList.length <= j || iconList[ j ]._index !== i ){ + if( i < startIndex ){ + iconList.splice( j, 0, FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) ); + } else + if( startIndex + iconList.length <= i ){ + iconList.push( FinderIconClass.get( this, folder.getChildFileAt( i ), _w, i, data.style ) ); + }; + }; + ++j; + }; + + //while( j < iconList.length ) iconList.pop().destroy(); + }, + resize : function( w ){ + var list = this.iconList, + i = list.length; + for( ; i; ) list[ --i ].resize( w ); + }, + destroy : function(){ + var icon; + while( icon = this.iconList.shift() ) icon.destroy(); + + this.elm.parentNode.removeChild( this.elm ); + } + }; + + var ApplicationButton = function(){}; + ApplicationButton.prototype = { + elm : null, + button : null, + app : null, + file : null, + fileUID : -1, + init : function( ui, elmParent, app, file ){ + if( this.elm === null ){ + this.elm = document.createElement( 'div' ); + }; + elmParent.appendChild( this.elm ); + this.elm.className = 'button'; + this.elm.innerHTML = app.getDisplayName(); + + var that = this; + this.button = ui.createButton( this.elm, function(){ + that.onClick(); + // that = null; + } ); + + this.app = app; + this.file = file; + this.fileUID = file.getUID(); + }, + onClick : function(){ + this.app.boot( this.file ); + return false; + }, + destroy : function(){ + var elm = this.elm; + elm.parentNode.removeChild( elm ); + + this.button.destroy(); + //this.kill() + //this.elm = elm; + } + }; + + var DetailPageClass = function(){}; + DetailPageClass.prototype = Util.extend( new PageClass(), { + appButtons : null, + init : function( finderData ){ + this.finderData = finderData; + this.apiuser = finderData.apiuser; + this.nodeRoot = finderData.nodeRoot; + this.elmRoot = finderData.elmRoot; + this.elmScroll = finderData.elmScroll; + + if( this.elm === null ){ + this.elm = Util.pullHtmlAsTemplete( [ + '
', + '
', + '
file name
', + '
file descriptiion
', + '
View this file
', + '
', + '
Edit this file
', + '
', + '
' + ].join( '' ) ); + }; + this.elm.style.display = 'none'; + this.elmScroll.appendChild( this.elm ); + this.node = this.nodeRoot.createNode( this.elm, true, false ); + + this.ui = this.apiuser.createUIGroup( this.node ); + this.appButtons = []; + }, + draw : function( file ){ + var elm = this.elm, + thumb = file.getThumbnail(), + elmThumb = Util.getElementsByClassName( elm, 'file-icon' )[ 0 ].firstChild, + elmName = Util.getElementsByClassName( elm, 'finder-detail-filename' )[ 0 ], + elmDesc = Util.getElementsByClassName( elm, 'finder-detail-summary' )[ 0 ], + tmpButtons = Util.copyArray( this.appButtons ), + apps, app, elmContainer, button; + if( thumb.image ){ + elmThumb.className = 'has-thumbnail'; + elmThumb.style.backgroundImage = [ 'url(', thumb.image, ')' ].join( '' ); + } else { + elmThumb.className = thumb.className; + elmThumb.style.backgroundImage = ''; + }; + + elmName.firstChild.data = file.getName(); + elmDesc.firstChild.data = file.getSummary(); + this.node.width( this.nodeRoot.width() ); + this.node.height( this.nodeRoot.height() ); + + this.appButtons.length = 0; + + apps = file.viewerApplicationList(); + elmContainer = Util.getElementsByClassName( elm, 'viewer-apps' )[ 0 ]; + for( i = 0; i < apps.length; ++i ){ + button = 0 < tmpButtons.length ? tmpButtons.shift() : new ApplicationButton(); + button.init( this.ui, elmContainer, apps[ i ], file ); + this.appButtons.push( button ); + }; + apps = file.editorApplicationList(); + elmContainer = Util.getElementsByClassName( elm, 'editor-apps' )[ 0 ]; + for( i = 0; i < apps.length; ++i ){ + button = 0 < tmpButtons.length ? tmpButtons.shift() : new ApplicationButton(); + button.init( this.ui, elmContainer, apps[ i ], file ); + this.appButtons.push( button ); + }; + + while( button = tmpButtons.shift() ) button.destroy(); + + this.resize(); + }, + pan : function(){ + var page = this, + x = page.currentX = easeOutQuad( page.panTime, page.startX, page.offsetX, page.panTotalTime ); + // page.elm.style.left = x + 'px'; + this.node.x( x ); + if( page.panTotalTime < ++page.panTime ){ + delete page.panTime; + delete page.startX; + delete page.offsetX; + delete page.panTotalTime; + delete page.sliding; + if( this.isPanOut === true ) this.elm.style.display = 'none'; + }; + }, + onScroll : function(){ + + }, + resize : function(){ + this.elmScroll.style.height = this.nodeRoot.height() + 'px'; + }, + destroy : function(){ + var button; + while( button = this.appButtons.shift() ) button.destroy(); + this.ui.destroy(); + this.node.remove(); + } + }); + +/** + * FinderPrivateData + */ + var FinderPrivateData = Class.create( + Class.PRIVATE_DATA, { + finder : null, + apiuser : null, + elmRoot : null, + nodeRoot : null, + elmScroll : null, + elmPath : null, + nodePath : null, + tree : null, + onSelect : null, + viewerOption : null, + editorOption : null, + pathList : null, + headH : 0, + iconW : 0, + iconH : 0, + style : 0, + pageIcons1 : null, + pageIcons2 : null, + panInPage : null, + panOutPage : null, + pageDetail : null, + currentFile : null, + Constructor : function( finder, apiuser, elm, tree, onSelect, viewerOption, editorOption ){ + this.finder = finder; + this.apiuser = apiuser; + if( PointingDeviceEventTree.isNodeInstance( elm ) === true ){ + this.nodeRoot = elm; + this.elmRoot = PointingDeviceEventTree._getNodePrivateData( elm ).elm; + } else { + // App が eventTree を持っている? + // App が eventTree を持っていない + this.elmRoot = elm; + }; + this.nodeRoot.addEventListener( 'click', this.onIconClick, this ); + this.nodeRoot.addEventListener( 'scroll', this.onScroll, this ); + + this.elmScroll = document.createElement( 'div' ); + this.elmRoot.appendChild( this.elmScroll ); + this.elmScroll.className = 'finder-elm-scroll'; + this.elmScroll.style.cssText = 'width:100%;overflow:hidden;'; + + this.tree = tree; + this.onSelect = onSelect; + this.viewerOption = viewerOption; + this.editorOption = editorOption; + + var size = Util.getElementSize( ELM_ORIGIN_FINDER_ICON ); + this.iconW = size.width; + this.iconH = size.height; + + tree.addTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw, this ); + Util.addClass( this.elmRoot, 'finder-body' ); + + if( this.panInPage === null ){ + this.pageIcons1 = new PageClass(); + this.pageIcons2 = new PageClass(); + this.pageDetail = new DetailPageClass(); + }; + this.pageIcons1.init( this.nodeRoot, this.elmRoot, this.elmScroll ); + this.pageIcons2.init( this.nodeRoot, this.elmRoot, this.elmScroll ); + this.pageDetail.init( this ); + }, + onIconClick : function( e ){ + if( this.panInPage === this.pageDetail ) return; + + var target = e.target, + list = this.panInPage.iconList, + i, icon, + file; + if( target === this.nodeRoot ) return; + for( i = list.length; i; ){ + icon = list[ --i ]; + if( icon.node === target ){ + i = icon._index; + file = this.currentFile.getChildFileAt( i ); + if( target.width() - 30 < e.layerX ){ + this.tree.down( i ); + this.draw( this.w, this.h, 1, true ); + } else + if( file.getChildFileLength() !== -1 || file.getType() === Const.FILE.TYPE.FOLDER ){ + this.tree.down( i ); + this.draw( this.w, this.h, 1 ); + } else + if( Type.isFunction( this.onSelect ) === true ){ /* && this.onSelect( file ) === true */ + this.onSelect( file ); + } else { + this.tree.down( i ); + this.draw( this.w, this.h, 1 ); + }; + file.destroy(); + break; + }; + }; + }, + onScroll : function( e ){ + this.panInPage.onScroll( e ); + }, + onPathClick : function( e ){ + var target = e.target, + i = target.nodeIndex(); + if( target === this.nodePath || this.nodePath.numNode() - 1 === i ) return; + this.tree.up( i ); + this.draw( this.w, this.h, -1 ); + }, + draw : function( w, h, way, showDetail ){ + var data = this, page; + data.w = w = Type.isFinite( w ) === true ? w : data.w; + data.h = h = Type.isFinite( h ) === true ? h : data.h; + + var file = this.currentFile = this.tree.getCurrentFile(), + isFolder = showDetail !== true && ( file.getChildFileLength() !== -1 || file.getType() === Const.FILE.TYPE.FOLDER ); + + data.elmPath && data.drawPath( w ); + page = this.panInPage; + if( Type.isNumber( way ) === true ){ + if( page.sliding === false ){ + if( isFolder === true ){ + this.panInPage = page === this.pageIcons1 ? this.pageIcons2 : ( page === this.pageIcons2 ? this.pageIcons1 : this.panOutPage ); + } else { + this.panInPage = this.pageDetail; + }; + this.panOutPage = page; + }; + this.panInPage.panInReady( way ); + //this.panInPage.elm.className = 'panIN'; + this.panOutPage.panOutReady( way ); + //this.panOutPage.elm.className = 'panOut'; + this.nodeRoot.disabled( true ); + SystemTimer.add( this.apiuser, this.tick, 16, false, this ); + } else { + if( isFolder === true ){ + this.panInPage = page === null ? this.pageIcons1 : page; + } else { + this.panInPage = this.pageDetail; + }; + }; + this.panInPage.draw( file ); + + data.nodeRoot.invalidateScrollbar(); + }, + tick : function(){ + if( this.panInPage.sliding === false && this.panOutPage.sliding === false ){ + SystemTimer.remove( this.apiuser, this.tick ); + this.nodeRoot.disabled( false ); + this.nodeRoot.invalidateScrollbar(); + return; + }; + this.panInPage.sliding === true && this.panInPage.pan(); + this.panOutPage.sliding === true && this.panOutPage.pan(); + }, + drawPath : function( w ){ + if( !this.elmPath.parentNode ) return; + w = this.nodePath.width(); + var data = this, + tree = data.tree, + pathList = data.pathList, + i = 0, + l = tree.hierarchy() + 1, + m = pathList.length, + wList = [], + totalW = 0, + minW = FinderPrivateData.MIN_PATH_WIDTH, + file, path, pathW, offset, remove, pathX = 0, fit = false; + + for( ; i < l; ++i ){ + file = i !== l - 1 ? tree.getParentFileAt( i ) : this.currentFile; + if( i < m ){ + pathList[ i ].init( this, file, i ); + } else { + pathList.push( PathClass.get( this, file, i ) ); + }; + }; + while( l < pathList.length ) pathList.pop().destroy(); + + for( i = l; i; ){ + pathW = pathList[ --i ].textWidth(); + wList.push( pathW ); + totalW += pathW; + }; + + //if( minW * ( l + 1 ) * 1.2 < w ){ + console.log( totalW + ' , ' + w ) + while( true ){ + if( fit === true ) break; + for( i = 0; i < l; ++i ){ + offset = totalW - w; + if( offset <= 0 ){ + fit = true; + break; + }; + remove = l - i; + remove = offset < remove ? offset : remove; + pathW = wList[ i ]; + if( pathW - remove < minW ){ + totalW -= ( pathW - minW ); + wList[ i ] = minW; + } else { + wList[ i ] = pathW - remove; + totalW -= remove; + }; + }; + }; + for( i = 0; i < l; ++i ){ + path = pathList[ i ]; + pathW = wList[ i ]; + path.update( pathX, pathW ); + pathX += pathW; + }; + //} else { + + //}; + }, + createPath : function( node ){ + if( this.elmPath ) return; + + if( PointingDeviceEventTree.isNodeInstance( node ) === true ){ + this.nodePath = node; + this.elmPath = PointingDeviceEventTree._getNodePrivateData( node ).elm; + + node.addEventListener( 'click', this.onPathClick, this ); + Util.addClass( this.elmPath, 'finder-path' ); + // this.elmPath = document.createElement( 'div' ); + // this.elmPath.className = ; + this.pathList = []; + // this.headH = 0; + AsyncCall.add( this.apiuser, this.draw, null, this ); + }; + }, + onKill : function(){ + this.tree.removeTreeEventListener( Const.TREE.EVENT.UPDATE, this.draw ); + + if( this.pathList ){ + while( this.pathList.length > 0 ) this.pathList.shift().destroy(); + }; + + this.pageIcons1.destroy(); + this.pageIcons2.destroy(); + this.pageDetail.destroy(); + this.nodeRoot.remove(); + + FINDER_LIST.splice( Util.getIndex( FINDER_LIST, this.finder ), 1 ); + var data = ApplicationPrivateData.get( this.apiuser ), + list = data.finderList, + i = Util.getIndex( list, this.finder ); + i !== -1 && list.splice( i, 1 ); + } + }); + FinderPrivateData.MIN_PATH_WIDTH = 25; + +/** + * FinderClass + */ + var Finder = Class.create( + FinderPrivateData, { + Constructor : function( application, elmRoot, tree, onSelect, viewerOption, editorOption ){ + Finder.newPrivateData( this, this, application, elmRoot, tree, onSelect, viewerOption, editorOption ); + }, + MIN_WIDTH : 200, + MIN_HEIGHT : 200, + resize : function( w, h ){ + var data = Finder.getPrivateData( this ); + data.panInPage && data.panInPage.resize( w ); + }, + createPath : function( node ){ + return Finder.getPrivateData( this ).createPath( node ); + }, + destroy : function(){ + this.kill(); + } + }); + + return { + init: function(){ + + }, + create: function( application, elmTarget, tree, onSelect, viewerOption, editorOption ){ + //if( Application.isApplicationInstance( _application ) === false ) return; + + var finder = new Finder( application, elmTarget, tree, onSelect, viewerOption, editorOption ); + FINDER_LIST.push( finder ); + return finder; + }, + registerFinderHead: function(){ + + }, + registerFinderPane: function( _finderPane ){ + + }, + isFinderInstance: function( _finder ){ + return _finder instanceof Finder; + }, + isFinderPaneInstance: function(){ + + }, + isFinderHeadInstance: function(){ + } + }; +})(); + + +/* + * -- len, % + * marginBottom, marginLeft, marginRight, marginTop, margin + * padding, paddingBottom, paddingLeft, paddingRight, paddingTop + * fontSize, textIndent + * height, width + * bottom, left, right, top (len, %) + * + * -- len + * borderBottomWidth, borderLeftWidth, borderRightWidth, borderTopWidth, borderWidth, + * letterSpacing + * + * -- color + * backgroundColor + * borderBottomColor, borderLeftColor, borderRightColor, borderTopColor, borderColor + * color + * + * -- special + * clip rect(0px, 40px, 40px, 0px); + * backgroundPosition (len, %) + * opacity + * lineHeight (len, %, num) + * zIndex ( order ) + */ + +var DHTML = ( function(){ + + var TICKET_ARRAY = [], + fpms = 50, + round = Math.round, + cround = function( v ){ return round( v * 100 ) / 100 }; + + function startAnimation( _elm, _cssObject, _onComplete, _onEnterFrame, _numFrames ){ + var _ticket, i = TICKET_ARRAY.length; + for( ; i; ){ + _ticket = TICKET_ARRAY[ --i ]; + if( _ticket.elm === _elm ){ + return; + }; + }; + + var _currentValues = [], + _offsetValues = [], + _endValues = [], + _targetProperties = [], + _units = []; + var target, current, + inlineStyle = CSS.getInlineStyle( _elm ), + currentStyle = CSS.getWrappedStyle( _elm ), + targetStyle = CSS.getWrappedStyle( _elm, _cssObject ); + targetStyle.pxPerEm = currentStyle.get( 'fontSize' )._toPx(); + for( var p in _cssObject ){ + p = Util.camelize( p ); + target = targetStyle.get( p ); + current = currentStyle.get( p ); + + if( target.isValid() === false || current.isValid() === false || current.equal( target ) !== false ){ + target.clear(); + current.clear(); + continue; + }; + + current.convert( target ); + // alert( current.getValue() + ' , ' + target.getValue() ) + _currentValues.push( current.getValue() ); + _offsetValues.push( current.getOffset( target ) ); + _endValues.push( target.getValue() ); + _targetProperties.push( p ); + _units.push( target.getUnit() ); + + // IE has trouble with opacity if it does not have layout + // Force it by setting the zoom level + if( p === 'opacity' && SPECIAL.hasLayout ){ + if( SPECIAL.hasLayout( _elm ) === false ) inlineStyle.zoom = 1; + inlineStyle.filter = current.getValueText(); + } else { + inlineStyle[ p ] = current.getValueText(); + }; + + target.clear(); + current.clear(); + }; + + var i, cssTexts = []; + for( i = 0; i < _numFrames; ++i ){ + if( i < _numFrames - 1 ){ + tickValue( _currentValues, _offsetValues, _numFrames ); + cssTexts.push( createCssText( _currentValues, _targetProperties, targetStyle, inlineStyle ) ); + } else { + cssTexts.push( createCssText( _endValues, _targetProperties, targetStyle, inlineStyle ) ); + }; + }; + + TICKET_ARRAY.push( new AnimationTaskClass( + _elm, cssTexts, + Type.isFunction( _onComplete ) === true ? _onComplete : null, + Type.isFunction( _onEnterFrame ) === true ? _onEnterFrame : null, + _numFrames + ) ); + + currentStyle.clear(); + targetStyle.clear(); + SystemTimer.add( SUPER_USER_KEY, onEnterFrame, 1000 / fpms ); + }; + + function tickValue( current, offset, numFrames ){ + if( Type.isArray( current ) === true ){ + var ret, i = current.length; + for( ; i; ){ + --i; + ret = tickValue( current[ i ], offset[ i ], numFrames ); + if( Type.isNumber( ret ) === true ) current[ i ] = ret; + }; + } else { + return current + offset / numFrames; + }; + }; + function createCssText( update, props, style, inline ){ + var prop; + for( var i = props.length; i; ){ + prop = style.get( props[ --i ] ); + prop.setValue( update[ i ] ); + inline[ Util.uncamelize( prop.name ) ] = prop.getValueText(); + //if( prop.name === 'backgroundColor' ) alert( prop.getValueText() + '|' + update[ i ].join( ',') ) + prop.clear(); + }; + return CSS.toCssText( inline ); + }; + + function onEnterFrame(){ + var _ticket, l, + i = 0; + while( i < TICKET_ARRAY.length ){ + _ticket = TICKET_ARRAY[ i ]; + l = _ticket.cssTexts.length; + _ticket.elm.style.cssText = _ticket.cssTexts.shift(); + if( l === 1 ){ + _ticket.onComplete && _ticket.onComplete(); + delete _ticket.elm; + delete _ticket.cssTexts; + delete _ticket.onComplete; + delete _ticket.onEnterFrame; + delete _ticket.numFrame; + TICKET_ARRAY.splice( i, 1 ); + } else { + _ticket.onEnterFrame && _ticket.onEnterFrame( l / _ticket.numFrame ); + ++i; + }; + }; + if( TICKET_ARRAY.length === 0 ){ + SystemTimer.remove( SUPER_USER_KEY, onEnterFrame ); + }; + }; + + var AnimationTaskClass = function( elm, cssTexts, onEnterFrame, onComplete, numFrame ){ + this.elm = elm; + this.cssTexts = cssTexts; + this.onEnterFrame = onEnterFrame; + this.onComplete = onComplete; + this.numFrame = numFrame; + }; + + var VisualEffectClass = function( elm ){ + this.elm = elm; + }; + VisualEffectClass.prototype = { + anime : function( _cssObject, _onComplete, _onEnterFrame, _time ){ + var _numFrames = Math.floor( _time / fpms ); + startAnimation( this.elm, _cssObject, _onComplete, _onEnterFrame, _numFrames ); + }, + fadeIn : function(){ + + }, + fadeOut : function(){ + + }, + update : function( x, y, w, h ){ + var _cssText = this.elm.style.cssText; + } + }; + + return { + create: function( application, _elm ){ + return new VisualEffectClass( _elm ); + }, + isInstanceOfVisualEffect: function( _instance){ + return _instance instanceof VisualEffectClass; + } + } +})(); + + +/* -------------------------------------------- + * + */ + + Application.onCurrentApplicationChange( SUPER_USER_KEY ); + + SERVICE_LIST.push( MouseEvent ); + + new EventTicketClass( window, 'unload', function(){ + var _service; + while( SERVICE_LIST.length > 0 ){ + _service = SERVICE_LIST.shift(); + Type.isFunction( _service.onSystemShutdown ) === true && _service.onSystemShutdown(); + } + }); + // beforeunload + + +/* --------------------------------------------- + * broadcast to global + */ + window.gOS = {}; + + gOS.registerApplication = Application.register; + gOS.registerDriver = File.registerDriver; + +})( window, document );