@Ben Koehler, that's prefect! I made a minor modification so that using a single instance of the date picker more than once works as expected. Without this modification the date is parsed incorrectly and the previously selected date is not highlighted.

I liked the fact that you added code to display the selected date the next time the control is opened. However for some reason, The next time i open the datepicker, the year dropdown is missing. It appears again if i reselect a new month. It remains normal if I do not set the defaultDate and setDate in the beforeShow. Any idea what that might be about?
–
shakeApr 28 '11 at 20:42

@shake I'm not sure why that would be happening. Could be a conflict with something else on your page. A month has passed so you've probably hammered out the problem, but post back if you're still having issues.
–
BrianSJun 8 '11 at 17:28

I added the following line in "onClose" to update anybody listening for changes to value: $(this).triggerHandler('change');
–
raider33Jun 2 '13 at 20:21

2

You can use the input parameters of beforeShow to get the data too: if (input.value) { var day = inst.selectedDay; var year = inst.selectedYear; var month = inst.selectedMonth; var d = inst.input; d.datepicker('option', 'defaultDate', new Date(year, month, day)); d.datepicker('setDate', new Date(year, month, day)); } This way, you don't need to parse the input value yourself (depends on dateFormat)
–
Stijn De VosJun 11 '14 at 9:27

@StijnDeVos Thanks, really nice and short solution to get the selected date details.
–
informatik01Dec 3 '14 at 17:36

Thanks for this. Cleaner code and you can clear the value. Though I have a bug in Chrome when I close the datepicker, the calendar appears again and I have to press close a second time. I fixed this by removing the '.unbind("click")' Portion of your code.
–
TyronFeb 26 '14 at 14:56

in the end I'm downvoting this because it is unworkable, as the onSelect and/or onChangeMonthYear and/or onClose events either don't fire, or don't receive the correct values, or, if overriden, make the widget stop working
–
knocteDec 29 '14 at 18:19

Here's what I came up with. It hides the calendar without needing an extra style block and adds a clear button to deal with the problem of not being able to clear the value once you click on the input. Also works nicely with multiple monthpickers on the same page.

Is it just me or is this not working as it should in IE(8)?
The date changes when clicking done, but the datepicker opens up again, until you actually click somewhere in the page to loose focus on the input field...

I needed a Month/Year picker for two fields (From & To) and when one was chosen the Max/Min was set on the other one...a la picking airline ticket dates.
I was having issues setting the max and min...the dates of the other field would get erased. Thanks to several of the above posts...I finally figured it out. You have to set options and dates in a very specific order.

Made a couple of refinements to BrianS's nearly perfect response above:

I've regexed the value set on show because I think it does actually make it slightly more readable in this case (although note I'm using a slightly different format)

My client wanted no calendar so I've added an on show / hide class addition to do that without affecting any other datepickers. The removal of the class is on a timer to avoid the table flashing back up as the datepicker fades out, which seems to be very noticeable in IE.

EDIT: One problem left to solve with this is that there is no way to empty the datepicker - clear the field and click away and it repopulates with the selected date.

EDIT2: I have not managed to solve this nicely (i.e. without adding a separate Clear button next to the input), so ended up just using this: https://github.com/thebrowser/jquery.ui.monthpicker - if anyone can get the standard UI one to do it that would be amazing.

I liked the @user1857829 answer and his "extend-jquery-like-a-plugin approach".
I just made a litte modification so that when you change month or year in any way the picker actually writes the date in the field.
I found that I'd like that behaviour after using it a bit.

Like many others, I've encountered numerous problems trying to do this, and only a combination of the solutions posted, and eventually a big hack to make it perfect, has landed me a solution.

Problems with other solutions in this thread that I've tried:

Selecting a new date in a datepicker, would also change the (internal) date of other datepickers, so when you opened the other ones again (or tried getting their date), they would have a different date than the one displayed in their assigned input-field.

The datepicker wouldn't "remember" the date when opened again.

The code for juggling the dates used substringing so it wasn't compatible with all formats.

"My monthpicker" only changed the input-field on closing it, rather than whenever the values were changed.

The input-field isn't updated correctly, if you type in a wrongly formatted input-string for a date, and then click 'Close' on the datepicker.

I can't have normal datepickers, which show the days, on the same page as monthpickers, which don't show the days.

I've finally found a way to fix all of these problems. The first four can be fixed simply by being careful about how you reference your date- and monthpickers in their internal code, and of course doing some manual updating of your pickers. This you can see in the instantiation-examples near the bottom. The fifth problem can be helped by adding some custom code to the datepicker functions.

NOTE: You do NOT need to use the following monthpicker scripts to fix the first three problems in your normal datepicker. Simply use the datepicker instantiation-script near the bottom of this post.

Now, to use monthpickers and mend the last problem, we need to separate the datepickers and the monthpickers. We could get one of the few jQuery-UI monthpicker addons out there, but some lack localization flexibility/ability, some lack animation support...so, what to do? Roll your "own" from the datepicker-code! This gets you a fully-functioning monthpicker, with all the functionalities of the datepicker, just without the displaying of days.

I have supplied a monthpicker js-script and the accompanying CSS-script, using the method described below, with the jQuery-UI v1.11.1 code. Simply copy these code-snippets to two new files, monthpicker.js and monthpicker.css, respectively.

Here's the process I went through, to clone the original datepicker and make it a monthpicker

If you don't care about how I made these, scroll past this section, and down to the line "Now to add the datepickers and monthpickers to the page!"

I've taken all the javascript code from jquery-ui-1.11.1.js pertaining to their datepicker, pasted it into a new js-file, and replaced the following strings:

"datepicker" ==> "monthpicker"

"Datepicker" ==> "Monthpicker"

"date picker" ==> "month picker"

"Date picker" ==> "Month picker"

Then I removed the part of the for-loop which creates the entire ui-datepicker-calendar div (the one other solutions hide using CSS). This can be found in the _generateHTML: function (inst).

Find the line that says:

"</div><table class='ui-datepicker-calendar'><thead>" +

Mark everything from after the closing div-tag and down to (and not including) the line where it says:

drawMonth++;

Now it'll be unhappy, because we need to close some things. After that closing div-tag from before, add this:

";

The code should now be seamed together nicely. Here's a code-snippet showing what you should've ended up with:

Then I copy/pasted the code from jquery-ui.css pertaining to the datepickers to a new CSS-file, and replaced the following strings:

"datepicker" ==> "monthpicker"

Now to add the datepickers and monthpickers to the page!

These following javascript code-snippets work with multiple datepickers and/or monthpickers on the page, without the aforementioned problems! Fixed generally by using '$(this).' a lot :)

The first script is for a normal datepicker, and the second one is for the "new" monthpickers.

The out-commented .after, which lets you create some element to clear the input-field, is stolen from Paul Richards' answer.

I'm using the "MM yy" format in my monthpicker, and the 'yy-mm-dd' format in my datepicker, but this is completely compatible with all formats, so you are free to use whichever one you want. Simply change the 'dateFormat' option. The standard options 'showButtonPanel', 'showAnim', and 'yearRange' are of course optional and customizable to your wishes.

Adding a datepicker

Datepicker instantiation.
This one goes from 90 years ago and to the present day. It helps you to keep the input-field correct, especially if you set the defaultDate, minDate and maxDate options, but it can handle it if you don't. It will work with any dateFormat you choose.

$('#MyDateTextBox').datepicker({
dateFormat: 'yy-mm-dd',
changeMonth: true,
changeYear: true,
showButtonPanel: true,
showMonthAfterYear: true,
showWeek: true,
showAnim: "drop",
constrainInput: true,
yearRange: "-90:",
minDate: new Date((new Date().getFullYear() - 90), new Date().getMonth(), new Date().getDate()),
maxDate: new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate()),
defaultDate: new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate()),
onClose: function (dateText, inst) {
// When onClose is called after we have clicked a day (and not clicked 'Close' or outside the datepicker), the input-field is automatically
// updated with a valid date-string. They will always pass, because minDate and maxDate are already enforced by the datepicker UI.
// This try is to catch and handle the situations, where you open the datepicker, and manually type in an invalid date in the field,
// and then close the datepicker by clicking outside the datepicker, or click 'Close', in which case no validation takes place.
try {
// If datepicker can parse the date using our formatstring, the instance will automatically parse
// and apply it for us (after the onClose is done).
// If the input-string is invalid, 'parseDate' will throw an exception, and go to our catch.
// If the input-string is EMPTY, then 'parseDate' will NOT throw an exception, but simply return null!
var typedDate = $.datepicker.parseDate($(this).datepicker('option', 'dateFormat'), $(this).val());
// typedDate will be null if the entered string is empty. Throwing an exception will force the datepicker to
// reset to the last set default date.
// You may want to just leave the input-field empty, in which case you should replace 'throw "No date selected";' with 'return;'
if (typedDate == null)throw "No date selected";
// We do a manual check to see if the date is within minDate and maxDate, if they are defined.
// If all goes well, the default date is set to the new date, and datepicker will apply the date for us.
var minDate = $(this).datepicker("option", "minDate");
var maxDate = $(this).datepicker("option", "maxDate");
if (minDate !== null && typedDate < minDate) throw "Date is lower than minDate!";
if (maxDate !== null && typedDate > maxDate) throw "Date is higher than maxDate!";
// We update the default date, because the date seems valid.
// We do not need to manually update the input-field, as datepicker has already done this automatically.
$(this).datepicker('option', 'defaultDate', typedDate);
}
catch (err) {
console.log("onClose: " + err);
// Standard behavior is that datepicker does nothing to fix the value of the input field, until you choose
// a new valid date, by clicking on a day.
// Instead, we set the current date, as well as the value of the input-field, to the last selected (and
// accepted/validated) date from the datepicker, by getting its default date. This only works, because
// we manually change the default date of the datepicker whenever a new date is selected, in both 'beforeShow'
// and 'onClose'.
var date = $(this).datepicker('option', 'defaultDate');
$(this).val($.datepicker.formatDate($(this).datepicker('option', 'dateFormat'), date));
$(this).datepicker('setDate', date);
}
},
beforeShow: function (input, inst) {
// beforeShow is particularly irritating when initializing the input-field with a date-string.
// The date-string will be parsed, and used to set the currently selected date in the datepicker.
// BUT, if it is outside the scope of the minDate and maxDate, the text in the input-field is not
// automatically updated, only the internal selected date, until you choose a new date (or, because
// of our onClose function, whenever you click close or click outside the datepicker).
// We want the input-field to always show the date that is currently chosen in our datepicker,
// so we do some checks to see if it needs updating. This may not catch ALL cases, but these are
// the primary ones: invalid date-format; date is too early; date is too late.
try {
// If datepicker can parse the date using our formatstring, the instance will automatically parse
// and apply it for us (after the onClose is done).
// If the input-string is invalid, 'parseDate' will throw an exception, and go to our catch.
// If the input-string is EMPTY, then 'parseDate' will NOT throw an exception, but simply return null!
var typedDate = $.datepicker.parseDate($(this).datepicker('option', 'dateFormat'), $(this).val());
// typedDate will be null if the entered string is empty. Throwing an exception will force the datepicker to
// reset to the last set default date.
// You may want to just leave the input-field empty, in which case you should replace 'throw "No date selected";' with 'return;'
if (typedDate == null)throw "No date selected";
// We do a manual check to see if the date is within minDate and maxDate, if they are defined.
// If all goes well, the default date is set to the new date, and datepicker will apply the date for us.
var minDate = $(this).datepicker("option", "minDate");
var maxDate = $(this).datepicker("option", "maxDate");
if (minDate !== null && typedDate < minDate) throw "Date is lower than minDate!";
if (maxDate !== null && typedDate > maxDate) throw "Date is higher than maxDate!";
// We update the input-field, and the default date, because the date seems valid.
// We also manually update the input-field, as datepicker does not automatically do this when opened.
$(this).val($.datepicker.formatDate($(this).datepicker('option', 'dateFormat'), typedDate));
$(this).datepicker('option', 'defaultDate', typedDate);
}
catch (err) {
// Standard behavior is that datepicker does nothing to fix the value of the input field, until you choose
// a new valid date, by clicking on a day.
// We want the same behavior when opening the datepicker, so we set the current date, as well as the value
// of the input-field, to the last selected (and accepted/validated) date from the datepicker, by getting
// its default date. This only works, because we manually change the default date of the datepicker whenever
// a new date is selected, in both 'beforeShow' and 'onClose', AND have a default date set in the datepicker options.
var date = $(this).datepicker('option', 'defaultDate');
$(this).val($.datepicker.formatDate($(this).datepicker('option', 'dateFormat'), date));
$(this).datepicker('setDate', date);
}
}
})
//.after( // this makes a link labeled "clear" appear to the right of the input-field, which clears the text in it
// $("<a href='javascript: void(0);'>clear</a>").click(function() {
// $(this).prev().val('');
// })
//)
;

Adding a monthpicker

Include the monthpicker.js file and the monthpicker.css file in the page you want to use the monthpickers.

Monthpicker instantiation
The value retrieved from this monthpicker, is always the FIRST day of the selected month.
Starts at the current month, and ranges from 100 years ago and 10 years into the future.

I can't seem to make a jsfiddle work with this, but it is working for me in my ASP.NET MVC project. Just do what you normally do to add a datepicker to your page, and incorporate the above scripts, possibly by changing the selector (meaning $("#MyMonthTextBox")) to something that works for you.

I hope this helps someone.

Links to pastebins for some extra date- and monthpicker setups:

Two collaborating monthpickers; 'start' is working on the first of the month, and 'end' is working on the last of the month. They are both restricted by each other, so choosing a month on 'end' which is before the selected month on 'start', will change 'start' to be the same month as 'end'. And vice versa. OPTIONAL: When selecting a month on 'start', the 'minDate' is set on 'end'. To remove this feature, comment out one line in onClose (read the comments).

Two collaborating datepickers; They are both restricted by each other, so choosing a date on 'end' which is before the selected date on 'start', will change 'start' to be the same month as 'end'. And vice versa. OPTIONAL: When selecting a date on 'start', the 'minDate' is set on 'end'. To remove this feature, comment out one line in onClose (read the comments).

I tried the various solutions provided here and they worked fine if you simply wanted a couple of drop downs.

The best (in appearance etc) 'picker' (https://github.com/thebrowser/jquery.ui.monthpicker) suggested here is basically a copy of an old version of jquery-ui datepicker with the _generateHTML rewritten. However, I found it no longer plays nicely with current jquery-ui (1.10.2) and had other issues (doesn't close on esc, doesn't close on other widget opening, has hardcoded styles).

Rather than attempt to fix that monthpicker and rather than reattempt the same process with the latest datepicker, I went with hooking into the relevant parts of the existing date picker.

This involves overriding:

_generateHTML (to build the month picker markup)

parseDate (as it doesn't like it when there's no day component),

_selectDay (as datepicker uses .html() to get the day value)

As this question is a bit old and already well answered, here's only the _selectDay override to show how this was done: