From bf39fd0969d7053eccb0430596751bd1c4338d62 Mon Sep 17 00:00:00 2001 From: hidday Date: Sun, 14 Aug 2022 15:09:13 +0300 Subject: [PATCH] [semver:patch] Add aborting action when 'esc' to the element selection --- dist/development/strigo.sdk.js | 94 +++++++++++++------ .../assessment-recorder.ts | 81 ++++++++++------ .../element-selector/element-selector.js | 60 +++++------- src/strigo/index.ts | 13 ++- src/strigo/types.ts | 8 +- 5 files changed, 160 insertions(+), 96 deletions(-) diff --git a/dist/development/strigo.sdk.js b/dist/development/strigo.sdk.js index 1a395d4..2a81514 100644 --- a/dist/development/strigo.sdk.js +++ b/dist/development/strigo.sdk.js @@ -11769,20 +11769,23 @@ ${JSON.stringify(parsedContext)}` : ""); return elementSelector; } function startElementSelector(rootDocument, options) { - this.saveSelectedSelector = (e) => { - e.preventDefault(); - e.stopPropagation(); + this.removeOverlayElement = () => { console.log("Removing mouse over event listener from the selected element."); rootDocument.removeEventListener("mouseover", this.mouseOverEvent); - const elementProfile = getElementProfile(e, { - dataAttribute: "some-custom-strigo-attribute" - }); - this.elementProfile = elementProfile || {}; const selectorOverlay2 = rootDocument.getElementById("element-selector-overlay"); if (!selectorOverlay2) { console.error("Missing selector overlay element!"); } rootDocument?.body?.removeChild(selectorOverlay2); + }; + this.saveSelectedSelector = (e) => { + e.preventDefault(); + e.stopPropagation(); + this.removeOverlayElement(); + const elementProfile = getElementProfile(e, { + dataAttribute: "some-custom-strigo-attribute" + }); + this.elementProfile = elementProfile || {}; console.log("Selected element with elementProfile:", this.elementProfile); options.onElementProfileCreated(this.elementProfile); }; @@ -11852,6 +11855,15 @@ ${JSON.stringify(parsedContext)}` : ""); rootDocument.body.appendChild(selectorOverlay); rootDocument.addEventListener("mouseover", this.mouseOverEvent); rootDocument.addEventListener("mouseout", this.removeClickListenerFromHoveredElement); + window.focus(); + rootDocument.body.focus(); + window.addEventListener("keydown", (e) => { + if (e.key === "Escape") { + console.log("Aborting element selection...", e.key); + this.removeOverlayElement(); + options.onElementSelectionCancel(); + } + }, true); } // src/modules/assessment-recorder/assessment-recorder.types.ts @@ -11970,6 +11982,43 @@ ${JSON.stringify(parsedContext)}` : ""); } return false; } + function onElementProfileCreation(elementProfile, elementType) { + const recorederIframe = document.getElementById("strigo-assessment-recorder-iframe"); + const elementSelector = getElementSelector(elementProfile); + recorederIframe.classList.remove("semi-open"); + recorederIframe.classList.add("is-open"); + (0, import_html2canvas.default)(document.querySelector(elementSelector), { backgroundColor: "#c6c7e7" }).then((canvas) => { + const selectedElement = { + imageData: canvas.toDataURL(), + profile: elementProfile, + querySelector: elementSelector + }; + recorederIframe.contentWindow.postMessage(JSON.stringify({ + messageType: "end-capture" /* END_CAPTURE */, + payload: { + elementType, + selectedElement + }, + windowName: window.name + }), "*"); + }); + } + function onElementSelectionCancel(elementType) { + LoggerInstance.info("Aborting element selection..."); + const recorederIframe = document.getElementById("strigo-assessment-recorder-iframe"); + recorederIframe.contentWindow.postMessage(JSON.stringify({ + messageType: "end-capture" /* END_CAPTURE */, + payload: { + elementType, + selectedElement: null + }, + windowName: window.name + }), "*"); + recorederIframe.classList.remove("semi-open"); + setTimeout(() => { + recorederIframe.classList.add("is-open"); + }, 400); + } function addAssessmentRecorderIframe() { window.sessionStorage.setItem("isStrigoRecordingMode", "true"); const assessmentUuid = new URL(window.location.href).searchParams.get(ASSESSMENT_RECORDER_ID_PARAM); @@ -12004,27 +12053,7 @@ ${JSON.stringify(parsedContext)}` : ""); assessmentRecorderIframe.classList.add("semi-open"); }, 600); const { elementType, rootElementSelector } = payload?.captureParams; - window.Strigo.startElementSelector((elementProfile) => { - const recorederIframe = document.getElementById("strigo-assessment-recorder-iframe"); - const elementSelector = getElementSelector(elementProfile); - recorederIframe.classList.remove("semi-open"); - recorederIframe.classList.add("is-open"); - (0, import_html2canvas.default)(document.querySelector(elementSelector), { backgroundColor: "#c6c7e7" }).then((canvas) => { - const selectedElement = { - imageData: canvas.toDataURL(), - profile: elementProfile, - querySelector: elementSelector - }; - recorederIframe.contentWindow.postMessage(JSON.stringify({ - messageType: "end-capture" /* END_CAPTURE */, - payload: { - elementType, - selectedElement - }, - windowName: window.name - }), "*"); - }); - }, rootElementSelector); + window.Strigo.startElementSelector((elementProfile) => onElementProfileCreation(elementProfile, elementType), () => onElementSelectionCancel(elementType), rootElementSelector); break; } case "submit-assessment" /* SUBMIT_ASSESSMENT */: { @@ -13341,10 +13370,15 @@ ${JSON.stringify(parsedContext)}` : ""); await sendSuccessEvent(token, eventName); LoggerInstance.debug("sendEvent called", { eventName }); } - startElementSelector(onElementProfileCreated, rootElementSelector) { + startElementSelector(onElementProfileCreated, onElementSelectionCancel2, rootElementSelector) { LoggerInstance.debug("startElementSelector called"); const rootElement = rootElementSelector ? window.document.querySelector(rootElementSelector) : window.document.body; - startElementSelector(window.document, { onElementProfileCreated, zIndex: 9999999999, rootElement }); + startElementSelector(window.document, { + onElementProfileCreated, + onElementSelectionCancel: onElementSelectionCancel2, + zIndex: 9999999999, + rootElement + }); } assessmentRecorder() { addAssessmentRecorderIframe(); diff --git a/src/modules/assessment-recorder/assessment-recorder.ts b/src/modules/assessment-recorder/assessment-recorder.ts index 68e96c6..21d4055 100644 --- a/src/modules/assessment-recorder/assessment-recorder.ts +++ b/src/modules/assessment-recorder/assessment-recorder.ts @@ -26,6 +26,55 @@ export function isRecordingMode(): boolean { return false; } +function onElementProfileCreation(elementProfile: any, elementType): void { + const recorederIframe = document.getElementById('strigo-assessment-recorder-iframe') as HTMLIFrameElement; + const elementSelector = getElementSelector(elementProfile); + + recorederIframe.classList.remove('semi-open'); + recorederIframe.classList.add('is-open'); + + html2canvas(document.querySelector(elementSelector), { backgroundColor: '#c6c7e7' }).then((canvas) => { + const selectedElement: SelectedElement = { + imageData: canvas.toDataURL(), + profile: elementProfile, + querySelector: elementSelector, + }; + + recorederIframe.contentWindow.postMessage( + JSON.stringify({ + messageType: AssessmentRecorderMessageTypes.END_CAPTURE, + payload: { + elementType, + selectedElement, + }, + windowName: window.name, + }), + '*' + ); + }); +} + +function onElementSelectionCancel(elementType): void { + Logger.info('Aborting element selection...'); + const recorederIframe = document.getElementById('strigo-assessment-recorder-iframe') as HTMLIFrameElement; + recorederIframe.contentWindow.postMessage( + JSON.stringify({ + messageType: AssessmentRecorderMessageTypes.END_CAPTURE, + payload: { + elementType, + selectedElement: null, + }, + windowName: window.name, + }), + '*' + ); + + recorederIframe.classList.remove('semi-open'); + setTimeout(() => { + recorederIframe.classList.add('is-open'); + }, 400); +} + export function addAssessmentRecorderIframe(): void { window.sessionStorage.setItem('isStrigoRecordingMode', 'true'); const assessmentUuid = new URL(window.location.href).searchParams.get(ASSESSMENT_RECORDER_ID_PARAM); @@ -71,33 +120,11 @@ export function addAssessmentRecorderIframe(): void { const { elementType, rootElementSelector } = payload?.captureParams as CaptureParams; - window.Strigo.startElementSelector((elementProfile: any) => { - const recorederIframe = document.getElementById('strigo-assessment-recorder-iframe') as HTMLIFrameElement; - const elementSelector = getElementSelector(elementProfile); - - recorederIframe.classList.remove('semi-open'); - recorederIframe.classList.add('is-open'); - - html2canvas(document.querySelector(elementSelector), { backgroundColor: '#c6c7e7' }).then((canvas) => { - const selectedElement: SelectedElement = { - imageData: canvas.toDataURL(), - profile: elementProfile, - querySelector: elementSelector, - }; - - recorederIframe.contentWindow.postMessage( - JSON.stringify({ - messageType: AssessmentRecorderMessageTypes.END_CAPTURE, - payload: { - elementType, - selectedElement, - }, - windowName: window.name, - }), - '*' - ); - }); - }, rootElementSelector); + window.Strigo.startElementSelector( + (elementProfile: any) => onElementProfileCreation(elementProfile, elementType), + () => onElementSelectionCancel(elementType), + rootElementSelector + ); break; } diff --git a/src/modules/element-selector/element-selector.js b/src/modules/element-selector/element-selector.js index 408ed9e..f9205db 100644 --- a/src/modules/element-selector/element-selector.js +++ b/src/modules/element-selector/element-selector.js @@ -42,34 +42,35 @@ export function getElementSelector(nodesInfo, options) { * This function will add an overlay for hovered element to indicate the element selection functionality. * @param {Object} options - The element selector options * @param [options.onElementProfileCreated] { function } - A callback to return the selected element profile. + * @param [options.onElementSelectionCancel] { function } - A callback to cancel the element selection overlay. * @param [options.zIndex] { number } - A configurable z-index in which the selection overlay will appear. * @param [options.rootElement] { HtmlElement } - The starting dom element for the selection. * @param rootDocument- {DOMNode} The root document in which the selection overlay will append itself to hovered elements. */ export function startElementSelector(rootDocument, options) { - // this.rootElement = options?.rootElement ? options.rootElement : rootDocument.body; - this.saveSelectedSelector = (e) => { - e.preventDefault(); - e.stopPropagation(); + this.removeOverlayElement = () => { console.log('Removing mouse over event listener from the selected element.'); rootDocument.removeEventListener("mouseover", this.mouseOverEvent); - // this.rootElement.removeEventListener('mouseover', this.mouseOverEvent); - - const elementProfile = getElementProfile(e, { - dataAttribute: 'some-custom-strigo-attribute', - }); - - this.elementProfile = elementProfile || {}; - const selectorOverlay = rootDocument.getElementById('element-selector-overlay'); if (!selectorOverlay) { console.error('Missing selector overlay element!'); } rootDocument?.body?.removeChild(selectorOverlay); - // this.rootElement?.removeChild(selectorOverlay); + } + + this.saveSelectedSelector = (e) => { + e.preventDefault(); + e.stopPropagation(); + this.removeOverlayElement(); + + const elementProfile = getElementProfile(e, { + dataAttribute: 'some-custom-strigo-attribute', + }); + + this.elementProfile = elementProfile || {}; console.log('Selected element with elementProfile:', this.elementProfile); options.onElementProfileCreated(this.elementProfile); @@ -153,31 +154,20 @@ export function startElementSelector(rootDocument, options) { ` ); - // const rootElementDimensions = this.rootElement.getBoundingClientRect(); - // selectorOverlay.setAttribute( - // 'style', - // ` - // top: ${rootElementDimensions.top}px; - // left: ${rootElementDimensions.left}px; - // width: ${rootElementDimensions.width}px; - // height: ${rootElementDimensions.height}px; - // pointer-events: none; - // z-index: ${options.zIndex || 2147483646}; - // padding: 1px; - // position: fixed; - // background: rgba(105, 108, 191, 0.2); - // border: 2px dashed #696CBF; - // box-sizing: border-box; - // border-radius: 4px; - // ` - // ); - console.log('Appending overlay selector element.'); - // this.rootElement.appendChild(selectorOverlay); - // this.rootElement.addEventListener('mouseover', this.mouseOverEvent); - // this.rootElement.addEventListener('mouseout', this.removeClickListenerFromHoveredElement); rootDocument.body.appendChild(selectorOverlay); rootDocument.addEventListener("mouseover", this.mouseOverEvent); rootDocument.addEventListener("mouseout", this.removeClickListenerFromHoveredElement); + + // Setting "abort" action to the esc key + window.focus(); + rootDocument.body.focus(); + window.addEventListener("keydown", (e) => { + if (e.key === 'Escape') { + console.log('Aborting element selection...', e.key); + this.removeOverlayElement(); + options.onElementSelectionCancel(); + } + }, true); } diff --git a/src/strigo/index.ts b/src/strigo/index.ts index 73e4b9a..40e7920 100644 --- a/src/strigo/index.ts +++ b/src/strigo/index.ts @@ -235,10 +235,19 @@ class StrigoSDK implements IStrigoSDK { Logger.debug('sendEvent called', { eventName }); } - startElementSelector(onElementProfileCreated: any, rootElementSelector?: string): void { + startElementSelector( + onElementProfileCreated: any, + onElementSelectionCancel: any, + rootElementSelector?: string + ): void { Logger.debug('startElementSelector called'); const rootElement = rootElementSelector ? window.document.querySelector(rootElementSelector) : window.document.body; - startElementSelector(window.document, { onElementProfileCreated, zIndex: 9999999999, rootElement }); + startElementSelector(window.document, { + onElementProfileCreated, + onElementSelectionCancel, + zIndex: 9999999999, + rootElement, + }); } assessmentRecorder(): void { diff --git a/src/strigo/types.ts b/src/strigo/types.ts index 40842a1..54dc0a4 100644 --- a/src/strigo/types.ts +++ b/src/strigo/types.ts @@ -29,7 +29,11 @@ export interface IStrigoSDK { destroy: () => void; sendEvent: (eventName: string) => Promise; assessmentRecorder: () => void; - startElementSelector: (onElementProfileCreated: any, rootElementSelector?: string) => void; + startElementSelector: ( + onElementProfileCreated: any, + onElementSelectionCancel: any, + rootElementSelector?: string + ) => void; config: SdkConfig; isDevelopment: () => boolean; } @@ -41,4 +45,4 @@ export interface StrigoWindow extends Window { export interface ElementObserver { observedBodyElement?: Element; observer: MutationObserver; -} \ No newline at end of file +}