/**
 * wrapperのクラス入れ替えJS
 * jquery.swapwrapperclass.js
 * ver 1.2
 *
 * triger（操作もと）、wrapper（枠組み）の2つの要素からなる
 * trigerの操作（click、mouseover、mouseoutなど）に応じて、wrapperに特定のクラスの入れ替え、追加、削除を実行
 * クラスの入れ替え、追加、削除の前後に処理を実行（引数[$self, $wrapper, wrapperClasses, index]）
 * クラスの入れ替え、追加、削除の前処理にて、falseを返すと処理停止
 * クラスの入れ替え、追加、削除の前後の処理は、それぞれ独立して指定
 *
 * イベント設定
 *   swapEvent: classを入れ替えるイベント（デフォルト：click）
 *   removeEvent: classを除去するイベント（デフォルト：undefined）
 * 例）
 *   クリックで入れ替え
 *     swapEvent: "click", removeEvent: undefined
 *   マウスオーバーで入れ替え（マウスアウトでも削除する）
 *     swapEvent: "mouseover", removeEvent: "mouseout"
 *   マウスオーバーで入れ替え（マウスアウトでは削除しない）
 *     swapEvent: "mouseover", removeEvent: undefined
 * 
 */
(function($){
	//wrapperクラス入れ替え
	$.fn.swapWrapperClass = function(options){
		//存在しない場合は終了
		if(!this) return this;

		//トリガ
		var $self = this;

		//イベント指定時、データ格納時のnamespace
		var nameSpace = "swapWrapperClass";

		//オプション拡張
		options = $.extend({}, $.fn.swapWrapperClass.defaults, options, true);
		//wrapperに追加するクラスの配列
		var wrapperClasses = [];
		
		$self.each(
			function(index){
				//wrapperに追加するクラス取得
				var wrapperClass;
				if($.isFunction(options.wrapperClass)){
					wrapperClass = options.wrapperClass.apply(this);
				}
				else{
					wrapperClass = options.wrapperClass;
				}
				//wrapperに追加するクラスを配列にセット
				wrapperClasses[index]=wrapperClass;
			}
		);

		//トリガを走査
		return $self.each(
			function(index){
				var $trigger = $(this);
				//wrapper取得
				var $wrapper;
				if($.isFunction(options.wrapper)){
					$wrapper = options.wrapper.apply(this);
				}
				else{
					$wrapper = $(options.wrapper);
				}
				var callbackArg = [$self, $wrapper, wrapperClasses, index];
				
				//トリガのイベント設定
				//classを追加するイベント
				if(options.addEvent)
				{
					$trigger.bind(
						options.addEvent + "." + nameSpace,
						function(evnt){
							if(options.beforeAdd == undefined || $.isFunction(options.beforeAdd) && options.beforeAdd.apply(this, callbackArg)){
								//wrapperにクラスを追加
								$wrapper.addClass(wrapperClasses[index]);
								if($.isFunction(options.afterAdd)){
									options.afterAdd.apply(this, callbackArg);
								}
							}
							evnt.preventDefault();
							return false;
						}
					);
				}
				//classを除去するイベント
				if(options.removeEvent)
				{
					$trigger.bind(
						options.removeEvent + "." + nameSpace,
						function(evnt){
							if(options.beforeRemove == undefined || $.isFunction(options.beforeRemove) && options.beforeRemove.apply(this, callbackArg)){
								//wrapperから追加されるクラスを一度全て削除
								$wrapper.removeClass(wrapperClasses.join(" "));
								if($.isFunction(options.afterRemove)){
									options.afterRemove.apply(this, callbackArg);
								}
							}
							evnt.preventDefault();
							return false;
						}
					);
				}
				//classを入れ替えるイベント
				if(options.swapEvent)
				{
					$trigger.bind(
						options.swapEvent + "." + nameSpace,
						function(evnt){
							if(options.beforeSwap == undefined || $.isFunction(options.beforeSwap) && options.beforeSwap.apply(this, callbackArg)){
								//追加する前にwrapperから追加されるクラスを一度全て削除
								$wrapper.removeClass(wrapperClasses.join(" "));
								//対象のクラスを追加
								$wrapper.addClass(wrapperClasses[index]);
								if($.isFunction(options.afterSwap)){
									options.afterSwap.apply(this, callbackArg);
								}
							}
							evnt.preventDefault();
							return false;
						}
					);
				}
			}
		);
	};

	//wrapperクラス入れ替えのデフォルト設定
	$.fn.swapWrapperClass.defaults = {
		//wrapperの取得（this=トリガ）
		wrapper: undefined,
		//wrapperに追加されるクラスの取得（this=トリガ）
		wrapperClass: undefined,
		//classを入れ替えるイベント
		swapEvent: "click",
		//classを追加するイベント
		addEvent: undefined,
		//classを除去するイベント
		removeEvent: undefined,
		//class入れ替え前の処理（falseで停止）
		beforeSwap: undefined,
		//class入れ替え後の処理
		afterSwap: undefined,
		//class追加前の処理（falseで停止）
		beforeAdd: undefined,
		//class追加後の処理
		afterAdd: undefined,
		//class除去前の処理（falseで停止）
		beforeRemove: undefined,
		//class除去後の処理
		afterRemove: undefined
	};
})(jQuery);
