From 361e6ed96c67f120d424a0694c9300fd4d7d85f9 Mon Sep 17 00:00:00 2001 From: Pencho BELNEYSKI Date: Tue, 16 Aug 2022 16:35:29 +0200 Subject: [PATCH] - add form initialized event - post all events as messages to parent window when in iframe. - handle setfields message posted from the parent window --- public/js/src/module/controller-webform.js | 64 ++++++++++++++++++---- public/js/src/module/event.js | 4 ++ 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/public/js/src/module/controller-webform.js b/public/js/src/module/controller-webform.js index d0f760939..28be1da52 100644 --- a/public/js/src/module/controller-webform.js +++ b/public/js/src/module/controller-webform.js @@ -140,7 +140,7 @@ function init(formEl, data, loadErrors = []) { if (loadErrors.length > 0) { throw loadErrors; } - + form.view.html.dispatchEvent(events.FormInitialized()); return form; }); } @@ -821,17 +821,16 @@ function _setEventHandlers(survey) { }); if (inIframe() && settings.parentWindowOrigin) { - document.addEventListener( - events.SubmissionSuccess().type, - postEventAsMessageToParentWindow - ); - document.addEventListener( - events.Edited().type, - postEventAsMessageToParentWindow - ); - document.addEventListener( - events.Close().type, - postEventAsMessageToParentWindow + Object.keys(events).forEach((eventName) => { + document.addEventListener( + events[eventName]().type, + postEventAsMessageToParentWindow + ); + }); + window.addEventListener( + 'message', + processMessageFromParentWindow, + false ); } @@ -918,9 +917,50 @@ function postEventAsMessageToParentWindow(event) { } } +/** + * Handles messages from parent window when in iframe. + * https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#the_dispatched_event + * + * @param {Object} event The dispatched event object for the message + * @param {String} event.origin The origin of the window that sent the message + * @param {Object} event.source The window object that sent the message + * @param {Object} event.data The object passed from the other window + * @param {String} event.data.type The type (or command) of the message passed. Currently the only supported type is 'setfields' + * @param {Object} event.data.content Type specific content of the message. + * For the setfields type, it is expected to be a key / value map of field paths and their URI encoded values that should be set. + */ +function processMessageFromParentWindow(event) { + const { origin, data: payload } = event; + + if (origin !== settings.parentWindowOrigin) { + // bail, if the message is not sent from the expected origin + return; + } + + const { type, content } = payload; + + switch (type) { + case 'setfields': + Object.keys(content).forEach((fieldName) => { + const inputs = document.getElementsByName(fieldName); + inputs.forEach((inputElement) => { + form.input.setVal( + inputElement, + decodeURIComponent(content[fieldName]) + ); + inputElement.dispatchEvent(events.Change()); + }); + }); + break; + default: + break; + } +} + export default { init, setLogoutLinkVisibility, inIframe, postEventAsMessageToParentWindow, + processMessageFromParentWindow, }; diff --git a/public/js/src/module/event.js b/public/js/src/module/event.js index 8bf0b0410..7c433869b 100644 --- a/public/js/src/module/event.js +++ b/public/js/src/module/event.js @@ -20,6 +20,10 @@ events.ApplicationUpdated = function () { return new CustomEvent('applicationupdated', { bubbles: true }); }; +events.FormInitialized = function() { + return new CustomEvent('forminitialized', { bubbles: true }); +}; + events.FormUpdated = function () { return new CustomEvent('formupdated', { bubbles: true }); };