jQuery UI Datepicker - Date range - Highlight days in between

16,760

Solution 1

I added a bit to your script. Worked like a charm on JSFiddle. Take a look and let me know.

    $("#input-service_date_leave, #input-service_date_return").datepicker({
        rangeSelect: true,
        beforeShow: customRange,
        onSelect: customRange,
    });

    function customRange(input) {
        if (input.id == "input-service_date_leave") {

            $("#ui-datepicker-div td").die();

            if (selectedDate != null) {
                $('#input-service_date_return').datepicker('option', 'minDate', selectedDate).datepicker('refresh');
            }
        }
        if (input.id == "input-service_date_return") {

            $("#ui-datepicker-div td").live({
                mouseenter: function() {
                    $(this).parent().addClass("finalRow");
                    $(".finalRow").prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
                    $(this).prevAll("td:not(.ui-datepicker-unselectable)").addClass("highlight");
               },
                mouseleave: function() {
                    $(this).parent().removeClass("finalRow");
                    $("#ui-datepicker-div td").removeClass("highlight");
                }
            });

            var selectedDate = $("#input-service_date_leave").datepicker("getDate");                
            if (selectedDate != null) {
                $('#input-service_date_return').datepicker('option', 'minDate', selectedDate).datepicker('refresh');
            }
        }
    }

Solution 2

edit: This script does not work on jquery 3. however it does work on version 1 and 2

this JSFiddle is an example of doing it with 2 date tables ( multiple months )

$("#input-service_date_leave, #input-service_date_return").datepicker({
    rangeSelect: true,
    beforeShow: customRange,
    onSelect: customRange,
    numberOfMonths: [1, 2],
});

function customRange(input) {
    if (input.id == "input-service_date_leave") {

        $("#ui-datepicker-div td").die();

        if (selectedDate != null) {
            $('#input-service_date_return').datepicker('option', 'minDate', selectedDate).datepicker('refresh');
        }
    }
    if (input.id == "input-service_date_return") {

        $("#ui-datepicker-div td").live({
            mouseenter: function() {
                $(this).parent().addClass("finalRow");
                $(".finalRow").parents('.ui-datepicker-group-last').parent().find('.ui-datepicker-group-first').find('tr').last().addClass("finalRowRangeOtherTable");
                $(".finalRowRangeOtherTable").find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
                $(".finalRowRangeOtherTable").prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");

                $(".finalRow").prevAll().find("td:not(.ui-datepicker-unselectable)").addClass("highlight");
                $(this).prevAll("td:not(.ui-datepicker-unselectable)").addClass("highlight");
           },
            mouseleave: function() {
                $(this).parent().removeClass("finalRow");
                $("#ui-datepicker-div td").removeClass("highlight");

                  $(".finalRowRange").removeClass("finalRowRange").find('.highlight').removeClass("highlight");
            $(".finalRowRangeOtherTable").removeClass("finalRowRangeOtherTable").find('.highlight').removeClass("highlight");

            }
        });

        var selectedDate = $("#input-service_date_leave").datepicker("getDate");                
        if (selectedDate != null) {
            $('#input-service_date_return').datepicker('option', 'minDate', selectedDate).datepicker('refresh');
        }
    }
}

Solution 3

Made an example of date range hover for an inline datepicker here: http://codepen.io/denissamoilov/pen/RGKyPb?editors=0010

$(function(){
    var datepicker = {
        container: $("#datepicker"),
        dateFormat: 'mm/dd/yy',
        dates: [null, null],
        status: null,
        inputs: {
            checkin: $('#checkin'),
            checkout: $('#checkout'),
            dates: $('#dates')
        }
    };

    datepicker.container.datepicker({
        numberOfMonths: 2,
        dateFormat: datepicker.dateFormat,
        minDate: 0,
        maxDate: null,

        beforeShowDay: function(date) {
            var highlight = false,
            currentTime = date.getTime(),
            selectedTime = datepicker.dates;

            // Highlight date range
            if ((selectedTime[0] && selectedTime[0] == currentTime) || (selectedTime[1] && (currentTime >= selectedTime[0] && currentTime <= selectedTime[1]))) highlight = true;

            return [true, highlight ? 'ui-datepicker-select' : ""];
        },
        onSelect: function(dateText) {

            if (!datepicker.dates[0] || datepicker.dates[1] !== null) {
                // CHOOSE FIRST DATE

                // fill dates array with first chosen date
                datepicker.dates[0] = $.datepicker.parseDate(datepicker.dateFormat, dateText).getTime();
                datepicker.dates[1] = null;

                // clear all inputs
                datepicker.inputs.checkin.val('');
                datepicker.inputs.checkout.val('');
                datepicker.inputs.dates.val('');

                // set current datepicker state
                datepicker.status = 'checkin-selected';

                // create mouseover for table cell
                $('#datepicker').delegate('.ui-datepicker td', 'mouseover', function(){

                    // if it doesn't have year data (old month or unselectable date)
                    if ($(this).data('year') == undefined) return;

                    // datepicker state is not in date range select, depart date wasn't chosen, or return date already chosen then exit
                    if (datepicker.status != 'checkin-selected') return;

                    // get date from hovered cell
                    var hoverDate = $(this).data('year')+'-'+($(this).data('month')+1)+'-'+$('a',this).html();

                    // parse hovered date into milliseconds
                    hoverDate = $.datepicker.parseDate('yy-mm-dd', hoverDate).getTime();

                    $('#datepicker td').each(function(){

                        // compare each table cell if it's date is in date range between selected date and hovered
                        if ($(this).data('year') == undefined) return;

                        var year = $(this).data('year'),
                            month = $(this).data('month'),
                            day = $('a', this).html();

                        var cellDate = $(this).data('year')+'-'+($(this).data('month')+1)+'-'+$('a',this).html();

                        // convert cell date into milliseconds for further comparison
                        cellDate = $.datepicker.parseDate('yy-mm-dd', cellDate).getTime();

                        if ( (cellDate >= datepicker.dates[0] && cellDate <= hoverDate) || (cellDate <= datepicker.dates[0] && cellDate >= hoverDate) ) {
                            $(this).addClass('ui-datepicker-hover');
                        } else {
                            $(this).removeClass('ui-datepicker-hover');
                        }

                    });
                });

            } else {
                // CHOOSE SECOND DATE

                // push second date into dates array
                datepicker.dates[1] = $.datepicker.parseDate(datepicker.dateFormat, dateText).getTime();

                // sort array dates
                datepicker.dates.sort();

                var checkInDate = $.datepicker.parseDate('@', datepicker.dates[0]);
                var checkOutDate = $.datepicker.parseDate('@', datepicker.dates[1]);

                datepicker.status = 'checkout-selected';

                //fill input fields

                datepicker.inputs.checkin.val($.datepicker.formatDate(datepicker.dateFormat, checkInDate));
                datepicker.inputs.checkout.val($.datepicker.formatDate(datepicker.dateFormat, checkOutDate)).change();

                datepicker.inputs.dates.val(datepicker.inputs.checkin.val() + ' - ' + datepicker.inputs.checkout.val());

            }
        }
    });
});
Share:
16,760

Related videos on Youtube

Mayko
Author by

Mayko

Updated on June 14, 2022

Comments

  • Mayko
    Mayko almost 2 years

    I'm looking for a way of highlighting the days in between the date range of 2 inputs on mouse over.

    This example is nearly doing what I want to achieve: http://hackingon.net/files/jquery_datepicker/range.htm

    Only difference is that the highlighting of the selected range should happen on two separate datepickers and on mouse over.

    Any suggestions?


    Update:

    Ok, a bit more details:

    After selecting a date from the first datepicker, the second datepicker should highlight the previous selected date. If you then mouse over a day past the previous selected day, all days in between should highlight by adding a class.


    Update: This is how far I got:

        $("#input-service_date_leave, #input-service_date_return").datepicker({
            rangeSelect: true,
            beforeShow: customRange,
            onSelect: customRange,
        });
    
        function customRange(input) {
            if (input.id == "input-service_date_leave") {
    
                $("#ui-datepicker-div td").die();
    
                if (selectedDate != null) { 
                    $('#input-service_date_return').datepicker('option', 'minDate', selectedDate).datepicker('refresh');
                }
            }
            if (input.id == "input-service_date_return") {
    
                $("#ui-datepicker-div td").live({
                    mouseenter: function() {
                        $(this).prevAll("td:not(.ui-datepicker-unselectable)").addClass("highlight");
                    },
                    mouseleave: function() {
                        $("#ui-datepicker-div td").removeClass("highlight");
                    }
                });
    
                var selectedDate = $("#input-service_date_leave").datepicker("getDate");                
                if (selectedDate != null) { 
                    $('#input-service_date_return').datepicker('option', 'minDate', selectedDate).datepicker('refresh');
                }
            }
        }
    

    http://jsfiddle.net/mayko/WbWg3/1/

    Only problem, the live event just highlights the td's of the current hovered row, but not the td's of the rows before.

    Any ideas?

  • Marvzz
    Marvzz over 11 years
    This answer helped me! Thanks a lot!
  • Marvzz
    Marvzz over 11 years
    One more thing, can you help update this to span it to the next month? I'm showing two months in a picker. Thanks!
  • Aryeh Armon
    Aryeh Armon over 8 years
    @Marvzz i added an answer that included a script to do it with multiple months
  • Abhishek Saini
    Abhishek Saini over 6 years
    Somebody migrate it to jQuery 3 please.
  • Aryeh Armon
    Aryeh Armon over 6 years
    @AbhishekSaini should qork on jquery 3, not tested though. what functions here were deprecated in jq3?
  • Abhishek Saini
    Abhishek Saini over 6 years
    Nope, doesn't work. live() & die() are out of jQuery 3.