Home > Software engineering >  Custom timepicker with jQuery and bootstrap
Custom timepicker with jQuery and bootstrap

Time:04-08

I build a custom timepicker with jQuery and bootstrap. It's almost finished, but 1 "nice to have detail" is missing and I'm stucked getting to the result.

It should follow this rules:

  1. Select the time on click
  2. Only related times are possible to select.
  3. Only 1 time range at once is possible (e.g. 09:00-11:00 works but can't pick another time range)
  4. Disabled times are not possible to pick and if they are between a possible time range, only the range before or after disabled are allowed.
  5. It should be possible to click the start time and the end time and if there are no obstacles in between, the times between should be selected as well.

1-4 are working but I'm stucked on point 5.

So what I want to achieve is that if I click on 13:00-14:00 and 15:00-16:00, 14:00-15:00 should be selected automatically if allowed by above rules.

    $('.time-cal .time-btn').on('click',function(){
        if($('.time-cal .time-btn.btn-success').length == 0)
        {
            $(this).not(".btn-danger").toggleClass('btn-success');
            $(this).not(".btn-danger").toggleClass('btn-light');
        }else{
            if($(this).hasClass('btn-light'))
            {
                if($(this).next().hasClass('btn-success') || $(this).prev().hasClass('btn-success'))
                {
                    $(this).not(".btn-danger").toggleClass('btn-success');
                    $(this).not(".btn-danger").toggleClass('btn-light');
                }
            }else{
                let next = $(this).next();
                let prev = $(this).prev();
                
                if(!next.hasClass('btn-success') || ! prev.hasClass('btn-success'))
                {
                    $(this).not(".btn-danger").toggleClass('btn-success');
                    $(this).not(".btn-danger").toggleClass('btn-light');
                }
            }
        }
    });
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA 058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

<div >
                                <label>Pick times</label><br>
                                <button type="button"  data-start="07:00" data-end="08:00" disabled="">07:00 - 08:00</button>
                                <button type="button"  data-start="08:00" data-end="09:00" disabled="">08:00 - 09:00</button>
                                <button type="button"  data-start="09:00" data-end="10:00">09:00 - 10:00</button>
                                <button type="button"  data-start="10:00" data-end="11:00">10:00 - 11:00</button>
                                <button type="button"  data-start="11:00" data-end="12:00" disabled="">11:00 - 12:00</button>
                                <button type="button"  data-start="12:00" data-end="13:00">12:00 - 13:00</button>
                                <button type="button"  data-start="13:00" data-end="14:00">13:00 - 14:00</button>
                                <button type="button"  data-start="14:00" data-end="15:00">14:00 - 15:00</button>
                                <button type="button"  data-start="15:00" data-end="16:00">15:00 - 16:00</button>
                                <button type="button"  data-start="16:00" data-end="17:00" disabled="">16:00 - 17:00</button>
                                <button type="button"  data-start="17:00" data-end="18:00" disabled="">17:00 - 18:00</button>
                                <button type="button"  data-start="18:00" data-end="19:00">18:00 - 19:00</button>
                                <button type="button"  data-start="19:00" data-end="20:00">19:00 - 20:00</button>
                                <button type="button"  data-start="20:00" data-end="21:00">20:00 - 21:00</button>
                                <button type="button"  data-start="21:00" data-end="22:00">21:00 - 22:00</button>

                                <div >

                                </div>  
                            </div>
                            
                            <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
                            <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5 76PVCmYl" crossorigin="anonymous"></script>

CodePudding user response:

-edit altered behaviour based on the comments. At startup each time'button' is divided into a specific timeblock so buttons in the same timeblock can be quickly handled together (there might be some additional/other behavioral requirements when reselecting)

const 
        disabledClass = 'btn-danger',
    selectedClass = 'btn-success',
    notselectedClass = 'btn-light',        
    timeButtons = $('.time-cal .time-btn'),
    enabledButtons = timeButtons.not('.'   disabledClass ),
    timeBlocks = [];    
    
    timeButtons.each((index,btn)=>{btn.enabled=!$(btn).hasClass(disabledClass); 
        if(btn.enabled){
        if(index===0 || !timeButtons[index-1].enabled){         
          timeBlocks.push([]); //new timeblock
        }
        btn.timeBlock = timeBlocks[timeBlocks.length-1];
        btn.timeBlock.push(btn);
      }
      prevEnabled = btn.enabled;
        btn.index = index;btn.selected=false;       
      btn.setSelected = sel => {if(btn.selected===sel)return; btn.selected=sel;
            $(btn).toggleClass(notselectedClass,!sel).toggleClass(selectedClass,sel);}
      });
    

         
enabledButtons.click(function(){          
         if(this.selected){
                //deselect and make sure times in this block after this button are deselected too
                        this.timeBlock.filter(btn=>btn.index >= this.index).forEach(btn=>btn.setSelected(false));
            return;
         }
        
        let selected = false;
        enabledButtons.each((index,btn)=>{
            if(btn.timeBlock !== this.timeBlock)
                btn.setSelected(false); //other timeblocks, make sure to disable
          else{
            selected ||= btn.selected || btn.index===this.index;            
            btn.setSelected(selected && btn.index <= this.index);
          }
        });
        
    });
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA 058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

<div >
                                <label>Pick times</label><br>
                                <button type="button"  data-start="07:00" data-end="08:00" disabled="">07:00 - 08:00</button>
                                <button type="button"  data-start="08:00" data-end="09:00" disabled="">08:00 - 09:00</button>
                                <button type="button"  data-start="09:00" data-end="10:00">09:00 - 10:00</button>
                                <button type="button"  data-start="10:00" data-end="11:00">10:00 - 11:00</button>
                                <button type="button"  data-start="11:00" data-end="12:00" disabled="">11:00 - 12:00</button>
                                <button type="button"  data-start="12:00" data-end="13:00">12:00 - 13:00</button>
                                <button type="button"  data-start="13:00" data-end="14:00">13:00 - 14:00</button>
                                <button type="button"  data-start="14:00" data-end="15:00">14:00 - 15:00</button>
                                <button type="button"  data-start="15:00" data-end="16:00">15:00 - 16:00</button>
                                <button type="button"  data-start="16:00" data-end="17:00" disabled="">16:00 - 17:00</button>
                                <button type="button"  data-start="17:00" data-end="18:00" disabled="">17:00 - 18:00</button>
                                <button type="button"  data-start="18:00" data-end="19:00">18:00 - 19:00</button>
                                <button type="button"  data-start="19:00" data-end="20:00">19:00 - 20:00</button>
                                <button type="button"  data-start="20:00" data-end="21:00">20:00 - 21:00</button>
                                <button type="button"  data-start="21:00" data-end="22:00">21:00 - 22:00</button>

                                <div >

                                </div>  
                            </div>
                            
                            <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
                            <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5 76PVCmYl" crossorigin="anonymous"></script>

  • Related