﻿/*
 * Jax (jQuery activity extend) 0.2
 *
 * Copyright (c) 2008 Hoya Kim
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 * 
 * http://jax.ixcore.co.kr
 *
 * Depends:
 *	jQuery.js
 *	jax.js
 *	jax.imagebutton.js
 *
 * version: 0.2
 */
if(Jax.Rotator){
	throw new Error('Module "Jax.Rotator" already exists!');
}

Jax.Rotator = function(items, options){
	this.options = $.extend({}, Jax.Rotator.defaults, options || {});
	this.currentNumber = this.options.startNumber || 1; // start one base
	this.tabindex = this.options.tabIndex || 9000;
	this.extractItems(items);
	this.init();
}
Jax.Rotator.jax = '0.2';
Jax.Rotator.State = {
	Play: 'play',
	Stop: 'stop'};

Jax.Rotator.defaults = {
	res: {path: '/jax3/res/images/rotator/'},
	unit: 'em',
	css: {},
	interval: 4000,
	startNumber: 1, // start one base
	cmdIconSize: {width: 1.1, height: 1.1, margin: 0.1},
	state: Jax.Rotator.State.Stop,
	commands: {pos1: 'top', pos2: 'left'},
	numbers: {pos1: 'top', pos2: 'right'},
	effect: {mode: 'fade', speed: 'normal'},
	showcase: {width: 21.5, height: 13.5, margin: 0.1},
	rows: 1,
	cols: 1,
	correction: 0
};

$.extend(Jax.Rotator.prototype, {
	init: function(){
		var _self = this;
		this.setCommands();
		this.setNumbers();
		this.setLayout();
		this.appendEvent();
		this.$element.css(this.options.css);
		this.$element.data('jax', this);
	},
	extractTabindex: function(){
		var _self = this;
		this.$items.each(function(){
			$('[tabindex]', $(this)).each(function(i, e){ 
				var _ti = parseInt($(this).attr('tabindex')); 
				if(!isNaN(_ti)){_self.tabindex = Math.min((_ti < 1) ? _self.tabindex : _ti, _self.tabindex);} });
		});
	},
	extractItems: function(ele){
		if(!ele) throw new Error('ele is required.');
		if(typeof ele != 'string') throw new Error('ele must be string');
		var _self = this;
		// start zero base
		this.$items = $('a:has(img)', Jax.toId(ele)).wrap('<div class="jax-rotator-item"></div>').parent();
		this.$items.css({width: this.options.showcase.width + this.options.unit,
			             height: this.options.showcase.height + this.options.unit,
			             margin: this.options.showcase.margin + this.options.unit});

		this.extractTabindex();
 
		this.itemGroup = [];
		var _$temp = $('<div></div>');
		this.$items.each(function(i, e){
			if(i == 0) {
				_$temp.empty().append('<div class="jax-rotator-item-group"></div>');
			}else if((i % (_self.options.rows * _self.options.cols)) == 0) {
				_self.itemGroup.push($(_$temp.html()));
				_$temp.empty().append('<div class="jax-rotator-item-group"></div>');
			}
			$('.jax-rotator-item-group', _$temp).append($(this));
			if(i == _self.$items.length -1) {
				for(var _i = (_self.options.rows * _self.options.cols) - _self.getRemain(); _i > 0 ; _i--){
					var _$html = $(_self.options.emptyHtml || '<div class="jax-rotator-item"></div>');
					_$html.css({width: _self.options.showcase.width + _self.options.unit,
			                    height: _self.options.showcase.height + _self.options.unit,
			                    margin: _self.options.showcase.margin + _self.options.unit});
					$('.jax-rotator-item-group', _$temp).append(_$html);
				}
				_self.itemGroup.push($(_$temp.html()));
			}

		});

	},
	getHeightStep: function(){
		return (this.options.showcase.height + (this.options.showcase.margin * 2)) + this.options.unit;
	},
	getWidthStep: function(){
		return (this.options.showcase.width + (this.options.showcase.margin * 2)) + this.options.unit;
	},
	getLimit: function(){
		return Math.ceil(this.$items.length / (this.options.rows * this.options.cols));
	},
	getRemain: function(){
		return this.$items.length % (this.options.rows * this.options.cols);
	},
	setNumbers: function(){
		var _self = this;
		var _limit = this.getLimit();
		this.numbers = []; // start zero base
		for(var _i = 0; _i < _limit; _i++){
			this.numbers.push(new Jax.ImageButton({
			res: {path: '/jax3/res/images/rotator/',
			      disabled: 'num' + (_i+1) + '_disabled.gif',
				  selected: 'num' + (_i+1) + '_selected.gif',
				  unselected: 'num' + (_i+1) + '_unselected.gif'},
			css: {margin: '1px'},
			alt: (_i+1) + '번 알림 보기',
			tabindex: this.tabindex,
			checkOnClick: false,
			checked: false,
			size: this.options.cmdIconSize,
			state: Jax.ImageButton.State.Unselected,
			act: {click: _func(_i + 1),
				  stateChanged: function(newState, oldState, caller){}}
			}));
		}
		function _func(n){
			return function(){ _self.stop(); _self.moveTo(n);};
		}
	},
	appendNumbers: function(jquery){
		for(var _i=0; _i<this.numbers.length; _i++){
			this.numbers[_i].appendTo(jquery);
		}
	},
	setCommands: function(){
		var _self = this;
		this.btnPlay = new Jax.ImageButton({
			res: {path: '/jax3/res/images/rotator/',
			      disabled: 'play_disabled.gif',
				  selected: 'play_selected.gif',
				  unselected: 'play_unselected.gif'},
			alt: 'play',
			css: {margin: '1px'},
			tabindex: this.tabindex,
			checkOnClick: true,
			checked: true,
			size: this.options.cmdIconSize,
			state: Jax.ImageButton.State.Selected,
			act: {click: function(e){ if(_self.options.state != Jax.Rotator.State.Play){ _self.play(); } },
				  stateChanged: function(newState, oldState, caller){}}
		});
		this.btnStop = new Jax.ImageButton({
			res: {path: '/jax3/res/images/rotator/',
			      disabled: 'stop_disabled.gif',
				  selected: 'stop_selected.gif',
				  unselected: 'stop_unselected.gif'},
			alt: 'stop',
			css: {margin: '1px'},
			tabindex: this.tabindex,
			checkOnClick: true,
			checked: true,
			size: this.options.cmdIconSize,
			state: Jax.ImageButton.State.Unselected,
			act: {click: function(e){ if(_self.options.state != Jax.Rotator.State.Stop){ _self.stop(); } },
				  stateChanged: function(newState, oldState, caller){ /*if(caller == 'init' alert(newState + ':' + caller);)*/}}
		});
		this.btnPrev = new Jax.ImageButton({
			res: {path: '/jax3/res/images/rotator/',
			      disabled: 'prev_disabled.gif',
				  selected: 'prev_selected.gif',
				  unselected: 'prev_unselected.gif'},
			alt: 'prev',
			css: {margin: '1px'},
			tabindex: this.tabindex,
			checkOnClick: false,
			checked: false,
			size: this.options.cmdIconSize,
			state: Jax.ImageButton.State.Unselected,
			act: {click: function(e){ _self.prev(); },
				  stateChanged: function(newState, oldState, caller){}}
		});
		this.btnNext = new Jax.ImageButton({
			res: {path: '/jax3/res/images/rotator/',
			      disabled: 'next_disabled.gif',
				  selected: 'next_selected.gif',
				  unselected: 'next_unselected.gif'},
			alt: 'next',
			css: {margin: '1px'},
			tabindex: this.tabindex,
			checkOnClick: false,
			checked: false,
			size: this.options.cmdIconSize,
			state: Jax.ImageButton.State.Unselected,
			act: {click: function(e){ _self.next(); },
				  stateChanged: function(newState, oldState, caller){}}
		});
	},
	appendCommands: function(jquery){
		this.btnPrev.appendTo(jquery);
		this.btnPlay.appendTo(jquery);
		this.btnStop.appendTo(jquery);
		this.btnNext.appendTo(jquery);
	},
	appendEvent: function(){
		var _self = this;
		this.$displayPanel.bind('mouseover', function(e){
			_self.stateCache = _self.options.state;
			_self.stop();
		});
		this.$displayPanel.bind('mouseout', function(e){
			if(_self.stateCache == Jax.Rotator.State.Play){
				_self.play();
			}
			_self.stateCeche = '';
		});
	},
	setLayout: function(){
		this.$element = $('<div class="jax-rotator" ></div>');
		var _cmdPos1 = this.options.commands.pos1, _cmdPos2 = this.options.commands.pos2;
		var _numPos1 = this.options.numbers.pos1, _numPos2 = this.options.numbers.pos2;

		var _btnWidth = this.options.cmdIconSize.width + (this.options.cmdIconSize.margin * 2);
		var _btnHeight = this.options.cmdIconSize.height + (this.options.cmdIconSize.margin * 2);
		var _scWidth = (this.options.showcase.width + (this.options.showcase.margin * 2)) * this.options.cols + this.options.correction;
		var _scHeight = (this.options.showcase.height + (this.options.showcase.margin * 2)) * this.options.rows;
		var _width = _scWidth, _height = _scHeight;
		var _bodyWidth = _scWidth, _bodyHeight = _scHeight;

		if(_cmdPos1 == 'top' || _numPos1 == 'top')_height += _btnHeight;
		if(_cmdPos1 == 'left' || _numPos1 == 'left'){_width += _btnWidth; _bodyWidth += _btnWidth;}
		if(_cmdPos1 == 'right' || _numPos1 == 'right'){_width += _btnWidth; _bodyWidth += _btnWidth;}
		if(_cmdPos1 == 'bottom' || _numPos1 == 'bottom')_height += _btnHeight;

		this.$element.css({width: _width + this.options.unit,
				           height: _height + this.options.unit});

		// top
		if(_cmdPos1 == 'top' || _numPos1 == 'top'){
			this.$topCtrlPanel = $('<div class="jax-rotator-control-panel jax-rotator-control-panel-top"></div>');
			this.$topCtrlPanel.css({width: _width + this.options.unit,
				                    height: _btnHeight + this.options.unit});

			this.$element.append(this.$topCtrlPanel);
			if((_cmdPos1 == 'top' && _cmdPos2 == 'left') || (_numPos1 == 'top' && _numPos2 == 'left')){
				this.$topCtrlPanel.append('<div class="jax-rotator-control-subpanel jax-rotator-control-subpanel-left"></div>');
				if((_cmdPos1 == 'top' && _cmdPos2 == 'left')){
					this.appendCommands($('.jax-rotator-control-subpanel-left', this.$topCtrlPanel));
				}
				if((_numPos1 == 'top' && _numPos2 == 'left')){
					this.appendNumbers($('.jax-rotator-control-subpanel-left', this.$topCtrlPanel));
				}
			}
			if((_cmdPos1 == 'top' && _cmdPos2 == 'right') || (_numPos1 == 'top' && _numPos2 == 'right')){
				this.$topCtrlPanel.append('<div class="jax-rotator-control-subpanel jax-rotator-control-subpanel-right"></div>');
				if((_cmdPos1 == 'top' && _cmdPos2 == 'right')){
					this.appendCommands($('.jax-rotator-control-subpanel-right', this.$topCtrlPanel));
				}
				if((_numPos1 == 'top' && _numPos2 == 'right')){
					this.appendNumbers($('.jax-rotator-control-subpanel-right', this.$topCtrlPanel));
				}
			}
		}

		// body
		this.$bodyPanel = $('<div class="jax-rotator-body"></div>');
		this.$element.append(this.$bodyPanel);
		// left
		if(_cmdPos1 == 'left' || _numPos1 == 'left'){
			this.$leftCtrlPanel = $('<div class="jax-rotator-control-panel jax-rotator-control-panel-left"></div>');
			this.$leftCtrlPanel.css({width: _btnWidth + this.options.unit,
				                     height: _scHeight + this.options.unit});
			this.$bodyPanel.append(this.$leftCtrlPanel);
			if((_cmdPos1 == 'left' && _cmdPos2 == 'top') || (_numPos1 == 'left' && _numPos2 == 'top')){
				this.$leftCtrlPanel.append('<div class="jax-rotator-control-subpanel jax-rotator-control-subpanel-top"></div>');
				if((_cmdPos1 == 'left' && _cmdPos2 == 'top')){
					this.appendCommands($('.jax-rotator-control-subpanel-top', this.$leftCtrlPanel));
				}
				if((_numPos1 == 'left' && _numPos2 == 'top')){
					this.appendNumbers($('.jax-rotator-control-subpanel-top', this.$leftCtrlPanel));
				}
			}
			if((_cmdPos1 == 'left' && _cmdPos2 == 'bottom') || (_numPos1 == 'left' && _numPos2 == 'bottom')){
				this.$leftCtrlPanel.append('<div class="jax-rotator-control-subpanel jax-rotator-control-subpanel-bottom"></div>');
				if((_cmdPos1 == 'left' && _cmdPos2 == 'bottom')){
					this.appendCommands($('.jax-rotator-control-subpanel-bottom', this.$leftCtrlPanel));
				}
				if((_numPos1 == 'left' && _numPos2 == 'bottom')){
					this.appendNumbers($('.jax-rotator-control-subpanel-bottom', this.$leftCtrlPanel));
				}
			}
		}

		this.$actionPanel = $('<div class="jax-rotator-body-action"></div>');
		this.$bodyPanel.append(this.$actionPanel);
		this.$displayPanel = $('<div class="jax-rotator-body-action-display"></div>');
		this.$actionPanel.append(this.$displayPanel);

		this.$actionPanel.css({width: _scWidth + this.options.unit,
			                   height: _scHeight + this.options.unit});
		this.$displayPanel.css({width: _scWidth + this.options.unit});


		// right
		if(_cmdPos1 == 'right' || _numPos1 == 'right'){
			this.$rightCtrlPanel = $('<div class="jax-rotator-control-panel jax-rotator-control-panel-right"></div>');
			this.$rightCtrlPanel.css({width: _btnWidth + this.options.unit,
				                      height: _scHeight + this.options.unit});
			this.$bodyPanel.append(this.$rightCtrlPanel);
			if((_cmdPos1 == 'right' && _cmdPos2 == 'top') || (_numPos1 == 'right' && _numPos2 == 'top')){
				this.$rightCtrlPanel.append('<div class="jax-rotator-control-subpanel jax-rotator-control-subpanel-top"></div>');
				if((_cmdPos1 == 'right' && _cmdPos2 == 'top')){
					this.appendCommands($('.jax-rotator-control-subpanel-top', this.$rightCtrlPanel));
				}
				if((_numPos1 == 'right' && _numPos2 == 'top')){
					this.appendNumbers($('.jax-rotator-control-subpanel-top', this.$rightCtrlPanel));
				}
			}
			if((_cmdPos1 == 'right' && _cmdPos2 == 'bottom') || (_numPos1 == 'right' && _numPos2 == 'bottom')){
				this.$rightCtrlPanel.append('<div class="jax-rotator-control-subpanel jax-rotator-control-subpanel-bottom"></div>');
				if((_cmdPos1 == 'right' && _cmdPos2 == 'bottom')){
					this.appendCommands($('.jax-rotator-control-subpanel-bottom', this.$rightCtrlPanel));
				}
				if((_numPos1 == 'right' && _numPos2 == 'bottom')){
					this.appendNumbers($('.jax-rotator-control-subpanel-bottom', this.$rightCtrlPanel));
				}
			}
		}
		this.$bodyPanel.css({width: _bodyWidth + this.options.unit,
			                 height: _bodyHeight + this.options.unit});

		// bottom
		if(_cmdPos1 == 'bottom' || _numPos1 == 'bottom'){
			this.$bottomCtrlPanel = $('<div class="jax-rotator-control-panel jax-rotator-control-panel-bottom"></div>');
			this.$bottomCtrlPanel.css({width: _width + this.options.unit,
				                       height: _btnHeight + this.options.unit});
			this.$element.append(this.$bottomCtrlPanel);
			if((_cmdPos1 == 'bottom' && _cmdPos2 == 'left') || (_numPos1 == 'bottom' && _numPos2 == 'left')){
				this.$bottomCtrlPanel.append('<div class="jax-rotator-control-subpanel jax-rotator-control-subpanel-left"></div>');
				if((_cmdPos1 == 'bottom' && _cmdPos2 == 'left')){
					this.appendCommands($('.jax-rotator-control-subpanel-left', this.$bottomCtrlPanel));
				}
				if((_numPos1 == 'bottom' && _numPos2 == 'left')){
					this.appendNumbers($('.jax-rotator-control-subpanel-left', this.$bottomCtrlPanel));
				}
			}
			if((_cmdPos1 == 'bottom' && _cmdPos2 == 'right') || (_numPos1 == 'bottom' && _numPos2 == 'right')){
				this.$bottomCtrlPanel.append('<div class="jax-rotator-control-subpanel jax-rotator-control-subpanel-right"></div>');
				if((_cmdPos1 == 'bottom' && _cmdPos2 == 'right')){
					this.appendCommands($('.jax-rotator-control-subpanel-right', this.$bottomCtrlPanel));
				}
				if((_numPos1 == 'bottom' && _numPos2 == 'right')){
					this.appendNumbers($('.jax-rotator-control-subpanel-right', this.$bottomCtrlPanel));
				}
			}
		}

	},
	display: function(n){
		if(this.itemGroup.length < 1) return;
		if(!n) n = this.currentNumber; // start one base
		if(n <= 0 || n > this.itemGroup.length)n = 1;
		this.$displayPanel.empty().append(this.itemGroup[n-1]);
		for(var _i=0; _i<this.numbers.length; _i++){
			this.numbers[_i].setState(Jax.ImageButton.State.Unselected);
		}
		this.numbers[n-1].setState(Jax.ImageButton.State.Selected);
		this.currentNumber = n;
		
	},
	show: function(container){
		if(!container) throw new Error('container is required.');
		if(typeof container != 'string') throw new Error('container must be string');
		this.display(); this.$displayPanel.show();
		$(Jax.toId(container)).empty().append(this.$element);
		if(this.options.state == Jax.Rotator.State.Play){
			this.play();
		}else{
			this.stop();
		}
		return this;
	},
	fadeTo: function(n){
		if(this.itemGroup.length < 1) return;
		if(n == undefined || n.constructor != Number) n = (this.currentNumber + 1);
		if(n < 1) n = 5;
		else if(n > this.itemGroup.length) n = 1;
		if(n > 0 && n <= this.itemGroup.length){
			var _self = this;
			this.$displayPanel.fadeOut(this.options.effect.speed, function(){
				_self.display(n);
			});
			this.$displayPanel.fadeIn(this.options.effect.speed, function(){
				if(_self.options.state == Jax.Rotator.State.Play){
					_self.play();
				}else{
					_self.stop();
				}
			});
		}
	},
	slideLeft: function(n){
	},
	moveTo: function(n){
		switch(this.options.effect.mode){
			case 'fade':
				this.fadeTo(n);
				break;
		}
	},
	play: function(){
		var _self = this;
		_self.options.state = Jax.Rotator.State.Play;
		this.btnPlay.setDisable(true);
		this.btnStop.setDisable(false);
		this.timer = window.setTimeout(function(){_self.moveTo(_self.currentNumber + 1);}, this.options.interval);
	},
	stop: function(){
		var _self = this;
		_self.options.state = Jax.Rotator.State.Stop;
		this.btnPlay.setDisable(false);
		this.btnStop.setDisable(true);
		window.clearTimeout(this.timer);
		this.timer = null;
	},
	prev: function(){
		this.stop();
		this.moveTo(this.currentNumber - 1);
	},
	next: function(){
		this.stop();
		this.moveTo(this.currentNumber + 1);
	},
	go: function(n){
		this.stop();
		this.moveTo(n);
	} 
});
