[JS] jQuery Wizard

by Mesak

最近工作一直跟匯入的資料處理有關,弄到自己有點頭痛,其中比較頭痛的是 想要美觀的 Wizard 或是 Step 這種步驟式的plugin 大多都沒有達到我的需求

後來在網路上看到一段很簡略的 Step Wizard 應用上了一個案子,運行的很順暢。

不過還是不敷我使用,一直大量用到了之後決定寫成個 plugin 先寫個雛形方便未來修改擴增。

因為是用 Bootstrap 所以CSS範例也是跑 Bootstrap 

HTML 部分很簡單 最主要就是 id=wizard 要包住 wizard-sidebar 導航條,wizard-content 變成內容,一對一對應,內容不需要打標題,產生後會自動 的塞入

		<div class="row wizard" id="wizard">
		  <div class="col-md-3">
		    <div class="wizard-sidebar list-group">
		      <a>Import Step1</a>
		      <a>Import Step2</a>
		      <a>Import Step3</a>
		      <a>Import Step4</a>
		      <a>Import Step5</a>
		      <a>Import Step6</a>
		    </div>
		  </div>
		  <div class="col-md-9">
	      	<div id="step1" class="well wizard-content">1</div>
	      	<div id="step2" class="well wizard-content">2</div>
	      	<div id="step3" class="well wizard-content">3</div>
	      	<div id="step4" class="well wizard-content">4</div>
	      	<div id="step5" class="well wizard-content">5</div>
	      	<div id="step6" class="well wizard-content">6</div>
		  </div>
		</div>

JS的部分

$('#wizard').wizard({
	step_prev : 'Prev Step',
	step_next : 'Next Step',
	move3to4 : function(){
		alert('3to4');
        oWizard.moveToAction('next');
	},
	moveTo4after : function(){
        alert('this is 4');
	},
	move4to3 : function(){
		alert('4to3');
	},
	move4to5 : function(){
		return false;
	},
	move3to2 : function(){
		alert('3to2');
	}
})

基本上可以不用設定,想自訂上一步下一步的字串就自己新增然後是 event

在執行過程中會有 第 N 步到第 N+1 步的動作,只需要寫在 event 裡面 也很直觀的用數字呈現 如果回傳 return false 整個 步驟就暫停,適合對應 Validation 類型的套件

然後有個 倒退的事件,這個不少 plugin 都沒有做,事件寫法是 n to n-1  這種寫法適合用在RESET 資料,當然只要 return false 一樣可以停止退回

另外還寫了一個 moveTo?after 就是移動到 這個步驟之後要執行的 Function ,比較適合用選擇後載入某些AJAX 資料或是欄位關閉開啟變動,以下可以看範例

JS 沒有正式命名或是打上資料,目前先放這樣 XD需要自行複製存為 JS 檔

(function($){
	$.fn.wizard = function(data,opt) {
		var $that = $(this),
		options = {
			step_prev : 'Prev',
			step_next : 'Next'
		};
		if( jQuery.isPlainObject(data) )
		{
 			opt = data;
		}
		$.extend(options,data);
		$.each(options,function(k,v){
			if( jQuery.isFunction(v) )
			{
				$that.bind('wizard.'+k,v)
			}
		})
		function init(){
			$that.data({
				'now_step' : 0 ,
			});
			var links = $that.data('wizard-links');
			$that.find('.wizard-sidebar > a').each(function(i,n){
				if( typeof links != 'undefined' )
				{
					links = links.add(n);
				}else{
					links = $(n);
				}
				var title = n.innerHTML;
				$(n)
				  .attr('href','#')
				  .attr('data-step',(i+1) )
				  .data('title',title)
				  .addClass('list-group-item')
				  .html('<h4 class="list-group-item-heading">'+title+'</h4>');
			})
			$that.data('wizard-links',links);
			var wells = $that.find('.wizard-content');
			$that.data('wizard-wells',wells);
			wells.hide().each(function(i,n){
				var $well =	$(n);
				$well.attr('data-step',(i+1));
				if( ! $well.find('.header').lenght ){
					$well.prepend('<div class="header"><h2>'+ links.eq(i).data('title')+'</h2></div>');
				}
				if( ! $well.find('.btn-step-area').lenght ){
					$btnArea = $('<ul />', { class : 'btn-step-area pager' }).appendTo( $well );
				}
				if( i>0 && ! $well.find('.btn-prev').lenght ){
					$btnArea.append('<li class="previous"><a href="#" class="btn btn-info btn-prev">'+options.step_prev+'</a></li>')
				}
				if( ! $well.find('.btn-next').lenght ){
					$btnArea.append('<li class="next"><a href="#" class="btn btn-danger btn-next">'+options.step_next+'</a></li>')
				}
			})
			$that.on('click','.btn-next,.btn-prev',function(e){
				var caseMove = $(this).hasClass('btn-next') ? 'next' : 'prev';
				var $p = $(this).closest('div[data-step]');
				var step = parseInt( $p.data('step') ,10 ) 
					step = caseMove == 'next' ? step+1 : step-1;
					console.log(step)
				$that.moveToAction( step );
			    e.preventDefault();
			})
			$that.on('click','.wizard-sidebar > a',function(e){
				//var index = $that.data('links').index( this )
				var index = $('.wizard-sidebar > a').index( this );
				if ( !$(this).hasClass('disabled'))
				{
			    	$that.moveToAction( index+1 );
			    }
			    e.preventDefault();
			});
			$.extend($that,{
				eventMoveTo : function( form , to )
				{
					var result = true;
					form = parseInt(form,10);to = parseInt(to,10);
					var case_event = $that.createTo(form,to);
					for(x in case_event ){
						var ev = $that.triggerHandler('wizard.move'+case_event[x]);
						if( ev === false ){
							result = false;
							break;
						}
					}
					return result;
				},
				createTo : function createTo( a , b )
				{
				    var arr = [];
				    if( b > a )
				        for(var i = a;i < b;i++) arr.push( i + 'to' + (i+1)  );
				    else if( a > b )
				        for(var i = a;i > b;i--) arr.push( i + 'to' + (i-1)  );
				    return arr;
				},
				moveToAction : function(new_step){
					var now_step = $that.data('now_step');
					if( typeof new_step =='string'){
						new_step = (new_step=='next') ? now_step+1 : now_step-1;
					}
					var $item = $that.data('wizard-links').filter('[data-step="'+new_step+'"]');
			        if( $that.eventMoveTo( $that.data('now_step') , new_step ) )
			        {
						$that.data('now_step',new_step)
					    $that.data('wizard-links').addClass('disabled').removeClass('active');
						$item.addClass('active');
						$item.removeClass('disabled').prevAll().removeClass('disabled');
						$that.data('wizard-wells').hide().filter('[data-step="'+new_step+'"]').show();
						$that.triggerHandler('wizard.moveTo'+new_step+'after');
			        }
				}
			})
			$that.data('wizard' ,true);
			$that.moveToAction(1);
		}
		
		var initz = $that.data('wizard');
		if( initz !== true)
		{
			init();
		}
		return $that;
	}
})(jQuery);

 

You may also like