8 var pettanr = ( function(){
\r
9 var FUNCTION_ARRAY = [],
\r
10 URL = document.location.href.split( '#')[ 0],
\r
11 IS_LOCAL = URL.indexOf( 'file:') === 0,
\r
12 URL_PARAMS = ( function(){
\r
13 var search = document.location.search,
\r
16 var query = search.substring( 1),
\r
17 params = query.split( '&'),
\r
18 ret = {}, elm, name;
\r
19 while( params.length > 0){
\r
20 elm = params.shift().split( '=');
\r
21 name = decodeURIComponent( elm[ 0]);
\r
22 if( elm.length === 2){
\r
23 ret[ name] = ( function( v){
\r
24 if( '' + parseFloat( v) === v) return parseFloat( v);
\r
25 if( v === 'true') return true;
\r
26 if( v === 'false') return false;
\r
27 if( v === 'null') return null;
\r
28 if( v === 'undefined') return undefined;
\r
30 })( decodeURIComponent( elm[ 1]));
\r
32 if( elm.length === 1){
\r
40 IS_DEBUG = IS_LOCAL === true || URL_PARAMS.debug === true,
\r
41 jqWindow , jqDocument , jqBody;
\r
45 jqWindow = $( window);
\r
46 jqDocument = $( document);
\r
47 jqBody = $( document.body);
\r
49 var l = FUNCTION_ARRAY.length,
\r
51 for( var i=0; i<l; i++){
\r
52 _fn = FUNCTION_ARRAY[ i];
\r
53 _fn.init && _fn.init( _fn === pettanr.view ? FUNCTION_ARRAY : undefined);
\r
56 delete pettanr.init;
\r
59 FUNCTION_ARRAY.push( _fn);
\r
60 pettanr.init === undefined && _fn.init && _fn.init();
\r
62 jqWindow: function(){
\r
65 jqDocument: function(){
\r
71 URL_PARAMS: URL_PARAMS,
\r
80 * extend( baseInstance, extend)
\r
81 * cleanCommnetNode()
\r
83 * getElementSize( _elm)
\r
86 * getGrobalObjectName()
\r
89 pettanr.util = ( function(){
\r
90 var ELM_SIZE_GETTER = ( function(){
\r
91 var ret = document.createElement( 'DIV'),
\r
93 ret.id = 'elmSizeGetter';
\r
94 style.position = 'absolute';
\r
96 style.top = '-9999px';
\r
97 style.visibility = 'hidden';
\r
98 document.body.appendChild( ret);
\r
101 IMG_SIZE_GETTER = ( function(){
\r
102 var ret = ELM_SIZE_GETTER.cloneNode( true);
\r
103 ret.id = 'imgSizeGetter';
\r
104 document.body.appendChild( ret);
\r
107 CLEAN_TARGET_ELEMENT = 'script,style,object,applet,embed,iframe,frame,base,bgsound,frameset,listing'.split( ',');
\r
109 /* clean comment node */
\r
110 cleanCommnetNode();
\r
112 /* clean noscript */
\r
113 var nodeNoscript = document.getElementsByTagName( 'noscript'),
\r
115 for(var i=0; i<nodeNoscript.length; ++i){
\r
116 noscript = nodeNoscript[i];
\r
117 noscript.parentNode && noscript.parentNode.removeChild( noscript);
\r
119 nodeNoscript = noscript = null;
\r
121 function cleanCommnetNode( _targetElm){
\r
122 var _elms = ( _targetElm || document).getElementsByTagName( '*'),
\r
125 while( i < _elms.length){
\r
127 if( _elm.nodeType === 8 && _elm.parentNode){
\r
128 _elm.parentNode.removeChild( _elm);
\r
135 extend: function( baseInstance, extend){
\r
136 for( var key in extend){
\r
137 baseInstance[ key] = extend[ key];
\r
139 return baseInstance;
\r
141 createGlobalUniqueName: function(){
\r
142 var randomKey = null;
\r
144 randomKey = '_uniqueName'+(''+Math.random()).replace(/\./,'');
\r
145 if( window[randomKey] === undefined){
\r
151 cleanCommnetNode: cleanCommnetNode,
\r
152 cleanElement: function( _targetElm){
\r
153 var l = CLEAN_TARGET_ELEMENT.length,
\r
155 for( var i=0; i<l; ++i){
\r
156 elms = _targetElm.getElementsByTagName( CLEAN_TARGET_ELEMENT[ i]);
\r
157 if( elms.length > 0){
\r
158 for( j=0; i<elms.length; ++j){
\r
160 elm.parentNode && elm.parentNode.removeChild( elm);
\r
164 cleanCommnetNode( _targetElm);
\r
165 if( pettanr.ua.isIE === false) return;
\r
166 elms = document.getElementsByName( '*');
\r
168 for(i=0; i<l; ++i){
\r
170 elm.style.filter = '';
\r
171 elm.style.behavior = '';
\r
174 getElementSize: function( _elm){
\r
181 var parentElm = _elm.parentNode,
\r
182 prevElm = _elm.previousSibling,
\r
183 nextElm = _elm.nextSibling,
\r
184 displayNone = _elm.style.display === 'none';
\r
185 if( displayNone === true) _elm.style.display = '';
\r
186 ELM_SIZE_GETTER.appendChild( _elm);
\r
188 width: _elm.offsetWidth,
\r
189 height: _elm.offsetHeight
\r
191 if( displayNone === true) _elm.style.display = 'none';
\r
193 parentElm.insertBefore( _elm, nextElm);
\r
195 if( prevElm && prevElm.nextSibling){
\r
196 parentElm.insertBefore( _elm, prevElm.nextSibling);
\r
198 parentElm && parentElm.appendChild( _elm);
\r
202 getImageSize: function( img){
\r
203 var parentElm = img.parentNode,
\r
204 prevElm = img.previousSibling,
\r
205 nextElm = img.nextSibling,
\r
206 displayNone = img.style.display === 'none';
\r
207 if( displayNone === true) img.style.display = '';
\r
208 IMG_SIZE_GETTER.appendChild( img);
\r
209 var size = getActualDimension( img);
\r
210 IMG_SIZE_GETTER.removeChild( img);
\r
211 if( displayNone === true) img.style.display = 'none';
\r
213 parentElm.insertBefore( img, nextElm);
\r
215 if( prevElm && prevElm.nextSibling){
\r
216 parentElm.insertBefore( img, prevElm.nextSibling);
\r
218 parentElm && parentElm.appendChild( img);
\r
223 * AUTHOR: uupaa.js@gmail.com
\r
225 function getActualDimension(image) {
\r
226 var run, mem, w, h, key = "actual";
\r
228 // for Firefox, Safari, Google Chrome
\r
229 if ("naturalWidth" in image) {
\r
231 width: image.naturalWidth,
\r
232 height: image.naturalHeight
\r
236 if ("src" in image) { // HTMLImageElement
\r
237 if (image[key] && image[key].src === image.src) {
\r
240 if (document.uniqueID) { // for IE
\r
241 run = image.runtimeStyle;
\r
242 mem = { w: run.width, h: run.height }; // keep runtimeStyle
\r
243 run.width = "auto"; // override
\r
244 run.height = "auto";
\r
247 run.width = mem.w; // restore
\r
248 run.height = mem.h;
\r
249 } else { // for Opera and Other
\r
255 mem = { w: image.width, h: image.height }; // keep current style
\r
256 image.removeAttribute("width");
\r
257 image.addEventListener("DOMAttrModified", fn, false);
\r
258 image.removeAttribute("height");
\r
260 image.removeEventListener("DOMAttrModified", fn, false);
\r
261 image.width = mem.w; // restore
\r
262 image.height = mem.h;
\r
264 mem = { w: image.width, h: image.height }; // keep current style
\r
265 image.removeAttribute("width");
\r
266 image.removeAttribute("height");
\r
269 image.width = mem.w; // restore
\r
270 image.height = mem.h;
\r
272 return image[key] = { width: w, height: h, src: image.src }; // bond
\r
274 // HTMLCanvasElement
\r
275 return { width: image.width, height: image.height };
\r
278 loadImage: function( URLorELM, onLoad, onError, delay, timeout){
\r
279 delay = delay || 250;
\r
280 timeout = timeout || 5000;
\r
281 var type = typeof URLorELM,
\r
282 img, images, src, abstractPath;
\r
283 if( type === 'string'){
\r
287 // http://d.hatena.ne.jp/hottolinkblog/20090228/1235823487
\r
288 if( type === 'object' && typeof URLorELM.hspace !== 'undefined' && typeof URLorELM.vspace !== 'undefined'){
\r
295 abstractPath = this.getAbsolutePath( src);
\r
297 loadImage( images, abstractPath,
\r
298 function( abspath, actualW, actualH){
\r
299 if( abstractPath !== abspath) return;
\r
300 onLoad && setTimeout( function(){ // 一度読み込まれた画像は即座にonLoadされてしまうので遅延
\r
301 onLoad( src, actualW, actualH);
\r
304 function( abspath){
\r
305 if( abstractPath !== abspath) return;
\r
306 onError && setTimeout( function(){
\r
313 * URL: http://d.hatena.ne.jp/uupaa/20080413/1208067631
\r
314 * AUTHOR: uupaa.js@gmail.com
\r
316 * fixed for ie6-8 by pettanr
\r
317 * new Image -> document.createElement( 'IMG')
\r
319 function loadImage( images, abspath, onLoad, onError, delay, timeout) {
\r
320 images = images || document.images;
\r
322 i = 0, l = images.length,
\r
324 for(; i < l; ++i) {
\r
326 if ( img.src === abspath && img.complete) {
\r
327 var size = pettanr.util.getImageSize( img);
\r
328 onLoad( abspath, size.width, size.height);
\r
332 img = document.createElement( 'img'); //var img = new Image(); ではieでimgのsizeが取れない、、、removeChildも失敗し、imgSizeGetterにimgが残る
\r
333 img.finish = false;
\r
334 img.onabort = img.onerror = function() {
\r
335 if (img.finish) { return; }
\r
338 img.onload = img.onabort = img.onerror = "";
\r
340 img.onload = function() {
\r
342 if (window.opera && !img.complete) {
\r
344 img.onload = img.onabort = img.onerror = "";
\r
347 var size = pettanr.util.getImageSize( img);
\r
348 onLoad( abspath, size.width, size.height);
\r
349 img.onload = img.onabort = img.onerror = "";
\r
353 if (!img.finish && timeout) {
\r
354 setTimeout(function() {
\r
355 if (img.finish) { return; }
\r
356 if (img.complete) {
\r
358 if (img.width) { return; }
\r
360 img.onload = img.onabort = img.onerror = "";
\r
363 if ((tick += delay) > timeout) {
\r
366 img.onload = img.onabort = img.onerror = "";
\r
369 setTimeout(arguments.callee, delay);
\r
374 getAbsolutePath: function( path) {
\r
375 var e = document.createElement("div");
\r
376 e.innerHTML = '<a href=\"' + path + '\" />';
\r
377 return e.firstChild.href;
\r
379 getAbsolutePosition: function( _elm){
\r
380 // Find the destination's position
\r
381 var destx = _elm.offsetLeft,
\r
382 desty = _elm.offsetTop,
\r
384 body = document.body;
\r
385 while (thisNode.offsetParent && thisNode.offsetParent !== body){
\r
386 thisNode = thisNode.offsetParent;
\r
387 destx += thisNode.offsetLeft;
\r
388 desty += thisNode.offsetTop;
\r
395 pullHtmlAsTemplete: function( IDorELM){
\r
396 if( typeof IDorELM === 'string'){
\r
397 IDorELM = document.getElementById( IDorELM);
\r
399 if( !IDorELM) return;
\r
400 IDorELM.parentNode && IDorELM.parentNode.removeChild( IDorELM);
\r
401 if( IDorELM.id && IDorELM.id.indexOf( 'templete-') === 0){
\r
415 pettanr.ua = ( function(){
\r
416 var ua = (function(){
\r
420 var dua = n.userAgent;
\r
421 var dav = n.appVersion;
\r
422 var tv = parseFloat(dav);
\r
423 acme.isOpera = (dua.indexOf("Opera") >= 0) ? tv: undefined;
\r
424 acme.isKhtml = (dav.indexOf("Konqueror") >= 0) ? tv : undefined;
\r
425 acme.isWebKit = parseFloat(dua.split("WebKit/")[1]) || undefined;
\r
426 acme.isChrome = parseFloat(dua.split("Chrome/")[1]) || undefined;
\r
427 var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0);
\r
428 if(index && !acme.isChrome){
\r
429 acme.isSafari = parseFloat(dav.split("Version/")[1]);
\r
430 if(!acme.isSafari || parseFloat(dav.substr(index + 7)) <= 419.3){
\r
434 if(document.all && !acme.isOpera){
\r
435 acme.isIE = parseFloat(dav.split("MSIE ")[1]) || undefined;
\r
440 isIE = navigator.userAgent.toLowerCase().indexOf( 'msie') !== -1,
\r
441 ieVersion = isIE === true ? parseInt( navigator.appVersion.toLowerCase().replace( /.*msie[ ]/, '').match( /^[0-9]+/)) : 0,
\r
442 ieRenderingVersion = ieVersion === 8 ? document.documentMode : ieVersion,
\r
443 isStanderdMode = document.compatMode === 'CSS1Compat',
\r
444 VML = ( function(){
\r
445 if( isIE === false || ieVersion > 8) return false;
\r
446 var globalObjectName = pettanr.util.createGlobalUniqueName(),
\r
448 document.write( [ '<!--[if gte vml 1]><script id="detectVML">window', '.', globalObjectName, '=1;<\/script><![endif]-->'].join( ''));
\r
449 if( window[globalObjectName] === 1){
\r
450 script = document.getElementById( 'detectVML');
\r
451 script.parentNode.removeChild( script);
\r
452 window[globalObjectName] = script = null;
\r
455 //pettanr.util.cleanCommnetNode();
\r
458 isStandAloneMode = ( function(){
\r
459 if( isIE === false) return false;
\r
460 if( VML === true) return false;
\r
461 var globalObjectName = pettanr.util.createGlobalUniqueName(),
\r
463 document.write( [ '<!--[if IE ', Math.floor( ieVersion), ']><script id="detectStandAlone">window', '.', globalObjectName, '=1;<\/script><![endif]-->'].join( ''));
\r
464 if( window[globalObjectName] === 1){
\r
465 script = document.getElementById( 'detectStandAlone');
\r
466 script.parentNode.removeChild( script);
\r
467 window[globalObjectName] = script = null;
\r
470 //pettanr.util.cleanCommnetNode();
\r
478 WEBKIT: ua.isWebKit,
\r
479 CHROME: ua.isChrome,
\r
481 ieVersion: ieVersion,
\r
482 ieRenderingVersion: ieRenderingVersion,
\r
483 isStanderdMode: isStanderdMode,
\r
484 VENDER_PREFIX: ( function() {
\r
485 var ua = navigator.userAgent.toLowerCase();
\r
486 if ( ua.indexOf('opera') !== -1) {
\r
488 } else if ( ua.indexOf('msie') !== -1) {
\r
490 } else if ( ua.indexOf('webkit') !== -1) {
\r
492 } else if ( navigator.product === 'Gecko') {
\r
497 ACTIVEX: ( function(){
\r
498 if( isIE === false || ieVersion > 8) return false;
\r
499 var className = document.body.className,
\r
501 if( className && className.indexOf( 'pettanr-ActiveX-enabled') !== -1) return true;
\r
502 if( className && className.indexOf( 'pettanr-ActiveX-disabled') !== -1) return false;
\r
504 test = new ActiveXObject('DXImageTransform.Microsoft.gradient');
\r
511 STANDALONE: isStandAloneMode,
\r
512 startVML: function(){
\r
513 delete this.startVML;
\r
514 if( pettanr.ua.VML !== true) return false;
\r
515 if (!document.namespaces["v"]) {
\r
516 document.namespaces.add("v", "urn:schemas-microsoft-com:vml", "#default#VML");
\r
518 document.createStyleSheet().cssText = "v\:shape,v\:image{behavior:url(#default#VML);display:block;};";
\r
524 pettanr.CONST = ( function(){
\r
525 var isLocal = pettanr.LOCAL === true || pettanr.URL_PARAMS.exjson === false;
\r
527 URL_ORIGINAL_PICTURES_JSON: ( isLocal === true ? 'json\/' : 'http:\/\/pettanr.heroku.com\/') + 'original_pictures.json',
\r
528 URL_PANELS_JSON: ( isLocal === true ? 'json\/' : 'http:\/\/pettanr.heroku.com\/') + 'panels.json'
\r
533 pettanr.view = ( function(){
\r
534 /* create iframe overlay for user console */
\r
535 var location = document.location.pathname,
\r
536 isWorkPage = location.indexOf( '\/work.html') !== -1 || location.indexOf( '\work.html') !== -1,
\r
537 deep = location.indexOf( '\/diary\/') !== -1 ||
\r
538 location.indexOf( '\/text\/') !== -1 ||
\r
539 location.indexOf( '\/help\/') !== -1 ||
\r
540 location.indexOf( '\/sitemap\/') !== -1 ||
\r
541 location.indexOf( '\/wiki\/') !== -1,
\r
544 if( isWorkPage === false){
\r
545 LoginUserNavi = ( function(){
\r
546 var _body = document.body,
\r
547 _root = document.getElementsByTagName( 'html')[ 0],
\r
549 iframe, visible = false;
\r
551 init: function( viewIndex){
\r
552 filter = document.createElement( 'div');
\r
553 filter.style.position = 'absolute';
\r
554 filter.style.left = filter.style.top = '0px';
\r
555 filter.style.width = filter.style.height ='100%';
\r
556 filter.style.backgroundColor = '#fff';
\r
558 var ua = pettanr.ua,
\r
561 deep === true ? '../' : '',
\r
563 typeof viewIndex === 'number' ? '?view=' +viewIndex : ''
\r
566 var el = document.createElement(ua.isIE ? '<iframe name="' + id + '" src="' + src + '">' : 'iframe');
\r
567 el.id = el.name = id;
\r
568 el.setAttribute( 'name', id);
\r
570 el.style.position = 'absolute';
\r
571 el.style.left = el.style.top = '0px';
\r
572 el.style.width = el.style.height ='100%';
\r
573 //el.style.overflow = 'hidden';
\r
574 el.hspace = el.vspace = el.marginheight = el.marginwidth = 0;
\r
576 _body.appendChild(el);
\r
581 var idoc;//WebKit > 521 corresponds with Safari 3, which started with 522 WebKit version.
\r
582 if (ua.isWebKit > 521) {
\r
583 idoc = el.contentWindow.document;
\r
584 } else if (ua.isSafari) {
\r
585 idoc = el.document;
\r
586 } else { // if(d.isMozilla){
\r
587 idoc = el.contentWindow;
\r
593 el.contentWindow.location.replace = src;
\r
596 //el.contentWindow.location = src;
\r
599 el.location = src; // for Safari 2.0.3 ??
\r
602 } else if( ua.isOpera){
\r
603 el.src = src; // for Opera
\r
604 el.contentWindow.location.replace = src; // for Opera
\r
606 //el.src = src; // for firefox
\r
607 idoc.location.replace(src);
\r
611 delete LoginUserNavi.init;
\r
614 if(visible === true) return;
\r
616 _root.style.overflow = 'hidden';
\r
618 _body.style.overflow = 'hidden';
\r
620 var index = ( function( a){
\r
621 var node = a.parentNode.getElementsByTagName( 'a'),
\r
623 for( var i=0; i<l; ++i){
\r
624 if( node[ i] === a) return i
\r
628 if( index === -1) return false;
\r
630 LoginUserNavi.init && LoginUserNavi.init( index);
\r
632 iframe.parentNode !== _body && _body.appendChild( iframe);
\r
634 _body.insertBefore( filter, iframe);
\r
641 if(visible === false) return;
\r
643 _body.removeChild(filter);
\r
644 _body.style.overflow = '';
\r
646 _root.style.overflow = '';
\r
648 _body.removeChild(iframe);
\r
655 LoginUserNavi = ( function(){
\r
658 var index = ( function( a){
\r
659 var node = a.parentNode.getElementsByTagName( 'a'),
\r
661 for( var i=0; i<l; ++i){
\r
662 if( node[ i] === a) return i
\r
666 if( index === -1) return false;
\r
668 pettanr.view.show( index);
\r
675 var elmDl = document.getElementById( 'useragent'),
\r
678 ua: navigator.userAgent,
\r
679 platform: navigator.platform,
\r
680 appVersion: navigator.appVersion,
\r
681 appCodeName:navigator.appCodeName,
\r
682 appName: navigator.appName,
\r
683 language: navigator.browserLanguage || navigator.language
\r
687 //data.ua = 'Internet Explorer';
\r
688 data.version = ua.IE;
\r
689 if( ua.ieVersion >= 8) data.RenderingVersion = ua.ieRenderingVersion;
\r
690 data.browserType = ua.STANDALONE === true ? 'Standalone' : 'bundle';
\r
691 if( ua.ieVersion < 9) {
\r
697 data.RenderingMode = ua.isStanderdMode === true ? 'Standerd' : 'Quirks';
\r
699 for( var key in data){
\r
700 elmDt = document.createElement( 'dt');
\r
701 elmDt.innerHTML = key;
\r
702 elmDd = document.createElement( 'dd');
\r
703 elmDd.innerHTML = '' + data[ key];
\r
704 if( !data[ key]) elmDd.style.color = 'red';
\r
705 elmDl.appendChild( elmDt);
\r
706 elmDl.appendChild( elmDd);
\r
711 var navi = document.getElementById('global-navi'),
\r
712 origin = document.createElement('a'),
\r
713 items = ( function(){
\r
714 var ret = ['Home', 'Comic list', 'Picture', 'Setting'];
\r
715 if( pettanr.DEBUG === true) {
\r
716 ret.push( 'debug');
\r
717 navi.style.width = '400px';
\r
724 for(var i=0; i<l; ++i){
\r
725 item = origin.cloneNode( true);
\r
726 item.innerHTML = items[ i];
\r
727 item.onclick = LoginUserNavi.show;
\r
728 navi.appendChild( item);
\r
730 location = origin = item = null;
\r
733 // ua version, lang, os, plugin ( vml, svg), standerdmode, balloon, rimg
\r
736 * window resize event, overlay と currentなviewに流す
\r
738 * editor, overlay, comic-viewer, image-explorer
\r
744 HOME_ID = 'entrance',
\r
745 VIEW_ID_ARRAY = [ HOME_ID, 'cabinet', 'gallery', 'backyard'],
\r
748 currentID = ( function( _view){
\r
751 if( typeof _view === 'number' && _view < VIEW_ID_ARRAY.length){
\r
752 _viewID = VIEW_ID_ARRAY[ _view];
\r
754 if( typeof _view === 'string'){
\r
760 if( document.getElementById( _viewID)){
\r
764 })( pettanr.URL_PARAMS.view);
\r
766 pettanr.DEBUG === true && VIEW_ID_ARRAY.push( 'debug');
\r
770 function onWindowResize(){
\r
772 l = funcArray.length,
\r
773 w = jqWindow.width(),
\r
774 h = jqWindow.height();
\r
775 //for( var i=0; i<l; ++i){
\r
776 // _fn = funcArray[ i];
\r
777 // _fn.onWindowResize && _fn.onWindowResize( w, h);
\r
779 currentView && currentView.onWindowResize && currentView.onWindowResize( w, h);
\r
780 pettanr.overlay.currentID !== null && pettanr.overlay.onWindowResize( w, h);
\r
783 if( isWorkPage === false) return;
\r
785 var _elm = document.getElementById( currentID);
\r
786 if( elmCurrent) elmCurrent.style.display = 'none';
\r
787 _elm.style.display = 'block';
\r
790 var nodesA = navi.getElementsByTagName( 'a') || [],
\r
793 for(var i=0; i<l; ++i){
\r
795 nodesA[ i].className = VIEW_ID_ARRAY[ i] === currentID ? 'current' : '';
\r
799 if( !pettanr.view || pettanr.view.init !== undefined) return;
\r
800 currentView = pettanr[ currentID];
\r
801 if( !currentView) return;
\r
802 typeof currentView.onOpen === 'function' && currentView.onOpen();
\r
803 setTimeout( onWindowResize, 0);
\r
806 init: function( _funcArray){
\r
807 funcArray = _funcArray;
\r
808 jqWindow = pettanr.jqWindow();
\r
809 jqWindow.resize( onWindowResize);
\r
811 currentView = currentView || pettanr[ currentID];
\r
812 currentView && typeof currentView.onOpen === 'function' && currentView.onOpen();
\r
814 setTimeout( onWindowResize, 100);
\r
816 delete pettanr.view.init;
\r
818 show: function( _viewID){
\r
819 if( typeof _viewID === 'number' && _viewID < VIEW_ID_ARRAY.length){
\r
820 _viewID = VIEW_ID_ARRAY[ _viewID];
\r
822 if( typeof _viewID === 'string'){
\r
827 for( var key in pettanr.view){
\r
828 if( pettanr.view[ key] === _viewID){
\r
829 if( currentID !== _viewID && document.getElementById( _viewID)){
\r
830 this.currentID = currentID = _viewID;
\r
838 currentID: currentID,
\r
840 COMICS: VIEW_ID_ARRAY[ 1],
\r
841 IMAGES: VIEW_ID_ARRAY[ 2],
\r
842 SETTING: VIEW_ID_ARRAY[ 3],
\r
843 DEBUG: VIEW_ID_ARRAY[ 4],
\r
849 pettanr.overlay = ( function(){
\r
850 var SHADOW_OPACITY = 0.5,
\r
851 jqConteiner, jqShadow, jqCloseButton,// jqBody,
\r
852 currentOverlay = null,
\r
857 var IMAGE_GROUP_EXPROLER = ( function(){
\r
858 var ICON_ARRAY = [],
\r
860 containerW, containerH, wrapX,
\r
861 jqWrap, jqContainer, jqItemOrigin,
\r
863 jqName, jqButton, buttonW,
\r
864 folder, onUpdateFunction,
\r
866 onEnterInterval = null;
\r
868 var BASE_PATH = pettanr.LOCAL === false ? 'http://pettan.heroku.com/images/' : 'images/',
\r
869 THUMB_PATH = BASE_PATH, // + 'thumbnail/',
\r
870 LIMIT_FILESIZE = 1024 * 10; // 10KB
\r
871 var IMAGE_DATA = 0;
\r
873 var ImageGroupIconClass = function( INDEX, data){
\r
874 var JQ_ICON_WRAP = jqItemOrigin.clone( true),
\r
875 SRC = [ BASE_PATH, data.id, '.', data.ext].join( ''),
\r
876 LOW_SRC = data.filesize && data.filesize > LIMIT_FILESIZE ? [ THUMB_PATH, data.id, '.', data.ext].join( '') : null,
\r
877 reversibleImage = null,
\r
879 onEnterFlag = false;
\r
880 JQ_ICON_WRAP.children( 'div').eq( 0).html( data.filesize + 'bytes');
\r
881 jqContainer.append( JQ_ICON_WRAP.css( { left: INDEX * itemW}));
\r
883 function onLoad( url, _imgW, _imgH){
\r
884 if( reversibleImage === null) {
\r
888 actualW = _imgW || 64;
\r
889 actualH = _imgH || 64;
\r
890 JQ_ICON_WRAP.children( 'div').eq( 1).html( actualW +'x' +actualH);
\r
891 var zoom = 128 /( actualW > actualH ? actualW : actualH),
\r
892 _h = Math.floor( actualH *zoom),
\r
893 _w = Math.floor( actualW *zoom);
\r
894 reversibleImage.elm.style.width = _w +'px';
\r
895 reversibleImage.elm.style.height = _h +'px';
\r
896 reversibleImage.elm.style.margin = Math.floor( itemH /2 -_h /2)+'px 0 0';
\r
897 reversibleImage.resize( _w, _h);
\r
898 JQ_ICON_WRAP.click( onClick);
\r
901 function onClick( e){
\r
902 pettanr.overlay.hide();
\r
903 if (onUpdateFunction) {
\r
904 if( LOW_SRC === null){
\r
905 onUpdateFunction( SRC, actualW, actualH);
\r
907 onCloseUpdate( onUpdateFunction); // close()で値が消えるので、クロージャに保持
\r
913 function onCloseUpdate( onUpdate){
\r
914 pettanr.util.loadImage( SRC,
\r
915 function( _abspath, imgW, imgH){
\r
916 onUpdate( SRC, imgW, imgH);
\r
919 function( _abspath){
\r
920 onUpdate( SRC, data.width || 64, data.height || 64);
\r
927 onEnter: function(){
\r
928 if( onEnterFlag === true) return;
\r
929 reversibleImage = pettanr.image.createReversibleImage( LOW_SRC || SRC, itemW, itemH, onLoad);
\r
930 JQ_ICON_WRAP.children( 'img').replaceWith( reversibleImage.elm);
\r
931 onEnterFlag = true;
\r
933 destroy: function(){
\r
934 reversibleImage && reversibleImage.destroy();
\r
935 JQ_ICON_WRAP.remove();
\r
936 reversibleImage = JQ_ICON_WRAP = null;
\r
937 delete this.destroy;
\r
943 jqContainer.stop().animate( {
\r
945 top: Math.floor( windowH /2)
\r
949 while( ICON_ARRAY.length > 0){
\r
950 ICON_ARRAY.shift().destroy();
\r
952 onEnterInterval !== null && window.clearTimeout( onEnterInterval);
\r
953 onUpdateFunction = onEnterInterval = null;
\r
955 function onEnterShowImage(){
\r
956 var l = ICON_ARRAY.length,
\r
957 _start = -wrapX /itemW -1,
\r
958 _end = _start + winW /itemW +1;
\r
959 for( var i=0; i<l; ++i){
\r
960 _start < i && i < _end && ICON_ARRAY[ i].onEnter();
\r
962 onEnterInterval !== null && window.clearTimeout( onEnterInterval);
\r
963 onEnterInterval = null;
\r
965 function onCloseClick(){
\r
966 pettanr.overlay.hide();
\r
967 // onUpdateFunction && onUpdateFunction( textElement);
\r
970 function onMouseWheel( e, delta){
\r
971 if( winW < containerW){
\r
972 wrapX += delta *WHEEL_DELTA;
\r
973 wrapX = wrapX > 0 ? 0 : wrapX < winW -containerW ? winW -containerW : wrapX;
\r
974 jqContainer.css( { left: wrapX});
\r
976 onEnterInterval !== null && window.clearTimeout( onEnterInterval);
\r
977 onEnterInterval = window.setTimeout( onEnterShowImage, 500);
\r
979 //e.stopPropagation();
\r
984 this.jqWrap = jqWrap = $( '#image-gruop-wrapper').hide();
\r
985 jqContainer = $( '#image-icon-container').mousewheel( onMouseWheel);
\r
986 containerH = pettanr.util.getElementSize( jqContainer.get( 0)).height;
\r
987 jqItemOrigin = $( $( '#imageGruopItemTemplete').remove().html());
\r
988 var itemSize = pettanr.util.getElementSize( jqItemOrigin.get( 0));
\r
989 itemW = itemSize.width;
\r
990 itemH = itemSize.height;
\r
991 jqName = $( '#gruop-name-display');
\r
992 jqButton = $( '#image-gruop-button').click( onCloseClick);
\r
993 buttonW = pettanr.util.getElementSize( jqButton.get( 0)).width;
\r
995 delete IMAGE_GROUP_EXPROLER.init;
\r
998 show: function( _folder, _onUpdateFunction){
\r
999 this.init !== undefined && this.init();
\r
1002 onUpdateFunction = _onUpdateFunction;
\r
1003 pettanr.overlay.show( this);
\r
1005 var l = _folder.getChildFileLength();
\r
1006 for( var i=0; i<l; ++i){
\r
1007 ICON_ARRAY.push( new ImageGroupIconClass( i, _folder.getChildFileByIndex( i)));
\r
1010 containerW = l * itemW;
\r
1013 var w = winW > containerW ? winW : containerW,
\r
1014 h = windowH > containerH ? containerH : windowH;
\r
1017 jqContainer.css( {
\r
1021 top: Math.floor( windowH /2)
\r
1022 }).stop().animate( {
\r
1024 top: Math.floor( windowH /2 -h /2)
\r
1028 left: Math.floor( winW /2 -buttonW /2),
\r
1029 top: Math.floor( windowH /2 +containerH /2 +10)
\r
1032 onEnterShowImage();
\r
1034 onWindowResize: function( _windowW, _windowH){
\r
1035 var w = _windowW > containerW ? _windowW : containerW,
\r
1036 h = _windowH > containerH ? containerH : _windowH,
\r
1037 offsetW = Math.floor( _windowW /2 -winW /2);
\r
1039 if( offsetW <= 0){ // smaller
\r
1040 jqContainer.css( {
\r
1045 top: Math.floor( _windowH /2 -h /2)
\r
1048 jqContainer.css( { // bigger
\r
1051 borderLeftWidth: offsetW
\r
1053 top: Math.floor( _windowH /2 -h /2),
\r
1054 borderLeftWidth: 0
\r
1058 left: Math.floor( _windowW /2 -buttonW /2),
\r
1059 top: Math.floor( _windowH /2 +containerH /2 +10)
\r
1061 onEnterShowImage();
\r
1064 ID: 'imageGroupExproler'
\r
1072 currentOverlay && currentOverlay.onClose && currentOverlay.onClose();
\r
1073 pettanr.overlay.hide();
\r
1075 function asyncResize(){
\r
1076 currentOverlay.onWindowResize( windowW, windowH);
\r
1078 function onCloseClick( e){
\r
1080 e.preventDefault();
\r
1085 //jqBody = pettanr.jqBody();
\r
1086 jqConteiner = $( '#overlay-container');
\r
1087 jqShadow = $( '#overlay-shadow');
\r
1088 jqCloseButton = $( '#overlay-close-button').click( onCloseClick);
\r
1090 pettanr.key.addKeyDownEvent( pettanr.view.OVERLAY, 27, false, false, close); // 27.esc
\r
1092 delete pettanr.overlay.init;
\r
1094 show: function( _currentOverlay){
\r
1095 if( visible === true && currentOverlay === _currentOverlay) return;
\r
1096 jqConteiner.stop().css( {
\r
1100 this.visible = visible = true;
\r
1101 currentOverlay = _currentOverlay;
\r
1102 this.currentID = _currentOverlay.ID;
\r
1103 jqCloseButton.toggle( !!_currentOverlay.onClose);
\r
1106 currentOverlay = null;
\r
1107 if( visible === false) return;
\r
1108 jqConteiner.stop().css( {
\r
1112 this.visible = visible = false;
\r
1113 this.currentID = null;
\r
1117 onWindowResize: function( _windowW, _windowH){
\r
1118 jqConteiner.css( { height: _windowH});
\r
1119 jqShadow.css( { height: _windowH});
\r
1120 windowW = _windowW;
\r
1121 windowH = _windowH;
\r
1122 // 先にeditorのcanvasを確定する。
\r
1123 currentOverlay && currentOverlay.onWindowResize && setTimeout( asyncResize, 0);
\r
1128 /* ----------------------------------------
\r
1131 * - EDITABLE_TEXT_CONTROL
\r
1132 * - EditableTextClass
\r
1133 * .update: function,
\r
1134 * .show: function,
\r
1135 * .hide: function,
\r
1136 * .start: function,
\r
1137 * .finish: finish,
\r
1138 * .enabled: function,
\r
1139 * .index: function,
\r
1140 * .instance: function
\r
1142 * .SHIFT_DOWN_EVENT: 'shiftDown',
\r
1143 * .SHIFT_UP_EVENT: 'shiftUp',
\r
1144 * .CTRL_DOWN_EVENT: 'ctrlDown',
\r
1145 * .CTRL_UP_EVENT: 'ctrlUp',
\r
1146 * .SPACE_DOWN_EVENT: 'spaceDown',
\r
1147 * .SPACE_UP_EVENT: 'spaceUp',
\r
1148 * .init: function,
\r
1149 * .addKeyDownEvent: function,
\r
1150 * .keyEventDispatcher: function,
\r
1151 * .createEditableText: function,
\r
1153 * ショートカットキーの監視とテキスト入力(input, textarea)、チェックボックスを管理する。
\r
1154 * キー入力はdocumentで受けて、テキスト編集中(input, textarea)はそちらにキーイベント流す。
\r
1157 pettanr.key = ( function(){
\r
1160 keyOperationChatcher,
\r
1161 KEYEVENT_ARRAY = [],
\r
1162 shiftEnabled = false,
\r
1163 ctrlEnabled = false;
\r
1165 var EDITABLE_TEXT_CONTROL = ( function(){
\r
1166 var EDITABLE_TEXT_TABLE = {},
\r
1167 currentText = null;
\r
1169 var EditableTextClass = function( WRAPPER_ELM, ON_UPDATE_FUNCTION, GROUP_ID){
\r
1170 var ELM = WRAPPER_ELM.children( '.editable-value').eq( 0),
\r
1171 value = ELM.html(),
\r
1173 index = EDITABLE_TEXT_TABLE[ GROUP_ID].length,
\r
1176 A = $( '<a href="#"></a>').html( value).click( function(e){
\r
1177 instance = instance || EDITABLE_TEXT_TABLE[ GROUP_ID][ index];
\r
1178 EDITABLE_TEXT_CONTROL.start( instance);
\r
1180 jqInput = $( '<input type="text"/>').val( value);
\r
1181 ELM.append( jqInput);
\r
1182 jqInput.focus().select();
\r
1183 e.preventDefault();
\r
1186 ELM.addClass( 'editable-text').html( A);
\r
1189 update: function( _value){
\r
1190 value = _value !== undefined ? _value : value;
\r
1192 jqInput && jqInput.val( value);
\r
1193 currentText === instance && this.finish();
\r
1196 enabled === false && WRAPPER_ELM.show();
\r
1200 enabled === true && WRAPPER_ELM.hide();
\r
1203 start: function(){
\r
1204 !jqInput && A.click();
\r
1206 finish: function( keep){
\r
1207 var _newValue = keep === true ? value : jqInput.val();
\r
1208 A.html( _newValue).show();
\r
1211 ON_UPDATE_FUNCTION && _newValue !== value && ON_UPDATE_FUNCTION( _newValue, value);
\r
1212 EDITABLE_TEXT_CONTROL.finish( instance);
\r
1214 enabled: function(){
\r
1221 var CheckboxClass = function( WRAPPER_ELM, ON_UPDATE_FUNCTION, GROUP_ID){
\r
1222 var ELM = WRAPPER_ELM.children( '.checkbox-value').eq( 0),
\r
1223 value = ELM.html(),
\r
1225 index = EDITABLE_TEXT_TABLE[ GROUP_ID].length,
\r
1228 A = $( '<a href="#" onclick="return false;"></a>').html( value).click( function(e){
\r
1229 instance = instance || EDITABLE_TEXT_TABLE[ GROUP_ID][ index];
\r
1230 EDITABLE_TEXT_CONTROL.start( instance);
\r
1232 jqInput = $( '<input type="text"/>').val( value);
\r
1233 ELM.append( jqInput);
\r
1234 jqInput.focus().select();
\r
1235 e.preventDefault();
\r
1238 ELM.addClass( 'editable-text').html( A);
\r
1240 function finish(keep){
\r
1241 if(keep === true){
\r
1244 _finish( jqInput.val());
\r
1246 function _finish( VALUE_NEW){
\r
1247 value = VALUE_NEW;
\r
1248 A.html( VALUE_NEW).show();
\r
1251 ON_UPDATE_FUNCTION && VALUE_NEW !== value && ON_UPDATE_FUNCTION( VALUE_NEW, value);
\r
1252 EDITABLE_TEXT_CONTROL.finish( instance);
\r
1256 update: function( _value){
\r
1257 value = _value !== undefined ? _value : value;
\r
1259 jqInput && jqInput.val( value);
\r
1260 currentText === instance && finish();
\r
1263 enabled === false && WRAPPER_ELM.show();
\r
1267 enabled === true && WRAPPER_ELM.hide();
\r
1270 start: function(){
\r
1271 !jqInput && A.click();
\r
1274 enabled: function(){
\r
1281 createEditableText: function( ELM, ON_UPDATE_FUNCTION, GROUP_ID){
\r
1282 if( GROUP_ID && !EDITABLE_TEXT_TABLE[ GROUP_ID]) EDITABLE_TEXT_TABLE[ GROUP_ID] = [];
\r
1283 var ret = EditableTextClass.apply( {}, [ ELM, ON_UPDATE_FUNCTION, GROUP_ID]);
\r
1284 GROUP_ID && EDITABLE_TEXT_TABLE[ GROUP_ID].push( ret);
\r
1287 createCheckbox: function( ELM, ON_UPDATE_FUNCTION, GROUP_ID){
\r
1290 start: function( _currentText){
\r
1291 currentText !== _currentText && currentText && currentText.finish();
\r
1292 currentText = _currentText;
\r
1294 finish: function( _currentText){
\r
1295 if( currentText !== _currentText) return;
\r
1296 currentText = null
\r
1298 keyEventRellay: function( e){
\r
1299 if( e.type === 'keyup') return false;
\r
1300 if( currentText === null) return false;
\r
1302 var keyCode = e.keyCode;
\r
1303 if( keyCode === 13 || keyCode === 27 || keyCode === 9 || keyCode === 18 || e.altKey === true){ // 13.return 27.esc 9.tab 18.alt
\r
1304 var _groupID = currentText.groupID,
\r
1305 _index = currentText.index;
\r
1306 currentText.finish( keyCode === 27);
\r
1307 keyCode === 9 && _groupID && EDITABLE_TEXT_CONTROL.tabShift( _groupID, _index, e.shiftKey === true ? -1 : 1);
\r
1308 keyCode === 13 && _groupID && EDITABLE_TEXT_CONTROL.tabShift( _groupID, _index, 1);
\r
1312 tabShift: function( _groupID, _index, _way){
\r
1313 var GROUP_ARRAY = EDITABLE_TEXT_TABLE[ _groupID] || [],
\r
1314 l = GROUP_ARRAY.length,
\r
1316 if( l < 2) return;
\r
1317 while( i !== _index){
\r
1320 i === l ? 0 : i; // 0 < i < l
\r
1321 if( GROUP_ARRAY[ i].enabled() === true) break;
\r
1324 if( i === _index) return;
\r
1325 setTimeout( function(){ GROUP_ARRAY[ i].start();}, 0);
\r
1330 function keyHit( e){
\r
1331 log.html( [ e.keyCode, e.shiftKey, e.ctrlKey, e.altKey, e.type].join( ','));
\r
1332 //keyOperationChatcher.val( '');
\r
1333 var cancel = false,
\r
1334 callback = e.type,
\r
1336 overlayEnabled = pettanr.overlay.visible === true,
\r
1337 currentViewID = overlayEnabled === true ? pettanr.overlay.currentID : pettanr.view.currentID;
\r
1338 if( callback === 'keypress') callback = 'keydown';
\r
1339 if( EDITABLE_TEXT_CONTROL.keyEventRellay( e) === false){
\r
1340 var shift = e.shiftKey,
\r
1342 l = KEYEVENT_ARRAY.length,
\r
1344 if( key === 16 || e.shiftKey === true){
\r
1345 shiftEnabled = callback !== 'keyup';
\r
1347 if( key === 17 || e.ctrlKey === true){
\r
1348 ctrlEnabled = callback !== 'keyup';
\r
1351 for( var i=0; i<l; i++){
\r
1352 d = KEYEVENT_ARRAY[ i];
\r
1354 d.viewID === currentViewID ||
\r
1355 ( overlayEnabled === true && d.viewID === pettanr.view.OVERLAY)
\r
1357 d.keyCode === key &&
\r
1358 ( d.shift === undefined || d.shift === shift) &&
\r
1359 ( d.ctrl === undefined || d.ctrl === ctrl)
\r
1361 ( function( func, e){
\r
1362 func && setTimeout( function(){
\r
1366 })( d[callback], e);
\r
1371 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
1372 e.preventDefault();
\r
1374 e.cancelBubble = true;
\r
1375 e.returnValue = false;
\r
1380 var keyPress = pettanr.ua.isIE === true && pettanr.ua.ieRenderingVersion < 8 ? ( function( e){
\r
1381 var key = e.keyCode;
\r
1382 if( key === 13 || key === 27){
\r
1390 log = $( '#key-event-log').html( 'ready');
\r
1392 jqWindow = pettanr.jqWindow().focus();
\r
1393 keyOperationChatcher = pettanr.jqDocument()
\r
1396 .mouseenter( function(){
\r
1399 keyPress && keyOperationChatcher.keypress( keyPress);
\r
1401 delete pettanr.key.init;
\r
1403 addKeyDownEvent: function( _viewID, _keyCode, _shift, _ctrl, _callbackFunction){
\r
1404 KEYEVENT_ARRAY.push( {
\r
1406 keyCode: _keyCode,
\r
1409 keydown: _callbackFunction
\r
1412 addKeyUpdateEvent: function( _viewID, _keyCode, _shift, _ctrl, _callbackFunction){
\r
1413 KEYEVENT_ARRAY.push( {
\r
1415 keyCode: _keyCode,
\r
1418 keydown: _callbackFunction,
\r
1419 keyup: _callbackFunction
\r
1422 addCursorEvent: function( _viewID, _shift, _ctrl, _callbackFunction){
\r
1425 keyEventDispatcher: function(){
\r
1426 return keyOperationChatcher;
\r
1428 createEditableText: EDITABLE_TEXT_CONTROL.createEditableText,
\r
1429 createCheckbox: EDITABLE_TEXT_CONTROL.createCheckbox,
\r
1430 shiftEnabled: function(){
\r
1431 return shiftEnabled;
\r
1433 ctrlEnabled: function(){
\r
1434 return ctrlEnabled;
\r
1443 * form -> overlay -> view
\r
1446 pettanr.form = ( function(){
\r
1447 var FORM_GROUP_TABLE = {},
\r
1449 currentItem = null,
\r
1450 ELM_INPUT_TEXT = document.createElement( 'input');
\r
1451 ELM_INPUT_TEXT.type = 'text';
\r
1453 var InputTextClass = function( WRAPPER_ELM, ON_UPDATE_FUNCTION, GROUP_ID, validater){
\r
1454 validater = typeof validater === 'function' ? validater : null;
\r
1458 index = EDITABLE_TEXT_TABLE[ GROUP_ID].length,
\r
1464 var _nodes = WRAPPER_ELM.getElementsByTagName('*'),
\r
1467 for(var i=0; i<l; ++i){
\r
1468 _elm = _nodes[ i];
\r
1469 if( _elm.nodeType === 1 && _elm.className.indexof('editable-value') !== -1){
\r
1473 if( elmValue === undefined){
\r
1476 value = elmValue.innerHTML;
\r
1477 elmValue.className += ' editable-text';
\r
1479 elmA = elmAOrigin.cloneNode( true);
\r
1480 elmValue.appendChild( elmA);
\r
1481 elmA.onclick = onClick;
\r
1483 function onClick(){
\r
1485 elmA.style.display = 'none';
\r
1486 elmValue.appendChild( ELM_INPUT_TEXT);
\r
1487 ELM_INPUT_TEXT.value = value;
\r
1488 ELM_INPUT_TEXT.focus();
\r
1489 ELM_INPUT_TEXT.select();
\r
1498 update: function( _value){
\r
1499 value = _value !== undefined ? _value : value;
\r
1501 //jqInput && jqInput.val( value);
\r
1502 currentText === instance && this.finish();
\r
1504 start: function(){
\r
1507 finish: function( keep){
\r
1508 var _newValue = ELM_INPUT_TEXT.value,
\r
1509 _validated = validater !== null ? '' + validater( _newValue) : _newValue;
\r
1510 _newValue = keep !== true ? _validated : value;
\r
1512 elmValue.removeChild( ELM_INPUT_TEXT);
\r
1514 elmA.innerHTML = _newValue;
\r
1515 elmA.style.display = 'block';
\r
1517 ON_UPDATE_FUNCTION && _newValue !== value && ON_UPDATE_FUNCTION( _newValue, value);
\r
1518 finish( instance);
\r
1520 enabled: function(){
\r
1529 function start( _currentItem){
\r
1530 currentItem !== _currentItem && currentItem && currentItem.finish();
\r
1531 currentItem = _currentItem;
\r
1533 function finish( _currentItem){
\r
1534 if( currentItem !== _currentItem) return;
\r
1535 currentItem = null;
\r
1537 function keyEventRellay( e){
\r
1538 if( e.type === 'keyup') return false;
\r
1539 if( currentItem === null) return false;
\r
1541 var keyCode = e.keyCode;
\r
1542 if( keyCode === 13 || keyCode === 27 || keyCode === 9 || keyCode === 18 || e.altKey === true){ // 13.return 27.esc 9.tab 18.alt
\r
1543 var _groupID = currentItem.groupID,
\r
1544 _index = currentItem.index;
\r
1545 currentItem.finish( keyCode === 27);
\r
1546 keyCode === 9 && _groupID && tabShift( _groupID, _index, e.shiftKey === true ? -1 : 1);
\r
1547 keyCode === 13 && _groupID && tabShift( _groupID, _index, 1);
\r
1551 function tabShift( _groupID, _index, _way){
\r
1552 var GROUP_ARRAY = EDITABLE_TEXT_TABLE[ _groupID] || [],
\r
1553 l = GROUP_ARRAY.length,
\r
1555 if( l < 2) return;
\r
1556 while( i !== _index){
\r
1559 i === l ? 0 : i; // 0 < i < l
\r
1560 if( GROUP_ARRAY[ i].enabled() === true) break;
\r
1563 if( i === _index) return;
\r
1564 setTimeout( GROUP_ARRAY[ i].start, 0);
\r
1568 init: function(){},
\r
1569 focus: function(){
\r
1570 return currentItem !== null;
\r
1572 createInputText: function( _elm, _onUpdate, _groupID, _validater){
\r
1573 if( _groupID && !FORM_GROUP_TABLE[ _groupID]){
\r
1574 FORM_GROUP_TABLE[ _groupID] = [];
\r
1576 var ret = new InputTextClass( _elm, _onUpdate, _groupID, _validater);
\r
1578 _groupID && FORM_GROUP_TABLE[ _groupID].push( ret);
\r
1581 createCheckBox: function(){
\r
1584 createButton: function(){
\r
1587 createListBox: function(){
\r
1594 /* ----------------------------------------
\r
1607 * -----------------------
\r
1608 * ie9, other modern browser
\r
1611 * -----------------------
\r
1614 * 内部の角度計算は radian で統一したい。
\r
1615 * 当初 vectorEnabled = true で一度書いてみる。
\r
1616 * 駄目なら、代替のイメージのsrcの用意もここで担当。
\r
1620 pettanr.balloon = ( function() {
\r
1621 var MIN_BALLOON_WIDTH = 30,
\r
1622 MIN_BALLOON_HEIGHT = 30,
\r
1625 STROKE_WIDTH = 1.2,
\r
1626 PADDING_TOP = TAIL_HEIGHT,
\r
1627 PADDING_LEFT = TAIL_HEIGHT,
\r
1628 ACCURACY = 1, // 有効少数桁
\r
1629 IS_VML = pettanr.ua.isIE === true && pettanr.ua.ieVersion < 9,
\r
1630 ELM_BALLOON_ORIGIN = ( function(){
\r
1633 if( IS_VML === true){
\r
1634 ret = document.createElement( 'DIV');
\r
1635 var shape = document.createElement( 'v:shape');
\r
1636 shape.coordorigin = "0,0";
\r
1637 shape.strokecolor = "black";
\r
1638 shape.strokeweight = STROKE_WIDTH;
\r
1639 shape.fillcolor = "white";
\r
1640 ret.appendChild( shape);
\r
1642 var kSVGNS = 'http://www.w3.org/2000/svg';
\r
1643 ret = document.createElementNS( kSVGNS, 'svg');
\r
1644 var path = document.createElementNS( kSVGNS, 'path');
\r
1645 path.setAttribute( 'fill', "white");
\r
1646 path.setAttribute( 'stroke', "black");
\r
1647 path.setAttribute( 'strokeWidth', STROKE_WIDTH);
\r
1648 ret.appendChild( path);
\r
1655 NUM_BALLOON_IMAGE = 24,
\r
1656 vectorEnabled = ELM_BALLOON_ORIGIN !== null && pettanr.URL_PARAMS.vector !== false;
\r
1657 if( IS_VML === true && pettanr.ua.VML === false) vectorEnabled = false;
\r
1659 var XBROWSER_BALLOON_CLASS = function( w, h, a){
\r
1660 var balloonElm = vectorEnabled === true ? ELM_BALLOON_ORIGIN.cloneNode( true) : document.createElement( 'img'), // pettanr.imageに変更
\r
1661 path = balloonElm.getElementsByTagName( 'path')[ 0],
\r
1662 shape = balloonElm.getElementsByTagName( 'shape')[ 0],
\r
1663 cos = Math.cos, sin = Math.sin,
\r
1664 abs = Math.abs, pow = Math.pow,
\r
1665 round = Math.round,
\r
1666 floor = Math.floor,
\r
1667 TARGET = TAIL_WIDTH * TAIL_WIDTH,
\r
1668 DEG_TO_RAD = Math.PI / 180,
\r
1673 function draw( _a, _w, _h){
\r
1674 a = _a !== undefined ? _a : a;
\r
1675 w = _w !== undefined ? _w -PADDING_TOP *2 : w;
\r
1676 h = _h !== undefined ? _h -PADDING_LEFT *2 : h;
\r
1678 if( vectorEnabled === false){
\r
1679 balloonElm.setAttribute( 'src', balloonUrlBuilder( a));
\r
1685 tailRad = a * DEG_TO_RAD,
\r
1686 tailX = rx +( rx +TAIL_HEIGHT) * cos( tailRad),
\r
1687 tailY = ry +( ry +TAIL_HEIGHT) * sin( tailRad),
\r
1688 startX, startY, endX, endY;
\r
1690 * tailの太さをTAIL_WIDTHに一致させるため、角度を絞りつつ計算
\r
1692 var startRad, endRad,
\r
1693 _startX, _startY, _endX, _endY,
\r
1696 for( var i = 45; i > 0.01; i /= 2){
\r
1697 d = ( tailDeg +i) /2;
\r
1698 startRad = ( a +d) * DEG_TO_RAD;
\r
1699 endRad = ( a -d) * DEG_TO_RAD;
\r
1701 _startX = rx +cos( startRad) *rx;
\r
1702 _startY = ry +sin( startRad) *ry;
\r
1703 _endX = rx +cos( endRad) *rx;
\r
1704 _endY = ry +sin( endRad) *ry; //円弧上のY位置=円中心Y+sin(角度×PI÷180)×円半径
\r
1706 if( pow( ( _startX -_endX), 2) + pow( ( _startY -_endY), 2) < TARGET){
\r
1718 if( IS_VML === true){
\r
1719 var _tailX = tailX *10,
\r
1720 _tailY = tailY *10,
\r
1721 __startX = startX *10,
\r
1722 __startY = startY *10,
\r
1723 __endX = endX *10,
\r
1724 __endY = endY *10,
\r
1728 shape.style.width = w +'px';
\r
1729 shape.style.height = h +'px';
\r
1730 shape.coordsize = [ __w, __h].join( l);
\r
1732 ' ar ', 0, l, 0, l, __w, l, __h, l,
\r
1733 round( __endX), l, round( __endY), l,
\r
1734 round( __startX), l, round( __startY),
\r
1735 ' l ', round( _tailX), l, round( _tailY),
\r
1739 balloonElm.style.marginTop = _tailY < 0 ? floor( ( 60 +_tailY) /10) : 10;
\r
1740 balloonElm.style.marginLeft = _tailX < 0 ? floor( ( 60 +_tailX) /10) : 10;
\r
1742 balloonElm.setAttribute( 'width', w +PADDING_LEFT *2);
\r
1743 balloonElm.setAttribute( 'height', h +PADDING_TOP *2);
\r
1744 path.setAttribute( 'd', [
\r
1745 'M', cround( tailX + PADDING_LEFT), l, cround( tailY +PADDING_TOP),
\r
1746 'L', cround( startX +PADDING_LEFT), l, cround( startY +PADDING_TOP),
\r
1749 cround( endX +PADDING_LEFT), l, cround( endY +PADDING_TOP),
\r
1753 function cround( v, r){
\r
1754 r = r || ACCURACY;
\r
1755 return round( v *pow( 10.0, r)) /pow( 10.0, r);
\r
1759 function balloonUrlBuilder( _a){
\r
1760 var d = 360 /NUM_BALLOON_IMAGE;
\r
1762 return [ 'system_picture\/_w', _a < 360 -d /2 ? floor( _a /d) : 0, '.gif'].join( '');
\r
1767 angle: function( _a){
\r
1768 _a !== undefined && _a !== a &&
\r
1769 vectorEnabled === false ? balloonUrlBuilder( _a) : draw( _a);
\r
1772 type: function( _type){
\r
1775 getURL: function(){
\r
1776 return balloonUrlBuilder( a);
\r
1778 destroy: function(){
\r
1779 balloonElm.parentNode && balloonElm.parentNode.removeChild( balloonElm);
\r
1780 balloonElm = null;
\r
1781 delete this.destroy;
\r
1786 IS_VML === false && vectorEnabled === true && ( function(){
\r
1787 var detect = XBROWSER_BALLOON_CLASS.apply( {}, [ 100, 100, 0]),
\r
1788 size = pettanr.util.getElementSize( detect.elm);
\r
1789 vectorEnabled = size.width !== 0 && size.height !== 0;
\r
1791 detect = size = null;
\r
1795 createBalloon: function( _w, _h, _a){
\r
1796 return XBROWSER_BALLOON_CLASS.apply( {}, [ _w, _h, _a]);
\r
1799 TYPE_SPEACH_BALLOON: 1,
\r
1802 TYPE_BLACK_BOX: 4,
\r
1807 /* ----------------------------------------
\r
1810 * xBackendな画像反転、画像描画機能。
\r
1821 * png画像の表示(アルファpngをサポートしないie6以下のため)
\r
1827 * -moz-transform:scale( -1, -1);
\r
1829 pettanr.image = ( function(){
\r
1830 var REG_PNG = /\.png?/i,
\r
1836 IS_SILVERLIGHT = 5,
\r
1838 IS_ACTIVEX_SERVER = 7,
\r
1839 BACKEND = ( function(){
\r
1840 if( pettanr.DEBUG === true && pettanr.URL_PARAMS.rimg){
\r
1841 var rimg = pettanr.URL_PARAMS.rimg.toLowerCase();
\r
1842 if( rimg === 'css3') return IS_CSS3;
\r
1843 if( rimg === 'activex') return IS_ACTIVEX;
\r
1844 if( rimg === 'vml') return IS_VML;
\r
1846 if( pettanr.ua.isIE === false || pettanr.ua.ieVersion >= 9) return IS_CSS3; // 不十分!
\r
1847 if( pettanr.ua.VML === true) return IS_VML;
\r
1848 if( pettanr.ua.ACTIVEX === true) return IS_ACTIVEX;
\r
1849 if( pettanr.FLASH === true) return IS_FLASH;
\r
1850 if( pettanr.SILVERLIGHT === true) return IS_SILVERLIGHT;
\r
1853 PNG_FIX = pettanr.ua.isIE === true && pettanr.ua.ieVersion <= 6,
\r
1854 BACKEND_WHEN_PNG = PNG_FIX === false ? BACKEND : ( function(){
\r
1855 if( pettanr.ua.VML === true) return IS_VML;
\r
1856 if( pettanr.FLASH === true) return IS_FLASH;
\r
1857 if( pettanr.SILVERLIGHT === true) return IS_SILVERLIGHT;
\r
1858 if( pettanr.ua.ACTIVEX === true) return IS_ACTIVEX_SERVER;
\r
1862 var XBackendReversibleImageClass = ( function(){
\r
1863 var CLASS_NAME = 'reversible-image-container',
\r
1864 CLASS_NAME_LOADING = CLASS_NAME + ' loading',
\r
1865 CLASS_NAME_ERROR = CLASS_NAME +' error',
\r
1866 RETRY_DELAY = 5000;
\r
1869 var css3Image = function( url, w, h, onLoadCallback){
\r
1870 var elmWrap = document.createElement( 'div'),
\r
1873 retryTimer = null;
\r
1874 elmWrap.className = CLASS_NAME_LOADING;
\r
1875 pettanr.util.loadImage( url, onLoad, onError, 100, 10000);
\r
1876 function onLoad( _url, _actualW, _actualH){
\r
1877 if( elmWrap === null) return;
\r
1878 elmImg = new Image;
\r
1880 * createElement 直後に append しないと、ie(ActiveX)で img が正しく表示されない.
\r
1882 elmWrap.appendChild( elmImg);
\r
1883 elmImg.setAttribute( 'src', url);
\r
1884 elmWrap.className = CLASS_NAME;
\r
1885 onLoadCallback && onLoadCallback( _url, _actualW, _actualH);
\r
1886 onLoadCallback = null;
\r
1890 function onError( _url){
\r
1891 if( elmWrap === null) return;
\r
1892 elmWrap.className = CLASS_NAME_ERROR;
\r
1893 retryTimer = setTimeout( function(){
\r
1894 elmWrap.className = CLASS_NAME_LOADING;
\r
1895 pettanr.util.loadImage( url, onLoad, onError, 100, 10000);
\r
1898 function resize( _w, _h){
\r
1899 w = _w !== undefined ? _w : w;
\r
1900 h = _h !== undefined ? _h : h;
\r
1901 if( loaded === false) return;
\r
1902 elmImg.className = w < 0 || h < 0 ? ( 'img-flip-' + ( w < 0 && h < 0 ? 'vh' : ( w < 0 ? 'v' : 'h'))) : '';
\r
1907 destroy: function(){
\r
1908 loaded === true && elmWrap.removeChild( elmImg);
\r
1909 retryTimer !== null && clearTimeout( retryTimer);
\r
1910 elmWrap = vmlImg = onLoadCallback = retryTimer = null;
\r
1911 elmWrap = elmImg = onLoadCallback = null;
\r
1912 delete this.destroy;
\r
1916 var activexImage = css3Image;
\r
1917 var vmlImage = function( url, w, h, onLoadCallback){
\r
1918 var elmWrap = document.createElement( 'div'),
\r
1921 retryTimer = null;
\r
1922 elmWrap.className = CLASS_NAME_LOADING;
\r
1923 pettanr.util.loadImage( url, onLoad, onError, 100, 10000);
\r
1924 function onLoad( _url, _actualW, _actualH){
\r
1925 if( elmWrap === null) return;
\r
1926 elmWrap.className = CLASS_NAME;
\r
1927 vmlImg = document.createElement( 'v:image');
\r
1931 onLoadCallback && onLoadCallback( _url, _actualW, _actualH);
\r
1932 onLoadCallback = null;
\r
1934 function onError( _url){
\r
1935 if( elmWrap === null) return;
\r
1936 elmWrap.className = CLASS_NAME_ERROR;
\r
1937 retryTimer = setTimeout( function(){
\r
1938 elmWrap.className = CLASS_NAME_LOADING;
\r
1939 pettanr.util.loadImage( url, onLoad, onError, 100, 10000);
\r
1942 function resize( _w, _h){
\r
1943 w = _w !== undefined ? _w : w;
\r
1944 h = _h !== undefined ? _h : h;
\r
1945 if( loaded !== true) return;
\r
1946 vmlImg.style.width = w < 0 ? -w : w +'px';
\r
1947 vmlImg.style.height = h < 0 ? -h : h +'px';
\r
1948 //if( flipH !== _flipH || flipV !== _flipV){
\r
1949 vmlImg.parentNode === elmWrap && elmWrap.removeChild( vmlImg);
\r
1951 vmlImg.className = w < 0 || h < 0 ? ( 'img-flip-' + ( w < 0 && h < 0 ? 'vh' : ( w < 0 ? 'v' : 'h'))) : '';
\r
1952 elmWrap.appendChild( vmlImg);
\r
1957 destroy: function(){
\r
1958 loaded === true && elmWrap.removeChild( vmlImg);
\r
1959 retryTimer !== null && clearTimeout( retryTimer);
\r
1960 elmWrap = vmlImg = onLoadCallback = retryTimer = null;
\r
1961 delete this.destroy;
\r
1965 var serverImage = function( url, w, h, onLoadCallback){
\r
1969 return function( url, w, h, onLoadCallback){
\r
1970 var flipH = w < 0,
\r
1972 onLoadCallbackAsync = onLoadCallback,// ? function(){ setTimeout( onLoadCallback, 0);} : undefined,// 一度読み込んだ画像は即座にonLoadになるため遅延
\r
1973 xBackendImage = ( function( urlIsXDomain){
\r
1974 if( BACKEND === IS_CSS3) return css3Image.apply( {}, [ url, w, h, onLoadCallbackAsync]);
\r
1975 if( BACKEND === IS_VML) return vmlImage.apply( {}, [ url, w, h, onLoadCallbackAsync]);
\r
1976 if( BACKEND === IS_ACTIVEX) return activexImage.apply( {}, [ url, w, h, onLoadCallbackAsync]);
\r
1977 return serverImage.apply( {}, [ url, w, h, onLoadCallbackAsync]);
\r
1980 elm: xBackendImage.elm,
\r
1982 _w !== undefined && xBackendImage.resize( _w, h);
\r
1986 _h !== undefined && xBackendImage.resize( w, _h);
\r
1989 resize: xBackendImage.resize,
\r
1990 destroy: function(){
\r
1991 xBackendImage.destroy && xBackendImage.destroy();
\r
1992 xBackendImage = onLoadCallback = onLoadCallbackAsync = null;
\r
1993 delete this.destroy;
\r
1999 createReversibleImage: function( url, w, h, onLoadCallback){
\r
2000 return XBackendReversibleImageClass.apply( {}, [ url, w, h, onLoadCallback]);
\r
2012 var _gaq = _gaq || [];
\r
2013 _gaq.push(['_setAccount', 'UA-28023955-1']);
\r
2014 _gaq.push(['_trackPageview']);
\r
2017 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
\r
2018 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
\r
2019 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
\r