Categories: JavaScript

[JS] jQuery Wizard

最近工作一直跟匯入的資料處理有關,弄到自己有點頭痛,其中比較頭痛的是 想要美觀的 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);

 

Mesak

我是米薩克,想了解更多可以點選  關於我 

Disqus Comments Loading...
Share
Published by
Mesak

Recent Posts

[教學] 利用 n8n 建立 LINE 聊天機器人

n8n 有多厲害,這邊就不贅述...

3 週 ago

[開箱] IROCKS K103R 熱插拔無線機械式鍵盤

許久沒有開箱了,近年鍵盤的規格...

3 個月 ago

[開箱] IROCKS-K85R 無線機械鍵盤

最近一直想要組一把 無線的 9...

1 年 ago

[開箱] IROCKS K75M 銀色上蓋機械式鍵盤

IROCKS K75M 這款鍵...

2 年 ago

[開箱] IROCKS M31E 粉紅色光學遊戲滑鼠

喜歡粉紅色周邊產品的朋友,有一...

2 年 ago