21 * http://pettanr.sourceforge.jp/test/type.html
\r
24 isObject : function(v) {
\r
25 return v !== null && typeof v === 'object';
\r
27 isFunction : function(v) {
\r
28 return typeof v === 'function';
\r
30 isArray : function(v) {
\r
31 return Object.prototype.toString.call(v) === "[object Array]";
\r
33 isBoolean : function(v) {
\r
34 return typeof v === 'boolean';
\r
36 isString : function(v) {
\r
37 return typeof v === 'string';
\r
39 isNumber : function(v) {
\r
40 return typeof v === 'number';
\r
42 isFinite : function(v){
\r
43 return Type.isNumber(v) === true && isFinite(v);
\r
45 isHTMLElement : function(v){
\r
46 if( 'HTMLElement' in window ){
\r
47 Type.isHTMLElement = function(v){
\r
48 return v instanceof HTMLElement;
\r
51 Type.isHTMLElement = function(v) {
\r
52 if( Type.isObject(v) === false ){
\r
56 if(v && v.nodeType === 1){
\r
58 r = v.cloneNode(false);
\r
62 if(r === v) return false;
\r
65 return r.nodeType === 1;
\r
72 return Type.isHTMLElement(v);
\r
75 isElementCollection : function(v) {
\r
76 return (Object.prototype.toString.call(v) === "[object HTMLCollection]");
\r
79 isNull : function(v) {
\r
82 isUndefined : function(v) {
\r
83 return typeof v === 'undefined';
\r
87 /* ----------------------------------------------------
\r
90 * extend( baseInstance, extend)
\r
91 * cleanCommnetNode()
\r
93 * getElementSize( _elm)
\r
96 * getGrobalObjectName()
\r
99 var Util = ( function(){
\r
100 var doc = window.document,
\r
101 body = doc.getElementsByTagName( 'body' )[ 0 ];
\r
103 var ELM_SIZE_GETTER = ( function(){
\r
104 var ret = doc.createElement( 'DIV' );
\r
105 body.appendChild( ret );
\r
107 ret.id = 'elmSizeGetter';
\r
108 ret.style.cssText = 'position:absolute;left:0;top:-9999px;visibility:hidden';
\r
110 body.removeChild( ret );
\r
113 CLEAN_TARGET_ELEMENT = 'script,style,object,applet,embed,iframe,frame,base,bgsound,frameset,listing'.split( ',' );
\r
115 /* clean comment node */
\r
116 cleanCommnetNode();
\r
118 /* clean noscript */
\r
120 var nodeNoscript = doc.getElementsByTagName( 'noscript' ),
\r
122 for( var i=0; i<nodeNoscript.length; ++i ){
\r
123 noscript = nodeNoscript[i];
\r
124 noscript.parentNode && noscript.parentNode.removeChild( noscript );
\r
128 function cleanCommnetNode( _targetElm ){
\r
129 search( _targetElm || body );
\r
131 function search( _elm ){
\r
132 if( !_elm ) return;
\r
133 if( _elm.nodeType === 8 ){
\r
134 _elm.parentNode.removeChild( _elm );
\r
137 var i, l, _children = _elm.childNodes, _array = [];
\r
138 if( _children && typeof _children.length === 'number' ){
\r
139 // liveNode > array
\r
140 for( i=0, l=_children.length; i<l; ++i ){
\r
141 _array.push( _children[ i ] );
\r
143 while( _array.length !== 0 ){
\r
144 search( _array.shift() );
\r
151 extend: function( baseInstance, extend ){
\r
152 for( var key in extend ){
\r
153 if( Type.isUndefined( baseInstance[ key ] ) === true ){
\r
154 baseInstance[ key ] = extend[ key ];
\r
156 if( typeof baseInstance[ key ] === typeof extend[ key ] ){
\r
157 baseInstance[ key ] = extend[ key ];
\r
159 alert( 'extend error' );
\r
162 return baseInstance;
\r
164 cleanCommnetNode: cleanCommnetNode,
\r
165 cleanElement: function( _targetElm ){
\r
166 var _nodes, _elm, _array, j, m;
\r
167 for( var i=0, l=CLEAN_TARGET_ELEMENT.length; i<l; ++i){
\r
168 _nodes = _targetElm.getElementsByTagName( CLEAN_TARGET_ELEMENT[ i]);
\r
170 for( j=0, m = _nodes.length; j<m; ++j){
\r
171 _array.push( _nodes[ j]);
\r
173 for( j=0, m = _array.length; j<m; ++j){
\r
175 _elm.parentNode && _elm.parentNode.removeChild( _elm);
\r
178 cleanCommnetNode( _targetElm );
\r
179 if( UA.isIE === false ) return;
\r
180 _nodes = _targetElm.all || _targetElm.getElementsByName( '*' );
\r
181 for( i=0, l = _nodes.length; i<l; ++i){
\r
182 _elm = _nodes[ i ];
\r
183 _elm.style.filter = '';
\r
184 _elm.style.behavior = '';
\r
187 getElementSize: function( _elm ){
\r
188 if( Type.isHTMLElement( _elm ) === false ){
\r
194 var parentElm = _elm.parentNode,
\r
195 prevElm = _elm.previousSibling,
\r
196 nextElm = _elm.nextSibling,
\r
197 displayNone = _elm.style.display === 'none';
\r
198 if( displayNone === true ) _elm.style.display = 'block';
\r
200 body.appendChild( ELM_SIZE_GETTER );
\r
201 ELM_SIZE_GETTER.appendChild( _elm );
\r
204 width: _elm.offsetWidth,
\r
205 height: _elm.offsetHeight
\r
207 if( displayNone === true ) _elm.style.display = 'none';
\r
209 parentElm.insertBefore( _elm, nextElm );
\r
211 if( prevElm && prevElm.nextSibling ){
\r
212 parentElm.insertBefore( _elm, prevElm.nextSibling );
\r
214 parentElm && parentElm.appendChild( _elm );
\r
216 body.removeChild( ELM_SIZE_GETTER );
\r
220 getImageSize: function( img ){
\r
221 var parentElm = img.parentNode,
\r
222 prevElm = img.previousSibling,
\r
223 nextElm = img.nextSibling,
\r
224 displayNone = img.style.display === 'none';
\r
225 if( displayNone === true ) img.style.display = '';
\r
227 body.appendChild( ELM_SIZE_GETTER );
\r
228 ELM_SIZE_GETTER.appendChild( img );
\r
230 var size = getActualDimension( img );
\r
232 if( displayNone === true ) img.style.display = 'none';
\r
234 parentElm.insertBefore( img, nextElm );
\r
236 if( prevElm && prevElm.nextSibling ){
\r
237 parentElm.insertBefore( img, prevElm.nextSibling );
\r
239 parentElm && parentElm.appendChild( img );
\r
241 body.removeChild( ELM_SIZE_GETTER );
\r
244 * AUTHOR: uupaa.js@gmail.com
\r
246 function getActualDimension(image) {
\r
247 var run, mem, w, h, key = "actual";
\r
249 // for Firefox, Safari, Google Chrome
\r
250 if( "naturalWidth" in image ){
\r
252 width: image.naturalWidth,
\r
253 height: image.naturalHeight
\r
257 if( "src" in image ){ // HTMLImageElement
\r
258 if (image[key] && image[key].src === image.src) {
\r
261 if( doc.uniqueID ){ // for IE
\r
262 run = image.runtimeStyle;
\r
263 mem = { w: run.width, h: run.height }; // keep runtimeStyle
\r
264 run.width = "auto"; // override
\r
265 run.height = "auto";
\r
268 run.width = mem.w; // restore
\r
269 run.height = mem.h;
\r
270 } else { // for Opera and Other
\r
271 mem = { w: image.width, h: image.height }; // keep current style
\r
272 image.removeAttribute("width");
\r
273 image.removeAttribute("height");
\r
276 image.width = mem.w; // restore
\r
277 image.height = mem.h;
\r
279 return image[key] = { width: w, height: h, src: image.src }; // bond
\r
281 // HTMLCanvasElement
\r
282 return { width: image.width, height: image.height };
\r
287 getAbsolutePath: function( path) {
\r
288 var e = document.createElement("div");
\r
289 e.innerHTML = '<a href=\"' + path + '\" />';
\r
290 return e.firstChild.href;
\r
292 getAbsolutePosition: function( _elm ){
\r
293 // Find the destination's position
\r
294 // need html, body { fontfamily: "MS PGothic", "MS Gothic" } for ie6.
\r
295 var destx = _elm.offsetLeft,
\r
296 desty = _elm.offsetTop,
\r
298 body = document.body;
\r
299 while( thisNode.offsetParent && thisNode !== body ){
\r
300 thisNode = thisNode.offsetParent;
\r
301 destx += thisNode.offsetLeft;
\r
302 desty += thisNode.offsetTop;
\r
309 pullHtmlAsTemplete: function( html ){
\r
310 var elm = document.createElement( 'div' );
\r
311 elm.innerHTML = html;
\r
312 return elm.firstChild;
\r
314 getElementsByClassName: function( _elm, _className, opt_tagName){
\r
315 var _all = !opt_tagName || opt_tagName === '*',
\r
316 _nodes = _all === true ? ( _elm.all || _elm.getElementsByTagName( '*')) : _elm.getElementsByTagName( opt_tagName),
\r
317 _node, _classes, ret = [];
\r
318 for( var i=0, l = _nodes.length; i<l; ++i){
\r
319 _node = _nodes[ i];
\r
320 _node.nodeType === 1 && this.hasClassName( _node, _className) === true && ret.push( _node);
\r
324 getChildIndex: function( _parent, _child ){
\r
325 var _children = _parent.getElementsByTagName( _child.tagName ),
\r
326 l = _children.length;
\r
327 for(var i=0; i<l; ++i){
\r
328 if( _children[ i] === _child) return i;
\r
332 hasClassName: function( _elm, _className){
\r
333 var _classes = ( _elm.className || '').split( ' ');
\r
334 for( var i=0, l=_classes.length; i<l; ++i){
\r
335 if( _classes[ i] === _className) return true;
\r
339 removeAllChildren: function ( _elm){
\r
340 while( _elm.firstChild){
\r
341 remove( _elm.firstChild);
\r
343 function remove( _node){
\r
344 while( _node.firstChild){
\r
345 remove( _node.firstChild);
\r
347 _node.parentNode && _node.parentNode.removeChild( _node);
\r
350 getIndex: function( _array, _element){
\r
351 if( Array.prototype.indexof ){
\r
352 Util.getIndex = function( _array, _element){
\r
353 return _array.indexof( _element);
\r
356 Util.getIndex = function( _array, _element){
\r
357 for( var i=0, l = _array.length; i<l; ++i){
\r
358 if( _array[ i] === _element) return i;
\r
363 return Util.getIndex( _array, _element);
\r
365 copyArray: function( _array ){
\r
366 var ret = new Array( l );
\r
367 for( var i=0, l = _array.length; i<l; ++i ){
\r
368 ret[ i ] = _array[ i ];
\r
375 createGlobalFunction: function( _func ){
\r
376 var randomKey = null;
\r
378 randomKey = '_glovalFunction_' + ( '' + Math.random()).replace( /\./,'');
\r
379 if( eval( 'typeof '+randomKey) === 'undefined') {
\r
383 window[ randomKey ] = _func;
\r
386 createGlobalFunc: function( func){
\r
387 var randomKey = null;
\r
389 randomKey = 'hogeGlovalFunc_'+(''+Math.random()).replace(/\./,'');
\r
390 if(eval('typeof '+randomKey) == 'undefined') {
\r
394 eval(randomKey+'='+((typeof func=='string') ? func : func.toString()));
\r
397 createGlobalVar: function( obj){
\r
398 var randomKey = null;
\r
400 randomKey = 'hogeGlovalVar_'+(''+Math.random()).replace(/\./,'');
\r
401 if(eval('typeof '+randomKey+'') == 'undefined') {
\r
405 var globalObj = eval(randomKey+'={}');
\r
406 globalObj.value = obj;
\r
409 createGlobalUniqueName: function(){
\r
410 var randomKey = null;
\r
412 randomKey = '_uniqueName'+(''+Math.random()).replace(/\./,'');
\r
413 if( typeof window[randomKey] === 'undefined'){
\r
419 createIframe: function( id, callback){
\r
421 var el = document.createElement( ua.isIE ? '<iframe name="' + id + '" frameborder="0" scrolling="no">' : 'iframe');
\r
424 el.onreadystatechange = detect;
\r
426 // iron(chrome) の場合、append の前に onload を指定しないと onload が呼ばれない
\r
427 el.onload = onLoad;
\r
428 //setTimeout( asynkCallback, 0 );
\r
431 document.body.appendChild( el);
\r
432 el.id = el.name = id;
\r
433 el.setAttribute( 'name', id);
\r
434 el.style.cssText = 'width:1px;height:1px;visibility:hidden;position:absolute;top:1px;left:1px;';
\r
435 // http://d.hatena.ne.jp/onozaty/20070830/p1
\r
436 // [JavaScript]IE6ではJavaScriptで動的に作成したiframeに対してsubmitできない(IE7は未確認) ->解決
\r
437 el.contentWindow.name = id;
\r
442 if ( this.readyState === "complete" ){
\r
443 this.onreadystatechange = new Function();
\r
444 this.onreadystatechange = null;
\r
445 setTimeout( asynkCallback, 0 );
\r
450 setTimeout( asynkCallback, 0 );
\r
452 function asynkCallback(){
\r
466 var UA = ( function(){
\r
467 var ua = (function(){
\r
471 var dua = n.userAgent;
\r
472 var dav = n.appVersion;
\r
473 var tv = parseFloat(dav);
\r
474 acme.isOpera = (dua.indexOf("Opera") >= 0) ? tv: undefined;
\r
475 acme.isKhtml = (dav.indexOf("Konqueror") >= 0) ? tv : undefined;
\r
476 acme.isWebKit = parseFloat(dua.split("WebKit\/")[1]) || undefined;
\r
477 acme.isChrome = parseFloat(dua.split("Chrome\/")[1]) || undefined;
\r
478 acme.isGecko = (dua.indexOf("Gecko\/") >= 0) ? parseFloat(dua.split("rv:")[1].replace( /^(\d*\.\d*)\.(\d*)/, '$1$2' )) : undefined;
\r
479 var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0);
\r
480 if(index && !acme.isChrome){
\r
481 acme.isSafari = parseFloat(dav.split("Version/")[1]);
\r
482 if(!acme.isSafari || parseFloat(dav.substr(index + 7)) <= 419.3){
\r
486 if(document.all && !acme.isOpera){
\r
487 acme.isIE = parseFloat(dav.split("MSIE ")[1]) || undefined;
\r
492 isIE = navigator.userAgent.toLowerCase().indexOf( 'msie') !== -1,
\r
493 ieVersion = isIE === true ? parseInt( navigator.appVersion.toLowerCase().replace( /.*msie[ ]/, '').match( /^[0-9]+/)) : 0,
\r
494 ieRenderingVersion = ieVersion === 8 ? document.documentMode : ieVersion,
\r
495 isStanderdMode = document.compatMode === 'CSS1Compat',
\r
496 ActiveX = ( function(){
\r
497 if( isIE === false || ieVersion > 8 ) return false;
\r
498 var b = document.body,
\r
499 c = b.className || '',
\r
501 ret = undefined, //pettanr.URL_PARAMS.ActiveX,
\r
502 ns = 'pettanr-ActiveX-',
\r
503 enabled = 'enabled',
\r
504 disabled = 'disabled';
\r
505 if( ret !== true && ret !== false){
\r
506 if( Util.hasClassName( b, ns + enabled) === true ) return true;
\r
507 if( Util.hasClassName( b, ns + disabled) === true ) return false;
\r
508 x = document.createElement( 'div' );
\r
510 x.style.cssText = 'width:1px;height:1px;line-height:1px;filter:progid:DXImageTransform.Microsoft.Shadow()';
\r
511 ret = x.offsetHeight > 1;
\r
514 b.className += [ c !== '' ? ' ' : c, ns, ret === true ? enabled : disabled ].join( '');
\r
517 VML = ( function(){
\r
518 if( ActiveX === false || isIE === false || ieVersion > 8) return false;
\r
519 var globalObjectName = Util.createGlobalUniqueName(),
\r
522 document.write( [ '<!--[if gte vml 1]><script id="', id, '">window', '.', globalObjectName, '=1;<\/script><![endif]-->'].join( ''));
\r
523 if( window[globalObjectName] === 1){
\r
524 script = document.getElementById( id);
\r
525 script.parentNode.removeChild( script);
\r
526 window[globalObjectName] = null;
\r
531 isStandAloneMode = ( function(){
\r
532 if( isIE === false) return false;
\r
533 if( VML === true) return false;
\r
534 var globalObjectName = Util.createGlobalUniqueName(),
\r
536 id = 'detectStandAlone';
\r
537 document.write( [ '<!--[if IE ', Math.floor( ieVersion ), ']><script id="', id, '">window', '.', globalObjectName, '=1;<\/script><![endif]-->'].join( ''));
\r
538 if( window[globalObjectName] === 1){
\r
539 script = document.getElementById( id);
\r
540 script.parentNode.removeChild( script);
\r
541 window[globalObjectName] = null;
\r
551 WEBKIT: ua.isWebKit,
\r
552 CHROME: ua.isChrome,
\r
554 ieVersion: ieVersion,
\r
555 ieRenderingVersion: ieRenderingVersion,
\r
556 isStanderdMode: isStanderdMode,
\r
559 STANDALONE: isStandAloneMode,
\r
560 VENDER_PREFIX: ( function() {
\r
561 var ua = navigator.userAgent.toLowerCase();
\r
562 if ( ua.indexOf('opera') !== -1 ){
\r
564 } else if ( ua.indexOf('msie') !== -1 ){
\r
566 } else if ( ua.indexOf('webkit') !== -1 ){
\r
568 } else if ( navigator.product === 'Gecko' ){
\r
573 startVML: function(){
\r
574 delete UA.startVML;
\r
575 if( UA.VML !== true) return false;
\r
576 if (!document.namespaces["v"]) {
\r
577 document.namespaces.add("v", "urn:schemas-microsoft-com:vml", "#default#VML");
\r
579 document.createStyleSheet().cssText = "v\:shape,v\:image{behavior:url(#default#VML);display:block;};";
\r
586 /* ----------------------------------------------------
\r
591 ( function( window, undefined ){
\r
593 var doc = window.document;
\r
594 var body = doc.getElementsByTagName( 'body' )[ 0 ]; //( doc.compatMode || '' ) !== 'CSS1Compat' ? doc.body : doc.documentElement;//
\r
596 var SERVICE_LIST = [];
\r
597 var SUPER_USER_KEY = { getUID: function(){ return 0; }};
\r
598 var API_USER_LIST = [ SUPER_USER_KEY ];
\r
599 var numApiUser = 1;
\r
601 function isApiUser( _user ){
\r
602 if( _user === SUPER_USER_KEY ) return true;
\r
603 if( File.isDriver( _user ) === true ) return true;
\r
604 if( Application.isApplicationInstance( _user ) === true ) return true;
\r
628 _____: parseInt( '00000', 2 ),
\r
629 ____C: parseInt( '00001', 2 ), // hasCreateMenu
\r
630 ___W_: parseInt( '00010', 2 ), // isWritable
\r
631 ___WC: parseInt( '00011', 2 ), // isWritable
\r
632 __R__: parseInt( '00100', 2 ), // isRenamable
\r
633 __R_C: parseInt( '00101', 2 ), // hasCreateMenu
\r
634 __RW_: parseInt( '00110', 2 ), // isWritable
\r
635 __RWC: parseInt( '00111', 2 ), // isWritable
\r
636 _S___: parseInt( '01000', 2 ), // childrenIsSortable
\r
637 _S__C: parseInt( '01001', 2 ),
\r
638 _S_W_: parseInt( '01010', 2 ),
\r
639 _S_WC: parseInt( '01011', 2 ),
\r
640 _SR__: parseInt( '01100', 2 ),
\r
641 _SR_C: parseInt( '01101', 2 ),
\r
642 _SRW_: parseInt( '01110', 2 ),
\r
643 _SRWC: parseInt( '01111', 2 ),
\r
644 D____: parseInt( '10000', 2 ),
\r
645 D___C: parseInt( '10001', 2 ), // hasCreateMenu
\r
646 D__W_: parseInt( '10010', 2 ), // isWritable
\r
647 D__WC: parseInt( '10011', 2 ), // isWritable
\r
648 D_R__: parseInt( '10100', 2 ), // isRenamable
\r
649 D_R_C: parseInt( '10101', 2 ), // hasCreateMenu
\r
650 D_RW_: parseInt( '10110', 2 ), // isWritable
\r
651 D_RWC: parseInt( '10111', 2 ), // isWritable
\r
652 DS___: parseInt( '11000', 2 ), // childrenIsSortable
\r
653 DS__C: parseInt( '11001', 2 ),
\r
654 DS_W_: parseInt( '11010', 2 ),
\r
655 DS_WC: parseInt( '11011', 2 ),
\r
656 DSR__: parseInt( '11100', 2 ),
\r
657 DSR_C: parseInt( '11101', 2 ),
\r
658 DSRW_: parseInt( '11110', 2 ),
\r
659 DSRWC: parseInt( '11111', 2 ),
\r
667 UPDATE_ATTRIVUTE: 'onFileUpdate',
\r
668 GET_SEQENTIAL_FILES:'gotSeqentilFiles'
\r
670 DATA_PROPERTY_RESERVED: [
\r
671 'children', 'driver', 'state', 'type'
\r
676 UPDATE: 'onTreeUpdate'
\r
681 KEY_DOWN: 'keydown',
\r
683 KEY_CHANGE: 'keychange',
\r
696 var EX = ( function(){
\r
697 var F = new Function();
\r
699 function clone( src ) {
\r
701 if( Type.isArray(src) === true ){
\r
704 if( Type.isObject(src) === true ){
\r
707 if( Type.isNumber(src) === true || Type.isString(src) === true || Type.isBoolean( src ) === true ){
\r
712 for( var key in src ){
\r
713 ret[ key ] = clone( src[ key ]);
\r
719 extend: function( base, extend ){
\r
720 F.prototype = base;
\r
722 for( var p in extend ){
\r
723 ret[ p ] = extend[ p ];
\r
727 clone: function( obj ){
\r
728 return clone( obj );
\r
731 var self = this, v;
\r
733 if( self.hasOwnProperty && !self.hasOwnProperty( p ) ) continue;
\r
735 v && v instanceof TicketBase && self.kill();
\r
742 var TicketBase = function(){
\r
743 this.kill = function(){
\r
746 if( t.hasOwnProperty && !t.hasOwnProperty( p ) ) continue;
\r
748 v && v instanceof TicketBase && v.kill();
\r
756 /* --------------------------------------------------------------
\r
761 var SystemTimer = ( function(){
\r
762 var setTimeout = window.setTimeout;
\r
763 var clearTimeout = window.clearTimeout;
\r
764 var INTERVAL_TIME = 16;
\r
765 var TICKET_LIST = [];
\r
766 var timerId = undefined;
\r
770 for( var i = 0; i < TICKET_LIST.length; ) {
\r
771 if( TICKET_LIST[ i ].call( next ) !== false ) ++i;
\r
773 timerId = undefined;
\r
777 var l = TICKET_LIST.length,
\r
781 timerId !== undefined && clearTimeout( timerId );
\r
782 timerId = undefined;
\r
785 for( var i = 0; i<l; i++ ){
\r
786 c = TICKET_LIST[ i ].count;
\r
789 if( next > n || timerId === undefined ){
\r
790 timerId !== undefined && clearTimeout( timerId );
\r
791 timerId = setTimeout( loop, INTERVAL_TIME * n );
\r
796 var TimerTicketClass = function( _apiuser, _callback, _time, _once ){
\r
797 this.apiuser = _apiuser;
\r
798 this.callback = _callback;
\r
800 this.count = _time;
\r
802 _apiuser = _callback = null;
\r
804 TimerTicketClass.prototype = new TicketBase();
\r
805 TimerTicketClass.prototype.call = function( c ){
\r
807 if( this.count <= 0 ){
\r
809 if( this.once === true ){
\r
811 TICKET_LIST.splice( Util.getIndex( TICKET_LIST, this ), 1 );
\r
814 this.count = this.time;
\r
818 TimerTicketClass.prototype.destroy = function( _apiuser, _callback ){
\r
819 if( _apiuser && _apiuser !== this.apiuser ) return false;
\r
820 if( _callback && _callback !== this.callback ) return false;
\r
827 add: function( _apiuser, _handler, _time, _once ){
\r
828 if( Type.isNumber( _time ) === false || _time < INTERVAL_TIME ) _time = INTERVAL_TIME;
\r
830 var _ticket = new TimerTicketClass( _apiuser, _handler, Math.ceil( _time / INTERVAL_TIME ), _once );
\r
831 TICKET_LIST.push( _ticket );
\r
835 remove: function( _apiuser, _handler ) {
\r
838 while( _ticket = TICKET_LIST[ i ] ){
\r
839 if( _ticket.destroy( _apiuser, _handler ) === true ){
\r
840 TICKET_LIST.splice( i, 1 );
\r
850 /* --------------------------------------------------------------
\r
854 var AsyncCall = ( function(){
\r
855 var CALLBACK_LIST = [];
\r
857 var CallbackTicketClass = function( _apiuser, _callback, _argments ){
\r
858 this.apiuser = _apiuser;
\r
859 this.callback = _callback;
\r
860 this.argments = _argments;
\r
861 _apiuser = _callback = _argments = null;
\r
863 CallbackTicketClass.prototype = new TicketBase();
\r
864 CallbackTicketClass.prototype.call = function(){
\r
865 var f = this.callback,
\r
867 if( Type.isArray( a ) === true ){
\r
868 f.apply( this.apiuser, a );
\r
873 CallbackTicketClass.prototype.destroy = function( _apiuser, _callback ){
\r
874 if( _apiuser && _apiuser !== this.apiuser ) return false;
\r
875 if( _callback && _callback !== this.callback ) return false;
\r
881 function dispatch(){
\r
882 var _ticket = CALLBACK_LIST.shift();
\r
886 CALLBACK_LIST.length !== 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true );
\r
891 add: function( _apiuser, _callback, _argments ){
\r
892 CALLBACK_LIST.length === 0 && SystemTimer.add( SUPER_USER_KEY, dispatch, 1, true );
\r
893 CALLBACK_LIST.push( new CallbackTicketClass( _apiuser, _callback, _argments ) );
\r
895 remove: function( _apiuser, _callback ){
\r
898 while( _ticket = CALLBACK_LIST[ i ] ){
\r
899 if( _ticket.destroy( _apiuser, _callback ) === true ){
\r
900 CALLBACK_LIST.splice( i, 1 );
\r
909 /* -----------------------------------------------------------
\r
911 * お気に入り画像一覧 > tag:ペン次郎 > ペン次郎:笑う
\r
912 * 最近アップロードされた画像 > images
\r
913 * 最近使われた画像 > images
\r
914 * キャラクター画像庫 > アニマル系 > tag:ペン次郎 > ペン次郎:笑う
\r
921 var File = ( function(){
\r
922 var DRIVER_LIST = [];
\r
924 var FILE_TYPE_IS_FOLDER = Const.FILE.TYPE.FOLDER,
\r
925 numFileType = Const.FILE.TYPE.XML,
\r
926 FILEDATA_RESITER = [], // store all of fileData( json object )
\r
927 FILEDATA_ACCESS = [], // file operations for Kernel only ! hide from Out of File
\r
928 FILE_OBJECT_POOL = [],
\r
929 EVENT_LISTENER_REGISTER = [],
\r
931 TREE_ACCESS_ARRAY = [];
\r
933 var REQUEST_CONTROLER = ( function(){
\r
934 var REQUEST_TICKET_RESISTER = [],
\r
935 currentTicket = null,
\r
936 currentData = null,
\r
937 DATA_TYPE_ARRAY = 'json,xml,html,text'.split( ','),
\r
944 var RequestTicketClass = function( _apiuser, _type, _data, _url, _onLoad, _onError ){
\r
945 this.apiuser = _apiuser;
\r
949 this.onLoad = _onLoad;
\r
950 this.onError = _onError;
\r
952 _apiuser = _type = _data = _onLoad = _onError = null;
\r
954 RequestTicketClass.prototype = new TicketBase();
\r
955 RequestTicketClass.prototype.load = function( _data ){
\r
956 AsyncCall.add( this.apiuser, this.onLoad, [ this.data, _data ] );
\r
958 RequestTicketClass.prototype.error = function(){
\r
959 AsyncCall.add( this.apiuser, this.onError, this.data );
\r
962 function request(){
\r
963 if( currentTicket !== null || REQUEST_TICKET_RESISTER.length === 0 ) return;
\r
964 currentTicket = REQUEST_TICKET_RESISTER.shift();
\r
966 url: currentTicket.url,
\r
967 dataType: DATA_TYPE_ARRAY[ currentTicket.type ],
\r
968 success: onSuccess,
\r
972 function onSuccess( _data ){
\r
973 currentTicket.load( _data );
\r
974 currentTicket.kill();
\r
975 currentTicket = null;
\r
978 function onError(){
\r
980 currentTicket.error();
\r
981 currentTicket.kill(); // retry
\r
982 currentTicket = null;
\r
987 getNumTask: function(){
\r
988 return REQUEST_TICKET_RESISTER.length;
\r
990 getNumError: function(){
\r
993 getJson: function( _apiuser, _data, _url, _onLoad, _onError ){
\r
994 REQUEST_TICKET_RESISTER.push( new RequestTicketClass( _apiuser, DATA_IS_JSON, _data, _url, _onLoad, _onError ));
\r
995 currentTicket === null && request();
\r
1000 var FILE_CONTROLER = {
\r
1001 createTree: function( _apiuser, _rootFileData ){
\r
1002 var _tree = new TreeClass( _apiuser, _rootFileData );
\r
1003 TREE_ARRAY.push( _tree );
\r
1006 getFileUID: function( FILEDATAorFILE ){
\r
1007 if( FILEDATAorFILE instanceof FileClass ){
\r
1008 return FILEDATAorFILE.getUID();
\r
1011 var uid = Util.getIndex( FILEDATA_RESITER, FILEDATAorFILE );
\r
1013 uid = FILEDATA_RESITER.length;
\r
1014 FILEDATA_RESITER.push( FILEDATAorFILE );
\r
1018 getFileDataAccess: function( UIDorFILEorFILEDATA ){
\r
1019 var _uid, _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA ), _access;
\r
1021 if( _data === null || typeof _data !== 'object' ) return null;
\r
1022 for( var i=0, l = FILEDATA_ACCESS.length; i<l; ++i ){
\r
1023 _access = FILEDATA_ACCESS[ i ];
\r
1024 if( _access.DATA === _data ) return _access;
\r
1028 getFileData: function( UIDorFILEorFILEDATA ){
\r
1029 if( typeof UIDorFILEorFILEDATA === 'number' ){
\r
1030 return FILEDATA_RESITER[ UIDorFILEorFILEDATA ] || null;
\r
1032 if( UIDorFILEorFILEDATA instanceof FileClass ){
\r
1033 return FILEDATA_RESITER[ UIDorFILEorFILEDATA.getUID() ] || null;
\r
1035 if( Util.getIndex( FILEDATA_RESITER, UIDorFILEorFILEDATA ) !== -1 ){
\r
1036 return UIDorFILEorFILEDATA;
\r
1040 getChildren: function( UIDorFILEorFILEDATA ){
\r
1041 var _data = FILE_CONTROLER.getFileData( UIDorFILEorFILEDATA );
\r
1042 return _data !== null ? _data.children || null : null;
\r
1044 getDriver: function( _file ){
\r
1045 var _data = FILE_CONTROLER.getFileData( _file );
\r
1046 return _data !== null && _data.driver ? _data.driver : BASE_DRIVER;
\r
1048 getUpdateFlag: function( _file, _bit ){
\r
1049 var _driver = FILE_CONTROLER.getDriver( _file ),
\r
1051 if( typeof _driver.getUpdatePolicy === 'function' ){
\r
1052 _policy = _driver.getUpdatePolicy( _file );
\r
1055 if( typeof _policy !== 'number' ) {
\r
1056 _policy = BASE_DRIVER.getUpdatePolicy( _file )
\r
1058 return _policy % ( _bit * 2 ) >= _bit;
\r
1060 move: function( _prentUID, _targetfile, _newFolder, _newIndex, _opt_callback ){
\r
1061 var _parentData = FILE_CONTROLER.getFileDataAccess( _prentUID ),
\r
1062 _parentType = _parentData.TYPE,
\r
1063 _targetData = FILE_CONTROLER.getFileDataAccess( _targetfile ),
\r
1064 _targetType = _targetData.TYPE;
\r
1066 replace: function( _uid, _file, _newIndex ){
\r
1069 addEventListener: function( FILEorNULL, _eventType, _callback ){
\r
1070 var _uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL;
\r
1071 EVENT_LISTENER_REGISTER.push( new FileEventTicketClass( _uid, _eventType, _callback ));
\r
1073 removeEventListener: function( FILEorNULL, _eventType, _callback ){
\r
1074 var _uid = FILEorNULL instanceof FileClass ? FILEorNULL.getUID() : FILEorNULL,
\r
1076 for(var i=0, l = EVENT_LISTENER_REGISTER.length; i<l; ++i ){
\r
1077 _ticket = EVENT_LISTENER_REGISTER[ i ];
\r
1078 if( _ticket.fileUID === _uid && _ticket.eventType === _eventType && _ticket.callBack === _callback ){
\r
1079 EVENT_LISTENER_REGISTER.splice( i, 1 );
\r
1084 getTreeAccess: function(){
\r
1087 fileEventRellay: function( _uid, _event ){
\r
1088 var _fileAccess = FILE_CONTROLER.getFileDataAccess( _uid );
\r
1089 if( _fileAccess === null ) return;
\r
1090 var _treeUID = _fileAccess.TREE.getUID(),
\r
1091 _treeAccess = TREE_ACCESS_ARRAY[ _treeUID ],
\r
1092 _data = _fileAccess.DATA,
\r
1094 if( !_treeAccess ) return;
\r
1095 _treeAccess.dispatchFileEvent( _event );
\r
1096 for( var i=0, l = TREE_ARRAY.length; i<l; ++i ){
\r
1097 if( i !== _treeUID ){
\r
1098 _tree = TREE_ARRAY[ i ];
\r
1099 if( FILE_CONTROLER.getFileData( _tree.getCurrentFile() ) === _data ){
\r
1100 _treeAccess = TREE_ACCESS_ARRAY[ _tree.getUID() ];
\r
1101 _treeAccess && _treeAccess.dispatchFileEvent( _event );
\r
1108 var TreeClass = function( apiuser, rootFileData ){
\r
1109 var PARENT_FILE_RESITER = [],
\r
1111 apiuser : apiuser,
\r
1112 dispatchFileEvent: dispatchFileEvent
\r
1114 EVENT_LISTENER_ARRAY = [],
\r
1116 rootFile = new FileClass( instance, null, rootFileData ),
\r
1117 currentFile = rootFile;
\r
1119 currentFile.getSeqentialFiles();
\r
1120 TREE_ACCESS_ARRAY.push( ACCESS );
\r
1122 function dispatchFileEvent( e ){
\r
1123 var _eventType = e.eventType,
\r
1124 _targetFile = e.targetFile,
\r
1125 _uid = _targetFile.getUID(),
\r
1126 _ticket, _type, _callback;
\r
1127 for( var i=0, l = EVENT_LISTENER_REGISTER.length; i<l; ++i ){
\r
1128 _ticket = EVENT_LISTENER_REGISTER[ i ];
\r
1129 _type = _ticket.eventType;
\r
1130 _callback = _ticket.callBack;
\r
1131 if( _eventType === _type && _uid === _ticket.fileUID ){
\r
1132 AsyncCall.add( apiuser, _callback, [ _eventType, _targetFile, e.key, e.value ] );
\r
1134 if( _type === Const.TREE.EVENT.UPDATE && _eventType === Const.FILE.EVENT.GET_SEQENTIAL_FILES ){
\r
1135 //_callback( _eventType, _targetFile );
\r
1136 AsyncCall.add( apiuser, _callback, [ _eventType, _targetFile ] );
\r
1141 this.getUID = function(){
\r
1142 return Util.getIndex( TREE_ACCESS_ARRAY, ACCESS );
\r
1144 this.getRootFile = function(){
\r
1147 this.getCurrentFile = function(){
\r
1148 return currentFile;
\r
1150 this.hierarchy = function(){
\r
1151 return PARENT_FILE_RESITER.length;
\r
1153 this.getParentFileAt = function( _index ){
\r
1154 var l = PARENT_FILE_RESITER.length;
\r
1155 if( typeof _index !== 'number' || _index < 0 || _index >= l ) return null;
\r
1156 return PARENT_FILE_RESITER[ l -1 -_index ];
\r
1158 this.down = function( _index ){
\r
1159 if( typeof _index !== 'number' || _index < 0 || _index >= currentFile.getChildFileLength()) return;
\r
1160 PARENT_FILE_RESITER.unshift( currentFile );
\r
1161 currentFile = currentFile.getChildFileByIndex( _index );
\r
1162 currentFile.getSeqentialFiles();
\r
1163 return currentFile;
\r
1165 this.up = function( _index ){
\r
1166 var l = PARENT_FILE_RESITER.length;
\r
1167 if( l === 0) return null;
\r
1169 if( currentFile ){
\r
1170 var _currentFile = currentFile;
\r
1171 currentFile = null;
\r
1172 _currentFile.destroy();
\r
1174 if( typeof _index === 'number'){
\r
1175 if( _index >= l) return null;
\r
1176 currentFile = this.getParentFileAt( _index );
\r
1177 PARENT_FILE_RESITER.splice( 0, l -_index);
\r
1179 currentFile = PARENT_FILE_RESITER.shift();
\r
1181 currentFile.getSeqentialFiles();
\r
1182 return currentFile;
\r
1184 this.addTreeEventListener = function( _eventType, _callback ){
\r
1185 FILE_CONTROLER.addEventListener( null, _eventType, _callback );
\r
1187 this.removeTreeEventListener = function( _eventType, _callback ){
\r
1188 FILE_CONTROLER.removeEventListener( null, _eventType, _callback );
\r
1190 this.destroy = function( _apiuser ){
\r
1191 if( _apiuser && apiuser !== _apiuser ) return false;
\r
1193 var _currentFile = currentFile;
\r
1194 currentFile = rootFile = rootFileData = null;
\r
1195 // currentFile, rootFile を null にしないと .File.destroy() ができない.
\r
1196 _currentFile.destroy();
\r
1197 while( PARENT_FILE_RESITER.length > 0 ){
\r
1198 _currentFile = PARENT_FILE_RESITER.shift();
\r
1199 _currentFile.destroy();
\r
1202 AsyncCall.remove( apiuser );
\r
1203 instance = apiuser = null;
\r
1208 var FileEventTicketClass = function( _uid, _eventType, _callback ){
\r
1209 this.fileUID = _uid;
\r
1210 this.eventType = _eventType;
\r
1211 this.callBack = _callback;
\r
1212 _uid = _eventType = _callback = undefined;
\r
1214 FileEventTicketClass.prototype = new TicketBase();
\r
1216 var FileEventClass = function( eventType, file, key, value ){
\r
1217 this.eventType = eventType;
\r
1218 this.targetFile = file;
\r
1219 this.updatedAttribute = key;
\r
1220 this.updatedValue = value;
\r
1224 * file の data は object で保持している。
\r
1225 * File の外からファイルをみるときは、FileClassを通して操作する。
\r
1226 * fileの変更、それに付随して追加されたイベントは、TreeClassで管理される。
\r
1227 * treeがdestryされると、fileのイベントリスナーも全て削除される。
\r
1228 * 他の tree も data の共通する currentFile に対してのみは、file の変更イベントを受け取って流す.
\r
1232 var FileClass = function( tree, parentData, data ){
\r
1233 var uid = FILE_CONTROLER.getFileUID( data );
\r
1235 FILEDATA_ACCESS.push( {
\r
1237 parentData: parentData,
\r
1241 tree = parentData = data = null;
\r
1243 this.getUID = function(){
\r
1248 FileClass.prototype = {
\r
1249 isChildFile: function( _FILEorFILEDATA ){
\r
1250 return this.getChildFileIndex( _FILEorFILEDATA) !== -1;
\r
1252 getSeqentialFiles: function(){
\r
1253 var _driver = FILE_CONTROLER.getDriver( this );
\r
1254 if( _driver !== null && typeof _driver.getSeqentialFiles === 'function' ){
\r
1255 _driver.getSeqentialFiles( this );
\r
1258 addEventListener: function( _eventType, _callback ){
\r
1259 FILE_CONTROLER.addEventListener( this, _eventType, _callback );
\r
1261 removeEventListener: function( _eventType, _callback ){
\r
1262 FILE_CONTROLER.removeEventListener( this, _eventType, _callback );
\r
1264 dispatchEvent: function( e ){
\r
1265 e instanceof FileEventClass && FILE_CONTROLER.fileEventRellay( this.getUID(), e );
\r
1267 getChildFileLength: function(){
\r
1268 var children = FILE_CONTROLER.getChildren( this );
\r
1269 return Type.isArray( children ) === true ? children.length : -1;
\r
1271 getChildFileIndex: function( _FILEorFILEDATA ){
\r
1272 var children = FILE_CONTROLER.getChildren( this );
\r
1273 if( Type.isArray( children ) === false ) return -1;
\r
1274 var l = children.length,
\r
1275 _fileData = FILE_CONTROLER.getFileData( _FILEorFILEDATA );
\r
1276 if( _fileData === null ) return -1;
\r
1277 for( var i=0; i<l; ++i ){
\r
1278 if( children[ i ] === _fileData ) return i;
\r
1282 getChildFileByIndex: function( _index ){
\r
1283 var _access = FILE_CONTROLER.getFileDataAccess( this ),
\r
1284 _children = FILE_CONTROLER.getChildren( this );
\r
1285 if( typeof _index !== 'number' || _index < 0 || Type.isArray( _children ) === false || _index >= _children.length) return null;
\r
1286 var _file = new FileClass( _access.TREE, _access.DATA, _children[ _index ]);
\r
1290 getName: function(){
\r
1291 var driver = FILE_CONTROLER.getDriver( this );
\r
1292 if( typeof driver.getName === 'function'){
\r
1293 return driver.getName( this );
\r
1295 return BASE_DRIVER.getName( this);
\r
1297 getThumbnail: function(){
\r
1298 var driver = FILE_CONTROLER.getDriver( this );
\r
1299 if( typeof driver.getThumbnail === 'function'){
\r
1300 return driver.getThumbnail( this );
\r
1302 return BASE_DRIVER.getThumbnail( this );
\r
1304 getType: function(){
\r
1305 var _data = FILE_CONTROLER.getFileData( this );
\r
1306 return typeof _data.type === 'number' ? _data.type : Const.FILE.TYPE.UNKNOWN;
\r
1308 getState: function(){
\r
1309 var _data = FILE_CONTROLER.getFileData( this );
\r
1310 return typeof _data.state === 'number' ? _data.state : Const.FILE.STATE.OK;
\r
1312 getSummary: function(){
\r
1313 var driver = FILE_CONTROLER.getDriver( this );
\r
1314 if( typeof driver.getSummary === 'function'){
\r
1315 return driver.getSummary( this );
\r
1317 return BASE_DRIVER.getSummary( this );
\r
1319 isWritable: function(){
\r
1320 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.WRITE );
\r
1322 isSortable: function(){
\r
1323 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.SORT );
\r
1325 isCreatable: function(){
\r
1326 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.CREATE );
\r
1328 isRenamable: function(){
\r
1329 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.RENAME );
\r
1331 isDeletable: function(){
\r
1332 return FILE_CONTROLER.getUpdateFlag( this, Const.FILE.UPDATE_POLICY.DELETE );
\r
1336 var driver = FILE_CONTROLER.getDriver( this ),
\r
1338 if( typeof driver.read === 'function'){
\r
1339 data = driver.read( this );
\r
1341 return BASE_DRIVER.read( data || this );
\r
1343 write: function( _newData, _onUpdateFunction ){
\r
1344 var driver = FILE_CONTROLER.getDriver( this );
\r
1345 if( typeof driver.write === 'function'){
\r
1346 return driver.write( this, _newData, _onUpdateFunction );
\r
1348 return BASE_DRIVER.write( this, _newData, _onUpdateFunction );
\r
1350 viewerApplicationList: function(){
\r
1351 var driver = FILE_CONTROLER.getDriver( this );
\r
1352 if( typeof driver.viewerApplicationList === 'function'){
\r
1353 return driver.viewerApplicationList( this );
\r
1355 return BASE_DRIVER.viewerApplicationList( this );
\r
1357 editorApplicationList: function(){
\r
1358 var driver = FILE_CONTROLER.getDriver( this );
\r
1359 if( typeof driver.editorApplicationList === 'function'){
\r
1360 return driver.editorApplicationList( this );
\r
1362 return BASE_DRIVER.viwerApps( this );
\r
1364 create: function(){
\r
1370 onCopy: function(){
\r
1373 onDelete: function(){
\r
1376 move: function( _newFolder, _newIndex, opt_callback ){
\r
1377 var _access = FILE_CONTROLER.getFileDataAccess( this );
\r
1378 _access.TREE.move( _access.parentData, this.getUID(), _newFolder, _newIndex, opt_callback );
\r
1380 replace: function( _newIndex, opt_callback ){
\r
1381 var _access = FILE_CONTROLER.getFileDataAccess( this );
\r
1382 _access.TREE.replace( _access.parentData, this.getUID(), _newIndex, opt_callback);
\r
1386 * 探しているファイルの属性と値を指定.一致する child の index を配列で返す.
\r
1388 search: function( obj, rule ){
\r
1389 var _children = FILE_CONTROLER.getChildren( this ),
\r
1392 for( var i=0, l=_children.length; i<l; ++i ){
\r
1393 _child = _children[ i ];
\r
1396 if( obj[ k ] !== _child[ k ] ){
\r
1401 c === true && ret.push( i );
\r
1405 destroy: function(){
\r
1406 var _access = FILE_CONTROLER.getFileDataAccess( this );
\r
1407 var _tree = _access.TREE;
\r
1408 if( _tree.getCurrentFile() === this ) return;
\r
1409 if( _tree.getRootFile() === this ) return;
\r
1410 for( var i=0, l = _tree.hierarchy(); i<l; ++i ){
\r
1411 if( _tree.getParentFileAt( i ) === this ){
\r
1415 var _index = Util.getIndex( FILEDATA_ACCESS, _access );
\r
1416 if( _index === -1 ) return;
\r
1418 FILEDATA_ACCESS.splice( _index, 1 );
\r
1419 delete _access.DATA;
\r
1420 delete _access.TREE;
\r
1421 delete _access.parentData;
\r
1428 var FileDriverBase = function( driverClass ){
\r
1429 this.getUID = function(){
\r
1430 return Util.getIndex( API_USER_LIST, driverClass );
\r
1432 this.getSeqentialFiles = function( _file ){
\r
1434 this.getName = function( _file ){
\r
1435 var _data = FILE_CONTROLER.getFileData( _file );
\r
1436 return _data.name || 'No Name';
\r
1438 this.getThumbnail = function( _file ){
\r
1439 var _data = FILE_CONTROLER.getFileData( _file ),
\r
1440 _type = _data.type,
\r
1442 if( _type === Const.FILE.TYPE.FOLDER){
\r
1443 _className = 'folder';
\r
1445 if( _type === Const.FILE.TYPE.IMAGE){
\r
1448 if( _type === Const.FILE.TYPE.TEXT){
\r
1451 if( _type === Const.FILE.TYPE.HTML){
\r
1454 if( _type === Const.FILE.TYPE.CSV){
\r
1457 if( _type === Const.FILE.TYPE.JSON){
\r
1460 if( _type === Const.FILE.TYPE.XML){
\r
1465 className: ' file-type-' + _className
\r
1468 this.getSummary = function( _file ){
\r
1469 var _data = FILE_CONTROLER.getFileData( _file ),
\r
1470 _type = _data.type;
\r
1471 if( _type === Const.FILE.TYPE.FOLDER ){
\r
1474 if( _type === Const.FILE.TYPE.IMAGE ){
\r
1475 return 'image file';
\r
1477 if( _type === Const.FILE.TYPE.TEXT ){
\r
1478 return 'text file';
\r
1480 if( _type === Const.FILE.TYPE.HTML ){
\r
1481 return 'html document file';
\r
1483 if( _type === Const.FILE.TYPE.CSV ){
\r
1484 return 'csv daat file';
\r
1486 if( _type === Const.FILE.TYPE.JSON ){
\r
1487 return 'json data file';
\r
1489 if( _type === Const.FILE.TYPE.XML ){
\r
1490 return 'xml data file';
\r
1494 this.getUpdatePolicy = function( _file ){
\r
1495 // debug用 全てのメニューを許可
\r
1496 return Const.FILE.UPDATE_POLICY.DSRWC;
\r
1498 this.read = function( _FILEorDATA ){
\r
1500 protects = Const.FILE.DATA_PROPERTY_RESERVED;
\r
1501 if( _FILEorDATA instanceof FileClass ){
\r
1502 data = FILE_CONTROLER.getFileData( _FILEorDATA )
\r
1504 data = _FILEorDATA;
\r
1507 function clone( src ) {
\r
1509 if( Type.isArray(src) === true ){
\r
1512 if( Type.isObject(src) === true ){
\r
1515 if( Type.isNumber(src) === true || Type.isString(src) === true || Type.isBoolean( src ) === true ){
\r
1520 for( var key in src ){
\r
1521 if( Util.getIndex( protects, key ) === -1 ){
\r
1523 ret[ key ] = clone( src[ key ]);
\r
1529 return clone( data );
\r
1531 this.write = function( _file, _newData, _onUpdateFunction ){
\r
1532 var _data = FILE_CONTROLER.getFileData( _file ),
\r
1533 _type = _data.type;
\r
1536 this.viewerApplicationList = function(){
\r
1539 this.editorApplicationList = function(){
\r
1542 this.onCreate = function(){
\r
1545 this.onSort = function(){
\r
1548 this.onCopy = function(){
\r
1551 this.onDelete = function(){
\r
1556 var BASE_DRIVER = new FileDriverBase();
\r
1558 var ROOT_FILEDATA = {
\r
1559 name: 'system root',
\r
1560 type: FILE_TYPE_IS_FOLDER,
\r
1563 SYSTEM_TREE = FILE_CONTROLER.createTree( SUPER_USER_KEY, ROOT_FILEDATA ),
\r
1564 ROOT_FILE = SYSTEM_TREE.getRootFile();
\r
1566 function createFileTypeID(){
\r
1567 return ++numFileType;
\r
1570 var FileAPIClass = function( driver ){
\r
1572 this.createFolderUnderRoot = function( _fileData ){
\r
1573 if( _fileData !== null && Type.isObject( _fileData ) === true ){
\r
1574 ROOT_FILEDATA.children.push( _fileData );
\r
1575 ROOT_FILE.dispatchEvent( new FileEventClass( Const.FILE.EVENT.GET_SEQENTIAL_FILES, ROOT_FILE, 'children', null ));
\r
1578 this.createFileEvent = function( _eventType, _file, _key, _value ){
\r
1579 return new FileEventClass( _eventType, _file, _key, _value );
\r
1581 this.createFileTypeID = createFileTypeID;
\r
1582 this.getFileDataAccess = FILE_CONTROLER.getFileDataAccess;
\r
1583 this.getFileData = FILE_CONTROLER.getFileData;
\r
1584 this.getJson = function( _data, _url, _onLoad, _onError ){
\r
1585 REQUEST_CONTROLER.getJson( driver, _data, _url, _onLoad, _onError );
\r
1587 this.createTree = function( _rootFile ){
\r
1588 return FILE_CONTROLER.createTree( driver, _rootFile );
\r
1590 this.isTreeInstance = function( _tree ){
\r
1591 return _tree instanceof TreeClass;
\r
1593 this.isFileInstance = function( _file ){
\r
1594 return _file instanceof FileClass;
\r
1596 this.isFileEvent = function( _event ){
\r
1597 return _event instanceof FileEventClass;
\r
1599 this.getConst = function(){
\r
1600 return Const; // constObject = constObject || clone( Const )
\r
1605 registerDriver: function( _class ){
\r
1606 _class.prototype = new FileDriverBase( _class );
\r
1607 var _driver = new _class();
\r
1609 DRIVER_LIST.push( _driver );
\r
1610 API_USER_LIST.push( _class );
\r
1612 return new FileAPIClass( _driver );
\r
1614 isDriver: function( _driver ){
\r
1615 return _driver instanceof FileDriverBase;
\r
1617 isTreeInstance: function( _tree ){
\r
1618 return _tree instanceof TreeClass;
\r
1620 isFileInstance: function( _file ){
\r
1621 return _file instanceof FileClass;
\r
1627 /* ----------------------------------------------------
\r
1628 * ApplicationManager
\r
1629 * window resize event, overlayApplication currentAplication に流す
\r
1632 var APPLICATION_LIST = [];
\r
1634 var AbstractBasicPane = function(){
\r
1635 var instance = null;
\r
1636 this.MIN_WIDTH = 240;
\r
1637 this.MIN_HEIGHT = 240;
\r
1638 this.init = function(){
\r
1640 instance.onInit();
\r
1642 this.onInit = function(){};
\r
1643 this.resize = function( _w, _h ){
\r
1644 if( instance.MIN_WIDTH > _w || instance.MIN_HEIGHT > _h ){
\r
1645 if( Type.isHTMLElement( instance.rootElement ) === true ){
\r
1650 instance.onPaneResize( _w, _h );
\r
1652 this.onPaneResize = function( _w, _h ){};
\r
1653 this.close = function(){
\r
1654 instance.onClose();
\r
1659 var AbstractApplication = function( displayName, appClass, isOverlay ){
\r
1660 var self = null, // init で設定
\r
1663 fetchResource = 0,
\r
1664 bootParams = null,
\r
1666 this.rootElement = document.createElement( 'div' );
\r
1667 this.bgColor = '#C1CACF';
\r
1668 this.getUID = function(){
\r
1669 return Util.getIndex( API_USER_LIST, appClass );
\r
1671 this.init = function(){
\r
1677 this.open = function( _w, _h /*, _option */ ){
\r
1679 bootParams = Util.copyArray( arguments );
\r
1681 if( this.rootElement.innerHTML && this.rootElement.innerHTML.length > 0 ){
\r
1682 SystemTimer.add( self, detect, 16 );
\r
1687 function detect(){
\r
1688 if( self.rootElement.firstChild && fetchResource === 0 ){
\r
1689 SystemTimer.remove( self, detect );
\r
1694 function onOpen(){
\r
1695 if( self.MIN_WIDTH > _w || self.MIN_HEIGHT > _h ){
\r
1696 if( Type.isHTMLElement( self.rootElement ) === true ){
\r
1700 if( bootParams.length > 2 ){
\r
1701 self.onOpen.apply( self, bootParams );
\r
1703 self.onOpen( _w, _h );
\r
1708 this.resize = function( _w, _h ){
\r
1709 if( phase !== 4 ) return;
\r
1710 if( self.MIN_WIDTH > _w || self.MIN_HEIGHT > _h ){
\r
1711 if( Type.isHTMLElement( self.rootElement ) === true ){
\r
1716 self.onPaneResize( _w, _h );
\r
1718 this.close = function(){
\r
1720 if( self.onClose() === false ){
\r
1723 MouseEvent.remove( self );
\r
1724 KeyEvent.remove( self );
\r
1725 SystemTimer.remove( self );
\r
1726 AsyncCall.remove( self );
\r
1727 Css.unload( self );
\r
1729 while( uiList.length > 0 ){
\r
1730 uiList.shift().destroy();
\r
1732 while( finderList.length > 0 ){
\r
1733 finderList.shift().destroy();
\r
1735 var elm = self.rootElement;
\r
1736 Util.removeAllChildren( elm );
\r
1737 elm.parentNode.removeChild( elm );
\r
1738 self.rootElement = null;
\r
1740 Application.shutdown( self, isOverlay );
\r
1741 self = appClass = uiList = null;
\r
1745 this.createUIGroup = function(){
\r
1746 var _ui = UI.createUIGroup( self );
\r
1747 uiList.push( _ui );
\r
1750 this.createFinder = function( _elmTarget, _tree, _header, _footer, _onSelect, _viewerOption, _editorOption ){
\r
1751 var _finder = Finder.create( self, _elmTarget, _tree, _header, _footer, _onSelect, _viewerOption, _editorOption );
\r
1752 finderList.push( _finder );
\r
1755 this.createBasicPane = function( _class, _options ){
\r
1756 if( Type.isFunction( _class ) === false ) return null;
\r
1757 _class.prototype = new AbstractBasicPane();
\r
1758 return new _class( _options );
\r
1760 this.fetchCSS = function( _url, opt_onload, opt_onerror ){
\r
1761 if( phase === 1 ){
\r
1763 Css.load( self, _url, fetchResourceComplete, fetchResourceComplete );
\r
1767 function fetchResourceComplete(){
\r
1772 AbstractApplication.prototype = new AbstractBasicPane();
\r
1773 AbstractApplication.prototype.onInit = function(){
\r
1776 AbstractApplication.prototype.onOpen = function( _w, _h /*, _option */ ){
\r
1779 AbstractApplication.prototype.onClose = function(){
\r
1782 }; // false の場合、close の拒否
\r
1783 AbstractApplication.prototype.addMouseEventListener = function( _element, _eventType, _handler ){
\r
1784 MouseEvent.add( this, _element, _eventType, _handler );
\r
1786 AbstractApplication.prototype.removeMouseEventListener = function( _element, _eventType, _handler ){
\r
1787 MouseEvent.remove( this, _element, _eventType, _handler );
\r
1789 AbstractApplication.prototype.addKeyEventListener = function( _eventType, _handler, _keyCode, _shift, _ctrl ){
\r
1790 KeyEvent.add( this, _eventType, _handler, _keyCode, _shift, _ctrl );
\r
1792 AbstractApplication.prototype.removeKeyEventListener = function( _eventType, _handler, _keyCode, _shift, _ctrl ){
\r
1793 KeyEvent.remove( this, _eventType, _handler, _keyCode, _shift, _ctrl );
\r
1795 AbstractApplication.prototype.shiftEnabled = function(){
\r
1796 return KeyEvent.shiftEnabled;
\r
1798 AbstractApplication.prototype.ctrlEnabled = function(){
\r
1799 return KeyEvent.ctrlEnabled;
\r
1801 AbstractApplication.prototype.addTimer = function( handler, time, once ){
\r
1802 SystemTimer.add( this, handler, time, !!once );
\r
1804 AbstractApplication.prototype.removeTimer = function( handler ){
\r
1805 SystemTimer.remove( this, handler );
\r
1807 AbstractApplication.prototype.addAsyncCall = function( _callback, _argments ){
\r
1808 AsyncCall.add( this, _callback, _argments );
\r
1810 AbstractApplication.prototype.removeAsyncCall = function( _callback ){
\r
1811 AsyncCall.remove( this, _callback );
\r
1813 AbstractApplication.prototype.fetchHTMLElement = function( id ){
\r
1814 var elm = doc.getElementById( id );
\r
1816 elm.removeAttribute( 'id' );
\r
1817 elm.parentNode.removeChild( elm );
\r
1822 var Application = ( function(){
\r
1824 var LIVE_APPLICATION_LIST = [];
\r
1826 var currentApplication = null,
\r
1827 coveredApplication = null,
\r
1831 var ApplicationReference = function( appClass, isOverlay, displayName, id, thumbnailUrl, tailColor ){
\r
1833 var application = null;
\r
1835 this.displayName = displayName;
\r
1836 this.thumbnailUrl = thumbnailUrl;
\r
1837 this.tailColor = tailColor;
\r
1838 this.getUID = function(){
\r
1839 return Util.getIndex( API_USER_LIST, appClass );
\r
1841 this.boot = function( /* _option */ ){
\r
1842 application = Application.boot( displayName, self.getUID(), appClass, isOverlay, Util.copyArray( arguments ) );
\r
1844 this.shutdown = function(){
\r
1845 if( !application ) return false;
\r
1847 if( ( isOverlay === true ? Overlay.hide() : application.close() ) === false ) return false;
\r
1848 application = null;
\r
1852 function asyncBootHome(){
\r
1853 currentApplication === null && Home.boot();
\r
1855 function asyncOpen( /* arguments */ ){
\r
1856 var _arg = Util.copyArray( arguments );
\r
1857 _arg.unshift( winW, winH );
\r
1858 currentApplication.open.apply( currentApplication, _arg );
\r
1861 register: function( _class, _overlay, _tail, _displayName, _id, _thumbnailUrl, _tailColor ){
\r
1862 APPLICATION_LIST.push( _class );
\r
1863 API_USER_LIST.push( _class );
\r
1864 var _ref = new ApplicationReference( _class, _overlay, _displayName, _id, _thumbnailUrl, _tailColor );
\r
1865 _tail === true && Home.add( _ref );
\r
1868 isBasicPaneInstance: function( _basicPane ){
\r
1869 return _basicPane instanceof AbstractBasicPane;
\r
1871 isApplicationInstance: function( _application ){
\r
1872 return _application instanceof AbstractApplication;
\r
1874 isApplicationReference: function( _reference ){
\r
1875 return _reference instanceof ApplicationReference;
\r
1877 isCurrentAppplication: function( _application ){
\r
1880 boot: function( displayName, uid, appClass, isOverlay, arg ){
\r
1881 if( currentApplication ){
\r
1882 if( currentApplication.getUID() === uid ) return null;
\r
1883 if( isOverlay === false && currentApplication.close() === false ) return null;
\r
1886 appClass.prototype = new AbstractApplication( displayName, appClass, isOverlay );
\r
1887 var application = new appClass(); // new は boot で
\r
1889 coveredApplication = isOverlay === true ? currentApplication : null;
\r
1891 Application.onCurrentApplicationChange( application );
\r
1893 if( isOverlay === false ){
\r
1894 body.style.backgroundColor = application.bgColor;
\r
1896 body.appendChild( application.rootElement );
\r
1897 application.init();
\r
1899 application.addAsyncCall( asyncOpen, arg );
\r
1901 Overlay.show( application, arg );
\r
1904 return application;
\r
1906 shutdown: function( _application, isOverlay ){
\r
1907 if( isOverlay === false ){
\r
1908 currentApplication = null;
\r
1909 AsyncCall.add( SUPER_USER_KEY, asyncBootHome );
\r
1911 Application.onCurrentApplicationChange( coveredApplication );
\r
1912 coveredApplication = null;
\r
1915 onCurrentApplicationChange: function( _application ){
\r
1916 if( Application.isApplicationInstance( _application ) === false ) return;
\r
1917 if( currentApplication === _application ) return;
\r
1918 currentApplication = _application;
\r
1919 MouseEvent.onCurrentApplicationChange( _application );
\r
1920 KeyEvent.updateCurrentListener( _application );
\r
1922 onApplicationShutdown: function( _application ){
\r
1923 LIVE_APPLICATION_LIST.splice( Util.getIndex( LIVE_APPLICATION_LIST, _application ) );
\r
1925 onWindowResize: function( w, h ){
\r
1928 currentApplication && currentApplication.resize( w, h );
\r
1929 Overlay.onWindowResize( w, h );
\r
1930 UI.onWindowResize( w, h );
\r
1932 onSystemShutdown: function(){
\r
1938 /* --------------------------------------------------------------
\r
1942 var Home = ( function(){
\r
1943 var APP_REF_LIST = [];
\r
1944 var ELM_TAIL_ORIGIN = ( function(){
\r
1945 var ret = document.createElement( 'div' ),
\r
1946 h2 = document.createElement( 'h2' );
\r
1947 ret.className = 'tail-wrapper';
\r
1948 ret.appendChild( h2 );
\r
1949 h2.appendChild( document.createTextNode( 'appName' ) );
\r
1953 var TailClass = function( appRef ){
\r
1954 this.elm = ELM_TAIL_ORIGIN.cloneNode( true );
\r
1955 this.destroy = function(){
\r
1956 appRef = self = elmName = null;
\r
1960 elmName = this.elm.getElementsByTagName( 'h2' )[ 0 ].firstChild;
\r
1962 this.elm.style.backgroundColor = appRef.tailColor;
\r
1963 elmName.data = appRef.displayName;
\r
1966 var ref = Application.register( function(){
\r
1971 elmContainer, elmHeader;
\r
1975 for( var i=0, l=APP_REF_LIST.length; i<l; ++i ){
\r
1976 tail = new TailClass( APP_REF_LIST[ i ] );
\r
1977 tailList.push( tail );
\r
1979 elmContainer.appendChild( elm );
\r
1980 self.addMouseEventListener( elm, 'click', onTailClick );
\r
1984 function onTailClick( e ){
\r
1985 var _children = elmContainer.getElementsByTagName( 'div' );
\r
1986 for( var i=0, l=_children.length; i<l; ++i ){
\r
1987 if( this === _children[ i ] ){
\r
1988 APP_REF_LIST[ i ].boot();
\r
1994 this.bgColor = '#0F6D39';
\r
1995 this.MIN_WIDTH = 320;
\r
1996 this.MIN_HEIGHT = 320;
\r
1997 this.onInit = function(){
\r
1998 self.rootElement.id = 'home-root';
\r
2000 elmContainer = document.createElement( 'div' );
\r
2001 self.rootElement.appendChild( elmContainer );
\r
2002 elmContainer.id = 'home-tail-container';
\r
2004 elmHeader = document.createElement( 'div' );
\r
2005 self.rootElement.appendChild( elmHeader );
\r
2006 elmHeader.id = 'home-header';
\r
2008 this.onOpen = function( _w, _h ){
\r
2013 this.onPaneResize = function( _w, _h ){
\r
2016 this.onClose = function(){
\r
2017 self.removeMouseEventListener();
\r
2018 while( tailList.length > 0 ){
\r
2019 tailList.shift().destroy();
\r
2021 self = tailList = elmContainer = null;
\r
2023 }, false, false, 'home', 'home', null );
\r
2026 add: function( _appRef ){
\r
2027 if( Application.isApplicationReference( _appRef ) === false ) return;
\r
2028 Util.getIndex( APP_REF_LIST, _appRef ) === -1 && APP_REF_LIST.push( _appRef );
\r
2036 var Page = ( function(){
\r
2037 var pageNodes = [];
\r
2041 var ignoreTagList = [ 'script', 'noscript' ];
\r
2043 var MemoryClass = function( node ){
\r
2044 var _nodeType = node.nodeType;
\r
2045 if( _nodeType === 1 && Util.getIndex( ignoreTagList, node.tagName.toLowerCase() ) === -1 ){
\r
2047 this.type = _nodeType;
\r
2048 this.display = node.style.display;
\r
2050 if( _nodeType === 3 ){
\r
2051 if( node.data.replace( /\s/g, '' ).length !== 0 ){
\r
2053 this.type = _nodeType;
\r
2054 this.before = pageNodes.length === 0 ? null : pageNodes[ pageNodes.length - 1 ].node;
\r
2056 body.removeChild( node );
\r
2059 // body.removeChild( node );
\r
2063 MemoryClass.prototype = {
\r
2065 if( this.type === 1 ){
\r
2066 if( this.display ){
\r
2067 this.node.style.display = this.display;
\r
2069 this.node.style.display = '';
\r
2072 if( this.before ){
\r
2073 body.insertBefore( this.node, this.before );
\r
2075 body.appendChild( this.node );
\r
2080 if( this.type === 1 ){
\r
2081 this.node.style.display = 'none';
\r
2083 body.removeChild( this.node );
\r
2089 onReady: function(){
\r
2090 var _children = Util.copyArray( body.childNodes ),
\r
2092 for( var i = 0, l = _children.length; i<l; ++i ){
\r
2093 _mem = new MemoryClass( _children[ i ] );
\r
2094 _mem.node && pageNodes.push( _mem );
\r
2096 if( pageNodes.length !== 0 ){
\r
2097 ref = Application.register( function(){
\r
2102 elmContainer, elmHeader;
\r
2104 this.bgColor = '#ffffff';
\r
2105 this.MIN_WIDTH = 320;
\r
2106 this.MIN_HEIGHT = 320;
\r
2107 this.onInit = function(){
\r
2108 for( var i=0, l = pageNodes.length; i < l; ++i ){
\r
2109 pageNodes[ i ].show();
\r
2111 KeyEvent.add( self, Const.KEY.EVENT.KEY_DOWN, ref.shutdown, 27 ); // 27.esc
\r
2113 this.onOpen = function( _w, _h ){
\r
2116 this.onPaneResize = function( _w, _h ){
\r
2119 this.onClose = function(){
\r
2120 for( var i=0, l = pageNodes.length; i < l; ++i ){
\r
2121 pageNodes[ i ].hide();
\r
2124 }, false, true, doc.title, 'page', null, '#999999' );
\r
2126 delete Page.onReady;
\r
2129 ref && ref.boot();
\r
2131 registered: function(){
\r
2137 /* --------------------------------------------------------------
\r
2141 * スクリーン座標は、コンピュータのディスプレイの左上を原点とする座標系である。screenX, screenY属性で取得できる。Javascritpでは、同名のプロパティとして実装されている。
\r
2142 * しかし、これは、現実的には、何の役に立たない。ブラウザ自体がディスプレイのどの位置にいるのかがわからないので、画面上の位置を知ったところで、何にもならないからだ。
\r
2145 * ウインドウ座標とは、現在のブラウザのウインドウの、ドキュメントを表示している部分の左上原点とした座標である。
\r
2146 * 問題は、ウインドウは、必ずしもドキュメント全体を表示するとは限らない。スクロールと呼ばれるUIによって、ドキュメントの一部だけを表示しているかもしれない。
2148 var XBrowserEvent = ( function(){
\r
2149 var wrappedHandlerClass,
\r
2150 wrappedEventClass,
\r
2153 if( window.addEventListener ){
\r
2154 wrappedHandlerClass = function( element, handler ){
\r
2155 this.handler = function( e ){
\r
2156 if( handler.call( element, e ) !== false ) return;
\r
2157 e.preventDefault();
\r
2158 e.stopPropagation();
\r
2161 this.destroy = function(){
\r
2162 element = handler = null;
\r
2163 delete this.handler;
\r
2164 delete this.destroy;
\r
2168 wrappedEventClass = function( e, element ){
\r
2170 this.type = e.type;
\r
2171 this.target = e.srcElement;
\r
2172 this.currentTarget = element;
\r
2173 this.relatedTarget = e.formElement ? e.formElement : e.toElement;
\r
2174 this.eventPhase = e.srcElement === element ? 2: 3;
\r
2176 this.clientX = e.clientX;
\r
2177 this.clientY = e.clientY;
\r
2178 this.screenX = e.screenX;
\r
2179 this.screenY = e.screenY;
\r
2181 this.altKey = e.altKey;
\r
2182 this.ctrlKey = e.ctrlKey;
\r
2183 this.shiftKey = e.shiftKey;
\r
2184 this.charCode = e.keyCode;
\r
2186 this.wheelDelta = e.wheelDelta;
\r
2188 e = element = null;
\r
2190 wrappedEventClass.prototype.stopPropagation = function(){
\r
2191 this._event.cancelBubble = true;
\r
2193 wrappedEventClass.prototype.preventDefault = function(){
\r
2194 this._event.returnValue = false;
\r
2197 if( doc.attachEvent ){
\r
2198 wrappedHandlerClass = function( element, handler ){
\r
2199 this.handler = function(){
\r
2200 var e = new wrappedEventClass( window.event, element );
\r
2201 if( handler.call( element, e ) !== false ) return;
\r
2202 e.preventDefault();
\r
2203 e.stopPropagation();
\r
2206 this.destroy = function(){
\r
2207 element = handler = null;
\r
2208 delete this.handler;
\r
2209 delete this.destroy;
\r
2215 find: function( _ticket ){
\r
2216 for( var i=0, l= tmp.list.length, _item; i<l; ++i ){
\r
2217 _item = tmp.list[ i ];
\r
2218 if( _item.match( _ticket.element, _ticket.eventType ) === true ){
\r
2225 tmp.ticketClass = function( _ticket ){
\r
2227 this.element = _ticket.element;
\r
2228 this.eventType = _ticket.eventType;
\r
2229 this.handlers = [ _ticket.handler ];
\r
2230 this.element[ 'on' + this.eventType ] = function( e ){
\r
2231 return self.fire( self, e );
\r
2233 this.clean = function(){
\r
2238 tmp.ticketClass.prototype = {
\r
2239 add: function( _ticket ){
\r
2240 this.match( _ticket.element, _ticket.eventType ) === true &&
\r
2241 this.match( null, null, _ticket.handler ) === false &&
\r
2242 this.handlers.push( _ticket.handler );
\r
2244 remove: function( _ticket ){
\r
2245 if( this.match( _ticket.element, _ticket.eventType, _ticket.handler ) === true ){
\r
2246 var i = Util.getIndex( this.handlers, handler );
\r
2247 i !== 0 && this.handlers.splice( i, 1 );
\r
2248 this.handlers.length === 0 && this.destroy();
\r
2251 fire: function( self, e ){
\r
2252 e = e || new wrappedEventClass( window.event, self.element );
\r
2253 for( var i=self.handlers.length, cancel; i; ){
\r
2254 self.element._currentHandler = self.handlers[ --i ];
\r
2255 if( self.element._currentHandler( e ) === false ) cancel = false;
\r
2256 delete self.element._currentHandler;
\r
2260 match: function( element, eventType, handler ){
\r
2261 if( handler && Util.getIndex( this.handlers, handler ) === -1 ) return false;
\r
2262 if( eventType && this.eventType !== eventType ) return false;
\r
2263 if( element && this.element !== element ) return false;
\r
2266 destroy: function(){
\r
2268 this.element[ 'on' + this.eventType ] = '';
\r
2269 tmp.list.splice( Util.getIndex( tmp.list, this ), 1 );
\r
2270 delete this.element;
\r
2271 delete this.eventType;
\r
2272 delete this.handlers;
\r
2273 delete this.clean;
\r
2280 add: function( _ticket ){
\r
2281 if( doc.addEventListener ){
\r
2282 XBrowserEvent.add = function( _ticket ){
\r
2283 _ticket.wrappedHandler = new wrappedHandlerClass( _ticket.element, _ticket.handler );
\r
2284 _ticket.element.addEventListener( _ticket.eventType, _ticket.wrappedHandler.handler, false );
\r
2287 if( doc.attachEvent ){
\r
2288 XBrowserEvent.add = function( _ticket ){
\r
2289 _ticket.wrappedHandler = new wrappedHandlerClass( _ticket.element, _ticket.handler );
\r
2290 _ticket.element.attachEvent( 'on' + _ticket.eventType, _ticket.wrappedHandler.handler );
\r
2293 XBrowserEvent.add = function( _ticket ){
\r
2294 var t = tmp.find( _ticket );
\r
2298 tmp.list.push( new tmp.ticketClass( _ticket ) );
\r
2303 XBrowserEvent.add( _ticket );
\r
2305 remove: function( _ticket ){
\r
2306 if( doc.removeEventListener ){
\r
2307 XBrowserEvent.remove = function( _ticket ){
\r
2308 _ticket.element.removeEventListener( _ticket.eventType, _ticket.wrappedHandler.handler, false );
\r
2309 _ticket.wrappedHandler.destroy();
\r
2312 if( doc.detachEvent ){
\r
2313 XBrowserEvent.remove = function( _ticket ){
\r
2314 _ticket.element.detachEvent( 'on' + _ticket.eventType, _ticket.wrappedHandler.handler );
\r
2315 _ticket.wrappedHandler.destroy();
\r
2318 XBrowserEvent.remove = function( _ticket ){
\r
2319 var t = tmp.find( _ticket );
\r
2321 t.remove( _ticket );
\r
2326 XBrowserEvent.remove( _ticket );
\r
2332 * EventTicketClass
\r
2334 var EventTicketClass = function( _element, _eventType, _handler ){
\r
2335 this.element = _element;
\r
2336 this.eventType = _eventType;
\r
2337 this.handler = _handler;
\r
2338 this.wrappedHandler = null; // for ie
\r
2340 XBrowserEvent.add( this );
\r
2342 _element = _eventType = _handler = null;
\r
2344 EventTicketClass.prototype = {
\r
2345 match: function( _element, _eventType, _handler ){
\r
2346 if( _handler && _handler !== this.handler ) return false;
\r
2347 if( _eventType && _eventType !== this.eventType ) return false;
\r
2348 if( _element && _element !== this.element ) return false;
\r
2352 destroy: function( _element, _eventType, _handler ){
\r
2353 if( this.match( _element, _eventType, _handler ) === false ) return false;
\r
2355 XBrowserEvent.remove( this );
\r
2357 delete this.element;
\r
2358 delete this.eventType;
\r
2359 delete this.handler;
\r
2360 delete this.wrappedHandler;
\r
2366 var ReadyEvent = ( function(){
\r
2372 function detect(){
\r
2373 var state = document.readyState;
\r
2374 if( state === 'loaded' || state === 'complete' ){
\r
2375 timer && window.clearInterval( timer );
\r
2380 function ieDetect(){
\r
2381 if( this.readyState === 'loaded' || this.readyState === 'complete' ){
\r
2382 this.onreadystatechange = new Function();
\r
2383 this.onreadystatechange = null;
\r
2384 this.parentNode.removeChild( this );
\r
2390 function onReady(){
\r
2392 if( Page.registered() === true ){
\r
2397 ticketReady && ticketReady.destroy();
\r
2398 ticketLoad && ticketLoad.destroy();
\r
2399 ticketReady = ticketLoad = null;
\r
2402 // Apple WebKit (Safari, OmniWeb, ...)
\r
2403 if( doc.readyState && !!UA.WEBKIT ){
\r
2404 timer = window.setInterval( detect, 50 );
\r
2406 if( document.readyState && UA.isIE && UA.ieVersion < 9 ){
\r
2407 document.write('<script type="text/javascript" defer="defer" id="ieDOMContentLoaded" src="' +
\r
2408 ( ( window.location.protocol === 'https:' ) ? '://0' : 'javascript:void(0)' ) +
\r
2410 script = document.getElementById( 'ieDOMContentLoaded' );
\r
2411 script.onreadystatechange = ieDetect;
\r
2413 ticketReady = new EventTicketClass( doc, 'DOMContentLoaded', onReady );
\r
2414 ticketLoad = new EventTicketClass( doc, 'load', onReady );
\r
2421 /* =====================================================
\r
2426 var ResizeEvent = ( function(){
\r
2427 var _globalLock = 0;
\r
2429 var root = window;
\r
2432 function getInnerSize(){
\r
2434 w : root.innerWidth || root.clientWidth,
\r
2435 h : root.innerHeight || root.clientHeight
\r
2438 function unlock(){
\r
2442 if( document.uniqueID ){
\r
2443 _resize = function(){
\r
2444 root = (doc.compatMode || "") !== "CSS1Compat" ? doc.body : doc.documentElement;
\r
2448 if( !_globalLock++ ){
\r
2449 var size = getInnerSize();
\r
2450 if( w !== size.w || h !== size.h ){// resized
\r
2454 Application.onWindowResize( w, h );
\r
2456 window.setTimeout( unlock, 0 );
\r
2459 window.setTimeout( loop, 100 );
\r
2464 _resize = function(){
\r
2465 new EventTicketClass( window, 'resize', onResize );
\r
2467 function onResize(){
\r
2468 if( !_globalLock++ ) {
\r
2469 var size = getInnerSize();
\r
2470 if( w !== size.w || h !== size.h ){// resized
\r
2474 Application.onWindowResize( w, h );
\r
2476 window.setTimeout( unlock, 0 );
\r
2482 AsyncCall.add( SUPER_USER_KEY, _resize );
\r
2485 getSize: getInnerSize,
\r
2486 onSystemShutdown: function(){
\r
2493 /* =====================================================
\r
2497 var MouseEvent = ( function(){
\r
2498 var CLICK_OFFSET = 2 * 2;
\r
2500 var EVENT_LIST_MAP = [],
\r
2505 * mousedown, mouseup, の移動距離を調べて clickハンドラ を呼ぶ
\r
2507 var ClickEventTicketClass = function( element, clickhandler ){
\r
2508 var startX, startY,
\r
2509 mousedownTicket = new EventTicketClass( element, 'mousedown', mousedownHandler ),
\r
2510 mouseupTicket, mouseoutTicket;
\r
2512 function mousedownHandler( e ){
\r
2513 startX = e.clientX;
\r
2514 startY = e.clientY;
\r
2516 mouseupTicket = new EventTicketClass( element, 'mouseup', mouseupHandler );
\r
2517 mouseoutTicket = new EventTicketClass( element, 'mouseout', mouseoutHandler );
\r
2520 function mouseupHandler( e ){
\r
2521 var offsetX = e.clientX - startX,
\r
2522 offsetY = e.clientY - startY;
\r
2523 mouseoutHandler();
\r
2524 if( offsetX * offsetX + offsetY * offsetY < CLICK_OFFSET ){
\r
2525 if( Function.prototype.call ){
\r
2526 return clickhandler.call( element, e );
\r
2528 element._currentHandler = clickhandler;
\r
2529 var ret = element._currentHandler( e );
\r
2530 delete element._currentHandler;
\r
2534 function mouseoutHandler( e ){
\r
2535 mouseupTicket && mouseupTicket.destroy();
\r
2536 mouseoutTicket && mouseoutTicket.destroy();
\r
2537 mouseupTicket = mouseoutTicket = null;
\r
2540 this.element = element;
\r
2541 this.handler = clickhandler;
\r
2542 this.destroy = function( _element, _eventType, _handler ){
\r
2543 if( this.match( _element, _eventType, _handler ) === false ) return false;
\r
2545 mouseoutHandler();
\r
2546 mousedownTicket.destroy();
\r
2547 element = clickhandler = mousedownTicket = null;
\r
2549 delete this.element;
\r
2550 delete this.eventType;
\r
2551 delete this.handler;
\r
2556 ClickEventTicketClass.prototype = {
\r
2557 eventType: 'click',
\r
2558 match : EventTicketClass.prototype.match
\r
2563 var WheelEventTicketClass = ( function(){
\r
2565 return function( element, wheelhandler ){
\r
2566 this.wheelTicket = new EventTicketClass( element, 'DOMMouseScroll', onWheel );
\r
2567 this.element = element;
\r
2568 this.handler = wheelhandler;
\r
2569 this.destroy = function( _element, _eventType, _handler ){
\r
2570 if( this.match( _element, _eventType, _handler ) === false ) return false;
\r
2571 element = wheelhandler = null;
\r
2573 this.wheelTicket && this.wheelTicket.destroy();
\r
2575 delete this.wheelTicket;
\r
2576 delete this.element;
\r
2577 delete this.handler;
\r
2582 function onWheel( e ){
\r
2583 e.wheelDelta = e.detail * -40;
\r
2584 return wheelhandler.call( element, e );
\r
2588 if( true || UA.isIE ){
\r
2589 return function( element, wheelhandler ){
\r
2590 this.wheelTicket = new EventTicketClass( element, 'mousewheel', wheelhandler );
\r
2591 this.element = element;
\r
2592 this.handler = wheelhandler;
\r
2593 element = wheelhandler = null;
\r
2596 TMP.wheelList = [];
\r
2597 //TMP.wheelLegacy = undefined;
\r
2598 TMP.onWheel = function( e ){
\r
2599 e = e || window.event;
\r
2600 var cancel = true,
\r
2601 f = TMP.wheelLegacy;
\r
2602 if( f ) cancel = f.call( this, e );
\r
2604 for( i = TMP.wheelList.length; i; ){
\r
2605 if( TMP.wheelList[ --i ].call( this, e ) === false ) cancel = false;
\r
2609 return function( element, wheelhandler ){
\r
2610 this.wheelTicket = null;
\r
2611 this.element = element;
\r
2612 this.handler = wheelhandler;
\r
2613 this.destroy = function( _element, _eventType, _handler ){
\r
2614 if( this.match( _element, _eventType, _handler ) === false ) return false;
\r
2616 TMP.wheelList.splice( Util.getIndex( TMP.wheelList, this.handler ) );
\r
2617 if( TMP.wheelList.length === 0 ) this.element.onmousewheel = '';
\r
2619 delete this.element;
\r
2620 delete this.handler;
\r
2625 if( TMP.wheelList.length === 0 ){
\r
2626 //TMP.wheelLegacy = Type.isFunction( window.onmousewheel ) === true ? window.onmousewheel : undefined;
\r
2627 element.onmousewheel = TMP.onWheel;
\r
2629 TMP.wheelList.push( wheelhandler );
\r
2630 element = wheelhandler = null;
\r
2634 WheelEventTicketClass.prototype = {
\r
2635 eventType : 'mousewheel',
\r
2636 match : EventTicketClass.prototype.match,
\r
2637 destroy : function( _element, _eventType, _handler ){
\r
2638 if( this.match( _element, _eventType, _handler ) === false ) return false;
\r
2640 this.wheelTicket && this.wheelTicket.destroy();
\r
2642 delete this.wheelTicket;
\r
2643 delete this.element;
\r
2644 delete this.handler;
\r
2652 add: function( _apiuser, _element, _eventType, _handler ){
\r
2653 if( isApiUser( _apiuser ) === true &&
\r
2654 ( Type.isHTMLElement( _element ) === true || _element === window || _element === doc ) &&
\r
2655 Type.isString( _eventType ) === true &&
\r
2656 Type.isFunction( _handler ) === true
\r
2658 var _uid = _apiuser.getUID(),
\r
2659 _events = EVENT_LIST_MAP[ _uid ];
\r
2660 if( Type.isArray( _events ) === false ){
\r
2661 _events = EVENT_LIST_MAP[ _uid ] = [];
\r
2664 for( var i=0, l=_events.length; i<l; ++i ){
\r
2665 if( _events[ i ].match( _element, _eventType, _handler ) === true ) return;
\r
2668 if( _eventType === 'click' ){
\r
2669 _events.push( new ClickEventTicketClass( _element, _handler ) );
\r
2671 if( _eventType === 'mousewheel' ){
\r
2672 _events.push( new WheelEventTicketClass( _element, _handler ) );
\r
2674 _events.push( new EventTicketClass( _element, _eventType, _handler ) );
\r
2678 remove: function( _apiuser, _element, _eventType, _handler ){
\r
2679 if( isApiUser( _apiuser ) === true ){
\r
2680 var _uid = _apiuser.getUID(),
\r
2681 _events = EVENT_LIST_MAP[ _uid ],
\r
2684 if( Type.isArray( _events ) === false ) return;
\r
2685 for( ;i < _events.length; ){
\r
2686 if( _events[ i ].destroy( _element, _eventType, _handler ) === true ){
\r
2687 _events.splice( i, 1 );
\r
2692 if( _events.length === 0 ){
\r
2693 _events = EVENT_LIST_MAP[ _uid ] = null;
\r
2697 onCurrentApplicationChange: function(){
\r
2700 onApplicationShutdown: function(){
\r
2703 onSystemShutdown: function(){
\r
2709 /* ----------------------------------------
\r
2712 * - EDITABLE_TEXT_CONTROL
\r
2714 * .SHIFT_DOWN_EVENT: 'shiftDown',
\r
2715 * .SHIFT_UP_EVENT: 'shiftUp',
\r
2716 * .CTRL_DOWN_EVENT: 'ctrlDown',
\r
2717 * .CTRL_UP_EVENT: 'ctrlUp',
\r
2718 * .SPACE_DOWN_EVENT: 'spaceDown',
\r
2719 * .SPACE_UP_EVENT: 'spaceUp',
\r
2720 * .init: function,
\r
2721 * .addKeyDownEvent: function,
\r
2722 * .keyEventDispatcher: function,
\r
2724 * ショートカットキーの監視とテキスト入力(input, textarea)、チェックボックスを管理する。
\r
2725 * キー入力はdocumentで受けて、テキスト編集中(input, textarea)はそちらにキーイベント流す。
\r
2728 var KeyEvent = ( function(){
\r
2729 var EVENT_LIST_MAP = [],
\r
2730 application = null,
\r
2731 currentList = null;
\r
2735 var focusTicket = null,
\r
2736 keydownTicket = null,
\r
2737 keyupTicket = null,
\r
2739 keypressTicket = null;
\r
2741 function onKeyChange( e ){
\r
2742 var cancel = false,
\r
2744 key = e.keyCode || e.charCode || e.which,
\r
2745 shift = Type.isBoolean( e.shiftKey ) === true ? e.shiftKey : ( e.modifiers & Event.SHIFT_MASK ),
\r
2746 ctrl = Type.isBoolean( e.ctrlKey ) === true ? e.ctrlKey : ( e.modifiers & Event.CONTROL_MASK ),
\r
2749 if( key === 16 || shift === true ){
\r
2750 KeyEvent.shiftEnabled = type !== 'keyup';
\r
2752 if( key === 17 || ctrl === true ){
\r
2753 KeyEvent.ctrlEnabled = type !== 'keyup';
\r
2756 for( var i=currentList.length; t = currentList[ --i ]; ){
\r
2757 if( Type.isFunction( t[ type ] ) === true && t.keyCode === key && ( t.shift === undefined || t.shift === shift ) && ( t.ctrl === undefined || t.ctrl === ctrl )){
\r
2758 AsyncCall.add( t.apiuser, t[ type ], e );
\r
2762 if( cancel === true || key === 18 || key === 9 || key === 27 || e.altKey === true ){ // 13.enter 18.esc 9.tab 27.esc || ( key === 13 && overlayEnabled === false)
\r
2767 if( UA.isIE === true && UA.ieRenderingVersion < 9 ){
\r
2768 keyPress = function( e ){
\r
2769 var key = e.charCode;
\r
2770 if( key === 13 || key === 27 ){
\r
2771 e.type = 'keydown';
\r
2772 return onKeyChange( e );
\r
2777 var KeyEventTicketClass = function( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ){
\r
2778 this.apiuser = _apiuser;
\r
2779 this.type = _type;
\r
2780 this.keydown = _onKeydown;
\r
2781 this.keyup = _onKeyup;
\r
2782 this.keyCode = _keyCode;
\r
2783 this.shift = _shift;
\r
2784 this.ctrl = _ctrl;
\r
2785 _apiuser = _onKeydown = _onKeyup = null;
\r
2787 KeyEventTicketClass.prototype = {
\r
2788 match: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
\r
2789 if( _apiuser && _apiuser !== this.apiuser ) return false;
\r
2790 if( _type && _type !== this.type ) return false;
\r
2792 if( this.type === 'keydown' ){
\r
2793 if( _handler !== this.keydown ) return false;
\r
2795 if( _handler !== this.keyup ) return false;
\r
2798 if( _keyCode && _keyCode !== this.keyCode ) return false;
\r
2799 if( _shift && _shift !== this.shift ) return false;
\r
2800 if( _ctrl && _ctrl !== this.ctrl ) return false;
\r
2803 destroy: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
\r
2804 if( this.match( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ) === false ) return false;
\r
2806 delete this.apiuser;
\r
2807 delete this.keydown;
\r
2808 delete this.keyup;
\r
2814 function registerEvent( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ){
\r
2815 var _uid = _apiuser.getUID(),
\r
2816 _list = EVENT_LIST_MAP[ _uid ];
\r
2817 if( Type.isArray( _list ) === false ){
\r
2818 _list = EVENT_LIST_MAP[ _uid ] = [];
\r
2820 for( var i=0, l=_list.length; i<l; ++i ){
\r
2821 if( _list[ i ].match( _apiuser, _type, _onKeydown || _onKeyup, _keyCode, _shift, _ctrl ) === true ) return;
\r
2823 _list.push( new KeyEventTicketClass( _apiuser, _type, _onKeydown, _onKeyup, _keyCode, _shift, _ctrl ));
\r
2825 if( _apiuser === application ) KeyEvent.updateCurrentListener( _apiuser );
\r
2829 add: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
\r
2830 if( _type === 'keydown' ){
\r
2831 registerEvent( _apiuser, _type, _handler, null, _keyCode, _shift, _ctrl );
\r
2833 if( _type === 'keyup' ){
\r
2834 registerEvent( _apiuser, _type, null, _handler, _keyCode, _shift, _ctrl );
\r
2836 if( _type === 'keychange' ){
\r
2837 registerEvent( _apiuser, _type, _handler, _handler, _keyCode, _shift, _ctrl );
\r
2839 if( _type === 'cursol' ){
\r
2843 remove: function( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ){
\r
2844 var _list = EVENT_LIST_MAP[ _apiuser.getUID() ],
\r
2846 if( Type.isArray( _list ) === true ){
\r
2847 while( i < _list.length ){
\r
2848 if( _list[ i ].destroy( _apiuser, _type, _handler, _keyCode, _shift, _ctrl ) === true ){
\r
2849 _list.splice( i, 1 );
\r
2855 if( _apiuser === application ) KeyEvent.updateCurrentListener( _apiuser );
\r
2857 shiftEnabled: false,
\r
2858 ctrlEnabled: false,
\r
2861 * currrentApplication ( overlay Application ) or
\r
2864 updateCurrentListener: function( _apiuser ){
\r
2865 application = _apiuser;
\r
2866 currentList = EVENT_LIST_MAP[ _apiuser.getUID() ] || [];
\r
2871 for( var i=currentList.length; _ticket = currentList[ --i ]; ){
\r
2872 if( _down === false ) _down = !!_ticket.keydown;
\r
2873 if( _up === false ) _up = !!_ticket.keyup;
\r
2874 if( _down && _up ) break;
\r
2876 if( _down === true ){
\r
2877 keydownTicket = new EventTicketClass( doc, 'keydown', onKeyChange );
\r
2878 keypressTicket = keyPress !== null ? new EventTicketClass( doc, 'keypress', keyPress ) : null;
\r
2880 keydownTicket && keydownTicket.destroy();
\r
2881 keypressTicket && keypressTicket.destroy();
\r
2882 keydownTicket = keypressTicket = null;
\r
2884 if( _up === true ){
\r
2885 keyupTicket = new EventTicketClass( doc, 'keyup', onKeyChange );
\r
2887 keyupTicket && keyupTicket.destroy();
\r
2888 keyupTicket = null;
\r
2891 if( _down === true || _up === true ){
\r
2892 focusTicket = new EventTicketClass( doc, 'mouseenter', window.focus );
\r
2894 focusTicket && focusTicket.destroy();
\r
2895 focusTicket = null;
\r
2898 onApplicationShutdown: function( _apiuser ){
\r
2899 KeyEvent.remove( _apiuser );
\r
2901 onSystemShutdown: function(){
\r
2909 * http://thudjs.tumblr.com/post/637855087/stylesheet-onload-or-lack-thereof
2912 var Css = ( function(){
\r
2913 var head = doc.getElementsByTagName( 'head' )[ 0 ];
\r
2915 var TICKET_LIST = [];
\r
2916 var STATE_LIST = 'loaded,complete,uninitialized'.split( ',' );
\r
2918 var cssRules, sheet;
\r
2920 var FetchCssTicketClass = function( _apiuser, _url, _elm, _onload, _onerror ){
\r
2921 this.apiusers = [ _apiuser ];
\r
2924 this.onload = [ _onload ];
\r
2925 this.onerror = [ _onerror ];
\r
2928 FetchCssTicketClass.prototype = {
\r
2929 match: function( _apiuser, _url ){
\r
2930 if( _apiuser && Util.getIndex( this.apiusers, _apiuser ) === -1 ) return false;
\r
2931 if( _url && _url !== this.url ) return false;
\r
2934 destroy: function( _apiuser, _url ){
\r
2935 if( this.match( _apiuser, _url ) === false ) return false;
\r
2937 var i = Util.getIndex( this.apiusers, _apiuser );
\r
2939 this.apiusers.splice( i, 1 );
\r
2940 this.onload.splice( i, 1 );
\r
2941 this.onerror.splice( i, 1 );
\r
2943 if( this.apiusers.length !== 0 ) return false;
\r
2945 head.removeChild( this.elm );
\r
2946 this.elm.onreadystatechange = new Function();
\r
2947 this.elm.onload = null;
\r
2949 delete this.apiusers;
\r
2952 delete this.onload;
\r
2953 delete this.onerror;
\r
2958 loaded: function(){
\r
2959 for( var i = this.onload.length, f; i; ){
\r
2960 f = this.onload[ --i ];
\r
2961 Type.isFunction( f ) === true && AsyncCall.add( this.apiusers[ i ], f, this.url );
\r
2962 this.onload[ i ] = this.onerror[ i ] = null;
\r
2965 error: function(){
\r
2966 for( var i = this.onerror.length, c; i; ){
\r
2967 c = this.onerror[ --i ];
\r
2968 Type.isFunction( c ) === true && AsyncCall.add( t.apiusers[ i ], c, t.url );
\r
2969 this.onload[ i ] = this.onerror[ i ] = null;
\r
2972 check: function(){
\r
2973 var el = this.elm;
\r
2975 return el[ sheet ] && el[ sheet ][ cssRules ].length > 0;
\r
2983 function getTicket( elm ){
\r
2984 for( var i = TICKET_LIST.length, t; i; ){
\r
2985 t = TICKET_LIST[ --i ];
\r
2986 if( t.elm === elm ) return t;
\r
2990 function detect(){
\r
2991 var t = getTicket( this ), rs = this.readyState, c;
\r
2992 if( t && t.done === false && ( !rs || Util.getIndex( STATE_LIST, rs ) !== -1 ) ){
\r
2995 this.onreadystatechange = new Function();
\r
2996 this.onload = null;
\r
3000 function checkTimer(){
\r
3001 var l = TICKET_LIST.length,
\r
3003 for( var i = 0; i < l; ++i ){
\r
3004 t = TICKET_LIST[ i ];
\r
3006 if( t.check() === true ){
\r
3010 if( t.time > 99 ){
\r
3016 l === n && SystemTimer.remove( SUPER_USER_KEY, checkTimer );
\r
3020 load: function( _apiuser, _url, opt_onload, opt_onerror ){
\r
3021 _url = Util.getAbsolutePath( _url );
\r
3023 for( var i=TICKET_LIST.length; i; ){
\r
3024 t = TICKET_LIST[ --i ];
\r
3025 if( t.match( null, _url ) === true ){
\r
3026 if( t.match( _apiuser, _url ) === false ){
\r
3027 t.apiusers.push( _apiuser );
\r
3028 t.onload.push( opt_onload );
\r
3029 t.onerror.push( opt_onerror );
\r
3031 SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 );
\r
3035 var elm = doc.createElement( 'link' );
\r
3036 head.appendChild( elm );
\r
3037 elm.rel = 'stylesheet';
\r
3038 elm.type = 'text\/css';
\r
3039 elm.onreadystatechange = elm.onload = detect;
\r
3042 if( !sheet ){ // only assign these once
\r
3043 cssRules = 'cssRules';
\r
3045 if ( !( sheet in elm ) ) { // MSIE uses non-standard property names
\r
3046 cssRules = 'rules';
\r
3047 sheet = 'styleSheet';
\r
3051 TICKET_LIST.push( new FetchCssTicketClass( _apiuser, _url, elm, opt_onload, opt_onerror ) );
\r
3053 SystemTimer.add( SUPER_USER_KEY, checkTimer, 333 );
\r
3055 unload: function( _apiuser, _url ){
\r
3056 _url = _url ? Util.getAbsolutePath( _url ) : null;
\r
3057 for( var i = 0; i < TICKET_LIST.length; ){
\r
3058 t = TICKET_LIST[ i ];
\r
3059 if( t.destroy( _apiuser, _url ) === true ){
\r
3060 TICKET_LIST.splice( i, 1 );
\r
3065 if( TICKET_LIST.length === 0 ){
\r
3066 SystemTimer.remove( SUPER_USER_KEY, checkTimer );
\r
3073 /* ----------------------------------------
\r
3077 var Overlay = ( function(){
\r
3078 var elmContainer, elmShadow, elmCloseButton,
\r
3079 application = null,
\r
3081 bodyOverflow = '',
\r
3084 function onCloseClick( e ){
\r
3088 function asyncInit( /* arguments */ ){
\r
3090 //body.appendChild( application.rootElement );
\r
3091 elmContainer.insertBefore( application.rootElement, elmCloseButton );
\r
3092 application.init();
\r
3096 function asyncOpen( /* arguments */ ){
\r
3098 var _arg = Util.copyArray( arguments );
\r
3099 _arg.unshift( windowW, windowH );
\r
3100 application.open.apply( application, _arg );
\r
3102 elmContainer.style.cssText = "top:" + body.scrollTop + 'px;display:none;';
\r
3103 $( elmContainer ).stop().fadeIn( onFadeInComplete );
\r
3105 function onFadeInComplete(){
\r
3106 KeyEvent.add( application, Const.KEY.EVENT.KEY_DOWN, Overlay.hide, 27 ); // 27.esc
\r
3107 MouseEvent.add( application, elmCloseButton, 'click', onCloseClick );
\r
3109 function onFadeOutComplete(){
\r
3110 Util.removeAllChildren( elmContainer );
\r
3111 body.removeChild( elmContainer );
\r
3112 elmContainer = elmShadow = elmCloseButton = null;
\r
3115 show: function( _application, _bootParams ){
\r
3116 if( visible === true && application === _application ) return;
\r
3117 if( Application.isApplicationInstance( _application ) === false ) return;
\r
3119 elmContainer = document.createElement( 'div' );
\r
3120 body.appendChild( elmContainer );
\r
3122 elmContainer.id = 'overlay-container';
\r
3124 bodyOverflow = body.style.overflow;
\r
3125 body.style.overflow = 'hidden';
\r
3127 elmShadow = document.createElement( 'div' );
\r
3128 elmContainer.appendChild( elmShadow );
\r
3129 elmShadow.id = 'overlay-shadow';
\r
3131 elmCloseButton = document.createElement( 'div' );
\r
3132 elmContainer.appendChild( elmCloseButton );
\r
3133 elmCloseButton.id = 'overlay-close-button';
\r
3134 elmCloseButton.appendChild( document.createTextNode( 'x' ) );
\r
3136 elmContainer.style.display = 'none'; // hide for fadeIn
\r
3138 _application.addAsyncCall( asyncInit );
\r
3139 _application.addAsyncCall( asyncOpen, _bootParams );
\r
3142 application = _application;
\r
3145 if( visible === false ) return;
\r
3146 if( application.close() === false ) return false;
\r
3148 body.style.overflow = bodyOverflow;
\r
3150 $( elmContainer ).stop().css( {
\r
3153 }).fadeOut( onFadeOutComplete );
\r
3156 KeyEvent.remove( application, Const.KEY.EVENT.KEY_DOWN, Overlay.hide ); // 27.esc
\r
3157 MouseEvent.remove( application, elmCloseButton );
\r
3159 application = null;
\r
3161 onWindowResize: function( _windowW, _windowH ){
\r
3162 windowW = _windowW;
\r
3163 windowH = _windowH;
\r
3165 if( application === null ) return;
\r
3167 elmContainer.style.height = _windowH + 'px';
\r
3168 elmContainer.style.top = body.scrollTop + 'px';
\r
3170 elmShadow.style.height = _windowH + 'px';
\r
3172 AsyncCall.add( application, application.resize, [ _windowW, _windowH ] );
\r
3177 /* ----------------------------------------
\r
3181 * form -> overlay -> view
\r
3185 var UI = ( function(){
\r
3187 currentUser = null,
\r
3188 currentList = null,
\r
3190 currentItem = null,
\r
3194 var CLASSNAME_COMBOBOX_OPTION = 'combobox-option',
\r
3195 ELM_A_ORIGIN = ( function(){
\r
3196 var ret = document.createElement( 'a' );
\r
3200 ELM_INPUT_TEXT = ( function(){
\r
3201 var ret = document.createElement( 'input' );
\r
3202 ret.type = 'text';
\r
3205 ELM_COMBOBOX = ( function(){
\r
3206 var ret = document.createElement( 'a' ),
\r
3207 elmToggle = document.createElement( 'span' ),
\r
3208 elmValue = document.createElement( 'span' );
\r
3210 ret.appendChild( elmToggle );
\r
3211 ret.appendChild( elmValue );
\r
3212 elmToggle.className = 'combobox-toggle';
\r
3213 elmValue.className = 'combobox-value';
\r
3215 elmToggle.appendChild( document.createTextNode( '▼' ));
\r
3216 elmValue.appendChild( document.createTextNode( 'null' ));
\r
3220 var InputTextClass = function( apiuser, uiGroup, elmWrapper, elmValue, onUpdate, validater ){
\r
3221 var elmA = ELM_A_ORIGIN.cloneNode( true ),
\r
3226 value = elmValue.innerHTML;
\r
3227 elmValue.innerHTML = '';
\r
3228 elmValue.className += ' editable-text';
\r
3229 elmValue.appendChild( elmA );
\r
3231 this.value = function( _value ){
\r
3232 if( Type.isString( _value ) === true ){
\r
3233 elmA.innerHTML = value = _value;
\r
3234 if( focus === true ){
\r
3235 ELM_INPUT_TEXT.value = value;
\r
3238 focus === true && instance.blur();
\r
3241 this.focus = function( e ){
\r
3243 start( apiuser, uiGroup, instance );
\r
3244 elmA.style.display = 'none';
\r
3245 elmValue.appendChild( ELM_INPUT_TEXT );
\r
3247 ELM_INPUT_TEXT.value = value;
\r
3248 ELM_INPUT_TEXT.focus();
\r
3249 ELM_INPUT_TEXT.select();
\r
3253 this.blur = function( keep ){
\r
3254 var _newValue = ELM_INPUT_TEXT.value,
\r
3255 _validated = Type.isFunction( validater ) === true ? '' + validater( _newValue ) : _newValue;
\r
3256 _newValue = keep !== 27 ? _validated : value; // 27:ESC
\r
3258 elmValue.removeChild( ELM_INPUT_TEXT );
\r
3260 elmA.innerHTML = _newValue;
\r
3261 elmA.style.display = 'block';
\r
3263 onUpdate && _newValue !== value && onUpdate( _newValue, value );
\r
3265 value = _newValue;
\r
3267 finish( apiuser, uiGroup, instance );
\r
3269 this.enabled = function(){
\r
3272 this.visible = function( _visible ){
\r
3273 if( Type.isBoolean( _visible ) === true ){
\r
3274 elmWrapper.style.display = _visible ? '' : 'none';
\r
3275 visible = _visible;
\r
3279 this.destroy = function(){
\r
3280 if( focus === true ){
\r
3281 elmValue.removeChild( ELM_INPUT_TEXT );
\r
3283 MouseEvent.remove( apiuser, elmWrapper );
\r
3284 apiuser = uiGroup = elmWrapper = elmValue = elmA = onUpdate = validater = instance = null;
\r
3286 instance.value( value );
\r
3287 MouseEvent.add( apiuser, elmWrapper, 'click', instance.focus );
\r
3290 var ButtonClass = function( apiuser, uiGroup, elmWrapper, onUpdate ){
\r
3291 var className = elmWrapper.className || '',
\r
3296 MouseEvent.add( apiuser, elmWrapper, 'click', onClick );
\r
3298 function onClick(){
\r
3303 this.focus = function(){
\r
3305 elmWrapper.className = className + ' button-has-focus';
\r
3306 start( apiuser, uiGroup, instance );
\r
3308 this.blur = function( keyCode ){
\r
3309 keyCode === 13 && onClick();
\r
3310 elmWrapper.className = className;
\r
3312 finish( apiuser, uiGroup, instance );
\r
3314 this.enabled = function(){
\r
3317 this.visible = function( _visible ){
\r
3318 if( Type.isBoolean( _visible ) === true ){
\r
3319 elmWrapper.style.display = _visible ? '' : 'none';
\r
3320 visible = _visible;
\r
3324 this.destroy = function(){
\r
3325 MouseEvent.remove( apiuser, elmWrapper );
\r
3326 apiuser = uiGroup = elmWrapper = onUpdate = instance = null;
\r
3330 var FileInputClass = function( apiuser, uiGroup, elmWrapper, onUpdate, validater, elmFileInput ){
\r
3331 var elmFilePath = Util.getElementsByClassName( elmWrapper, 'file-path' )[ 0 ],
\r
3335 index = GROUP_ID ? itemList[ GROUP_ID ].length : -1,
\r
3338 elmFileInput = elmWrapper.getElementsByTagName('input')[0] || elmFileInput || document.createElement( 'input');
\r
3339 elmFileInput.type = 'file';
\r
3340 elmFileInput.style.visivility = 'hidden';
\r
3342 elmWrapper.onclick = onClick;
\r
3343 elmFileInput.onchange = onChange;
\r
3345 function onChange(){
\r
3346 elmFilePath.innerHTML = elmFileInput.value;
\r
3353 focus: function( e ){
\r
3355 start( apiuser, uiGroup, instance );
\r
3356 elmFileInput.click();
\r
3359 blur: function( keep ){
\r
3362 enabled: function(){
\r
3365 visible: function( _visible ){
\r
3366 if( Type.isBoolean( _visible ) === true ){
\r
3367 elmWrapper.style.display = _visible ? '' : 'none';
\r
3368 visible = _visible;
\r
3376 var ComboBoxClass = function( apiuser, uiGroup, elmWrapper, onUpdate ){
\r
3377 var elmBox = Util.getElementsByClassName( elmWrapper, 'combobox' )[ 0 ],
\r
3378 elmA = ELM_COMBOBOX.cloneNode( true ),
\r
3379 elmToggle = Util.getElementsByClassName( elmA, 'combobox-toggle' )[ 0 ],
\r
3380 elmValue = Util.getElementsByClassName( elmA, 'combobox-value' )[ 0 ].firstChild,
\r
3388 elmBox.appendChild( elmA );
\r
3390 this.elm = elmBox;
\r
3391 this.focus = function( e ){
\r
3392 MouseEvent.remove( apiuser, elmWrapper, 'click', instance.focus );
\r
3394 elmA.className = 'combobox-has-focus';
\r
3395 start( apiuser, uiGroup, instance );
\r
3396 OptionControl.show( apiuser, instance, optionList );
\r
3399 this.blur = function( keyCode ){
\r
3400 OptionControl.hide( instance );
\r
3402 elmA.className = '';
\r
3403 finish( apiuser, uiGroup, instance );
\r
3404 MouseEvent.add( apiuser, elmWrapper, 'click', instance.focus );
\r
3406 this.enabled = function(){
\r
3409 this.visible = function( _visible ){
\r
3410 if( Type.isBoolean( _visible ) === true ){
\r
3411 elmWrapper.style.display = _visible ? '' : 'none';
\r
3412 visible = _visible;
\r
3416 this.value = function( _value ){
\r
3417 if( Type.isString( _value ) === true && value !== _value ){
\r
3418 for( var i=0, l = optionList.length, _option; i<l; ++i ){
\r
3419 _option = optionList[ i ];
\r
3420 if( _value === _option.value ){
\r
3423 elmValue.data = _option.displayValue;
\r
3424 if( focus === true ){
\r
3425 OptionControl.update( instance, _value );
\r
3427 Type.isFunction( onUpdate ) === true && onUpdate( _value );
\r
3434 this.selectIndex = function(){
\r
3437 this.createOption = function( _displayValue, _value, _isSelected ){
\r
3438 var option = null,
\r
3441 _value = _value || _displayValue;
\r
3442 for( var i = 0, l = optionList.length; i < l; ++i ){
\r
3443 _option = optionList[ i ];
\r
3444 if( _value === _option.value ){
\r
3448 _option.current = _option.value === _value;
\r
3451 if( option === null ){
\r
3452 option = new OptionClass( instance, _displayValue, _value, _isSelected );
\r
3453 _index = optionList.length;
\r
3454 optionList.push( option );
\r
3456 if( _isSelected === true ){
\r
3457 elmValue.data = _displayValue;
\r
3460 this.destroy = function(){
\r
3462 MouseEvent.remove( apiuser, elmWrapper );
\r
3463 optionList.length = 0;
\r
3464 apiuser = uiGroup = elmWrapper = onUpdate = elmBox = elmA = elmToggle = elmValue = optionList = instance = null;
\r
3466 MouseEvent.add( apiuser, elmWrapper, 'click', instance.focus );
\r
3468 var OptionClass = function( combobox, displayValue, value, isCurrent ){
\r
3469 this.displayValue = displayValue;
\r
3470 this.value = value = value || displayValue;
\r
3471 this.current = isCurrent;
\r
3472 displayValue = value = null;
\r
3475 var OptionControl = ( function(){
\r
3476 var ELM_OPTION_WRAPPER = ( function(){
\r
3477 var ret = document.createElement( 'div' );
\r
3478 ret.className = 'option-container';
\r
3481 ELM_OPTION_ORIGIN = ( function(){
\r
3482 var ret = document.createElement( 'a' );
\r
3483 ret.appendChild( document.createTextNode( 'option' ) );
\r
3488 var OptionClass = function( apiuser, option ){
\r
3489 this.elm = ELM_OPTION_ORIGIN.cloneNode( true );
\r
3490 this.data = option;
\r
3491 this.current = function( _current ){
\r
3492 this.elm.className = CLASSNAME_COMBOBOX_OPTION;
\r
3493 option.current = _current;
\r
3494 currentOption = this;
\r
3496 this.destroy = function(){
\r
3497 MouseEvent.remove( apiuser, this.elm );
\r
3498 apiuser = option = null;
\r
3499 ELM_OPTION_WRAPPER.removeChild( this.elm );
\r
3504 ELM_OPTION_WRAPPER.appendChild( this.elm );
\r
3505 this.elm.firstChild.data = option.displayValue;
\r
3506 this.current( option.current );
\r
3507 MouseEvent.add( SUPER_USER_KEY, this.elm, 'mousedown', onOptionSelect );// onclick では 選択ボックス 隠すように body に設定した onmouseup が先に動いてしまう!
\r
3510 function onOptionSelect( e ){
\r
3511 for( var i = 0, l = OPTION_LIST.length, _option; i < l; ++i){
\r
3512 _option = OPTION_LIST[ i ];
\r
3513 if( this === _option.elm ){
\r
3514 updateCurrrentOption( _option.data.value, true );
\r
3515 currentCombobox.blur();
\r
3522 var OPTION_LIST = [],
\r
3523 currentCombobox = null,
\r
3529 function updateCurrrentOption( _value, _updateCombobox ){
\r
3531 for( var i = OPTION_LIST.length; i; ){
\r
3532 _option = OPTION_LIST[ --i ];
\r
3533 if( _value === _option.data.value ){
\r
3534 currentOption && currentOption.current( false );
\r
3535 _option.current( true );
\r
3536 currentOption = _option;
\r
3538 _updateCombobox === true && currentCombobox.value( _value );
\r
3544 function bodyMouseupHandler(){
\r
3545 currentCombobox.blur();
\r
3546 OptionControl.hide( currentCombobox );
\r
3548 function updateWrapperPosition(){
\r
3549 var position = Util.getAbsolutePosition( elm );
\r
3551 ELM_OPTION_WRAPPER.style.cssText = [
\r
3552 'width:', elm.offsetWidth - 2, 'px;',
\r
3553 'left:', position.x, 'px;',
\r
3554 'top:', position.y + elm.offsetHeight, 'px;'
\r
3557 function change( e ){
\r
3558 var l = OPTION_LIST.length,
\r
3559 i = currentIndex + e.keyCode === 40 ? 1 : -1;
\r
3560 if( currentCombobox === null || l < 2 ) return;
\r
3564 updateCurrrentOption( OPTION_LIST[ i ].data.value, true );
\r
3568 show: function( _apiuser, _combobox, _optionList ){
\r
3569 if( currentItem !== _combobox || currentCombobox === _combobox ) return;
\r
3570 currentCombobox && currentCombobox.blur();
\r
3572 apiuser = _apiuser;
\r
3573 currentCombobox = _combobox;
\r
3574 elm = _combobox.elm;
\r
3576 for( var i = 0, l = _optionList.length; i<l; ++i ){
\r
3577 OPTION_LIST.unshift( new OptionClass( _apiuser, _optionList[ i ] ) );
\r
3579 MouseEvent.add( SUPER_USER_KEY, doc, 'mouseup', bodyMouseupHandler );
\r
3580 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 38 );
\r
3581 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change, 40 );
\r
3582 //KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter, 13 );
\r
3583 //KeyEvent.updateCurrentListener( SUPER_USER_KEY );
\r
3585 body.appendChild( ELM_OPTION_WRAPPER );
\r
3587 updateCurrrentOption( _combobox.value(), false );
\r
3588 updateWrapperPosition();
\r
3590 hide: function( _combobox ){
\r
3591 if( currentCombobox !== _combobox || currentCombobox === null ) return;
\r
3594 while( _option = OPTION_LIST.shift() ){
\r
3595 _option.destroy();
\r
3598 body.removeChild( ELM_OPTION_WRAPPER );
\r
3600 MouseEvent.remove( SUPER_USER_KEY, doc, 'mouseup', bodyMouseupHandler );
\r
3601 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change );
\r
3602 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, change );
\r
3603 //KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onEnter );
\r
3604 //KeyEvent.updateCurrentListener( apiuser );
\r
3607 currentCombobox = null;
\r
3608 currentOption = null;
\r
3609 currentIndex = 0;
\r
3611 onEnter: function(){
\r
3612 currentCombobox.value( currentOption.data.value );
\r
3613 //currentCombobox.blur();
\r
3614 //OptionControl.hide( currentCombobox );
\r
3616 update: function( _combobox, _value ){
\r
3617 if( currentCombobox !== _combobox || currentItem !== _combobox ) return;
\r
3618 if( currentOption.data.value === _value ) return;
\r
3619 updateCurrrentOption( _value, true );
\r
3621 onWindowResize: function( _w, _h ){
\r
3622 currentCombobox && AsyncCall.add( apiuser, updateWrapperPosition );
\r
3627 var UIGroupClass = function( apiuser ){
\r
3630 currentItem = null,
\r
3633 this.focus = function( _value ){
\r
3634 if( _value === true ){
\r
3635 if( currentItem ){
\r
3636 start( apiuser, self, currentItem );
\r
3638 if( itemList.length > 0 ){
\r
3639 start( apiuser, self, itemList[ 0 ] );
\r
3642 if( _value === false ){
\r
3643 finish( apiuser, self, currentItem );
\r
3645 if( _value && Util.getIndex( itemList, _value ) !== -1 ){
\r
3646 currentItem = _value;
\r
3647 currentList = itemList;
\r
3649 return currentUi === self;
\r
3651 this.blur = function(){
\r
3652 if( currentList === itemList ){
\r
3653 currentList = null;
\r
3656 this.createInputText = function( _elmWrapper, _onUpdate, _validater ){
\r
3657 var _elmValue = Util.getElementsByClassName( _elmWrapper, 'editable-value' )[ 0 ];
\r
3659 var ret = new InputTextClass( apiuser, self, _elmWrapper, _elmValue, _onUpdate, _validater );
\r
3660 itemList.push( ret );
\r
3663 alert( 'error createInputText' );
\r
3665 this.createButton = function( _elm, _onClick ){
\r
3666 var ret = new ButtonClass( apiuser, self, _elm, _onClick );
\r
3667 itemList.push( ret );
\r
3670 this.createFileInput = function( _elm, _onUpdate, _validater, _elmFileInput ){
\r
3671 var ret = FileInputClass( apiuser, self, _elm, _onUpdate, _validater, _elmFileInput );
\r
3672 itemList.push( ret );
\r
3675 this.createCombobox = function( _elm, _onUpdate, _optionList ){
\r
3676 var ret = new ComboBoxClass( apiuser, self, _elm, _onUpdate, _optionList );
\r
3677 itemList.push( ret );
\r
3680 this.createCheckBox = function(){
\r
3683 this.createRadio = function(){
\r
3686 this.createSlider = function(){
\r
3689 this.destroy = function(){
\r
3691 while( _item = itemList.shift() ){
\r
3697 function start( _apiuser, _uigroup, _item ){
\r
3698 if( currentItem !== _item ){
\r
3699 currentItem !== null && currentItem.blur();
\r
3701 if( currentUser !== _apiuser ) {
\r
3702 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 );
\r
3703 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 );
\r
3704 KeyEvent.add( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 9 );
\r
3705 KeyEvent.updateCurrentListener( SUPER_USER_KEY );
\r
3707 if( currentUi !== _uigroup ){
\r
3708 currentUi && currentUi.blur();
\r
3710 currentUser = _apiuser;
\r
3711 currentUi = _uigroup;
\r
3712 currentItem = _item;
\r
3714 _uigroup.focus( _item );
\r
3717 function finish( _apiuser, _uigroup, _item ){
\r
3718 if( currentItem === _item ){
\r
3721 currentUser = null;
\r
3723 currentItem = null;
\r
3725 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 13 );
\r
3726 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 27 );
\r
3727 KeyEvent.remove( SUPER_USER_KEY, Const.KEY.EVENT.KEY_DOWN, onKeyDown, 9 );
\r
3728 KeyEvent.updateCurrentListener( _apiuser );
\r
3732 function onKeyDown( e ){
\r
3733 if( currentItem === null ) return true;
\r
3734 var keyCode = e.keyCode,
\r
3735 _index = Util.getIndex( currentList, currentItem );
\r
3736 if( keyCode === 13 || keyCode === 27 || keyCode === 9 || keyCode === 18 || e.altKey === true ){ // 13.return 27.esc 9.tab 18.alt
\r
3737 keyCode === 9 && tabShift( _index, e.shiftKey === true ? -1 : 1 );
\r
3738 keyCode === 13 && currentItem instanceof ComboBoxClass && OptionControl.onEnter();
\r
3739 keyCode === 13 && tabShift( _index, 1 );
\r
3740 currentItem && currentItem.blur( keyCode );
\r
3745 function tabShift( _index, _way ){
\r
3746 var l = currentList.length,
\r
3747 i = _index + _way,
\r
3749 if( l < 2 ) return;
\r
3750 while( i !== _index ){
\r
3753 i < l ? i : 0; // 0 < i < l
\r
3754 _item = currentList[ i ];
\r
3755 if( _item.enabled() === true && _item.visible() === true ){
\r
3756 AsyncCall.add( currentUser, _item.focus );
\r
3764 createUIGroup: function( _apiuser ){
\r
3765 var _uid = _apiuser.getUID(),
\r
3766 _list = UI_LIST[ _uid ],
\r
3767 _ui = new UIGroupClass( _apiuser );
\r
3768 if( Type.isArray( _list ) === false ){
\r
3769 _list = UI_LIST[ _uid ] = [];
\r
3771 _list.push( _ui );
\r
3774 onWindowResize: function( w, h ){
\r
3777 currentItem instanceof ComboBoxClass && OptionControl.onWindowResize( w, h );
\r
3779 onCurrentApplicationChange: function( _apiuser ){
\r
3780 currentList = UI_LIST[ _apiuser.getUID() ];
\r
3782 onApplicationShutdown: function( _apiuser ){
\r
3783 KeyEvent.remove( _apiuser );
\r
3785 onSystemShutdown: function(){
\r
3792 var Finder = ( function(){
\r
3793 var HTML_FINDER_ICON = ( function(){
\r
3794 return ( UA.isIE === true && UA.ieVersion < 8 ?
\r
3796 '<div class="finder-icon fnder-icon-ie7">',
\r
3797 '<a href="#" class="finder-icon-main">',
\r
3798 '<span class="finder-icon-handle"></span>',
\r
3799 '<span class="finder-icon-thumbnail"></span>',
\r
3800 '<span class="finder-icon-cell finder-icon-ie-filename">',
\r
3801 '<span class="finder-icon-vertical-middle-outer">',
\r
3802 '<span class="finder-icon-vertical-middle-inner">',
\r
3803 '<span class="finder-icon-filename break-word">file name</span>',
\r
3807 '<span class="finder-icon-cell finder-icon-ie-summary">',
\r
3808 '<span class="finder-icon-vertical-middle-outer">',
\r
3809 '<span class="finder-icon-vertical-middle-inner">',
\r
3810 '<span class="finder-icon-summary break-word">file descriptiion</span>',
\r
3815 '<div class="finder-icon-console">',
\r
3816 '<a href="#" class="finder-icon-console-action"></a>',
\r
3817 '<a href="#" class="finder-icon-console-editor-apps"></a>',
\r
3818 '<a href="#" class="finder-icon-console-viewer-apps"></a>',
\r
3823 '<div class="finder-icon fnder-icon-modern">',
\r
3824 '<span class="finder-icon-handle"></span>',
\r
3825 '<span class="finder-icon-thumbnail"></span>',
\r
3826 '<span class="finder-icon-filename break-word">file name</span>',
\r
3827 '<span class="finder-icon-summary break-word">file descriptiion</span>',
\r
3828 '<div class="finder-icon-console">',
\r
3829 '<a href="#" class="finder-icon-console-action"></a>',
\r
3830 '<a href="#" class="finder-icon-console-editor-apps"></a>',
\r
3831 '<a href="#" class="finder-icon-console-viewer-apps"></a>',
\r
3838 var FINDER_ARRAY = [],
\r
3839 ELM_ORIGIN_FINDER_LOCATION_ITEM = Util.pullHtmlAsTemplete( '<li id="templete-finder-location-item" class="finder-location-item"><a href="#"></a></li>'),
\r
3840 ELM_ORIGIN_FINDER_ICON = Util.pullHtmlAsTemplete( HTML_FINDER_ICON ),
\r
3841 ELM_ORIGIN_CONTAINER = Util.pullHtmlAsTemplete( [
\r
3842 '<div id="templete-finder-container" class="finder-container">',
\r
3843 '<div class="finder-header">',
\r
3844 '<ul class="finder-location"></ul>',
\r
3845 '<div class="finder-sidebar-switch button">side</div>',
\r
3846 '<div class="finder-style-switch button">style</div>',
\r
3847 '<div class="finder-action-switch button">action</div>',
\r
3849 '<div class="finder-body"></div>',
\r
3852 ICON_HEIGHT = Util.getElementSize( ELM_ORIGIN_FINDER_ICON ).height,
\r
3853 ICON_CLASSNAME = 'finder-icon-thumbnail',
\r
3854 FINDER_ICON_POOL = [],
\r
3855 BREAD_OBJECT_POOL = [];
\r
3857 var FinderIconClass = function(){
\r
3859 ELM_WRAPPER = ELM_ORIGIN_FINDER_ICON.cloneNode( true),
\r
3860 ELM_THUMBNAIL = Util.getElementsByClassName( ELM_WRAPPER, ICON_CLASSNAME )[ 0 ],
\r
3861 ELM_FILENAME = Util.getElementsByClassName( ELM_WRAPPER, 'finder-icon-filename' )[ 0 ],
\r
3862 ELM_DESCRIPTION = Util.getElementsByClassName( ELM_WRAPPER, 'finder-icon-summary' )[ 0 ],
\r
3863 ELM_EDITOR_BUTTON = Util.getElementsByClassName( ELM_WRAPPER, 'finder-icon-console-editor-apps' )[ 0 ],
\r
3864 ELM_VIEWER_BUTTON = Util.getElementsByClassName( ELM_WRAPPER, 'finder-icon-console-viewer-apps' )[ 0 ],
\r
3865 ELM_ACTION_BUTTON = Util.getElementsByClassName( ELM_WRAPPER, 'finder-icon-console-action' )[ 0 ],
\r
3867 file, w, index, style,
\r
3868 onDownCallback, onEditorCallback, onViewerCallback, onActionCallback,
\r
3869 viewerList, editorList;
\r
3871 MouseEvent.add( SUPER_USER_KEY, ELM_WRAPPER, 'click', onDownClick );
\r
3872 MouseEvent.add( SUPER_USER_KEY, ELM_EDITOR_BUTTON, 'click', onEditorClick );
\r
3873 MouseEvent.add( SUPER_USER_KEY, ELM_VIEWER_BUTTON, 'click', onViwerClick );
\r
3874 MouseEvent.add( SUPER_USER_KEY, ELM_ACTION_BUTTON, 'click', onActionClick );
\r
3875 function onDownClick(){
\r
3876 onDownCallback( index );
\r
3879 function onEditorClick(){
\r
3880 onEditorCallback( file, editorList[ 0 ] );
\r
3883 function onViwerClick(){
\r
3884 onViewerCallback( file, viewerList[ 0 ] );
\r
3887 function onActionClick(){
\r
3888 onActionCallback( file );
\r
3892 var _thumb = file.getThumbnail();
\r
3893 if( _thumb.image ){
\r
3894 ELM_THUMBNAIL.className = ICON_CLASSNAME + ' has-thumbnail';
\r
3895 ELM_THUMBNAIL.style.backgroundImage = [ 'url(', _thumb.image, ')'].join( '');
\r
3897 ELM_THUMBNAIL.className = ICON_CLASSNAME + ' ' + _thumb.className;
\r
3898 ELM_THUMBNAIL.style.backgroundImage = '';
\r
3900 ELM_FILENAME.firstChild.data = file.getName();
\r
3901 ELM_DESCRIPTION.firstChild.data = file.getSummary();
\r
3903 if( Type.isArray( viewerList ) === true && viewerList.length > 0 ){
\r
3904 ELM_VIEWER_BUTTON.style.display = '';
\r
3906 ELM_VIEWER_BUTTON.style.display = 'none';
\r
3908 if( Type.isArray( editorList ) === true && editorList.length > 0 ){
\r
3909 ELM_EDITOR_BUTTON.style.display = '';
\r
3911 ELM_EDITOR_BUTTON.style.display = 'none';
\r
3914 function resize(){
\r
3915 // ELM_WRAPPER.style.top = (index * ICON_HEIGHT) +'px';
\r
3917 function onCollect(){
\r
3918 elmContainer.removeChild( ELM_WRAPPER );
\r
3919 elmContainer = null;
\r
3920 FINDER_ICON_POOL.push( instansce );
\r
3923 this.init = function( _file, _elmContainer, _w, _index, _style, _onDownCallback, _onEditorCallback, _onViewerCallback, _onActionCallback ){
\r
3924 if( elmContainer !== _elmContainer){
\r
3925 _elmContainer.appendChild( ELM_WRAPPER );
\r
3926 elmContainer = _elmContainer;
\r
3928 if( file !== _file ){
\r
3929 file && file.destroy();
\r
3931 viewerList = file.viewerApplicationList();
\r
3932 editorList = file.editorApplicationList();
\r
3935 if( index !== _index){
\r
3939 onDownCallback = _onDownCallback;
\r
3940 onEditorCallback = _onEditorCallback;
\r
3941 onViewerCallback = _onViewerCallback;
\r
3942 onActionCallback = _onActionCallback;
\r
3944 this.elm = ELM_WRAPPER,
\r
3945 this.index = function( _index){
\r
3948 this.style = function( _style ){
\r
3951 this.onResize = function( w ){
\r
3954 this.destroy = function(){
\r
3955 //MouseEvent.remove( SUPER_USER_KEY, ELM_WRAPPER, 'click', onDownClick );
\r
3956 //MouseEvent.remove( SUPER_USER_KEY, ELM_EDITOR_BUTTON, 'click', onEditorClick );
\r
3957 //MouseEvent.remove( SUPER_USER_KEY, ELM_VIEWER_BUTTON, 'click', onViwerClick );
\r
3958 //MouseEvent.remove( SUPER_USER_KEY, ELM_ACTION_BUTTON, 'click', onActionClick );
\r
3959 elmContainer.removeChild( ELM_WRAPPER );
\r
3960 file && file.destroy();
\r
3961 file = elmContainer = onDownCallback = onEditorCallback = onViewerCallback = onActionCallback = viewerList = editorList = null;
\r
3962 FINDER_ICON_POOL.push( instansce );
\r
3965 function updateIconPosition( _style, _w, _index, _elm ){
\r
3968 var BreadcrumbClass = function(){
\r
3970 ELM_WRAPPER = ELM_ORIGIN_FINDER_LOCATION_ITEM.cloneNode( true ),
\r
3971 ELM_FILENAME = ELM_WRAPPER.getElementsByTagName( 'a' )[ 0 ],
\r
3975 MouseEvent.add( SUPER_USER_KEY, ELM_WRAPPER, 'click', onClick );
\r
3977 ELM_FILENAME.className = 'file-icon-' + file.getType();
\r
3978 ELM_FILENAME.innerHTML = file.getName();
\r
3980 function resize( index ){
\r
3981 ELM_WRAPPER.style.left = ( index * 90 ) + 'px';
\r
3983 function onClick(){
\r
3984 callback( index );
\r
3987 this.init = function( _file, _elmContainer, _index, _callback ){
\r
3989 if( elmContainer !== _elmContainer ){
\r
3990 _elmContainer.appendChild( ELM_WRAPPER );
\r
3991 elmContainer = _elmContainer;
\r
3993 if( file !== _file){
\r
3997 if( index !== _index){
\r
4001 callback = _callback;
\r
4003 this.elm = ELM_WRAPPER;
\r
4004 this.index = function( _index ){
\r
4007 this.onResize = function( w ){
\r
4010 this.destroy = function(){
\r
4011 elmContainer.removeChild( ELM_WRAPPER );
\r
4012 file = elmContainer = null;
\r
4013 BREAD_OBJECT_POOL.push( this );
\r
4017 var FinderClass = function( application, elmRoot, tree, header, footer, onSelect, viewerOption, editorOption ){
\r
4018 var ICON_ARRAY = [],
\r
4020 elmContainer = ELM_ORIGIN_CONTAINER.cloneNode( true ),
\r
4021 elmLocation = elmContainer.getElementsByTagName( 'ul' )[ 0 ],
\r
4022 nodesDiv = elmContainer.getElementsByTagName( 'div' ),
\r
4023 elmSidebarButton = nodesDiv[ 1 ],
\r
4024 elmStyleButton = nodesDiv[ 2 ],
\r
4025 elmActionButton = nodesDiv[ 3 ],
\r
4026 elmBody = nodesDiv[ nodesDiv.length -1 ],
\r
4029 headH = Util.getElementSize( nodesDiv[ 0 ] ).height,
\r
4031 currentFile = null,
\r
4033 size = Util.getElementSize( ELM_ORIGIN_FINDER_ICON ),
\r
4034 iconW = size.width,
\r
4035 iconH = size.height,
\r
4040 tree.addTreeEventListener( Const.TREE.EVENT.UPDATE, draw );
\r
4041 elmRoot.appendChild( elmContainer );
\r
4043 function draw( _w, _h ){
\r
4044 w = Type.isFinite( _w ) === true ? _w : w;
\r
4045 h = Type.isFinite( _h ) === true ? _h : h;
\r
4046 bodyH = h - headH;
\r
4047 var l = tree.hierarchy() + 1,
\r
4048 m = BREAD_ARRAY.length,
\r
4050 for( var i=0; i<l; ++i ){
\r
4051 _file = i !== l-1 ? tree.getParentFileAt( i ) : tree.getCurrentFile();
\r
4053 BREAD_ARRAY[ i ].init( _file, elmLocation, i, onHeadClick );
\r
4055 BREAD_ARRAY.push( getBreadcrumb( _file, elmLocation, i, onHeadClick ));
\r
4058 while( l < BREAD_ARRAY.length ){
\r
4059 BREAD_ARRAY.pop().destroy();
\r
4062 l = _file.getChildFileLength();
\r
4063 m = ICON_ARRAY.length;
\r
4065 for( i=0; i<l; ++i ){
\r
4067 ICON_ARRAY[ i ].init( _file.getChildFileByIndex( i ), elmBody, w, i, style, onDown, onEditor, onViwer, onAction );
\r
4069 ICON_ARRAY.push( getFinderIcon( _file.getChildFileByIndex( i ), elmBody, _w, i, style, onDown, onEditor, onViwer, onAction ));
\r
4072 if( _file.getState() === Const.FILE.STATE.LOADING ){
\r
4073 elmBody.className = 'finder-body loading';
\r
4075 elmBody.className = 'finder-body';
\r
4078 elmBody.style.height = bodyH + 'px';
\r
4080 while( l < ICON_ARRAY.length && ICON_ARRAY.length > 0 ){
\r
4081 ICON_ARRAY.pop().destroy();
\r
4085 function onHeadClick( i ){
\r
4086 var l = BREAD_ARRAY.length - 1;
\r
4088 var _file = tree.getParentFileAt( i);
\r
4089 if( _file !== null){
\r
4095 function onDown( i ){
\r
4096 if( i < ICON_ARRAY.length ){
\r
4097 var _file = tree.getCurrentFile().getChildFileByIndex( i );
\r
4098 if( _file !== null && ( _file.getChildFileLength() !== -1 || _file.getType() === Const.FILE.TYPE.FOLDER )){
\r
4102 Type.isFunction( onSelect ) === true && onSelect( _file );
\r
4107 function onEditor( _file, _app, editorOption ){
\r
4108 _app.boot( _file, editorOption );
\r
4110 function onViwer( _file, _app ){
\r
4111 _app.boot( _file, viewerOption );
\r
4113 function onAction( _file ){
\r
4116 this.MIN_WIDTH = 240;
\r
4117 this.MIN_HEIGHT = 240;
\r
4118 this.onInit = function(){
\r
4119 var position = Util.getAbsolutePosition( elmLocation );
\r
4120 headX = position.x;
\r
4121 headY = position.y;
\r
4122 bodyY = Util.getAbsolutePosition( elmBody ).y;
\r
4124 this.onPaneResize = function( _w, _h ){
\r
4129 elmBody.style.height = ( _h - headH ) + 'px';
\r
4131 for( var i = ICON_ARRAY.length; i; ){
\r
4132 ICON_ARRAY[ --i ].onResize( _w );
\r
4135 this.destroy = function(){
\r
4136 tree.removeTreeEventListener( Const.TREE.EVENT.UPDATE, draw );
\r
4138 while( BREAD_ARRAY.length > 0 ){
\r
4139 BREAD_ARRAY.shift().destroy();
\r
4141 while( ICON_ARRAY.length > 0 ){
\r
4142 ICON_ARRAY.shift().destroy();
\r
4145 FINDER_ARRAY.splice( Util.getIndex( FINDER_ARRAY, instance ), 1 );
\r
4148 FinderClass.prototype = new AbstractBasicPane();
\r
4150 function getFinderIcon( _file, _elmContainer, w, index, style, onDown, onEditor, onViwer, onAction ){
\r
4152 if( FINDER_ICON_POOL.length > 0){
\r
4153 _icon = FINDER_ICON_POOL.shift();
\r
4155 _icon = new FinderIconClass();
\r
4157 _icon.init( _file, _elmContainer, w, index, style, onDown, onEditor, onViwer, onAction );
\r
4161 function getBreadcrumb( _file, _elmContainer, index, callback ){
\r
4163 if( BREAD_OBJECT_POOL.length > 0 ){
\r
4164 _bread = BREAD_OBJECT_POOL.shift();
\r
4166 _bread = new BreadcrumbClass();
\r
4168 _bread.init( _file, _elmContainer, index, callback );
\r
4176 create: function( _application, _elmTarget, _tree, _header, _footer, _onSelect, _viewerOption, _editorOption ){
\r
4177 //if( Application.isApplicationInstance( _application ) === false ) return;
\r
4179 var _finder = new FinderClass( _application, _elmTarget, _tree, _header, _footer, _onSelect, _viewerOption, _editorOption );
\r
4181 FINDER_ARRAY.push( _finder );
\r
4184 registerFinderHead: function(){
\r
4187 registerFinderPane: function( _finderPane ){
\r
4190 isFinderInstance: function( _finder ){
\r
4191 return _finder instanceof FinderClass;
\r
4193 isFinderPaneInstance: function(){
\r
4196 isFinderHeadInstance: function(){
\r
4202 /* --------------------------------------------
\r
4206 Application.onCurrentApplicationChange( SUPER_USER_KEY );
\r
4208 SERVICE_LIST.push( MouseEvent );
\r
4210 new EventTicketClass( window, 'unload', function(){
\r
4212 while( SERVICE_LIST.length > 0 ){
\r
4213 _service = SERVICE_LIST.shift();
\r
4214 Type.isFunction( _service.onSystemShutdown ) === true && _service.onSystemShutdown();
\r
4220 /* ---------------------------------------------
\r
4221 * broadcast to global
4225 gOS.registerApplication = Application.register;
\r
4226 gOS.registerDriver = File.registerDriver;
\r