(function() {
const {v2: M} = Help4.engine.ur.UrHarmonizationEngine.MSG_TYPE;
/** Guided Tour handling for UR harmonization */
Help4.engine.ur.Tour = class {
/**
* map UR event to tour event types
* @private
*/
static #EVENT_MAP = {
[M.activateElement]: 'click',
[M.hoverElement]: 'mouseover',
[M.interactOnElement]: 'keyup',
[M.leaveElement]: 'blur',
[M.hotkeyPress]: 'key'
};
/**
* forwarding UR postMessage events
* @param {Help4.engine.ur.UrHarmonizationEngine} engine
* @param {string} eventType
* @param {string} [hotspotId]
* @param {string|number} [key]
* @param {boolean} [shift]
* @param {boolean} [ctrl]
* @param {boolean} [alt]
*/
static onEvent(engine, eventType, {hotspotId, key, shift, ctrl, alt}) {
// keeping the input key parameters for now, but the only values used by the tour observer are
// event.type and event.params.value (which isn't communicated by UR)
const {view} = Help4.widget.getActiveInstance()?.getContext().widget.tour || {}; // CMP4
const handler = !view && engine.controller.getHandler(); // CMP3
const tour = handler instanceof Help4.controller.Tour
? /** @type {Help4.controller.Tour} */ handler
: /** @type {?Help4.widget.tour.View} */ view;
// ignore events when tour is not active, e.g. when they arrive late
if (!tour) return;
// ignore unsupported events
const type = this.#EVENT_MAP[eventType];
if (!type) return;
// handle hotkeyPress event without hotspotId
const tourEvent = {event: {type}};
if (eventType === M.hotkeyPress) {
// support for both key codes and key names
const keyName = typeof key === 'number'
? Help4.service.HotkeyService.getKey({event: {type: 'key', keyCode: key, shiftKey: shift, ctrlKey: ctrl, altKey: alt}})
: key;
// for tours only tab and enter are relevant and get their own event types
if (keyName === 'tab' || keyName === 'enter') tourEvent.event.type = keyName;
if (!hotspotId) {
tour.onUrTourEvent(tourEvent);
return;
}
}
// validate the hotspot event targets the current tour step; ignore events for other hotspots
const {hotspotAnchor} = (view ? view.getCurrentTile() : handler.getTile(handler._step)) || {};
const {Help} = Help4.widget.companionCore.data;
const value = Help.decodeUrHotspot(hotspotAnchor)?.ur;
if (value !== hotspotId) return;
// forward the event
tour.onUrTourEvent(tourEvent);
}
/**
* send request to UR app to scroll the hotspot into view
* @param {Help4.engine.ur.UrHarmonizationEngine} engine
* @param {string} hotspotId
*/
static scrollIntoView(engine, hotspotId) {
const {
_appFrame,
_connected,
_running,
constructor: {MSG_TYPE: {v2}},
} = engine;
if (!hotspotId || !_connected || !_running) return;
const {Connection} = Help4.engine.ur;
const service = v2.scrollIntoView;
engine._log?.('CMP: sending', 'ℹ️ ' + service, ()=>hotspotId);
_appFrame?.contentWindow?.postMessage(Help4.JSON.stringify({
type: 'request',
service,
body: {hotspotId}
}), Connection.getTargetOrigin(engine));
}
}
})();