OSDN Git Service

ac96c53d4aadecbe23327ae744dae3dd309e3be1
[pettanr/clientJs.git] / 0.4.x / javascripts / system.js
1 /*
2  * pettanR system.js
3  *   version 0.4.4
4  *   
5  * author:
6  *   itozyun
7  * licence:
8  *   3-clause BSD
9  */
10
11
12 pettanr.log = ( function(){
13         return {
14                 init: function(){}
15         }
16 })();
17
18 pettanr.io = ( function(){
19         
20         return {
21                 init: function(){}
22         }
23 })();
24
25 /*
26  * 画像一覧は
27  *      お気に入り画像一覧 > tag:ペン次郎 > ペン次郎:笑う
28  *  最近アップロードされた画像 > images
29  *  最近使われた画像 > images
30  *  キャラクター画像庫 > アニマル系 > tag:ペン次郎 > ペン次郎:笑う
31  *  風景画像庫 >
32  *  効果画像庫 >
33  *  アイテム画像庫 >
34  *  
35  * 画像一覧を読み込むタイミング
36  */
37 pettanr.file = ( function(){
38         var FILE_TYPE_IS_FOLDER = 1,
39                 numFileType = FILE_TYPE_IS_FOLDER,
40                 FILEDATA_RESITER = [],                  // store all of fileData( json object )
41                 FILEDATA_ACCESS = [],                   // file operations for Kernel only ! hide from Out of pettanr.file
42                 FILE_OBJECT_POOL = [],
43                 EVENT_LISTENER_RESISTER = [],
44                 TREE_ARRAY = [],
45                 TREE_ACCESS_ARRAY = [];
46         
47         var REQUEST_CONTROLER = ( function(){
48                 var REQUEST_TICKET_RESISTER = [],
49                         DATA_TYPE_ARRAY = 'json,xml,html,text'.split( ','),
50                         DATA_IS_JSON = 0,
51                         DATA_IS_XML = 1,
52                         DATA_IS_HTML = 2,
53                         DATA_IS_TEXT = 3,
54                         numError = 0;
55                 
56                 var RequestTicketClass = function( _type, _data, _url, _onLoad, _onError){
57                         this.type = DATA_TYPE_ARRAY[ _type];
58                         this.data = _data;
59                         this.url = _url;
60                         this.onLoad = _onLoad;
61                         this.onError = _onError;
62                         this.state = 0;
63                 };
64                 
65                 function request(){
66                         if( REQUEST_TICKET_RESISTER.length === 0) return;
67                         var _ticket = REQUEST_TICKET_RESISTER.shift();
68                         $.ajax({
69                                 url:            _ticket.url,
70                                 dataType:       _ticket.type,
71                                 success:        function( _data){
72                                         _ticket.onLoad( _ticket.data, _data);
73                                 },
74                                 error:          function(){
75                                         ++numError;
76                                         _ticket.onError( _ticket.data);
77                                 }
78                         });
79                 }
80                 
81                 return {
82                         getNumTask: function(){
83                                 return REQUEST_TICKET_RESISTER.length;
84                         },
85                         getNumError: function(){
86                                 return numError;
87                         },
88                         getJson: function( _data, _url, _onLoad, _onError){
89                                 REQUEST_TICKET_RESISTER.push( new RequestTicketClass( DATA_IS_JSON, _data, _url, _onLoad, _onError));
90                                 request();
91                         }
92                 }
93         })();
94
95
96
97         var FILE_CONTROLER = ( function(){
98                 
99                 return {
100                         createTree: function( _rootFileData){
101                                 var _tree = new TreeClass( _rootFileData);
102                                 _tree.init();
103                                 TREE_ARRAY.push( _tree);
104                                 return _tree;
105                         },
106                         getFileData: function( UIDorFILEorFILEDATA){
107                                 var _access = FILE_CONTROLER.getFileDataAccess( UIDorFILEorFILEDATA);
108                                 return _access !== null ? _access.DATA : null;
109                         },
110                         getChildren: function( UIDorFILEorFILEDATA){
111                                 var _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA);
112                                 return _data !== null ? _data.children || null : null;
113                         },
114                         getFileDataAccess: function( UIDorFILEorFILEDATA){
115                                 var _uid, _data, _access;
116                                 
117                                 if( typeof UIDorFILEorFILEDATA === 'number'){
118                                         _data = FILEDATA_RESITER[ UIDorFILEorFILEDATA] || null;
119                                 } else
120                                 if( UIDorFILEorFILEDATA instanceof FileClass){
121                                         _uid = UIDorFILEorFILEDATA.getUID();
122                                         _data = FILEDATA_RESITER[ _uid] || null;
123                                 } else {
124                                         _data = UIDorFILEorFILEDATA || null;
125                                 }
126                                 
127                                 if( _data === null || !_data) return null;
128                                 for( var i=0, l = FILEDATA_ACCESS.length; i<l; ++i){
129                                         _access = FILEDATA_ACCESS[ i];
130                                         if( _access.DATA === _data) return _access;
131                                 }
132                                 return null;
133                         },
134                         getDriver: function( _file){
135                                 var _data = FILE_CONTROLER.getFileData( _file);
136                                 return _data !== null && _data.driver ? ( _data.driver || FileDriverBase) : null;
137                         },
138                         getUID: function ( _filedata){
139                                 var l = FILEDATA_RESITER.length;
140                                 for( var i=0; i<l; ++i){
141                                         if( FILEDATA_RESITER[ i] === _filedata) return i;
142                                 }
143                                 return -1;
144                         },
145                         getSeqentialFiles: function( _file){
146                                 var _driver = FILE_CONTROLER.getDriver( _file);
147                                 if( _driver !== null && typeof _driver.getSeqentialFiles === 'function'){
148                                         _driver.getSeqentialFiles( _file);
149                                 }
150                         },
151                         updateFileAttribute: function( _uid, key, _value, _opt_callback){
152                                 var _data = FILE_CONTROLER.getFileDataAccess( _uid),
153                                         _type = _data.TYPE;
154                                 
155                         },                      
156                         getFileAttribute: function( _uid, KEYorKEYARRAY){
157                                 var _fileData = FILE_CONTROLER.getFileDataAccess( _uid),
158                                         _type = _fileData.TYPE;
159                         },
160                         move: function( _prentUID, _targetfile, _newFolder, _newIndex, _opt_callback){
161                                 var _parentData = FILE_CONTROLER.getFileDataAccess( _prentUID),
162                                         _parentType = _parentData.TYPE,
163                                         _targetData = FILE_CONTROLER.getFileDataAccess( _targetfile),
164                                         _targetType = _targetData.TYPE;
165                         },
166                         replace: function( _uid, _file, _newIndex){
167                                 
168                         },
169                         addEventListener: function( FILEorNULL, _eventType, _callback){
170                                 var _uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL;
171                                 EVENT_LISTENER_RESISTER.push( new FileEventTicketClass( _uid, _eventType, _callback));
172                         },
173                         removeEventListener: function( FILEorNULL, _eventType, _callback){
174                                 var _uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL,
175                                         _ticket;
176                                 for(var i=0, l = EVENT_LISTENER_RESISTER.length; i<l; ++i){
177                                         _ticket = EVENT_LISTENER_RESISTER[i];
178                                         if( _ticket.fileUID === _uid && _ticket.eventType === _eventType && _ticket.callBack === _callback){
179                                                 EVENT_LISTENER_RESISTER.splice( i, 1);
180                                                 _ticket.destroy();
181                                         }
182                                 }
183                         },
184                         fileEventRellay: function( _targetFile, _targetTree, _event){
185                                 var _uid = _targetTree.getUID(),
186                                         _access = TREE_ACCESS_ARRAY[ _uid],
187                                         l = TREE_ARRAY.length,
188                                         _tree, _currentFile;
189                                 _access !== undefined && _access.dispatchFileEvent( _event);
190                                 for(var i=0; i<l; ++i){
191                                         if( i !== _uid){
192                                                 _tree = TREE_ARRAY[i];
193                                                 _currentFile = _tree.getCurrentFile();
194                                                 if( FILE_CONTROLER.getFileData( _currentFile) === _access.DATA){
195                                                         TREE_ACCESS_ARRAY[ _tree.getUID()].dispatchFileEvent( _event);
196                                                 }
197                                         }
198                                 }
199                         }
200                 }
201         })();
202
203         var TreeClass = function( ROOTFILE_DATA){
204                 var UID = TREE_ACCESS_ARRAY.length,
205                         PARENT_FILE_RESITER = [],
206                         ACCESS = {
207                                 dispatchFileEvent:      dispatchFileEvent,
208                                 destroy:                        onDestroy
209                         },
210                         EVENT_LISTENER_ARRAY = [],
211                         rootFile,
212                         rootFileData,
213                         currentFile,
214                         currentFileData,
215                         instance;
216                         
217                 TREE_ACCESS_ARRAY.push( ACCESS);
218                 
219                 function onDestroy(){
220                         
221                 }
222                 
223                 function dispatchFileEvent( e){
224                         var _eventType = e.eventType,
225                                 _targetFile = e.targetFile,
226                                 _uid = _targetFile.getUID(),
227                                 _ticket, _type, _callback;
228                         for(var i=0, l = EVENT_LISTENER_RESISTER.length; i<l; ++i){
229                                 _ticket = EVENT_LISTENER_RESISTER[i],
230                                 _type = _ticket.eventType,
231                                 _callback = _ticket.callBack;
232                                 if( _eventType === _type && _uid === _ticket.fileUID){
233                                         _callback( _eventType, _targetFile, e.key, e.value);
234                                 } else
235                                 if( _type === pettanr.file.TREE_EVENT.UPDATE && _eventType === pettanr.file.FILE_EVENT.GET_SEQENTIAL_FILES){
236                                         _callback( _eventType, _targetFile);
237                                 }
238                         }
239                 }
240                 
241                 return {
242                         init: function(){
243                                 instance = this;
244                                 currentFile = rootFile = new FileClass( this, null, ROOTFILE_DATA);
245                                 rootFile.init();
246                                 FILE_CONTROLER.getSeqentialFiles( currentFile);
247                                 delete this.init;
248                         },
249                         getUID: function(){ return UID},
250                         getRootFile : function(){
251                                 return rootFile;
252                         },
253                         getCurrentFile: function(){
254                                 return currentFile;
255                         },
256                         hierarchy: function(){
257                                 return PARENT_FILE_RESITER.length;
258                         },
259                         getParentFileAt: function( _index){
260                                 var l = PARENT_FILE_RESITER.length;
261                                 if( typeof _index !== 'number' || _index < 0 || _index >= l) return null;
262                                 return PARENT_FILE_RESITER[ l -1 -_index];
263                         },
264                         down: function( _index){
265                                 if( typeof _index !== 'number' || _index < 0 || _index >= currentFile.getChildFileLength()) return;
266                                 PARENT_FILE_RESITER.unshift( currentFile);
267                                 currentFile = currentFile.getChildFileByIndex( _index);
268                                 FILE_CONTROLER.getSeqentialFiles( currentFile);
269                                 return currentFile;
270                         },
271                         up: function( _index){
272                                 var l = PARENT_FILE_RESITER.length;
273                                 if( l === 0) return null;
274                                 if( typeof _index === 'number'){
275                                         if( _index >= l) return null;
276                                         currentFile = this.getParentFileAt( _index);
277                                         PARENT_FILE_RESITER.splice( 0, l -_index);
278                                 } else {
279                                         currentFile = PARENT_FILE_RESITER.shift();
280                                 }
281                                 FILE_CONTROLER.getSeqentialFiles( currentFile);
282                                 return currentFile;     
283                         },
284                         addTreeEventListener: function( _eventType, _callback){
285                                 FILE_CONTROLER.addEventListener( null, _eventType, _callback);
286                         },
287                         removeTreeEventListener: function( _eventType, _callback){
288                                 FILE_CONTROLER.removeEventListener( null, _eventType, _callback);
289                         },
290                         destroy: function(){
291                                 FILE_CONTROLER.destroyTree( UID);
292                         }
293                 }
294         };
295
296         var FileEventTicketClass = function( UID, _eventType, _callback){
297                 this.fileUID = UID;
298                 this.eventType = _eventType;
299                 this.callBack = _callback;
300                 this.destroy = function(){
301                         this.callBack = _callback = null;
302                 }
303         }
304         
305         var FileEventClass = function( eventType, file, key, value){
306                 this.eventType = eventType;
307                 this.targetFile = file;
308                 this.updatedAttribute = key;
309                 this.updatedValue = value;
310         }
311
312 /*
313  * fileのdataはobjectで保持している。
314  * pettanr.file.の外からファイルをみるときは、FileClassを通して操作する。
315  * fileの変更、それに付随して追加されたイベントは、TreeClassで管理される。
316  * treeがdestryされると、fileのイベントリスナーも全て削除される。
317  * 他の tree も data の共通する currentFile に対してのみは、file の変更イベントを受け取って流す.
318  */
319         
320         var FileClass = function( TREE, parentFile, data){
321                 if( !data.children){
322                         data.children = [];
323                 }
324                 var TYPE = data.type,
325                         name = null,
326                         driver = data.driver || FileDriverBase,
327                         thumbnail = null,
328                         uid = FILE_CONTROLER.getUID( data),
329                         CHILDREN = data.children,
330                         instance = this;
331                 
332                 if( uid === -1){
333                         uid = FILEDATA_RESITER.length;
334                         FILEDATA_RESITER.push( data);
335                 }
336                 
337                 FILEDATA_ACCESS.push(
338                         {
339                                 TYPE:                           TYPE,
340                                 DATA:                           data,
341                                 destroy:                        destroy,
342                                 updateParent:           updateParent,
343                                 dispatchFileEvent:      dispatchEvent
344                         }
345                 );
346                 function destroy(){
347                         name = thumbnail = parentFile = data = CHILDREN = driver = null;
348                         
349                 }
350                 function updateParent( _parent){
351                         parentFile = _parent;
352                 }
353                 function dispatchEvent( e){
354                         FILE_CONTROLER.fileEventRellay( instance, TREE, e);
355                 }
356                 
357                 /* grobal Methods */
358                 this.init = function(){
359                         //instance = this;
360                         delete this.init;
361                 }
362                 this.getType = function(){
363                         return TYPE;
364                 }
365                 this.getName = function(){
366                         if( name !== null) return name;
367                         if( typeof driver.getName === 'function'){
368                                 name = driver.getName( instance);
369                         }
370                         return name;
371                 }
372                 this.getThumbnail = function(){
373                         if( thumbnail !== null) return thumbnail;
374                         if( typeof driver.getThumbnail === 'function'){
375                                 thumbnail = driver.getThumbnail( instance);
376                         }
377                         return thumbnail || null;
378                 }
379                 this.getUID = function(){
380                         return uid;
381                 }
382                 this.getChildFileByIndex = function( _index){
383                         if( typeof _index !== 'number' || _index < 0 || typeof CHILDREN.length !== 'number' || _index >= CHILDREN.length) return null;
384                         _file = new FileClass( TREE, this, CHILDREN[ _index]);
385                         _file.init();
386                         return _file;
387                 }
388                 this.move = function( _newFolder, _newIndex, opt_callback){
389                         TREE.move( parentFile, UID, _newFolder, _newIndex, opt_callback);
390                 }
391                 this.replace = function( _newIndex, opt_callback){
392                         TREE.replace( parentFile, UID, _newIndex, opt_callback);
393                 }
394                 this.destroy = function(){
395                         
396                 }
397         };
398         FileClass.prototype = {
399                 isChildFile: function( _FILEorFILEDATA){
400                         return this.getChildFileIndex( _FILEorFILEDATA) !== -1;
401                 },
402                 getSeqentialFiles: function(){
403                         FILE_CONTROLER.getSeqentialFiles( this);
404                 },
405                 addEventListener: function( _eventType, _callback){
406                         FILE_CONTROLER.addEventListener( this, _eventType, _callback);
407                 },
408                 removeEventListener: function( _eventType, _callback){
409                         FILE_CONTROLER.removeEventListener( this, _eventType, _callback);
410                 },
411                 getChildFileLength: function(){
412                         var CHILDREN = FILE_CONTROLER.getChildren( this);
413                         return CHILDREN && typeof CHILDREN.length === 'number' ? CHILDREN.length : 0;
414                 },
415                 getChildFileIndex: function( _FILEorFILEDATA){
416                         var CHILDREN = FILE_CONTROLER.getChildren( this);
417                         
418                         if( !CHILDREN || typeof CHILDREN.length !== 'number') return -1;
419                         var l = CHILDREN.length,
420                                 _fileData = FILE_CONTROLER.getFileData( _FILEorFILEDATA);
421                         if( _fileData === null) return -1;
422                         for(var i=0; i<l; ++i){
423                                 if( CHILDREN[ i] === _fileData) return i;
424                         }
425                         return -1;
426                 },
427                 getState: function(){
428                         var _data = FILE_CONTROLER.getFileData( this);
429                         return _data.state !== undefined ? _data.state : pettanr.file.FILE_STATE.OK;
430                 }
431         }
432
433         /*
434          * FileDriverBase
435          */
436         var FileDriverBase = {
437                 getSeqentialFiles: function( _file){
438                 },
439                 getName: function( _file){
440                         var _data = FILE_CONTROLER.getFileData( _file);
441                         return _data.name || 'No Name';
442                 },
443                 getThumbnail: function( _file){
444                         var _data = FILE_CONTROLER.getFileData( _file);
445                                 _type = _data.type,
446                                 _className = '';
447                         if( _type === pettanr.file.FILE_TYPE.FOLDER){
448                                 _className = 'folder';
449                         } else
450                         if( _type === pettanr.file.FILE_TYPE.IMAGE){
451                                 
452                         } else
453                         if( _type === pettanr.file.FILE_TYPE.TEXT){
454                                 
455                         } else
456                         if( _type === pettanr.file.FILE_TYPE.HTML){
457                                 
458                         } else
459                         if( _type === pettanr.file.FILE_TYPE.CSV){
460                                 
461                         } else
462                         if( _type === pettanr.file.FILE_TYPE.JSON){
463                                 
464                         } else
465                         if( _type === pettanr.file.FILE_TYPE.XML){
466                                 
467                         }
468                         return {
469                                 image:          null,
470                                 className:      ' file-type-' + _className
471                         }
472                 },
473                 isWritable: function( _file){
474                         return false;
475                 },
476                 isSortable: function( _file){
477                         return false;
478                 },              
479                 isCreatable: function( _file){
480                         return false;
481                 },
482                 read: function(){
483                         return false;
484                 },
485                 write: function( _newName, _newData){
486                         return false;
487                 },
488                 onCreate: function(){
489                         
490                 },
491                 onSort: function(){
492                         
493                 },
494                 onCopy: function(){
495                         
496                 },
497                 onDelete: function(){
498                         
499                 }
500         }
501
502         function getFileObject( TREE, parentFile, data){
503                 var _file = FILE_OBJECT_POOL.length > 0 ? FILE_OBJECT_POOL.shift() : new FileClass();
504                 _file.init( TREE, parentFile, data);
505                 return _file;
506         }
507
508         var ROOT_FILEDATA = {
509                         name:           'system root',
510                         type:           FILE_TYPE_IS_FOLDER,
511                         children:       []
512                 },
513                 SYSTEM_TREE = FILE_CONTROLER.createTree( ROOT_FILEDATA),
514                 ROOT_FILE = SYSTEM_TREE.getRootFile();
515         
516         function createFolderUnderRoot( _fileData){
517                 ROOT_FILEDATA.children.push( _fileData);
518                 FILE_CONTROLER.getFileDataAccess( ROOT_FILE)
519                         .dispatchFileEvent( new FileEventClass( pettanr.file.FILE_EVENT.GET_SEQENTIAL_FILES, ROOT_FILE, 'children', null));
520         }
521         function createFileEvent( _eventType, _file, _key, _value){
522                 return new FileEventClass( _eventType, _file, _key, _value)
523         }
524         function createFileTypeID(){
525                 return ++numFileType;
526         }
527         
528         return {
529                 init: function(){
530                         //REQUEST_CONTROLER.init();
531                         //FILE_CONTROLER.init();
532                         delete pettanr.file.init;
533                 },
534                 resisterDriver: function( _driver){
535                         _driver.prototype = FileDriverBase;
536                         /*
537                          * File API
538                          */
539                         return {
540                                 createFolderUnderRoot:  createFolderUnderRoot,
541                                 getFileDataAccess:              FILE_CONTROLER.getFileDataAccess,
542                                 getFileData:                    FILE_CONTROLER.getFileData,
543                                 getJson:                                REQUEST_CONTROLER.getJson,
544                                 createFileEvent:                createFileEvent,
545                                 createFileTypeID:               createFileTypeID
546                         }
547                 },
548                 createTree: function( _rootFile){
549                         return FILE_CONTROLER.createTree( _rootFile);
550                 },
551                 isTreeInstance: function( _tree){
552                         return _tree instanceof TreeClass;
553                 },
554                 isFileInstance: function( _file){
555                         return _file instanceof FileClass;
556                 },
557                 FILE_TYPE: {
558                         FOLDER:         FILE_TYPE_IS_FOLDER,
559                         IMAGE:          createFileTypeID(),
560                         TEXT:           createFileTypeID(),
561                         HTML:           createFileTypeID(),
562                         CSV:            createFileTypeID(),
563                         JSON:           createFileTypeID(),
564                         XML:            createFileTypeID()
565                 },
566                 FILE_STATE: {
567                         UNKNOWN:        0,
568                         OK:                     1,
569                         LOADING:        2,
570                         ERROR:          3,
571                         BROKEN:         4
572                 },
573                 TREE_EVENT: {
574                         UPDATE:                         'onTreeUpdate'
575                 },
576                 FILE_EVENT: {
577                         UPDATE_ATTRIVUTE:       'onFileUpdate',
578                         GET_SEQENTIAL_FILES:'gotSeqentilFiles'
579                 },
580                 FILE_DATA_PROPERTY_RESERVED: [
581                         'children', 'driver', 'state', 'type', 'name'
582                 ]
583         }
584 })();
585
586 pettanr.finder = ( function(){
587         var FINDER_ARRAY = [],
588                 ELM_ORIGIN_FINDER_LOCATION_ITEM = pettanr.util.pullHtmlAsTemplete( 'templete-finder-location-item'),
589                 ELM_ORIGIN_FINDER_ICON = pettanr.util.pullHtmlAsTemplete( 'templete-finder-icon'),
590                 ELM_ORIGIN_CONTAINER = pettanr.util.pullHtmlAsTemplete( 'templete-finder-container'),
591                 ICON_HEIGHT = pettanr.util.getElementSize( ELM_ORIGIN_FINDER_ICON).height,
592                 ICON_CLASSNAME = ELM_ORIGIN_FINDER_ICON.getElementsByTagName( 'div')[0].className,
593                 FINDER_ICON_POOL = [],
594                 BREAD_OBJECT_POOL = [];
595         
596         var FinderIconClass = function(){
597                 var elmContainer,
598                         ELM_WRAPPER = ELM_ORIGIN_FINDER_ICON.cloneNode( true),
599                         ELM_THUMBNAIL = pettanr.util.getElementsByClassName( ELM_WRAPPER, 'finder-icon-thumbnail', 'div')[0],
600                         ELM_FILENAME = pettanr.util.getElementsByClassName( ELM_WRAPPER, 'finder-icon-filename', 'div')[0],
601                         file, w, index, style, instansce, callback;
602                 
603                 ELM_WRAPPER.onclick = onClick;
604                 function onClick(){
605                         callback( index);
606                 }
607
608                 function draw(){
609                         var _thumb = file.getThumbnail();
610                         if( _thumb.image){
611                                 ELM_THUMBNAIL.className = ICON_CLASSNAME + ' has-thumbnail';
612                                 ELM_THUMBNAIL.style.backgroundImage = [ 'url(', _thumb.image, ')'].join( '');
613                         } else {
614                                 ELM_THUMBNAIL.className = ICON_CLASSNAME + ' ' +_thumb.className;
615                                 ELM_THUMBNAIL.style.backgroundImage = '';
616                         }
617                         ELM_FILENAME.innerHTML = file.getName();
618                 }
619                 function resize(){
620                         ELM_WRAPPER.style.top = (index * ICON_HEIGHT) +'px';
621                 }
622                 function onCollect(){
623                         elmContainer.removeChild( ELM_WRAPPER);
624                         elmContainer = null;
625                         FINDER_ICON_POOL.push( instansce);
626                 }
627                 
628                 return {
629                         init: function( _file, _elmContainer, _w, _index, _style, _callback){
630                                 instansce = this;
631                                 if( elmContainer !== _elmContainer){
632                                         _elmContainer.appendChild( ELM_WRAPPER);
633                                         elmContainer = _elmContainer;
634                                 }
635                                 if( file !== _file){
636                                         file = _file;
637                                         draw();
638                                 }
639                                 if( index !== _index){
640                                         index = _index;
641                                         resize();
642                                 }
643                                 callback = _callback;
644                         },
645                         elm: ELM_WRAPPER,
646                         index: function( _index){
647                                 
648                                 return index;
649                         },
650                         style: function( _style){
651                                 
652                                 return style;
653                         },
654                         onResize: function( w){
655                                 
656                         },
657                         destroy: function(){
658                                 elmContainer.removeChild( ELM_WRAPPER);
659                                 file = elmContainer = null;
660                                 FINDER_ICON_POOL.push( instansce);
661                         }
662                 }
663         }
664         function updateIconPosition( _style, _w, _index, _elm){
665                 
666         }
667         var BreadcrumbClass = function(){
668                 var elmContainer,
669                         ELM_WRAPPER = ELM_ORIGIN_FINDER_LOCATION_ITEM.cloneNode( true),
670                         ELM_FILENAME = ELM_WRAPPER.getElementsByTagName( 'a')[0],
671                         file, w, index, instansce,
672                         callback;
673                 ELM_WRAPPER.onclick = onClick;
674                 function draw(){
675                         ELM_FILENAME.className = 'file-icon-' +file.getType();
676                         ELM_FILENAME.innerHTML = file.getName();
677                 }
678                 function resize( index){
679                         ELM_WRAPPER.style.left = (index * 90) +'px';
680                 }
681                 function onClick(){
682                         callback( index);
683                         return false;
684                 }
685
686                 return {
687                         init: function( _file, _elmContainer, _index, _callback){
688                                 instansce = this;
689                                 if( elmContainer !== _elmContainer){
690                                         _elmContainer.appendChild( ELM_WRAPPER);
691                                         elmContainer = _elmContainer;
692                                 }
693                                 if( file !== _file){
694                                         file = _file;
695                                         draw();
696                                 }
697                                 if( index !== _index){
698                                         index = _index;
699                                         resize( index);
700                                 }
701                                 callback = _callback;
702                         },
703                         elm: ELM_WRAPPER,
704                         index: function( _index){
705                                 
706                                 return index;
707                         },
708                         onResize: function( w){
709                                 
710                         },
711                         destroy: function(){
712                                 elmContainer.removeChild( ELM_WRAPPER);
713                                 file = elmContainer = null;
714                                 BREAD_OBJECT_POOL.push( this);
715                         }
716                 }
717         }
718         
719         var FinderClass = function( ELM_CONTAINER, tree, detailSwitchEnabled, styleSwitchEnabled, actionSwitchEnabled){
720                 var ICON_ARRAY = [],
721                         BREAD_ARRAY = [],
722                         elmContainer = ELM_ORIGIN_CONTAINER.cloneNode( true),
723                         elmLocation = elmContainer.getElementsByTagName( 'ul')[0],
724                         nodesDiv = elmContainer.getElementsByTagName( 'div'),
725                         elmSidebarButton = nodesDiv[1],
726                         elmStyleButton = nodesDiv[2],
727                         elmActionButton = nodesDiv[3],
728                         elmBody = nodesDiv[ nodesDiv.length -1],
729                         //tree = pettanr.file.createTree( TREE_TYPE),
730                         headX,
731                         headY,
732                         headH = pettanr.util.getElementSize( ELM_ORIGIN_FINDER_ICON).height,
733                         bodyY,
734                         currentFile = null,
735                         breadW = 90,
736                         size = pettanr.util.getElementSize( ELM_ORIGIN_FINDER_ICON),
737                         iconW = size.width,
738                         iconH = size.height,
739                         style = 0;
740                         w = 800;
741
742                 tree.addTreeEventListener( pettanr.file.TREE_EVENT.UPDATE, draw);
743                 
744                 function draw(){
745                         var     l = tree.hierarchy() +1,
746                                 m = BREAD_ARRAY.length,
747                                 _file, _bread;
748                         for(var i=0; i<l; ++i){
749                                 _file = i !== l-1 ? tree.getParentFileAt( i) : tree.getCurrentFile();
750                                 if( i < m){
751                                         BREAD_ARRAY[ i].init( _file, elmLocation, i, onHeadClick);
752                                 } else {
753                                         BREAD_ARRAY.push( getBreadcrumb( _file, elmLocation, i, onHeadClick));
754                                 }
755                         }
756                         while( l < BREAD_ARRAY.length){
757                                 BREAD_ARRAY.pop().destroy();
758                         }
759                         
760                         l = _file.getChildFileLength();
761                         m = ICON_ARRAY.length;
762
763                         for( i=0; i<l; ++i){
764                                 if( i < m){
765                                         ICON_ARRAY[ i].init( _file.getChildFileByIndex( i), elmBody, w, i, style, onBodyClick);
766                                 } else {
767                                         ICON_ARRAY.push( getFinderIcon( _file.getChildFileByIndex( i), elmBody, w, i, style, onBodyClick));
768                                 }
769                         }
770                         while( l < ICON_ARRAY.length){
771                                 ICON_ARRAY.pop().destroy();
772                         }
773                 }
774                 function onHeadClick( i){
775                         var l = BREAD_ARRAY.length -1;
776                         if( i < l){
777                                 var _file = tree.getParentFileAt( i);
778                                 if( _file !== null){
779                                         tree.up( i);
780                                         draw();
781                                 }
782                         }
783                 }
784                 function onBodyClick( i){
785                         var l = ICON_ARRAY.length;
786                         if( i < l){
787                                 var _file = tree.getCurrentFile().getChildFileByIndex( i);
788                                 if( _file !== null && ( _file.getChildFileLength() > 0 || _file.getType() === pettanr.file.FILE_TYPE.FOLDER)){
789                                         tree.down( i);
790                                         draw();
791                                 }
792                         }
793                 }
794                 
795                 this.init = function(){
796                         ELM_CONTAINER.appendChild( elmContainer);
797                         //$( elmLocation).click( onHeadClick);
798                         //$( elmContainer).click( onBodyClick);
799                         var position = pettanr.util.getAbsolutePosition( elmLocation);
800                         headX = position.x;
801                         headY = position.y;
802                         bodyY = pettanr.util.getAbsolutePosition( elmBody).y;
803                         delete this.init;
804                 }
805                 this.onOpen = function(){
806                         this.init !== undefined && this.init();
807                         draw();
808                 }
809                 this.onClose = function(){
810                         
811                 }
812                 this.onWindowResize = function( _w, _h){
813                                 
814                 }
815         }
816         function getFinderIcon( _file, _elmContainer, w, index, style, callback){
817                 var _icon;
818                 if( FINDER_ICON_POOL.length > 0){
819                         _icon = FINDER_ICON_POOL.shift();
820                 } else {
821                         _icon = new FinderIconClass();
822                 }
823                 _icon.init( _file, _elmContainer, w, index, style, callback);
824                 return _icon;
825         }
826         
827         function getBreadcrumb( _file, _elmContainer, index, callback){
828                 var _bread;
829                 if( BREAD_OBJECT_POOL.length > 0){
830                         _bread = BREAD_OBJECT_POOL.shift();
831                 } else {
832                         _bread = new BreadcrumbClass();
833                 }
834                 _bread.init( _file, _elmContainer, index, callback);
835                 return _bread;
836         }
837
838         return {
839                 init: function(){
840                         
841                 },
842                 createFinder: function( _elmTarget, _tree, detailSwitchEnabled, styleSwitchEnabled, actionSwitchEnabled){
843                         var _finder = new FinderClass( _elmTarget, _tree, detailSwitchEnabled, styleSwitchEnabled, actionSwitchEnabled);
844                         FINDER_ARRAY.push( _finder);
845                         return _finder;
846                 },
847                 createFinderHead: function(){
848                         
849                 },
850                 resisterFinderPane: function( _finderPane){
851                         
852                 },
853                 isFinderInstance: function( _finder){
854                         return _finder instanceof FinderClass;
855                 }
856         }
857 })();
858
859
860 pettanr.driver = ( function(){
861         var MyAuthorID = 'current_author' in window ? current_author.id : 1,
862                 MyArtistID = 'current_artist' in window ? current_artist.id : 1,
863                 Driver = {
864                         getSeqentialFiles: function( _file){
865                                 var _data = FileAPI.getFileData( _file),
866                                         _json = _data !== null ? _data.json : null;
867                                 if( typeof _json === 'string'){
868                                         FileAPI.getJson( _file, _json, onLoadJson, onErrorJson);
869                                         _data.state = pettanr.file.FILE_STATE.LOADING;
870                                         delete _data.json;
871                                 }
872                         },
873                         getName: function( _file){
874                                 var _data = FileAPI.getFileData( _file),
875                                         _type = _data !== null ? _data.type : null;
876                                 if( _type === pettanr.driver.FILE_TYPE.PICTURE){
877                                         return [ _data.id, _data.ext ].join( '.');
878                                 } else
879                                 if( _type === pettanr.driver.FILE_TYPE.PANEL){
880                                         return [ _data.t, ':', _data.comic.name || _data.comic.title ].join( '');
881                                 } else
882                                 if( _type === pettanr.driver.FILE_TYPE.ARTIST){
883                                         return _data.name + '先生';
884                                 } else
885                                 if( _type === pettanr.driver.FILE_TYPE.AUTHOR){
886                                         return _data.name + '先生';
887                                 }
888                                 return _data.name || _data.title;
889                         },
890                         getThumbnail: function( _file){
891                                 var _data = FileAPI.getFileData( _file);
892                                         _type = _data !== null ? _data.type : null;
893                                 if( _type === pettanr.driver.FILE_TYPE.PICTURE){
894                                         return { image: [ pettanr.CONST.RESOURCE_PICTURE_PATH, 'thumbnail/', _data.id, '.', _data.ext ].join( '')};
895                                 }
896                                 if( _data === FILE_DATA_COMIC_ROOT){
897                                         return { className: 'file-type-cabinet'};
898                                 }
899                                 if( _type === pettanr.driver.FILE_TYPE.COMIC){
900                                         return { className: 'file-type-comic'};
901                                 }
902                                 if( _type === pettanr.driver.FILE_TYPE.PANEL){
903                                         return { className: 'file-type-panel'};
904                                 }
905                                 if( _type === pettanr.driver.FILE_TYPE.AUTHOR){
906                                         return { className: 'file-type-author'};
907                                 }
908                                 if( _type === pettanr.driver.FILE_TYPE.ARTIST){
909                                         return { className: 'file-type-artist'};
910                                 }
911                                 if( _type === pettanr.driver.FILE_TYPE.FOLDEER){
912                                         return { className: 'file-type-folder'};
913                                 }
914                                 return { className: 'file-type-folder'};
915                         }
916                 },
917                 FileAPI = pettanr.file.resisterDriver( Driver),
918                 FILE_DATA_SERVICE_ROOT = {
919                         name:           'PettanR root',
920                         type:           pettanr.file.FILE_TYPE.FOLDER,
921                         children:       []
922                 },
923                 FILE_DATA_COMIC_ROOT = {
924                         name:           'Comics',
925                         type:           pettanr.file.FILE_TYPE.FOLDER,
926                         children:       [],
927                         driver:         Driver,
928                         json:           pettanr.CONST.URL_PANELS_JSON
929                 },
930                 FILE_DATA_PICTURE_ROOT = {
931                         name:           'Picutures',
932                         type:           pettanr.file.FILE_TYPE.FOLDER,
933                         children:       [],
934                         driver:         Driver,
935                         json:           pettanr.CONST.URL_ORIGINAL_PICTURES_JSON
936                 },
937                 FILE_DATA_MY_COMICS_ROOT = {
938                         name:           'My Comics',
939                         type:           pettanr.file.FILE_TYPE.FOLDER,
940                         children:       []
941                 },
942                 FILE_DATA_MY_PICTURES_ROOT = {
943                         name:           'My Pictures',
944                         type:           pettanr.file.FILE_TYPE.FOLDER,
945                         children:       []
946                 },
947                 FILE_DATA_AUTHOR_ROOT = {
948                         name:           'Authors',
949                         type:           pettanr.file.FILE_TYPE.FOLDER,
950                         children:       []
951                 },
952                 FILE_DATA_ARTIST_ROOT = {
953                         name:           'Artists',
954                         type:           pettanr.file.FILE_TYPE.FOLDER,
955                         children:       []
956                 },
957                 FILE_DATA_LICENSE_ROOT = {
958                         name:           'Original Licenses',
959                         type:           pettanr.file.FILE_TYPE.FOLDER,
960                         children:       []
961                 },
962                 FILE_DATA_BALLOON_ROOT = {
963                         name:           'Balloon templetes',
964                         type:           pettanr.file.FILE_TYPE.FOLDER,
965                         children:       []
966                 },
967                 AUTHOR_ARRAY = [],
968                 ARTIST_ARRAY = [],
969                 PANEL_ARRAY = [],
970                 COMIC_ARRAY = [],
971                 RESOURCE_PICTURE_ARRAY = [],
972                 BALLOON_TEMPLETE_ARRAY = [],
973                 ORIGINAL_LICENSE_ARRAY = [],
974                 BASIC_LICENSES = 'cc_by,cc_nc,cc_nd,cc_sa,keep_aspect_ratio,no_convert,no_flip,no_resize'.split( ',');
975         FILE_DATA_SERVICE_ROOT.children.push( FILE_DATA_COMIC_ROOT, FILE_DATA_PICTURE_ROOT, FILE_DATA_LICENSE_ROOT, FILE_DATA_BALLOON_ROOT);
976         FILE_DATA_COMIC_ROOT.children.push( FILE_DATA_MY_COMICS_ROOT, FILE_DATA_AUTHOR_ROOT);
977         FILE_DATA_PICTURE_ROOT.children.push( FILE_DATA_MY_PICTURES_ROOT, FILE_DATA_ARTIST_ROOT);
978         
979         FileAPI.createFolderUnderRoot( FILE_DATA_SERVICE_ROOT);
980         
981         function onLoadJson( _file, _json){
982                 var _access = FileAPI.getFileDataAccess( _file),
983                         _data = _access !== null ? _access.DATA : null,
984                         l = _json.length;
985                 if( _data === null){
986                         onErrorJson( _file);
987                         return;
988                 }
989                 _data.state = pettanr.file.FILE_STATE.OK;
990                 if( l === 0) return;
991                 for(var i=0; i<l; ++i){
992                         buildFileData( _json[ i], _data);
993                 }
994                 _access.dispatchFileEvent( FileAPI.createFileEvent( pettanr.file.FILE_EVENT.GET_SEQENTIAL_FILES, _file, 'children', null));
995         }
996         function onErrorJson( _file){ 
997                 var _data = FileAPI.getFileData( _file);
998                 if( _data !== null){
999                         _data.state = pettanr.file.FILE_STATE.ERROR;
1000                 }
1001         }
1002         function buildFileData( _data, _parent){
1003                 var _type, _array,
1004                         _id = _data.id,
1005                         i, l;
1006                 if( _parent === FILE_DATA_COMIC_ROOT){
1007                         _data.type = pettanr.driver.FILE_TYPE.PANEL;
1008                         _array = PANEL_ARRAY;
1009                 } else
1010                 if( _parent === FILE_DATA_PICTURE_ROOT){
1011                         _data.type = pettanr.driver.FILE_TYPE.PICTURE;
1012                         _array = RESOURCE_PICTURE_ARRAY;
1013                         
1014                         // original_license を含まなければ、license object を削除して ビットデータ で保持
1015                         // original_license なら ファイルを作る buildFileData( _license, FILE_DATA_LICENSE_ROOT)
1016                         var _license = _data.license,
1017                                 _Math_pow = Math.pow,
1018                                 _bits = 0;
1019                         if( typeof _license === 'object'){
1020                                 for( i=0, l=BASIC_LICENSES.length; i<l; ++i){
1021                                         if( typeof _license[ BASIC_LICENSES[ i]] === 'number'){
1022                                                 _bits += _Math_pow( 2, i);
1023                                         }
1024                                 }
1025                                 _data.license = _bits;
1026                         }
1027                 } else
1028                 if( _parent === FILE_DATA_LICENSE_ROOT){
1029                         _data.type = pettanr.driver.FILE_TYPE.LICENSE;
1030                         _array = ORIGINAL_LICENSE_ARRAY;
1031                 }
1032                 
1033                 _data.driver = Driver;
1034                 
1035                 // _array に _data を格納 または 上書き
1036                 if( typeof _id === 'number'){
1037                         var __data = _array[ _id];
1038                         if( __data){
1039                                 for( var key in _data){
1040                                         __data[ key ] = _data[ key ];
1041                                 }
1042                                 _data = __data; // このタイミングで参照が切れるので注意!!
1043                         } else {
1044                                 _array[ _id] = _data;
1045                         }
1046                 }
1047                 
1048                 if( _parent === FILE_DATA_COMIC_ROOT){
1049                         if( _data.comic && _data.author){
1050                                 var _comic = getFolderData( _data, 'comic', FILE_DATA_COMIC_ROOT),
1051                                         _comics = getFolderData( _data, 'author', FILE_DATA_AUTHOR_ROOT).children;
1052                                 _comic.children.push( _data);
1053                                 pettanr.util.getIndex( _comics, _comic) === -1 && _comics.push( _comic);
1054                         }
1055                         // picture data をファイルに取り出し
1056                         var _elements = _data.panel_elements || [],
1057                                 _elm;
1058                         for(var i=0, l=_elements.length; i<l; ++i){
1059                                 _elm = _elements[ i];
1060                                 if( _elm.resource_picture){
1061                                         _elm.resource_picture = buildFileData( _elm.resource_picture, FILE_DATA_PICTURE_ROOT); // 上記参照切れに備えてここで上書き
1062                                 }
1063                                 if( _elm.resource_picture_id && RESOURCE_PICTURE_ARRAY[ _elm.resource_picture_id]){
1064                                         _elm.resource_picture = RESOURCE_PICTURE_ARRAY[ _elm.resource_picture_id];
1065                                 }
1066                         }
1067                 } else
1068                 if( _parent === FILE_DATA_PICTURE_ROOT){
1069                         _data.artist && getFolderData( _data, 'artist', FILE_DATA_ARTIST_ROOT).children.push( _data);
1070                 }
1071                 
1072                 return _data;
1073         }
1074         /**
1075          * folder には Artist, Author, Comic, 
1076          */
1077         function getFolderData( _data, _key, _parentData){
1078                 if( typeof _data[ _key ] !== 'object') return {children:[]};
1079                 var _ret,
1080                         _id = _data[ _key ].id,
1081                         _array;
1082                 if( typeof _id !== 'number') return {children:[]};
1083                 
1084                 _array =        _parentData === FILE_DATA_ARTIST_ROOT ? ARTIST_ARRAY :
1085                                         _parentData === FILE_DATA_AUTHOR_ROOT ? AUTHOR_ARRAY :
1086                                         _parentData === FILE_DATA_COMIC_ROOT ? COMIC_ARRAY : []
1087
1088                 if( typeof _array[ _id] === 'object'){
1089                         var __data = _array[ _id];
1090                         for( var i in _data[ _key ]){
1091                                 __data[ i ] = _data[ _key ][ i ];
1092                         }
1093                         return _data[ _key ] = __data;// このタイミングで参照が切れるので注意!!
1094                 }
1095                 
1096                 _ret = _array[ _id ] = _data[ _key ];
1097                 if( _ret.title){
1098                         _ret.name = _ret.title;
1099                         delete _ret.title;
1100                 }
1101                 _ret.children = [];
1102                 _ret.driver = Driver;
1103                 
1104                 if( _parentData === FILE_DATA_AUTHOR_ROOT){
1105                         _ret.type = pettanr.driver.FILE_TYPE.AUTHOR;
1106                         _id === MyAuthorID && FILE_DATA_MY_COMICS_ROOT.children.push( _ret);
1107                 } else
1108                 if( _parentData === FILE_DATA_ARTIST_ROOT){
1109                         _ret.type = pettanr.driver.FILE_TYPE.ARTIST;
1110                         _id === MyArtistID && FILE_DATA_MY_PICTURES_ROOT.children.push( _ret);
1111                 } else
1112                 if( _parentData === FILE_DATA_COMIC_ROOT){
1113                         _ret.type = pettanr.driver.FILE_TYPE.COMIC;
1114                         return _ret;
1115                 } else {
1116                         _ret.type = pettanr.file.FILE_TYPE.FOLDER;
1117                 }
1118                 
1119                 _parentData.children.push( _ret);
1120                 
1121                 return _ret;
1122         }
1123
1124         return {
1125                 createComicTree: function(){
1126                         return pettanr.file.createTree( FILE_DATA_SERVICE_ROOT); //FILE_DATA_COMIC_ROOT);
1127                 },
1128                 createPictureTree: function(){
1129                         return pettanr.file.createTree( FILE_DATA_PICTURE_ROOT);
1130                 },
1131                 createServiceTree: function(){
1132                         return pettanr.file.createTree( FILE_DATA_SERVICE_ROOT);
1133                 },
1134                 isPettanrFile: function( _file){
1135                         
1136                 },
1137                 FILE_TYPE: {
1138                         COMIC:                          FileAPI.createFileTypeID(),
1139                         PANEL:                          FileAPI.createFileTypeID(),
1140                         PICTURE:                        FileAPI.createFileTypeID(),
1141                         PANEL_PICTURE:          FileAPI.createFileTypeID(),
1142                         BALLOON:                        FileAPI.createFileTypeID(),
1143                         AUTHOR:                         FileAPI.createFileTypeID(),
1144                         ARTIST:                         FileAPI.createFileTypeID(),
1145                         LICENSE:                        FileAPI.createFileTypeID()
1146                 }
1147         }
1148 })();
1149
1150
1151 pettanr.gallery = ( function(){
1152         var finder,
1153                 elmContainer = document.getElementById( 'gallery'),
1154                 option;
1155                 
1156         return {
1157                 init: function( _option){
1158                         option = _option;
1159                         delete pettanr.gallery.init;
1160                 },
1161                 firstOpen: function(){
1162                         finder = pettanr.finder.createFinder( elmContainer, pettanr.driver.createPictureTree());
1163                         delete pettanr.gallery.firstOpen;
1164                 },
1165                 onOpen: function(){
1166                         pettanr.gallery.firstOpen !== undefined && pettanr.gallery.firstOpen();
1167                         finder.onOpen();
1168                         
1169                 },
1170                 onClose: function(){
1171                         finder.onClose();
1172                 },
1173                 onWindowResize: function( _w, _h){
1174                         finder.onWindowResize( _w, _h);
1175                 }
1176         }
1177 })();
1178
1179 pettanr.cabinet = ( function(){
1180         var finder,
1181                 elmContainer = document.getElementById( 'cabinet'),
1182                 option;
1183                 
1184         return {
1185                 init: function( _option){
1186                         option = _option;
1187                         delete pettanr.cabinet.init;
1188                 },
1189                 firstOpen: function(){
1190                         finder = pettanr.finder.createFinder( elmContainer, pettanr.driver.createComicTree());
1191                         delete pettanr.cabinet.firstOpen;
1192                 },
1193                 onOpen: function(){
1194                         pettanr.cabinet.firstOpen !== undefined && pettanr.cabinet.firstOpen();
1195                         finder.onOpen();
1196                         
1197                 },
1198                 onClose: function(){
1199                         finder.onClose();
1200                 },
1201                 onWindowResize: function( _w, _h){
1202                         finder.onWindowResize( _w, _h);
1203                 }
1204         }
1205 })();
1206
1207 // i18n
1208 // login
1209 // lib
1210
1211 pettanr.fn( pettanr.view);
1212 pettanr.fn( pettanr.overlay);
1213 pettanr.fn( pettanr.key);
1214 pettanr.fn( pettanr.balloon);
1215 pettanr.fn( pettanr.editor);
1216 pettanr.fn( pettanr.file);
1217 pettanr.fn( pettanr.finder);
1218 pettanr.fn( pettanr.gallery);
1219 pettanr.fn( pettanr.cabinet);
1220
1221 $(window).ready( pettanr.init);