/******************************************************************/
/*            solidBox   by eleven-nine   v1.0.8                  */
/*                                     (  MIT-style license. )    */
/******************************************************************/
/* Original code based on ...                                     */
/*     "Slimbox" by Christophe Beyls:                             */
/*         http://www.digitalia.be                                */
/*     "MOOdalBox" by Razvan Brates:                              */
/*         http://www.e-magine.ro/moodalbox                       */
/*     "Smoothbox" by Boris Popoff:                               */
/*         http://gueschla.com                                    */
/******************************************************************/
/*
<<<EX.>>>
<a href="FOO" rel="solidbox">BAR</a>
<a href="FOO" rel="solidbox iframe">BAR</a>
<a href="FOO" rel="solidbox 320px 240px">BAR</a>
<a href="FOO" rel="solidbox 80% 90%">BAR</a>
<a href="FOO" rel="solidbox fullscreen">BAR</a>
<a href="FOO" rel="solidbox[GROUP_NAME]">BAR</a>

FOO: image-file or html-file
*/
/******************************************************************/

// prevent javascript error before the content has loaded
var _SB_ERROR_MESSAGE = '【エラー】<br /><br />' +
						'リンク先が見つかりませんでした<br /><br />' +
						'<em>（クリックで閉じる）</em>'; // the error message displayed when the request has a problem

var _SB_RESIZE_DURATION 		= 400; 		// Duration of height and width resizing (ms)
var _SB_INITIAL_WIDTH			= 250;		// Initial width of the box (px)
var _SB_INITIAL_HEIGHT			= 250;		// Initial height of the box (px)
var _SB_CONTENTS_WIDTH 			= 500;		// Actual width of the box (px)
var _SB_CONTENTS_HEIGHT			= 400;		// Actual height of the box (px)
var _SB_DEF_CONTENTS_WIDTH		= 500;		// Default width of the box (px) - used for resetting when a different setting was used
var _SB_DEF_CONTENTS_HEIGHT		= 400;		// Default height of the box (px) - used for resetting when a different setting was used
var _SB_DEF_FULLSCREEN_WIDTH	= 0.95;		// Default fullscreen width (%)
var _SB_DEF_FULLSCREEN_HEIGHT	= 0.78;		// Default fullscreen height (%)
var _SB_ANIMATE_CAPTION			= true;		// Enable/Disable caption animation
var _SB_EVAL_SCRIPTS			= false;	// Option to evaluate scripts in the response text
var _SB_EVAL_RESPONSE			= false;	// Option to evaluate the whole response text

var solidBox = {
	// init the solidBox
	initialize: function(options) {
		// init default options
		this.options = Object.extend({
			resizeDuration: 	_SB_RESIZE_DURATION,
			initialWidth: 		_SB_INITIAL_WIDTH,	
			initialHeight: 		_SB_INITIAL_HEIGHT,
			contentsWidth: 		_SB_CONTENTS_WIDTH,
			contentsHeight: 	_SB_CONTENTS_HEIGHT,
			defContentsWidth: 	_SB_DEF_CONTENTS_WIDTH,
			defContentsHeight: 	_SB_DEF_CONTENTS_HEIGHT,
			defFullscreenWidth:	_SB_DEF_FULLSCREEN_WIDTH,
			defFullscreenHeight:_SB_DEF_FULLSCREEN_HEIGHT,
			animateCaption: 	_SB_ANIMATE_CAPTION,
			evalScripts: 		_SB_EVAL_SCRIPTS,
			evalResponse: 		_SB_EVAL_RESPONSE
		}, options || {});

		// scan anchors for those opening a solidBox
		this.anchors = [];
		$A($$('a')).each(function(el){
			if(el.rel && el.href && el.rel.test(/^solidbox/i)) {
				el.onclick = this.click.pass(el, this);
				this.anchors.push(el);
			}
		}, this);

		if(this.anchors <= 0) { return 0; }

		// add event listeners
		this.eventKeyDown = this.keyboardListener.bindAsEventListener(this);
		this.eventPosition = this.position.bind(this);

		// init the HTML elements
		// the overlay (clickable to close)
		var tmpW = Math.max(this.options.contentsWidth,  document.body.scrollWidth,  document.documentElement.scrollWidth,  window.getWidth());
		var tmpH = Math.max(this.options.contentsHeight, document.body.scrollHeight, document.documentElement.scrollHeight, window.getHeight());
		this.overlay = new Element('div').setProperty('id', 'mb_overlay').injectInside(document.body);
		this.overlay.setStyles({'top': 0, 'width': tmpW+'px', 'height': tmpH+'px' });
		// the center element
		this.center = new Element('div').setProperty('id', 'mb_center').setStyles({
			width: this.options.initialWidth+'px',
			height: this.options.initialHeight+'px',
			marginLeft: '-'+(this.options.initialWidth/2)+'px',
			display: 'none'
		}).injectInside(document.body);
		// the actual page contents
		this.contents = new Element('div').setProperty('id', 'mb_contents').injectInside(this.center);

		// the bottom part (caption / close)
		this.bottom = new Element('div').setProperty('id', 'mb_bottom').setStyle('display', 'none').injectInside(document.body);
		this.bottomcontent = new Element('div').setProperty('id', 'mb_bottom_content').injectInside(this.bottom);
		this.prevdiv = new Element('div').setProperty('id', 'mb_prev_div').injectInside(this.bottomcontent);
		this.prevlink = new Element('a').setProperties({id: 'mb_prev_link', href: 'javascript:void(0)'}).injectInside(this.prevdiv);
		if(!window.ie) this.prevlink.setOpacity(0.01);
		this.nextdiv = new Element('div').setProperty('id', 'mb_next_div').injectInside(this.bottomcontent);
		this.nextlink = new Element('a').setProperties({id: 'mb_next_link', href: 'javascript:void(0)'}).injectInside(this.nextdiv);
		if(!window.ie) this.nextlink.setOpacity(0.01);

		this.number = new Element('div').setProperty('id', 'mb_number').injectInside(this.bottomcontent);
		new Element('div').setStyle('clear', 'both').injectInside(this.bottomcontent);

		this.closediv = new Element('div').setProperty('id', 'mb_close_div').injectInside(this.bottom);
		this.closelink = new Element('a').setProperties({id: 'mb_close_link', href: 'javascript:void(0)'}).injectInside(this.closediv);
		if(!window.ie) this.closelink.setOpacity(0.01);

		this.caption = new Element('div').setProperty('id', 'mb_caption').injectInside(this.bottom);
		new Element('div').setStyle('clear', 'both').injectInside(this.bottom);

		this.error = new Element('div').setProperty('id', 'mb_error').setHTML(_SB_ERROR_MESSAGE);

		// init the effects
		var nextEffect = this.nextEffect.bind(this);
		this.fx = {
			overlay: 	this.overlay.effect('opacity', { duration: 500 }).hide(),
			resize: 	this.center.effects({ duration: this.options.resizeDuration, onComplete: nextEffect }),
			contents: 	this.contents.effect('opacity', { duration: 500, onComplete: nextEffect }),
			bottom: 	this.bottom.effects({ duration: 400, onComplete: nextEffect }),
			prevlink: 	this.prevlink.effect('opacity', { wait: false, duration: 500, transition: Fx.Transitions.quadOut }),
			nextlink: 	this.nextlink.effect('opacity', { wait: false, duration: 500, transition: Fx.Transitions.quadOut }),
			closelink: 	this.closelink.effect('opacity', { wait: false, duration: 500, transition: Fx.Transitions.quadOut })
		};

		// rollover
		if(!window.ie) { 
			this.prevlink.addEvent('mouseenter', function(){ this.fx.prevlink.start(0.99, 0.5); }.bind(this));
			this.prevlink.addEvent('mouseleave', function(){ this.fx.prevlink.start(this.prevlink.getStyle('opacity'), 0.01); }.bind(this));
			this.prevlink.addEvent('click', function(){ this.prevlink.setOpacity(0.01); }.bind(this));
			this.nextlink.addEvent('mouseenter', function(){ this.fx.nextlink.start(0.99, 0.5); }.bind(this));
			this.nextlink.addEvent('mouseleave', function(){ this.fx.nextlink.start(this.nextlink.getStyle('opacity'), 0.01); }.bind(this));
			this.nextlink.addEvent('click', function(){ this.nextlink.setOpacity(0.01); }.bind(this));
			this.closelink.addEvent('mouseenter', function(){ this.fx.closelink.start(0.99, 0.5); }.bind(this));
			this.closelink.addEvent('mouseleave', function(){ this.fx.closelink.start(this.closelink.getStyle('opacity'), 0.01); }.bind(this));
			this.closelink.addEvent('click', function(){ this.closelink.setOpacity(0.01); }.bind(this));
		}

		// attach the prev/next/close event to buttons
		this.prevlink.onclick = this.previous.bind(this);
		this.nextlink.onclick = this.next.bind(this);
		this.closelink.onclick = this.close.bind(this);

		// attach the close event to the overlay
		this.overlay.onclick = this.close.bind(this);

		this.ajaxRequest = Class.empty;
	},

	click: function(link) {


		if (!link.rel.test(/^solidbox\[\w+\]/i)) return this.show(link.href, link.title, link.rel);

		var j, imageNum, images = [];
		link.rel.match(/^solidbox\[(\w+)\]/i);
		var regstr = RegExp.$1;
		this.anchors.each(function(el){
			el.rel.match(/^solidbox\[(\w+)\]/i);
			if (RegExp.$1 == regstr){
				for (j = 0; j < images.length; j++) if(images[j][0] == el.href) break;
				if (j == images.length){
					images.push([el.href, el.title]);
					if (el.href == link.href) imageNum = j;
				}
			}
		}, this);

		return this.open(images, link.rel, imageNum);
	},

	show: function(url, title, rel){
		return this.open([[url, title]], rel, 0);
	},

	open: function(sLinkSet, sLinkRel, sLinkNum) {
		var tmpW = Math.max(this.options.contentsWidth,  document.body.scrollWidth,  document.documentElement.scrollWidth,  window.getWidth());
		var tmpH = Math.max(this.options.contentsHeight, document.body.scrollHeight, document.documentElement.scrollHeight, window.getHeight());
		var tmpSCL = window.getScrollLeft() ? window.getScrollLeft() : document.body.scrollLeft;
		var tmpSCT = window.getScrollTop()  ? window.getScrollTop()  : document.body.scrollTop;

		this.images = sLinkSet;
		this.rel = sLinkRel;
		this.setup(true);
		this.position;
		this.top = tmpSCT + (window.getHeight() / 15);
		this.left = window.getWidth()/2 + window.tmpSCL;
		this.center.setStyles({left: this.left+'px', top: this.top+'px', display: ''});
		this.bottom.setStyles({left: this.left+'px', top: this.top+this.options.contentsHeight+19+'px', display: ''});
		this.overlay.setStyles({
			width:  tmpW +'px',
			height: tmpH+'px',
			display: ''
		});
		this.fx.overlay.custom(0.8);
		return this.changeImage(sLinkNum);
	},

	position: function() {
		this.overlay.setStyle('display', 'none');
		var tmpW = Math.max(this.options.contentsWidth,  document.body.scrollWidth,  document.documentElement.scrollWidth,  window.getWidth());
		var tmpH = Math.max(this.options.contentsHeight, document.body.scrollHeight, document.documentElement.scrollHeight, window.getHeight());
		var tmpSCL = window.getScrollLeft() ? window.getScrollLeft() : document.body.scrollLeft;
		var tmpSCT = window.getScrollTop()  ? window.getScrollTop()  : document.body.scrollTop;
		this.overlay.setStyles({
			width:  tmpW +'px',
			height: tmpH+'px',
			display: ''
		});

		if(this.step <= 0) {
			this.top = tmpSCT + (window.getHeight() / 15);
			this.left = window.getWidth()/2 + tmpSCL;
			new Fx.Styles('mb_center', {duration: 200, transition: Fx.Transitions.sineInOut}).start({
				'left': this.left + 'px',
				'top': this.top + 'px'
			});
			new Fx.Styles('mb_bottom', {duration: 200, transition: Fx.Transitions.sineInOut}).start({
				'left': this.left + 'px',
				'top': this.top + this.options.contentsHeight+19+'px'
			});
		}
	},

	setup: function(open) {
		var elements = $A($$('object'));
		elements.extend($$(window.ActiveXObject ? 'select' : 'embed'));
		elements.each(function(el){ el.style.visibility = open ? 'hidden' : ''; });
		var fn = open ? 'addEvent' : 'removeEvent';
		window[fn]('scroll', this.eventPosition)[fn]('resize', this.eventPosition);
		document[fn]('keydown', this.eventKeyDown);
		this.step = 0;
	},

	changeImage: function(imageNum){
		if (this.step || (imageNum < 0) || (imageNum >= this.images.length)) return false;
		this.activeImage = imageNum;

		this.bottom.style.display = this.prevdiv.style.display = this.nextdiv.style.display = this.number.style.display = 'none';
		this.center.className = 'mb_loading';

/*		this.imageflag = (this.images[imageNum][0].test(/\.gif$/g)
			|| this.images[imageNum][0].test(/\.jpg$/g)
			|| this.images[imageNum][0].test(/\.jpeg$/g)
			|| this.images[imageNum][0].test(/\.png$/g));*/

		this.imageflag = (this.images[imageNum][0].indexOf(".gif")!=-1 || this.images[imageNum][0].indexOf(".GIF")!=-1
			|| this.images[imageNum][0].indexOf(".jpg")!=-1 || this.images[imageNum][0].indexOf(".JPG")!=-1
			|| this.images[imageNum][0].indexOf(".jpeg")!=-1 || this.images[imageNum][0].indexOf(".JPEG")!=-1
			|| this.images[imageNum][0].indexOf(".png")!=-1 || this.images[imageNum][0].indexOf(".PNG")!=-1);

		if(this.imageflag) {
			this.step = 1;
			this.preload = new Image();
			this.preload.onload = this.nextEffect.bind(this);
			this.preload.src = this.images[imageNum][0];
			return false;
		} else {
			return this.loadContents(this.images[imageNum][0]);
		}
	},

	loadContents: function() {
		if(this.step) return false;
		this.step = 1;

		if (this.rel.test("fullscreen")){
			this.options.contentsWidth 	= this.options.defFullscreenWidth*window.getWidth();
			this.options.contentsHeight = this.options.defFullscreenHeight*window.getHeight();

		} else { // we check for other specified dimensions (px or %)
			var aDim = this.rel.match(/[0-9.]+(px|%)/g);

			if (aDim && aDim[0]){ //first dimension is interpreted as width
				var w = aDim[0].toInt();

				if (aDim[0].test("%")) {
					this.options.contentsWidth = (w > 0) ? 0.01*w*window.getWidth() : this.options.defFullscreenWidth*window.getWidth();
				} else {
					this.options.contentsWidth = (w > 0) ? w : this.options.defContentsWidth;
					this.options.contentsWidth = Math.min(this.options.contentsWidth, 0.85*window.getWidth());
				}
			} else { // we switch to defaults if there aren't any dimensions specified
				this.options.contentsWidth 	= this.options.defContentsWidth;
				this.options.contentsHeight = this.options.defContentsHeight;
			}

			if (aDim && aDim[1]){ // we have a second dimension specified, which we'll interpret as height

				var h = aDim[1].toInt();

				if (aDim[1].test("%")) {
					this.options.contentsHeight = (h > 0) ? 0.01*h*window.getHeight() : this.options.defFullscreenHeight*window.getHeight();
				} else {
					this.options.contentsHeight = (h > 0) ? h : this.options.defContentsHeight;
					this.options.contentsHeight = Math.min(this.options.contentsHeight, 0.78*window.getHeight());
				}
			} else if (aDim && aDim[0]) { 
				// we have the first dimension specified, but not the second
				// so we interpret as width = height = the given value
				if (aDim[0].test("%")) {
					this.options.contentsHeight = (w > 0) ? 0.01*w*window.getHeight() : this.options.defFullscreenHeight*window.getHeight();
				} else {
					this.options.contentsHeight = (w > 0) ? w : this.options.defContentsHeight;
				}
			}
			// correct a little approximation bug (size flickers)
			this.options.contentsWidth = Math.floor(this.options.contentsWidth);
			this.options.contentsHeight = Math.floor(this.options.contentsHeight);
		}

		this.wizardMode = this.rel.test("wizard");

		// this is where we'll check for other options passed via the rel attribute

		this.bottom.setStyles({opacity: '0', height: '0', display: 'none'});
		this.center.addClass('mb_loading');

		this.fx.contents.hide();

		if(this.rel.indexOf('iframe') != -1){
			this.contents.setHTML('');
			if(!window.ie) {
				this.iframe = new Element('iframe').setProperties({'id': 'mb_iframe', 'src': this.images[this.activeImage][0], 'border': '0', 'frameborder': '0'}).injectInside(this.contents);
				this.iframe.onload = this.nextEffect.bind(this);
			} else {
				this.contents.setHTML('<iframe id="mb_iframe" src="'+this.images[this.activeImage][0]+'" border="0" frameborder="0"></iframe>');
				this.iframe = $('mb_iframe');
				this.iframe.onreadystatechange = function() {
					if (this.iframe.readyState == "complete") { this.iframe.onreadystatechange = null; setTimeout(this.nextEffect.bind(this), 500); }
				}.bind(this);
			}
			this.contents.setStyle('overflow', 'hidden');

		} else {
			// AJAX call here
			var nextEffect = this.nextEffect.bind(this);
			var ajaxFailure = this.ajaxFailure.bind(this);
			var ajaxOptions = {
				method: 		'get',
				update: 		this.contents, 
				evalScripts: 	this.options.evalScripts,
				evalResponse: 	this.options.evalResponse,
				onComplete: 	nextEffect, 
				onFailure: 		ajaxFailure
			};
			this.ajaxRequest = new Ajax(this.images[this.activeImage][0], ajaxOptions).request();
		}

		return false;
	},
	
	ajaxFailure: function(){
		this.contents.setHTML('');
		this.error.clone().injectInside(this.contents);
		this.nextEffect();
		this.center.setStyle('cursor', 'pointer');
		this.bottom.setStyle('cursor', 'pointer');
		this.center.onclick = this.close.bind(this);
	},

	nextEffect: function() {
		switch(this.step++) {
		case 1:
			// remove previous styling from the elements 
			// (e.g. styling applied in case of an error)
			this.center.removeClass('mb_loading');
			this.center.setStyle('cursor', 'default');
			this.bottom.setStyle('cursor', 'default');

			this.center.onclick = this.bottom.onclick = '';
			this.caption.setHTML(this.images[this.activeImage][1] || '');
			this.number.setHTML((this.images.length == 1) ? '' : 'Page '+(this.activeImage+1)+' of '+this.images.length);
			this.number.style.display = ((this.images.length == 1) ? 'none' : '');

			if(this.imageflag) {
				this.contents.style.backgroundImage = 'url('+this.images[this.activeImage][0]+')';
				this.contents.setStyles ({width: this.preload.width + "px", height: this.preload.height + "px"});
			} else {
				this.contents.setStyles ({width: this.options.contentsWidth + "px", height: this.options.contentsHeight + "px"});
			}
			if(this.iframe){ this.iframe.setStyles ({width: this.options.contentsWidth + "px", height: this.options.contentsHeight + "px"}); }

			if(this.center.clientHeight != this.contents.offsetHeight) {
				this.fx.resize.custom({height: [this.center.clientHeight, this.contents.offsetHeight]});
				break;
			}

			this.step++;

		case 2:
			if(this.center.clientWidth != this.contents.offsetWidth) {
				this.fx.resize.custom({width: [this.center.clientWidth, this.contents.offsetWidth], marginLeft: [-this.center.clientWidth/2, -this.contents.offsetWidth/2]});
				break;
			}
			this.step++;

		case 3:
			if (this.activeImage) this.prevdiv.style.display = '';
			if (this.activeImage != (this.images.length - 1)) this.nextdiv.style.display = '';
			this.bottom.setOpacity(0);
			this.bottom.setStyles({top: (this.top + this.center.clientHeight)+'px', width: this.contents.style.width, marginLeft: this.center.style.marginLeft, display: ''});
			this.fx.contents.custom(0,1);
			break;

		case 4:
			if(this.options.animateCaption) {
				this.fx.bottom.custom({opacity: [0, 1], height: [0, this.bottom.scrollHeight]});
				break;
			} else {
				this.bottom.setStyles({opacity: '1', height: this.bottom.scrollHeight+'px'});
			}

		case 5:
			this.step = 0;
		}
	},

	keyboardListener: function(event) {
		if(event.keyCode == 27) { this.close(); return true; }
		if(window.event) {
			if(window.event.ctrlKey || !window.event.altKey || window.event.shiftKey) { return false; }
			switch (event.keyCode){
				// Close: ESC, C, W, X
				case 27: case 67: case 87: case 88: this.close(); break;
				// Previous: LEFT_CURSOR, P
				case 37: case 80: this.previous(); break;
				// Next: RIGHT_CURSOR, N
				case 39: case 78: this.next();
			}
		}
	},

	previous: function(){
		this.reset();
		return this.changeImage(this.activeImage-1);
	},

	next: function(){
		this.reset();
		return this.changeImage(this.activeImage+1);
	},

	close: function() {
		if(this.step < 0) return;
		this.step = -1;
		if (this.preload){
			this.preload.onload = Class.empty;
			this.preload = null;
		}
		for(var f in this.fx) this.fx[f].clearTimer();
		this.center.style.display = this.bottom.style.display = 'none';
		this.reset();
		this.fx.overlay.chain(this.setup.pass(false, this)).custom(0);
		this.contents.setHTML('');
		if(this.iframe) { this.iframe = undefined; }
		return false;
	},

	reset: function() {
		this.contents.setStyle('background-image', 'none');
		this.fx.contents.hide();
		this.center.addClass('mb_loading');
		if(!window.ie) {
			this.prevlink.fireEvent('mouseleave');
			this.nextlink.fireEvent('mouseleave');
			this.closelink.fireEvent('mouseleave');
		}
	}

};
// startup
window.addEvent('load', solidBox.initialize.bind(solidBox));
