SapUI5: Всплывающий ResponsivePopover при наведении мыши на Appointments в sap.m.PlanningCalendar.
В официальной документации по sap.m.ResponsivePopover есть пример, в котором открытие ResponsivePopover происходит по нажатию на кнопку.
Как быть, если необходимо показывать ResponsivePopover при наведении мыши на элемент, а не по клику на него?
Полу-решение задачи проиллюстрировано тут https://embed.plnkr.co/jAFIHK/.
В примере выше мы имеем дело с mouseover/mouseout, это не очень удобно, когда на элементе у нас расположены еще и другие элементы, как, например, тут:
На appointment’е расположена еще и иконка. Когда указатель уйдет с целевого дива на иконку или текст, popover закроется. Попробуйте поводить мышкой по кнопке в примере выше.
Чтобы решить эту проблему необходимо использовать 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:
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:
//Вызываем после отрисовки экрана 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 с другими параметрами.