After debugging the JS code I discovered that the call made to ice.component.calendar.updateProperties() function causes the focus to be lost. The function is called when the returned DOM update is applied, more precisely the script element containing the call to the function is evaluated.
While debugging further I could see how the entire HTML table representing the calendar widget is removed/destroyed and the re-added to the document. The removal of the table containing the element owning the focus is obviously the cause of the problem. Commenting out the code that destroys the table seems to fix the issue (although I don't know with what implications):
updateProperties: function(clientId, jsProps, jsfProps, events) {
Event.onContentReady(clientId, function(){
// console.log("jsProps =", JSON.stringify(jsProps, null, 4));
// console.log("jsfProps =", JSON.stringify(jsfProps, null, 4));
// logger.log("In updateProperties()");
// logger.log("renderAsPopup = " + jsfProps.renderAsPopup);
var context = ice.component.getJSContext(clientId);
// if (context && context.isAttached()) {
// var prevProps = lang.merge(context.getJSProps(), context.getJSFProps());
// var currProps = lang.merge(jsProps, jsfProps);
// for (var prop in currProps)
{
//// console.log(prop);
// if (!lang.hasOwnProperty(currProps, prop)) continue;
// if (currProps[prop] == prevProps[prop]) continue;
// context.getComponent().destroy();
// document.getElementById(clientId)['JSContext'] = null;
// JSContext[clientId] = null;
// break;
// }
// }
ice.component.updateProperties(clientId, jsProps, jsfProps, events, this);
}, this, true);
}
Note that this issue doesn't seem to occur when "renderAsPopup=true" and the same types of date or time selections are made in the popup calendar, with the exception that in Chrome if you select a date it still loses focus, but not if yo select a time.