MikeN
MikeN

Reputation: 46287

Can I highlight an entire week in the standard Jquery UI date picker?

Can I highlight an entire week in the standard Jquery UI date picker?

Upvotes: 27

Views: 31643

Answers (12)

Samuele Diella
Samuele Diella

Reputation: 81

Is not working with multiple pickers / last jquery.ui. Try this little rewrite:

jQuery(function() {
    var startDate; // closure
    var endDate;

    var baseAttachHandler = jQuery.datepicker._attachHandlers;
    jQuery.datepicker._attachHandlers = function(inst) {
            baseAttachHandler.apply(this, [inst]);

            var element_data = jQuery._data(inst.dpDiv.get(0));
            var ori_handler_mouseover = element_data.events.mouseover[0].handler;
            var ori_handler_mouseout = element_data.events.mouseout[0].handler;

            // remove handlers
            inst.dpDiv.undelegate("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a", 'mouseover');
            inst.dpDiv.undelegate("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a", 'mouseout');
            inst.dpDiv.undelegate("button, .ui-datepicker-prev, .ui-datepicker-next", 'mouseover');
            inst.dpDiv.undelegate("button, .ui-datepicker-prev, .ui-datepicker-next", 'mouseout');
            inst.dpDiv.find(".ui-datepicker-calendar tr").unbind('mouseover');
            inst.dpDiv.find(".ui-datepicker-calendar tr").unbind('mouseout');

            // attach proper ones
            if (this._get(inst, "weekSelector")) {
                inst.dpDiv.delegate("button, .ui-datepicker-prev, .ui-datepicker-next", 'mouseover', ori_handler_mouseover);
                inst.dpDiv.delegate("button, .ui-datepicker-prev, .ui-datepicker-next", 'mouseout', ori_handler_mouseout);
                inst.dpDiv.find(".ui-datepicker-calendar tr").bind('mouseover', function() { 
                    jQuery(this).find('td a').addClass('ui-state-hover');
                });
                inst.dpDiv.find(".ui-datepicker-calendar tr").bind('mouseout', function() { 
                    jQuery(this).find('td a').removeClass('ui-state-hover');
                });
            } else {
                inst.dpDiv.delegate("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a", 'mouseover', ori_handler_mouseover);
                inst.dpDiv.delegate("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a", 'mouseout', ori_handler_mouseout);
            }
        };

    jQuery.datepicker.calcWeekBoundaries = function () {
        var date = jQuery(this).datepicker('getDate');
        if (date) {
            var tmp = date.getDay();
            if (tmp == 0) { // starting with monday, i'm italian ;-)
                endDate = date;
                startDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() - 6);
            } else {
                startDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() - tmp + 1);
                endDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() - tmp + 7);
            }
        }
    };

    jQuery("#yourcontrol").datepicker(
        jQuery.extend({}, jQuery.datepicker.regional["yourlanguage"], {
            showOtherMonths: true
            , selectOtherMonths: true
            , changeMonth: true
            , changeYear: true
            , onSelect: function(dateText, inst) { 
                if (jQuery.datepicker._get(inst, "weekSelector")) {
                    jQuery.datepicker.calcWeekBoundaries.apply(this, []);
                    jQuery(this).datepicker('setDate', startDate);
                }
                inst.input.trigger("change");
            }
            , beforeShowDay: function(date) {
                var inst = jQuery.data(this, "datepicker");
                var cssClass = '';
                if (jQuery.datepicker._get(inst, "weekSelector") && date) {
                    if(date >= startDate && date <= endDate) {
                        cssClass = 'ui-state-active';
                    }
                }
                return [true, cssClass];
            }
            , beforeShow: function(input, inst) {
                jQuery.datepicker.calcWeekBoundaries.apply(this, []);
            }
            , weekSelector: true // the magic is here
        })
    );
});

Upvotes: 0

HRI
HRI

Reputation: 91

You can check the answered question in the link below

How to use jQuery UI Calendar/Date PIcker for week rather than day?

$(function() {
var startDate;
var endDate;

var selectCurrentWeek = function() {
    window.setTimeout(function () {
        $('.week-picker').find('.ui-datepicker-current-day a').addClass('ui-state-active')
    }, 1);
}

$('.week-picker').datepicker( {
    showOtherMonths: true,
    selectOtherMonths: true,
    onSelect: function(dateText, inst) { 
        var date = $(this).datepicker('getDate');
        startDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() - date.getDay());
        endDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() - date.getDay() + 6);
        var dateFormat = inst.settings.dateFormat || $.datepicker._defaults.dateFormat;
        $('#startDate').text($.datepicker.formatDate( dateFormat, startDate, inst.settings ));
        $('#endDate').text($.datepicker.formatDate( dateFormat, endDate, inst.settings ));

        selectCurrentWeek();
    },
    beforeShowDay: function(date) {
        var cssClass = '';
        if(date >= startDate && date <= endDate)
            cssClass = 'ui-datepicker-current-day';
        return [true, cssClass];
    },
    onChangeMonthYear: function(year, month, inst) {
        selectCurrentWeek();
    }
});

$('.week-picker .ui-datepicker-calendar tr').live('mousemove', function() { $(this).find('td a').addClass('ui-state-hover'); });
$('.week-picker .ui-datepicker-calendar tr').live('mouseleave', function() { $(this).find('td a').removeClass('ui-state-hover'); });

});

Upvotes: 0

Sander Marechal
Sander Marechal

Reputation: 23216

I have created a jQuery plugin based on the top answer. Get it at https://github.com/Prezent/jquery-weekpicker or through Bower. Example usage:

$('#selector').weekpicker({
    startField: '#date-start',
    endField: '#date-end'
});

Upvotes: 1

cardonator
cardonator

Reputation: 396

AntFalco's answer is great, however it doesn't work well if you need to do what I did. I needed a way to select a week and have the first day of the week populate into an input box, a click on which generated the datepicker. Here is the code I used to accomplish this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js"></script>
    <link rel="stylesheet" type="text/css" media="screen" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/base/jquery-ui.css">
<script type="text/javascript">
$(function() {
    var startDate;
    var endDate;

    var selectCurrentWeek = function() {
        window.setTimeout(function () {
            $('#ui-datepicker-div').find('.ui-datepicker-current-day a').addClass('ui-state-active')
        }, 1);
    }

    $('.datepicker').datepicker( {
        showOtherMonths: true,
        selectOtherMonths: true,
        onSelect: function(dateText, inst) { 
            var date = $(this).datepicker('getDate');
            startDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() - date.getDay());
            endDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() - date.getDay() + 6);
            var dateFormat = inst.settings.dateFormat || $.datepicker._defaults.dateFormat;
            $(this).attr("value",$.datepicker.formatDate( dateFormat, startDate, inst.settings ));   
            selectCurrentWeek();
        },
        beforeShowDay: function(date) {
            var cssClass = '';
            if(date >= startDate && date <= endDate)
                cssClass = 'ui-datepicker-current-day';
            return [true, cssClass];
        },
        onChangeMonthYear: function(year, month, inst) {
            selectCurrentWeek();
        }
    });

    $('#ui-datepicker-div .ui-datepicker-calendar tr').live('mousemove', function() { $(this).find('td a').addClass('ui-state-hover'); });
    $('#ui-datepicker-div .ui-datepicker-calendar tr').live('mouseleave', function() { $(this).find('td a').removeClass('ui-state-hover'); });
});
</script>
</head>
<body>
    <input type="text" id="from_date" name="from_date" class="datepicker" />
    <input type="text" id="to_date" name="to_date" class="datepicker" />
</body>
</html>

This also has the side effect of working for multiple input values as well. This chunk of code is by far the most useful if you need some sort of "week" selector. There is very little code so making small modifications to test is quite easy. Also, it works fine with minDate/maxDate functions.

Upvotes: 3

AntFalco
AntFalco

Reputation: 261

I know this post is quite old but I just found this code on another site and thought it might help.

Source code - from this post :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.js"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
    <link rel="stylesheet" type="text/css" media="screen" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/themes/base/jquery-ui.css">
<script type="text/javascript">
$(function() {
    var startDate;
    var endDate;

    var selectCurrentWeek = function() {
        window.setTimeout(function () {
            $('.week-picker').find('.ui-datepicker-current-day a').addClass('ui-state-active')
        }, 1);
    }

    $('.week-picker').datepicker( {
        showOtherMonths: true,
        selectOtherMonths: true,
        onSelect: function(dateText, inst) { 
            var date = $(this).datepicker('getDate');
            startDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() - date.getDay());
            endDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() - date.getDay() + 6);
            var dateFormat = inst.settings.dateFormat || $.datepicker._defaults.dateFormat;
            $('#startDate').text($.datepicker.formatDate( dateFormat, startDate, inst.settings ));
            $('#endDate').text($.datepicker.formatDate( dateFormat, endDate, inst.settings ));

            selectCurrentWeek();
        },
        beforeShowDay: function(date) {
            var cssClass = '';
            if(date >= startDate && date <= endDate)
                cssClass = 'ui-datepicker-current-day';
            return [true, cssClass];
        },
        onChangeMonthYear: function(year, month, inst) {
            selectCurrentWeek();
        }
    });

    $('.week-picker .ui-datepicker-calendar tr').live('mousemove', function() { $(this).find('td a').addClass('ui-state-hover'); });
    $('.week-picker .ui-datepicker-calendar tr').live('mouseleave', function() { $(this).find('td a').removeClass('ui-state-hover'); });
});
</script>
</head>
<body>
    <div class="week-picker"></div>
    <br /><br />
    <label>Week :</label> <span id="startDate"></span> - <span id="endDate"></span>
</body>
</html

>

Upvotes: 26

mrampton
mrampton

Reputation: 21

I was looking to do the same thing but also wanted the input field to display the selected week range -- here's what I ended up doing (basically use the altField to store the selected date, but display a formatted week range in the input field that is replaced by the actual date using the datepicker beforeShow callback. Coffeescript is below; gist can be found here: https://gist.github.com/2048010

    weekchooser = -> 
    $('#datepicker').datepicker({
        dateFormat: "M d, yy",
        altFormat:  "M d, yy",
        altField:       "#actualdate",
        selectWeek: true,
        firstDay:       1,
        showOtherMonths: true,
        selectOtherMonths: true,
        beforeShow: -> 
            $('#datepicker').val($('#actualdate').val())
        onClose: (date) ->
            reformatWeek(date)
            this.blur()
    }).click -> 
        currentDay = $('.ui-datepicker-current-day')
        currentDay.siblings().find('a').addClass('ui-state-active')

    calendarTR = $('.ui-datepicker .ui-datepicker-calendar tr');
    calendarTR.live 'mousemove', (event) ->
        $(this).find('td a').addClass('ui-state-hover');

    calendarTR.live 'mouseleave', (event) ->
        $(this).find('td a').removeClass('ui-state-hover');

    reformatWeek = (dateText) ->
        $('#datepicker').datepicker('refresh')
        current = parseInt($('.ui-datepicker-current-day').find('a').html())
        weekstart = parseInt($('.ui-datepicker-current-day').siblings().find('a').first().html())
        weekend     = parseInt($('.ui-datepicker-current-day').siblings().find('a').last().html())
        pattern = ///
            ^([a-zA-Z]+)\s+([0-9]{1,2})(,.*)
        ///
        [month, day, year] = dateText.match(pattern)[1..3]
        date = if weekstart > current
            first_month = relativeMonth(month, -1)
            "#{first_month} #{weekstart} - #{month} #{weekend}#{year}"
        else if weekend < current
            last_month = relativeMonth(month, 1)
            "#{month} #{weekstart} - #{last_month} #{weekend}#{year}"
        else
            "#{month} #{weekstart} - #{weekend}#{year}"
        $('#datepicker').val( date )

    relativeMonth = (month, c) -> 
        monthArray = $('#datepicker').datepicker('option', "monthNamesShort")
        index = monthArray.indexOf(month)
        if c > 0
            return if index + c > monthArray.length - 1 then monthArray[0] else monthArray[index + c]
        else
            return if index + c < 0 then monthArray[monthArray.length - 1] else monthArray[index + c]

Upvotes: 1

Jeremy
Jeremy

Reputation: 41

I wrote a solution to this, which highlights the week. It will still pick the date selected, but that is fine for my purposes. #week is the input box that has the datepicker attached.

$('#week').datepicker({

  beforeShowDay: $.datepicker.noWeekends,
  duration : 0,
  onChangeMonthYear: function() {   setTimeout("applyWeeklyHighlight()", 100); },
  beforeShow: function() { setTimeout("applyWeeklyHighlight()", 100); }

}).keyup(function() { setTimeout("applyWeeklyHighlight()", 100); });

function applyWeeklyHighlight()
{

    $('.ui-datepicker-calendar tr').each(function() {

        if($(this).parent().get(0).tagName == 'TBODY')
        {
            $(this).mouseover(function() {
                    $(this).find('a').css({'background':'#ffffcc','border':'1px solid #dddddd'});
                    $(this).find('a').removeClass('ui-state-default');
                    $(this).css('background', '#ffffcc');
            });
            $(this).mouseout(function() {
                    $(this).css('background', '#ffffff');
                    $(this).find('a').css('background','');
                    $(this).find('a').addClass('ui-state-default');
            });
        }

    });
}

Upvotes: 4

EpicVoyage
EpicVoyage

Reputation: 754

EDIT: Frictionless's answer is great, except that the question was of how to select the entire week (not the 6 days following whatever is clicked on). It was recommended that I copy my patch here.

This is a simplified version of what I am using on my site. Note that the week picker is pegged to a <span> tag in order to show the first and last days of the week. This necessitates a trigger button which references /images/schedule.png.

Change as required:

<style type="text/css">
    .highlighted-week a.ui-state-default{
        background: #FFFFFF;
        border: 1px solid #AAAAAA;
        color: #212121;
        font-weight: normal
    }
</style>
<!-- include jquery and jquery-ui here -->
<script type="text/javascript">
    // This $(function()) block could be moved to another file. It's what I did.
    $(function() {
        var internal = 0;
        if (typeof SVG == 'undefined') SVG = {};
        if (typeof SVG.Weekpicker == 'undefined') SVG.Weekpicker = {};
            SVG.Weekpicker.GetWeek = function(_selectedDate) {
            var week = new Array();
                /* ***NOTE*** This is the only line required to "fix" Frictionless' code. */
                _selectedDate.setDate(_selectedDate.getDate()-_selectedDate.getDay());

            for (i = 0; i < 7; i++) {
                var tempDate = new Date(_selectedDate.getTime());
                tempDate.setDate(tempDate.getDate() + i);
                    week.push(tempDate.getTime());
                }
                return week;
            };
            SVG.Weekpicker.Init = function(selector) {
                var elem = $(selector);
                var insert = $('<input type="hidden" name="weekpicker'+(++internal)+'" value="'+elem.html()+'" />');
            SVG.Weekpicker._dates = SVG.Weekpicker.GetWeek(new Date());

                insert = insert.insertAfter(elem);
                insert.datepicker({
                beforeShowDay: function(_date) {
                if ($.inArray(_date.getTime(), SVG.Weekpicker._dates) >= 0)
                    return [true, "highlighted-week", "Week Range"];
                    return [true, "", ""];
                },
                onSelect: function(_selectedDate) {
                    var _date = new Date(_selectedDate);
                    SVG.Weekpicker._dates = SVG.Weekpicker.GetWeek(_date);

                    var start = new Date(SVG.Weekpicker._dates[0]);
                    var end = new Date(SVG.Weekpicker._dates[6]);

                    $(elem).html(($.datepicker.formatDate('MM d, yy', start, '')+' &mdash; '+$.datepicker.formatDate('MM d, yy', end, ''))+'&nbsp;&nbsp;');
                },
                showOn: "button",
                buttonImage: "/images/schedule.png",
                buttonImageOnly: false,
                showAnim: "slideDown",
            });
        };
    });

    $(document).ready(function() {
        // Attach a week picker to the weekpicker <span> tag.
        SVG.Weekpicker.Init("#weekpicker");
    }
</script>

<body>
    <span id="weekpicker"></span>
</body>

Upvotes: 1

frictionlesspulley
frictionlesspulley

Reputation: 12368

The script highlights a week starting from the selected date.

Checkout a working example here: http://jsfiddle.net/frictionless/W5GMg/

Logic:

beforeShowDay : is run for each date in the calendar displayed. It is called at the time of display of the calendar and when a particular date is selected.

onSelect : function captures the selected week starting from the selectedDay and beforeShowDay renders the selected week

Here is a snippet which works with Jquery 1.5.1 and JQuery UI 1.8.1

$(function () {
    var _dates=new Array();
    $('#datepicker').datepicker({
        beforeShowDay:function(_date){
            if($.inArray(_date.getTime(),_dates)>=0)
                return [true,"highlighted-week","Week Range"];
            return[true,"",""];
        },
        onSelect:function(_selectedDate){
            var _date=new Date(_selectedDate);
            _dates=new Array();
            for(i=0;i<7;i++){
                var tempDate=new Date(_date.getTime());
                tempDate.setDate(tempDate.getDate()+i);
                _dates.push(tempDate.getTime());
            }

        }
    });

});

Upvotes: 1

Ryley
Ryley

Reputation: 21226

This is incredibly late, but I was searching for the same solution and could only find reference to these types of answers (i.e. for a different date picker). In my case, I'm using it inline, so that's how this code works. If you want it to pop-up with a week highlighted, you would have to modify. Here is something that works:

var selectedWeek;//remember which week the user selected here
$("#inlineDIVdatepicker").datepicker({
    firstDay:1,
    showOtherMonths:true,
    onSelect: function(dateText){
       selectedWeek = $.datepicker.iso8601Week(new Date(dateText));
    } ,

    //set the class 'week-highlight' for the whole week
    beforeShowDay: function(d){
        if (!selectedWeek) { return [true,''];}
        if (selectedWeek == $.datepicker.iso8601Week(d)){
              return [true,'week-highlight'];   
        }
        return [true,''];
    }
});

Then define some CSS (I haven't really done this part myself, so this is ugly):

#inlineDIVdatepicker .week-highlight a {
  background:none;
  background-color:yellow;  
}

Upvotes: 1

Joseph
Joseph

Reputation: 25523

Here's an article that has an example of how to select an entire week with the datepicker.

$(function()
{
    $('.date-pick').datePicker({selectWeek:true,closeOnSelect:false});
});    

Upvotes: 2

Ricket
Ricket

Reputation: 34057

You may be able to follow the suggestions in this discussion to achieve your week selection feature: http://code.google.com/p/jquery-datepicker/issues/detail?id=13

Unfortunately, though, it looks like the jQuery datepicker can't handle picking an entire week. It'll need to be custom coded.

Upvotes: 1

Related Questions