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 :-).

Great addition... Will propose this internally as wel...
ReplyDeleteThanks, very useful
ReplyDeleteI used this example with an existing jquery-ui datepicker (with image) that I had already implemented. This worked very well with a few CSS tweaks. I just had to make sure I put my style CSS on the page AFTER I had called in the jquery-ui CSS and JS files. Maybe someone else will find that tip useful. Otherwise, thank you very much for sharing your implementation of the datepicker-spinner combo!
ReplyDelete