This is an extended PrimeFaces Calendar with added "dateSpinner" mode. I would like to omit JSF part and only show HTML / CSS / JavaScript part of such combined calendar. All what you need is to wrap the datepicker markup with a span element, add themable up / down arrows and use datepicker utility functions $.datepicker.formatDate(format, date, settings) and $.datepicker.parseDate(format, value, settings).
HTML
Original HTML with a calendar icon (called icon trigger in jQuery Datepicker) looks very simple
<input id="datepicker" class="hasDatepicker" type="text"> <img class="ui-datepicker-trigger" src="images/calendar.gif" alt="..." title="...">You have to extend this as follows
<span id="datepickerWrapper" class="ui-ccalendar ui-widget ui-corner-all"> <input id="datepicker" class="hasDatepicker" type="text"> <img class="ui-datepicker-trigger" src="images/calendar.gif" alt="..." title="..."> <a class="ui-ccalendar-button ui-ccalendar-up ui-corner-tr ui-button ui-widget ui-state-default ui-button-text-only"> <span class="ui-button-text"> <span class="ui-icon ui-icon-triangle-1-n"></span> </span> </a> <a class="ui-ccalendar-button ui-ccalendar-down ui-corner-br ui-button ui-widget ui-state-default ui-button-text-only"> <span class="ui-button-text"> <span class="ui-icon ui-icon-triangle-1-s"></span> </span> </a> </span>
CSS
The most CSS classes above are jQuery UI classes. I marked own classes with ui-ccalendar. In the CSS part is very important to shift spinner's arrow buttons to left. I have shifted absolute positioned buttons with CSS statement right: 17px;. We achieve with this displacement that the calendar icon is visible.
.ui-ccalendar { display: inline-block; overflow: visible; padding: 0; position: relative; vertical-align: middle; } .ui-ccalendar-button { cursor: default; display: block; font-size: 0.5em; height: 50%; margin: 0; overflow: hidden; padding: 0; position: absolute; right: 17px; text-align: center; vertical-align: middle; width: 16px; z-index: 100; } .ui-ccalendar .ui-icon { left: 0; margin-top: -8px; position: absolute; top: 50%; } .ui-ccalendar-up { top: 0; } .ui-ccalendar-down { bottom: 0; } .ui-ccalendar .ui-icon-triangle-1-s { background-position: -65px -16px; } .ui-ccalendar .ui-icon-triangle-1-n { margin-top: -9px; }
JavaScript
In this part I use the mentioned above utility functions formatDate() / parseDate() and setDate() / getDate() API of Date object to increment / decrement a single day. Month and year boundaries are considered automatically and in- / decremented if necessary. In- / decrementation logic is bound to mousedown event on spinner buttons.
var datepickerInput = $('#datepicker'); datepickerInput.datepicker({dateFormat: 'yy-mm-dd', ... other configuration if needed ...}); $('#datepickerWrapper').children('.ui-ccalendar-button').mouseover(function() { $(this).addClass('ui-state-hover'); }).mouseout(function() { $(this).removeClass('ui-state-hover'); }).mouseup(function() { $(this).removeClass('ui-state-active'); }).mousedown(function() { var el = $(this); el.addClass('ui-state-active'); try { // get configured date format var dateFormat = datepickerInput.datepicker("option", "dateFormat"); // extract a date from a string value with a specified format var date = $.datepicker.parseDate(dateFormat, datepickerInput.val()); if (el.hasClass('ui-ccalendar-up')) { // increment day date.setDate(date.getDate() + 1); } else { // decrement day date.setDate(date.getDate() - 1); } // format a date into a string value with a specified format var strDate = $.datepicker.formatDate(dateFormat, date); datepickerInput.val(strDate); } catch (err) { // ignore and nothing to do } });Important is here "dateFormat" option. Date format normally depends on user locale and should be passed from outside.
P.S. Just now I found a desktop example of such combined calendar too. So, you see, it's an useful and established widget :-).