The solution here: https://stackoverflow.com/a/10598178/19074969 solved the basic problem for me to position the datepicker on a specific side of the date input field. However, the problem remains to define an offset in order to finetune the position of the datepicker popup box. This seems to be easily accomplished by applying some css style transform translate to the datepicker div:
setTimeout(function() {
jQuery("input[name='date']").datepicker({
beforeShow: function(input, inst) {
var calendar = inst.dpDiv;
setTimeout(function () {
calendar.position({
my: 'left bottom',
at: 'left top',
collision: 'none',
of: input
});
jQuery("#ui-datepicker-div").css('transform', 'translate( -40px, -10px )');
}, 0);
},
});
}, 800);
Problem is, if you click somewhere else, the datepicker box disappears and if you click on the date input field again, jQuery recalculates and updates the position of the datepicker div before opening it and the effect of the css style transform translate is lost.
To tackle this, we need to reset the css style transform translate to zero each time the datepicker popup box is closed. In the following, a mutation observer is set up, like here: Javascript detect when computed css property changes, to watch for the event when the datepicker is closed while the CSS style attribute "display" changes to "none" and the css style transform translate can be resetted back to zero:
if ( !window.document.documentMode ) { // would break IE11
setTimeout(function() { // after page is loaded, otherwise (input.hasDatepicker) would not be available
if ( jQuery("input.hasDatepicker").length > 0 ) {
var $observation_target = document.getElementById('ui-datepicker-div');
let style = window.getComputedStyle($observation_target);
var $mutation_observer = new MutationObserver(function(mutations){ // callback function
mutations.forEach(function(mutation){
if ( style.display === 'none' ) {
$observation_target.style.transform = 'translate( 0px, 0px )';
}
});
});
$mutation_observer.observe( $observation_target , {attributes:true} ); // Start the mutation observer (options: What is observed? CSS style attributes!)
}
}, 800);
}
In both cases the "setTimeout" function is needed to wait until page load is complete, otherwise input.hasDatepicker does not yet exist and cannot be found. Adjust the delay (milliseconds) according to your speed of page load!
Now, it works every time and the position of the datepicker div is adjusted after it is recalculated by jQuery.
The only limitation: the transform translate hack does not work with IE11. (Tested and works with Edge and Firefox!)