I'm building my own date range picker (I am aware of jQuery UI's own datepicker, it just doesn't suit my needs).

I'm using on('mouseover') to select a range of dates between the already selected check in date, and the current hover date:

function datepicker_live_selection_hover_css(checkin) {

        $('.datepicker-cal-wrapper table tbody tr td.datepicker-cal-available').on('mouseover', function () {

            var checkout_selected = datepicker_checkout_selected();

            if ( (checkin !== null) && (checkout_selected == false) ) {

                var hover_date = $(this).attr('data-date');

                $('.datepicker-cal-wrapper table tbody tr td').each (function() {

                    var date = $(this).attr('data-date');

                    if ( (date > checkin) && (date <= hover_date) || (date < checkin) && (date >= hover_date) ) {
                        $('.datepicker-cal-wrapper table tbody tr td[data-date="' + date + '"]').addClass('datepicker-cal-selected-date');
                    } else {
                        $('.datepicker-cal-wrapper table tbody tr td[data-date="' + date + '"]').removeClass('datepicker-cal-selected-date');
                    }

                });

            }

        });

    }

This is working fine, but it's very slow and laggy and I'm sure there must be a far better method for doing the above. At the moment I'm using a foreach function to loop through all of the table cells.

Can anyone suggest a more efficent way of doing this?

Full working JSFiddle here: https://jsfiddle.net/yfn1gLh5/

1 Answers

1
Recep Karadas On Best Solutions

Here is an example how you can achieve that.

Note: This function also works across the other tables. How it works:

  1. Get the parent element that holds the tables
  2. Get all elements that contains the class 'datepicker-cal-available'
  3. Get the index of the current and checkin element
  4. Set the slice start and end values so we can get the range of the affected cells.
  5. Remove the '..selected-date' class (cleanup) and add the class to the affected cells.
function datepicker_live_selection_hover_css(checkin) {

        $('.datepicker-cal-wrapper table tbody tr td.datepicker-cal-available').on('mouseover', function () {
            var checkout_selected = datepicker_checkout_selected();

            if ( (checkin !== null) && (checkout_selected == false) ) {

                var parent = $(this).closest(".datepicker-cal");
                var availableChildren = parent.find(".datepicker-cal-available");
                var checkInElement = parent.find('[data-date="' + checkin + '"]')[0];

                var idxOfCurrent = availableChildren.index($(this));
                var idxOfCheckIn = availableChildren.index(checkInElement);

                var idxStart = idxOfCheckIn > idxOfCurrent ? idxOfCurrent : idxOfCheckIn;
                var idxEnd = idxStart == idxOfCheckIn ? idxOfCurrent : idxOfCheckIn;
                var hoverChildren = availableChildren.slice(idxStart, idxEnd + 1 );

                availableChildren.removeClass('datepicker-cal-selected-date');
                hoverChildren.addClass('datepicker-cal-selected-date');
            }
        });
    }

I also simplified your checkin and checkout functions.

function datepicker_checkin_selected() {
    var elements = $('.datepicker-cal-selected-checkin');
    return elements.length > 0;
}

function datepicker_checkout_selected() {
    var elements = $('.datepicker-cal-selected-checkout');
    return elements.length > 0;
}