diff --git a/index.html b/index.html index ddffbf1..2e2ca04 100644 --- a/index.html +++ b/index.html @@ -207,6 +207,66 @@

closeModalDialog


+ + +
+
+

onCanCancel

+
˄
+
+
+

+ Das Ereignis onCanCancel dient als Registrierungsmechanismus, der während der Initialisierungsphase aufgerufen werden sollte. Sie ermöglicht die Entscheidung, ob der modale Dialog beim Auftreten eines ESC-Tastenereignisses innerhalb eines modalen Dialog-Add-ons beendet oder seine Anzeige beibehalten werden soll. Weitere Einzelheiten zur Dokumentation. + +

+

+

+ Syntax: lib.registerOnCanCancelCallback(() => value) +

+
+

Klicken Sie auf eine der Schaltflächen, um den Wert zuzuweisen, und drücken Sie dann die ESC-Taste, um das Verhalten zu beobachten.

+
+ + +
+
+
+
+
+ + +
+
+

setDialogCaption

+
˄
+
+
+

+ Die Methode setDialogCaption ermöglicht Entwicklern, den Titel des Dialogfelds dynamisch anzupassen, selbst nachdem das modale Dialogfeld geöffnet wurde. Dies bietet eine höhere Flexibilität bei der Gestaltung der Benutzererfahrung im Kontext des Projekts. + Weitere Einzelheiten zur Dokumentation. +

+

+

+ Syntax: setDialogCaption(value) +

+
+
+
+ + +
+
+
+ + +
+
+
+
+ +
diff --git a/js/action.js b/js/action.js index 7244e1e..13cd834 100644 --- a/js/action.js +++ b/js/action.js @@ -50,6 +50,16 @@ async function setFieldValueByInternal() { await action.setFieldValueByInternal(internalFieldName, internalFieldValue); } +/** + * Sets the caption of the dialog. + * + * This function retrieves the caption from an HTML element with the ID "captionName" and sets it as the dialog's caption. + */ +async function setDialogCaption() { + const newCaption = document.getElementById("captionName").value; + await action.setDialogCaption(newCaption); +} + /** * Closes the modal dialog with a specific value. * @@ -78,7 +88,11 @@ document .getElementById("setFieldValueByInternal") .addEventListener("click", setFieldValueByInternal); -// Set up event listeners +document + .getElementById("setDialogCaption") + .addEventListener("click", setDialogCaption); + +// Event listeners for closeModalDialog document .getElementById("closeModalSave") .addEventListener("click", function () { @@ -98,6 +112,39 @@ document closeModalDialog(); // Here we pass the no parameter and the dialog will be closed with default value '1' }); + + + +/** + * This function attempts to execute the onCanCancelMethod from the action object with a given value. + * + * @param {any} value - The value to be passed to the onCanCancelMethod of the action object. + * @throws {Error} If an error occurs during the execution of the onCanCancelMethod, it logs the error and rethrows it. + */ +function onCanCancelMethod(value) { + try { + action.onCanCancelMethod(value); + } catch (error) { + console.error("Error onCanCancel method:", error); + throw error; + } +} + + +// Event listeners for onCanCancel +document + .getElementById("onCanCancelEnable") + .addEventListener("click", function () { + onCanCancelMethod(1); // Here we pass the parameter '1' + }); + +document + .getElementById("onCanCancelDisable") + .addEventListener("click", function () { + onCanCancelMethod(2); // Here we pass the parameter '2' + }); + + /** * Clears content and input values when a clear button is clicked. */ @@ -108,7 +155,7 @@ function setupClearButtonActions() { clearContainer("getFieldValueByInternal_response"); clearContainer("setFieldValueByInternal_response"); clearContainer("getEnvironment_response"); - clearInputFields("internalFieldName", "internalFieldValue", "internalSetFieldName"); + clearInputFields("internalFieldName", "internalFieldValue", "internalSetFieldName", "captionName"); }); }); } diff --git a/js/library/library.js b/js/library/library.js index f4c555e..a1aa9c7 100644 --- a/js/library/library.js +++ b/js/library/library.js @@ -47,7 +47,7 @@ async function openIndexData(inNewTab, mode, objectId, objectTypeId = undefined) if (isModalDialog()) { throw "Not implemented for modal dialog"; } - + return sendClientMessage(["openIndexData", [inNewTab, mode, objectId, objectTypeId]]); } @@ -66,7 +66,7 @@ async function openLocation(inNewTab, objectId, objectTypeId = undefined, parent if (isModalDialog()) { throw "Not implemented for modal dialog"; } - + await sendClientMessage(["openLocation", [inNewTab, objectId, objectTypeId, parentId, parentTypeId]]); } @@ -84,7 +84,7 @@ async function getSelectedObjects() { if (isModalDialog()) { throw "Not implemented for modal dialog"; } - + return sendClientMessage(["getSelectedObjects", []]); } @@ -99,7 +99,7 @@ async function refreshHitListObjects(osIds) { if (isModalDialog()) { throw "Not implemented for modal dialog"; } - + await sendClientMessage(["refreshHitListObjects", [osIds]]); } @@ -118,8 +118,8 @@ async function openHitListByIds(objects, inNewTab = false, title = "", subTitle if (isModalDialog()) { throw "Not implemented for modal dialog"; } - - await sendClientMessage(["openHitListByIds", { + + await sendClientMessage(["openHitListByIds", { objects, inNewTab, title, @@ -142,7 +142,7 @@ async function getFieldValueByInternal(json) { if (!isModalDialog()) { throw "Not implemented for dashlets"; } - + return sendClientMessage(["getFieldValueByInternal", [jsonObjectToString(json)]]); } @@ -173,12 +173,27 @@ async function getEnvironment() { if (!isModalDialog()) { throw "Not implemented for dashlets"; } - + return sendClientMessage(["getEnvironment", []]); } /** - * Closes the modal dialog + * This function is only available for modal dialogs. It sets the caption of the dialog to the provided value. + * + * @param {string} newDialogCaption - The caption to be set for the modal dialog. Defaults to an empty string if no value is provided. + * @throws {string} Throws a string error message if the function is used outside of a modal dialog context. + * @remarks The caption is set as an array for webclient compatibility. The rich client only accepts a string. + */ +function setDialogCaption(newDialogCaption = "") { + if (!isModalDialog()) { + throw "Not implemented for dashlets"; + } + + return sendClientMessage(["setDialogCaption", [newDialogCaption]]); +} + +/** + * Cancel the modal dialog * * @param buttonScriptReturnValue The numeric value which should be sent to the button script */ @@ -201,8 +216,8 @@ async function sendClientMessage(payload) { try { if (window.osClient) { return libRichClient.sendToRichClient(payload); - } - + } + return libWebClient.sendWebclientMessage(payload); } catch (error) { console.log(`dashlet says: error caught in ${payload[0]}`, error); @@ -218,7 +233,7 @@ async function sendClientMessage(payload) { */ function jsonObjectToString(jsonObject) { if (!(jsonObject instanceof String) && typeof jsonObject !== "string") { - if (jsonObject.value instanceof Object && typeof jsonObject.value === "object") { + if (typeof jsonObject.value === "object" && !Array.isArray(jsonObject.value)) { jsonObject.value = JSON.stringify(jsonObject.value); } @@ -238,19 +253,60 @@ function isModalDialog() { if (window.osClient) { return libRichClient.isModalDialog(); } - + return libWebClient.isModalDialog(); } +// This will store the value for the onCanCancel behavior. +// It's initialized to a default value to ensure it's always callable. +let onCanCancelValue = 1; + +/** + * Registers the callback for the ESC key event. + * + * @param {Function} valueFunction - A function that returns the current value for the callback. + */ +function registerOnCanCancelCallback(valueFunction) { + return new Promise((resolve, reject) => { + // Delay is necessary to ensure the availability of the function. + setTimeout(() => { + if (!isModalDialog()) { + reject("Not implemented for dashlets"); + } else { + // We assign the function passed from main.js to onCanCancelValue. + // This allows the function to be updated dynamically from main.js. + onCanCancelValue = valueFunction; + resolve(); + } + }, 1000); + }); +} + +// Event listener for the ESC key. +window.addEventListener('keydown', function (event) { + // Check if the ESC key was pressed, and the modal dialog is active. + if (event.key === "Escape" && !window.osClient && isModalDialog()) { + // Retrieve the current onCanCancelValue by calling the function. + const currentValue = typeof onCanCancelValue == 'function' ? onCanCancelValue() : onCanCancelValue; + // If the value is not 2, we close the modal dialog. + if (currentValue !== 2) { + closeModalDialog(currentValue); + } else { + console.warn("ESC key event is disabled."); + } + } +}); + // Export functions to be used in other JavaScript files. // Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import export { // Event Callbacks registerOnInitCallback, registerOnUpdateCallback, + registerOnCanCancelCallback, // Methods Dashlets - openIndexData, + openIndexData, openLocation, getSelectedObjects, refreshHitListObjects, @@ -260,5 +316,9 @@ export { // Methods modal dialogs getFieldValueByInternal, setFieldValueByInternal, - getEnvironment + getEnvironment, + setDialogCaption, + + // export for unit tests + isModalDialog }; diff --git a/js/library/libraryRichClient.js b/js/library/libraryRichClient.js index b154f13..7241e86 100644 --- a/js/library/libraryRichClient.js +++ b/js/library/libraryRichClient.js @@ -75,16 +75,33 @@ async function internalOnInitUpdateDashlet(data) { } let selectedEntries = await getSelectedObjects(); + let lastObjectType = { + mainType: 0, + objectType: "UNKNOWN" + }; if (selectedEntries == null || selectedEntries.length === 0 || selectedEntries[0].objectId === "" || selectedEntries[0].objectId === void 0) { // On opening an index data mask for a different ECM object out of the dashlet the selectedEntries has one element // but the objectId and objectTypeId are empty. We fix this by assigning the information from the init event. selectedEntries = [{ - "objectId": data.objectident, - "objectTypeId": data.objecttype + objectId: data.objectident, + objectTypeId: data.objecttype }]; } + // For search masks we have a selected object with objectId zero. There isn't a selected object. + if (selectedEntries.length === 1 && selectedEntries[0].objectId === "0" && selectedEntries[0].objectTypeId === "0") { + selectedEntries = []; + } + + for (const selectedEntry of selectedEntries) { + addObjectTypeAndMainType(selectedEntry); + + if (selectedEntry.objectId === data.objectident) { + lastObjectType = selectedEntry; + } + } + // get base url if (typeof location.origin === 'undefined') { location.origin = location.protocol + '//' + location.host; @@ -105,10 +122,10 @@ async function internalOnInitUpdateDashlet(data) { }, lastSelectedEntry: { hasVariants: null, // no information from enaio rich client - mainType: null, // no information from enaio rich client + mainType: lastObjectType.mainType, objectTypeId: data.objecttype, osid: data.objectident, - objectType: null // no information from enaio rich client + objectType: lastObjectType.objectType }, osDashletInit: { objectident: data.objectident, @@ -120,8 +137,12 @@ async function internalOnInitUpdateDashlet(data) { pagecount: data.pagecount, searchterm: data.searchterm }, - selectedEntries: selectedEntries - .map(f => ({osid: f.objectId, objectTypeId: f.objectTypeId})), + selectedEntries: selectedEntries.map(selectedEntry => ({ + osid: selectedEntry.objectId, + objectTypeId: selectedEntry.objectTypeId, + objectType: selectedEntry.objectType, + mainType: selectedEntry.mainType + })), sessionInfo: { language: dashletCache.languageGuiSelected.substring(0, 2), // only "fr" instead of "fra" languageObjectDefinition: dashletCache.languageObjectDefinition.split("_")[0], // only "de" instead of "de_DE" @@ -209,6 +230,7 @@ async function sendToRichClient(payload) { case "setFieldValueByInternal": return setFieldValueByInternal(payload); case "getEnvironment": return getEnvironment(); case "closeModalDialog": return closeModalDialog(payload); + case "setDialogCaption": return setDialogCaption(payload); } } @@ -249,12 +271,15 @@ async function openIndexData(payload) { */ async function getSelectedObjects() { const selectedObjects = await window.osClient.osjxGetSelectedObjects(); - return selectedObjects - .split(";") - .map(f => ({ - objectId: f.split(",")[0], - objectTypeId: f.split(",")[1] - })); + return selectedObjects.split(";").map(selectedObject => { + const split = selectedObject.split(","); + const retVal = { + objectId: split[0], + objectTypeId: split[1] + }; + addObjectTypeAndMainType(retVal); + return retVal; + }); } /** @@ -280,7 +305,7 @@ async function openHitListByIds(payload) { const request = { title, - hits: ids.map(f => ({id: f.objectId, type: f.objectTypeId})) + hits: ids.map(hit => ({id: hit.objectId, type: hit.objectTypeId})) }; await window.osClient.osjxOpenResultList(JSON.stringify(request)); @@ -322,6 +347,32 @@ async function closeModalDialog(payload) { await window.osClient.closeModalDialog(payload[1][0]); } +/** + * Documentation see library.js + * + * @private + */ +async function setDialogCaption(payload) { + return window.osClient.setDialogCaption(payload[1][0]); +} + +/** + * Calculate the mainType and objectType from objectTypeId and add the properties to the + * hand in object. + * + * @param selectedObject The object to extend + */ +function addObjectTypeAndMainType(selectedObject) { + // In WebClient it is a string. Therefore toString(); + selectedObject.mainType = (selectedObject.objectTypeId >>> 16).toString(); + + switch (selectedObject.mainType) { + case "0": selectedObject.objectType = "FOLDER"; break; + case "99": selectedObject.objectType = "REGISTER"; break; + default: selectedObject.objectType = "DOCUMENT"; break; + } +} + /** * Return true if we are running inside a modal dialog. If we are running inside a dashlet the return is false. */ diff --git a/js/main.js b/js/main.js index e5b50cd..3faf810 100644 --- a/js/main.js +++ b/js/main.js @@ -48,6 +48,23 @@ async function getFieldValueByInternal(internalFieldName = "") { } } +/** + * Sets the caption of the modal dialog using the provided value. + * + * @param {string} value - The caption to be set for the modal dialog. Defaults to an empty string if no value is provided. + * @throws {Error} If an error occurs during the process, it logs the error with the function name. + */ +async function setDialogCaption(value = "") { + try { + // Fetching field value from enaio® web-client based on the provided internal name. + await lib.setDialogCaption(value); + // Display the fetched data on the webpage and in the console. + } catch (error) { + // Handle any errors that occur during the fetch. + logError("setDialogCaption", error); + } +} + /** * Sets (or updates) a field's value using its internal name and a specified value. * @param {string} internalFieldName - The unique identifier (internal name) of the index field in enaio® web-client. @@ -156,6 +173,23 @@ function onInit(data) { // with the initial data provided by the web-client. lib.registerOnInitCallback(onInit); + +// This value is used to control the behavior of the ESC key event in the iframe. +let onCanCancelValue = 1; + +// Register a function to handle the ESC key event. +// Instead of passing a getter, we're directly passing the value itself. +lib.registerOnCanCancelCallback(() => onCanCancelValue); + +/** + * Sets the value for onCanCancel. + * + * @param {number} [value=1] - The value to set for onCanCancel. + */ +function onCanCancelMethod(value = 1) { + onCanCancelValue = value; +} + // ======================= // EXPORTS // @@ -167,5 +201,7 @@ export { getEnvironment, getFieldValueByInternal, setFieldValueByInternal, - closeModalDialog + closeModalDialog, + onCanCancelMethod, + setDialogCaption };