Search code examples
jquerydatepickerdate-range

jQuery Datepicker - issue with start and end dates classes


Initially I was searching for solution for generating some class for start and end dates under the jQuery Datepicker, and the solution was given to me under this post https://stackoverflow.com/a/67191802/14723575

But it works only if start and end dates are under the same month. There is an issue with both of suggested codes if I need to slide to some next month in order to select end date. For example, if I select 24 April as start date and 6 May as end date, it brakes at the last day of the current month.

I got suggestion to open separated ticket for this problem, so here we go.


Solution

  • I have modified the code to adapt to your problem. As you could see, the code have to test lot of different situations, i think i have not forgotten...

    i have put the code in snippet, because there lot of lines of code, but the snippet is not functional...

    $(function () {
      var dates_selected = [];
      var firstdate_present = false;//is firstdate present in the current display?
      var lastdate_present = false;//is lastdate present in the current display?
    
      $(".date-picker-input").datepick({
        rangeSelect: true,
        dateFormat: "dd/mm/yyyy",
        changeMonth: false,
        prevText: "<",
        nextText: ">",
        showOtherMonths: true,
        dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
        onShow: function (dates) {setTimeout(() => {Open();}, 0);},
        onChangeMonthYear: function (year, month) { Change(year, month);},
        onDate: highlightDays,
        onClose: Close,
        showTrigger: "#calImg",
      });
    
      // function waits a return, false or true or other but
      // dunno the utility
      function highlightDays(date) {
        if (dates_selected.length == 0) return false;
    
        if (compareDates(date, dates_selected[0]) == 0) {
          firstdate_present = true;//yes present in current display
        }
        if (compareDates(date, dates_selected[1]) == 0) {
          lastdate_present = true;//yes present in current display
        }
        return true;
      }
    
      function Change(y, m) {
        firstdate_present = false;
        lastdate_present = false;
      }
    
      function Open() {
        if (dates_selected.length == 0) return;
        //current year month displayed YYYYMM
        let current = parseDate($(".datepick-month-header").text());
        //year month for first and last date of range
        let months = new objDate(dates_selected[0].getFullYear() * 100 + dates_selected[0].getMonth(), 
                                 dates_selected[1].getFullYear() * 100 + dates_selected[1].getMonth());
        let days = new objDate(dates_selected[0].getDate(), dates_selected[1].getDate());
        //let years = new objDate(dates_selected[0].getFullYear(), dates_selected[1].getFullYear() );
    
        let others = $(".datepick-other-month").map( (_, e) => parseInt($(e).text())).get();
    
        if (firstdate_present && lastdate_present) {
          if (current == months.first && current == months.last) {
            $(".datepick-popup .datepick-selected:first, .datepick-popup .datepick-selected:last").addClass("selected");
          } else if (current == months.first) {
            $(".datepick-popup .datepick-selected:first").addClass("selected");
            let indexfirst = others.findIndex( num => num < 15);
            let indexlast = others.findIndex( num => num == days.last);
            for(let i = indexfirst; i <= indexlast; i++){
              if(i == indexlast ) $(".datepick-other-month").eq(i).addClass("selected");
              $(".datepick-other-month").eq(i).addClass("datepick-selected");
            }
          } else if (current == months.last) {
            $(".datepick-popup .datepick-selected:last").addClass("selected");
            let indexfirst = others.findIndex( num => num == days.first);
            for(let i = indexfirst; i < others.length && others[i] > 15; i++){
              if(i == indexfirst ) $(".datepick-other-month").eq(i).addClass("selected");
              $(".datepick-other-month").eq(i).addClass("datepick-selected");
            }
          } else if (current != months.first && current != months.last) {  
            let indexfirst = others.findIndex( num => num == days.first);
            let indexlast = others.findIndex( num => num == days.last);
            for(let i = indexfirst; i <= indexlast; i++){
                if( i == indexfirst || i == indexlast ) $(".datepick-other-month").eq(i).addClass("selected");
                $(".datepick-other-month").eq(i).addClass("datepick-selected");
            }
          }
        } else if (firstdate_present) {
          if (current == months.first) {
            $(".datepick-popup .datepick-selected:first").addClass("selected");
            let indexfirst = others.findIndex( num => num < 15);
            for(let i = indexfirst; i <= others.length && i >= 0; i++){
              $(".datepick-other-month").eq(i).addClass("datepick-selected");
            }
          } else if (current != months.first) {  
            let indexfirst = others.findIndex( num => num == days.first);
            for(let i = indexfirst; i < others.length; i++){
                if( i == indexfirst ) $(".datepick-other-month").eq(i).addClass("selected");
                $(".datepick-other-month").eq(i).addClass("datepick-selected");
            }
          }
        } else if (lastdate_present) {
          if (current == months.last) {
            $(".datepick-popup .datepick-selected:last").addClass("selected");
            for(let i = 0; i <= others.length && others[i] >= 15; i++){
              $(".datepick-other-month").eq(i).addClass("datepick-selected");
            }
          } else if (current != months.last) {  
            let indexfirst = others.findIndex( num => num == days.last);
            for(let i = indexfirst; i < others.length; i++){
                if( i == indexfirst ) $(".datepick-other-month").eq(i).addClass("selected");
                $(".datepick-other-month").eq(i).addClass("datepick-selected");
            }
          }
        } else if( current > months.first && current < months.last){
          $(".datepick-other-month").addClass("datepick-selected");
        }
    
      }
    
      function Close(dates) {
        dates_selected = dates;
        firstdate_present = false;
        lastdate_present = false;
      }
    
      function compareDates(a, b) {
        if (a < b) return -1;
        if (a > b) return +1;
    
        return 0; // dates are equal
      }
    
      function objDate(first, last) {
        this.first = first;
        this.last = last;
        this.same = first == last;
      }
    
      // arg:string MMMM YYYY, return:number YYYYMM
      function parseDate(s) {
        // to adapt following the setting of name month displayed
        var months = {january: 0, february: 1, march: 2, april: 3, may: 4, june: 5, july: 6, august: 7, september: 8, october: 9, november: 10, december: 11};
        var p = s.split(" ");
        return parseInt(p[1]) * 100 + parseInt(months[p[0].toLowerCase()]);
      }
    });

    enter image description here