SapUI5: Всплывающий ResponsivePopover при наведении мыши на Appointments в sap.m.PlanningCalendar.

В официальной документации по sap.m.ResponsivePopover есть пример, в котором открытие ResponsivePopover происходит по нажатию на кнопку.

Как быть, если необходимо показывать ResponsivePopover при наведении мыши на элемент, а не по клику на него?

Полу-решение задачи проиллюстрировано тут https://embed.plnkr.co/jAFIHK/.

В примере выше мы имеем дело с mouseover/mouseout, это не очень удобно, когда на элементе у нас расположены еще и другие элементы, как, например, тут:
Appointments

На appointment’е расположена еще и иконка. Когда указатель уйдет с целевого дива на иконку или текст, popover закроется. Попробуйте поводить мышкой по кнопке в примере выше.

mouseout

Чтобы решить эту проблему необходимо использовать mouseenter и mouseleave!

События открытия и закрытия popover’а будет происходить только при заходе на целевой div и выходе мышки с него. Нам все равно сколько слоев внутри целевого div и на каком слое в данный момент расположен курсор мыши.

Отличная статья про mouseover/mouseout и mouseenter/mouseleave с примерами — https://learn.javascript.ru/mousemove-mouseover-mouseout-mouseenter-mouseleave.

Применим mouseenter & mouseleave!

Пример приложения смотрим тут:
https://github.com/kannade/popover_mouseenter_sapui5.

Пример контроллера с mouseover/mouseout:

/popover_mouseenter_sapui5/blob/master/controller/Home.controller.js
onInit: function() {
        //после инициализации присвоим onmouseover и onmouseout для целевого элемента this.byId("target")
	this.attachPopoverOnMouseover(this.byId("target"), this.byId("popover"));
},
 
attachPopoverOnMouseover: function(targetControl, popover) {
	targetControl.addEventDelegate({
		onmouseover: this._showPopover.bind(this, targetControl, popover),
		onmouseout: this._clearPopover.bind(this, targetControl, popover)
	}, this);
},
 
//показываем popover
_showPopover: function(targetControl, popover) {
	this._timeId = setTimeout(() => popover.openBy(targetControl), 500);
},
 
//закрываем popover
_clearPopover: function(targetControl, popover) {
	clearTimeout(this._timeId) || popover.close();
},

Пример контроллера с mouseenter/mouseleave:

/popover_mouseenter_sapui5/blob/master/controller/Home.controller.js
//Вызываем после отрисовки экрана
onAfterRendering: function() {
	this.attachPopoverOnMouseover(this.byId("target"), this.byId("popover"));
},
 
attachPopoverOnMouseover: function(targetControl, popover) {
	jQuery.event.add($("#" + targetControl.getId())[0], "mouseenter", this._showPopover.bind(this, targetControl, popover));
	jQuery.event.add($("#" + targetControl.getId())[0], "mouseleave", this._clearPopover.bind(this, targetControl, popover));
},
 
//показываем popover
_showPopover: function(targetControl, popover) {
	popover.openBy(targetControl);
},
 
//закрываем popover
_clearPopover: function(targetControl, popover) {
	if (popover.isOpen()) {
		popover.close();
	}
}

В примере https://github.com/kannade/popover_mouseenter_sapui5 первый способ (mouseover/mouseout) закомментирован.

Теперь пару слов о том, как применить метод attachPopoverOnMouseover для всех Appointments в групповом календаре (PlanningCalendar).

Думаю, решить данную задачу можно разными способами, мой:

Скопировать CalendarRow.js и использовать в модуле (тоже скопированном) PlanningCalendarRow вместо «sap/m/CalendarRow» наш файл «./CalendarRow».

В котором редактируем метод CalendarRow.prototype.onAfterRendering:

CalendarRow.prototype.onAfterRendering = function() {
	for (var i = 0; i < this._aVisibleAppointments.length; i++) {
		var aAppoints = this._aVisibleAppointments[i];
		var isArray = this._aVisibleAppointments[i].appointment._aAppointments;
		if ((aAppoints) && !(isArray instanceof Array)) {
			this.getParent().getParent().getParent().getParent().attachPopoverOnMouseover(aAppoints, sap.ui.getCore().byId(this.getParent().getParent()
						.getParent().getParent().getId() + "-eventDetailPopover"));
		} else if ((aAppoints) && (isArray instanceof Array)) {
			this.getParent().getParent().getParent().getParent().attachPopoverOnMouseover(aAppoints, sap.ui.getCore().byId(this.getParent().getParent()
						.getParent().getParent().getId() + "-eventDetailPopover_2"));
		}
	}
}

Все очень напутано :), но логика такая:
Перебираем массив всех Appointments (this._aVisibleAppointments).
Если это обычный Appointment, то вызываем метод attachPopoverOnMouseover с одними параметрами.
Если это сгруппированный Appointment, то вызываем метод attachPopoverOnMouseover с другими параметрами.