domElement.addEventListener
) to handle events, you have
to adapt your coding to support both.To prevent the event handler from being called twice for each touch event, additional emulated mouse events shouldn't be handled. This can be
achieved by checking the _sapui_delayedMouseEvent
flag that we set on these emulated mouse events. We have extended
the jQuery.Event
object with an isMarked
function for checking UI5-specific flags on the real event
object. The sapui
prefix is already considered within the isMarked
function, so only the semantic
part needs to be passed into the function (for example, for checking if the _sapui_delayedMouseEvent
flag is marked,
simply call isMarked(delayedMouseEvent)
). However, when event handler is bound using a browser API like
addEventListener
, the flag needs to be checked using the full flag name, since there is no
isMarked
function on the browser event object.
In most cases, the event handler was previously bound by checking if touch is supported, like shown below:
// "Device" required from module "sap/ui/Device" jQuery(document).on(Device.support.touch ? "touchmove" : "mousemove", function(oEvent) { ...... });
When using jQuery:
jQuery(document).on("touchmove mousemove", function(oEvent) { if (oEvent.isMarked("delayedMouseEvent")) { // Suppress the emulated mouse event from the touch interface return; } ...... });
When using native browser event listeners:
var fnHandler = function (oEvent ) { if (oEvent . _sapui_delayedMouseEvent ) { // Suppress the emulated mouse event from the touch interface return ; } ...... }; document . addEventListener ( "touchmove" , fnHandler ); document . addEventListener ( "mousemove" , fnHandler );
touchstart
and mousedown
touchmove
and mousemove
touchend
, touchcancel
and
mouseup
We have also adapted some controls within sap.m
for devices supporting both mouse and touch input. Let's take
sap/m/RatingIndicator
as an example, where the user can drag a rating indicator to change a rating value. This is
implemented by registering a touchmove
or mousemove
event in the ontouchstart
function, and deregister
from touchmove
or mousemove
by listening to
touchend
, touchcancel
or mouseup
.
Code before the adaptation:
// "RatingIndicator" defined in module "sap/m/RatingIndicator" // "Device" required from module "sap/ui/Device" RatingIndicator.prototype.ontouchstart = function(oEvent) { if (this.getEnabled()) { ...... if (!this._touchEndProxy) { this._touchEndProxy = jQuery.proxy(this._ontouchend, this); } if (!this._touchMoveProxy) { this._touchMoveProxy = jQuery.proxy(this._ontouchmove, this); } // here also bound to the mouseup mousemove event to enable it working in // desktop browsers if (Device.support.touch) { jQuery(window.document).on("touchend touchcancel", this._touchEndProxy); jQuery(window.document).on("touchmove", this._touchMoveProxy); } else { jQuery(window.document).on("mouseup", this._touchEndProxy); jQuery(window.document).on("mousemove", this._touchMoveProxy); } ...... } }; RatingIndicator.prototype._ontouchmove = function(oEvent) { ...... }; RatingIndicator.prototype._ontouchend = function(oEvent) { if (this.getEnabled()) { ...... if (Device.support.touch) { jQuery(window.document).off("touchend touchcancel", this._touchEndProxy); jQuery(window.document).off("touchmove", this._touchMoveProxy); } else { jQuery(window.document).off("mouseup", this._touchEndProxy); jQuery(window.document).off("mousemove", this._touchMoveProxy); } ...... } };
Code after adaptation:
// "RatingIndicator" defined in module "sap/m/RatingIndicator" // "Device" required from module "sap/ui/Device" RatingIndicator.prototype.ontouchstart = function (oEvent) { if (this.getEnabled()) { ...... if (!this._touchEndProxy) { this._touchEndProxy = jQuery.proxy(this._ontouchend, this); } if (!this._touchMoveProxy) { this._touchMoveProxy = jQuery.proxy(this._ontouchmove, this); } // The if (Device.support.touch) is removed and both mouse and touch events are supported always jQuery(window.document).on("touchend touchcancel mouseup", this._touchEndProxy); jQuery(window.document).on("touchmove mousemove", this._touchMoveProxy); ...... } }; RatingIndicator.prototype._ontouchmove = function (oEvent) { // Check the _sapui_delayedMouseEvent flag for the emulated mouse event from the touch interface if (oEvent.isMarked("delayedMouseEvent")) { return; } ...... }; RatingIndicator.prototype._ontouchend = function (oEvent) { // Check the _sapui_delayedMouseEvent flag for the emulated mouse event from the touch interface if (oEvent.isMarked("delayedMouseEvent")) { return; } if (this.getEnabled()) { ...... // The if (Device.support.touch) is removed, just deregister from every event jQuery(window.document).off("touchend touchcancel mouseup", this._touchEndProxy); jQuery(window.document).off("touchmove mousemove", this._touchMoveProxy); ...... } };