@unvired/turboforms-embed-sdk 1.0.22 → 1.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -1
- package/dist/unvired-form-sdk.html +33 -10
- package/dist/unvired-forms-sdk.js +330 -69
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -251,7 +251,9 @@ document.addEventListener('deviceready', function() {
|
|
|
251
251
|
| `GET_ATTACHMENT` | Attachment request |
|
|
252
252
|
| `ERROR` | Error occurred |
|
|
253
253
|
|
|
254
|
-
## ✅ Button Visibility & Enablement
|
|
254
|
+
## ✅ Button Visibility & Enablement (Normal Forms)
|
|
255
|
+
|
|
256
|
+
The following rules apply to standard (non-wizard) forms:
|
|
255
257
|
|
|
256
258
|
| privateExternal | Permission | Main Toolbar Button | More Options (Dropdown) | Enable / Disable Rule |
|
|
257
259
|
| ------------------ | --------------- | -------------------------- | ------------------------------- | -------------------------------------------------- |
|
|
@@ -261,6 +263,18 @@ document.addEventListener('deviceready', function() {
|
|
|
261
263
|
| **true (Private)** | `writesingle` | **Complete** (`submitBtn`) | **Save** (`saveOption`) | Complete enabled **ONLY when form is 100% filled** |
|
|
262
264
|
| **Any** | `read` | None | None | N/A (Read-only mode) |
|
|
263
265
|
|
|
266
|
+
## 🧙 Wizard Form Navigation & Visibility
|
|
267
|
+
|
|
268
|
+
For Wizard forms, the standard action buttons are managed per-page to prioritize navigation:
|
|
269
|
+
|
|
270
|
+
| Page Status | Action Buttons (Save/Complete) | Navigation Buttons | Action Menu (More Options) |
|
|
271
|
+
| :--- | :--- | :--- | :--- |
|
|
272
|
+
| **Intermediate Steps** | **Hidden** | **Previous**, **Next** | **Help** / **Comments** (if enabled) |
|
|
273
|
+
| **Final Step** | **Visible** (Follows standard rules above) | **Previous** | **All Actions** (Follows standard rules above) |
|
|
274
|
+
|
|
275
|
+
* **Intermediate Steps**: To ensure a clean experience, the SDK automatically hides all final submission actions (buttons, icons, and "More" dropdown items) until the user reaches the end of the wizard.
|
|
276
|
+
* **Final Step**: Once the user reaches the last page, the standard logic defined in the table above is applied. The **Next** button is replaced by the appropriate **Save** or **Complete** action based on permissions and form state.
|
|
277
|
+
|
|
264
278
|
## 🧭 “More Options” Dropdown Logic
|
|
265
279
|
|
|
266
280
|
### ▶ **Complete appears in More Options**
|
|
@@ -56365,6 +56365,11 @@ class SignatureComponent extends InputComponentForSignature {
|
|
|
56365
56365
|
}
|
|
56366
56366
|
if (this.refs.clicktoSign) {
|
|
56367
56367
|
this.refs.clicktoSign.disabled = true;
|
|
56368
|
+
this.refs.clicktoSign.style.pointerEvents = 'none';
|
|
56369
|
+
this.refs.clicktoSign.style.display = 'none';
|
|
56370
|
+
|
|
56371
|
+
const clickBox = this.refs.clicktoSign.closest('.click-to-sign-box');
|
|
56372
|
+
if(clickBox) clickBox.style.display = 'none';
|
|
56368
56373
|
}
|
|
56369
56374
|
if (this.refs.signatureImage && this.dataValue) {
|
|
56370
56375
|
this.refs.signatureImage.setAttribute('src', this.dataValue);
|
|
@@ -56376,6 +56381,12 @@ class SignatureComponent extends InputComponentForSignature {
|
|
|
56376
56381
|
}
|
|
56377
56382
|
if (this.refs.clicktoSign) {
|
|
56378
56383
|
this.refs.clicktoSign.disabled = false;
|
|
56384
|
+
this.refs.clicktoSign.style.pointerEvents = 'auto';
|
|
56385
|
+
if (this.component.isEnableClicktoSign) {
|
|
56386
|
+
this.refs.clicktoSign.style.display = 'inline-flex';
|
|
56387
|
+
const clickBox = this.refs.clicktoSign.closest('.click-to-sign-box');
|
|
56388
|
+
if(clickBox) clickBox.style.display = '';
|
|
56389
|
+
}
|
|
56379
56390
|
}
|
|
56380
56391
|
}
|
|
56381
56392
|
}
|
|
@@ -56447,6 +56458,11 @@ class SignatureComponent extends InputComponentForSignature {
|
|
|
56447
56458
|
this.refs.refresh.classList.add('disabled');
|
|
56448
56459
|
if (this.refs.clicktoSign) {
|
|
56449
56460
|
this.refs.clicktoSign.disabled = true;
|
|
56461
|
+
this.refs.clicktoSign.style.pointerEvents = 'none';
|
|
56462
|
+
this.refs.clicktoSign.style.display = 'none';
|
|
56463
|
+
|
|
56464
|
+
const clickBox = this.refs.clicktoSign.closest('.click-to-sign-box');
|
|
56465
|
+
if(clickBox) clickBox.style.display = 'none';
|
|
56450
56466
|
}
|
|
56451
56467
|
}
|
|
56452
56468
|
|
|
@@ -58954,16 +58970,13 @@ function showDynamicModal(
|
|
|
58954
58970
|
.custom-modal.show, .custom-modal-backdrop.show {
|
|
58955
58971
|
display: flex;
|
|
58956
58972
|
}
|
|
58957
|
-
/*
|
|
58973
|
+
/* Flexbox on the parent handles centering */
|
|
58958
58974
|
.custom-modal-dialog {
|
|
58959
58975
|
width: 100%;
|
|
58960
58976
|
max-width: 500px;
|
|
58961
|
-
margin:
|
|
58977
|
+
margin: auto;
|
|
58962
58978
|
box-sizing: border-box;
|
|
58963
58979
|
position: relative;
|
|
58964
|
-
top: 50%;
|
|
58965
|
-
left: 50%;
|
|
58966
|
-
transform: translate(-50%, -50%);
|
|
58967
58980
|
}
|
|
58968
58981
|
.custom-modal-content {
|
|
58969
58982
|
background: #fff;
|
|
@@ -59015,9 +59028,7 @@ function showDynamicModal(
|
|
|
59015
59028
|
@media (max-width: 600px) {
|
|
59016
59029
|
.custom-modal-dialog {
|
|
59017
59030
|
max-width: 95vw;
|
|
59018
|
-
|
|
59019
|
-
top: 40%;
|
|
59020
|
-
transform: translate(-50%, -40%);
|
|
59031
|
+
margin: 1rem auto;
|
|
59021
59032
|
}
|
|
59022
59033
|
.custom-modal-content {
|
|
59023
59034
|
border-radius: 0.15rem;
|
|
@@ -59996,7 +60007,7 @@ async function renderRNform(
|
|
|
59996
60007
|
}
|
|
59997
60008
|
|
|
59998
60009
|
// Hide FormIO submit button component and wizard buttons in readOnly mode
|
|
59999
|
-
if (mode == "readOnly") {
|
|
60010
|
+
if (mode == "readOnly" || permission == "read") {
|
|
60000
60011
|
const submitComponents = document.querySelectorAll(
|
|
60001
60012
|
".formio-component-submit"
|
|
60002
60013
|
);
|
|
@@ -60004,6 +60015,18 @@ async function renderRNform(
|
|
|
60004
60015
|
component.style.display = "none";
|
|
60005
60016
|
});
|
|
60006
60017
|
|
|
60018
|
+
// Disable signature pads robustly via CSS
|
|
60019
|
+
if (!document.getElementById("readonly-signature-style")) {
|
|
60020
|
+
const style = document.createElement("style");
|
|
60021
|
+
style.id = "readonly-signature-style";
|
|
60022
|
+
style.innerHTML = `
|
|
60023
|
+
.formio-component-signature { pointer-events: none !important; }
|
|
60024
|
+
.formio-component-signature [ref="clicktoSign"],
|
|
60025
|
+
.formio-component-signature .click-to-sign-box { display: none !important; }
|
|
60026
|
+
`;
|
|
60027
|
+
document.head.appendChild(style);
|
|
60028
|
+
}
|
|
60029
|
+
|
|
60007
60030
|
// Hide wizard navigation buttons
|
|
60008
60031
|
const wizardNextBtns = document.querySelectorAll(
|
|
60009
60032
|
".btn-wizard-nav-next"
|
|
@@ -60687,7 +60710,7 @@ window.CommentOnBack = CommentOnBack;
|
|
|
60687
60710
|
|
|
60688
60711
|
|
|
60689
60712
|
<div id="sticky-footer">
|
|
60690
|
-
<div class="build-version">SDK v1.0.
|
|
60713
|
+
<div class="build-version">SDK v1.0.29</div>
|
|
60691
60714
|
<div class="relative-position">
|
|
60692
60715
|
<button id="unvired-more-btn" class="ui button primary dataGrid-addRow" onclick="toggleTooltip()">
|
|
60693
60716
|
<i class="icon options"></i>
|
|
@@ -43,11 +43,18 @@ function attachMasterDataToForm(obj, masterdataResults, key = "dataSrc", type =
|
|
|
43
43
|
attachMasterDataToForm(obj[k], masterdataResults, key, type, true);
|
|
44
44
|
} else if (k === key && obj[k] === type) {
|
|
45
45
|
if (Array.isArray(masterdataResults)) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
let matchedData = [];
|
|
47
|
+
if (obj.selMasterdataId) {
|
|
48
|
+
const match = masterdataResults.find((md) => md.masterdataId === obj.selMasterdataId);
|
|
49
|
+
if (match && match.submissionData) {
|
|
50
|
+
matchedData = match.submissionData;
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
matchedData = masterdataResults.flatMap((md) => md.submissionData || []);
|
|
54
|
+
}
|
|
55
|
+
obj.masterdata = matchedData.map((item) => item && item.data !== void 0 ? item : { data: item });
|
|
49
56
|
} else if (masterdataResults && Array.isArray(masterdataResults.submissionData)) {
|
|
50
|
-
obj.masterdata = masterdataResults.submissionData;
|
|
57
|
+
obj.masterdata = masterdataResults.submissionData.map((item) => item && item.data !== void 0 ? item : { data: item });
|
|
51
58
|
} else {
|
|
52
59
|
obj.masterdata = [];
|
|
53
60
|
}
|
|
@@ -939,6 +946,8 @@ async function loadUnviredForms({
|
|
|
939
946
|
const template = formJson;
|
|
940
947
|
const nestedFormArrTemp = options.nestedFormData || [];
|
|
941
948
|
const masterDataArrTemp = options.masterData || [];
|
|
949
|
+
console.log("[SDK:3] Debug - options.masterData received:", options.masterData);
|
|
950
|
+
console.log("[SDK:3] Debug - masterDataArrTemp evaluated to:", masterDataArrTemp);
|
|
942
951
|
const nestedFormError = validateNestedForms(formJson, nestedFormArrTemp);
|
|
943
952
|
if (nestedFormError) {
|
|
944
953
|
console.error("[SDK] \u274C Step 3: Nested form validation failed", nestedFormError);
|
|
@@ -27823,6 +27832,7 @@ select.ui.dropdown {
|
|
|
27823
27832
|
height: 100%;
|
|
27824
27833
|
background: rgba(255, 255, 255, 0.95);
|
|
27825
27834
|
backdrop-filter: blur(10px);
|
|
27835
|
+
-webkit-backdrop-filter: blur(10px);
|
|
27826
27836
|
display: flex;
|
|
27827
27837
|
flex-direction: column;
|
|
27828
27838
|
justify-content: center;
|
|
@@ -27842,15 +27852,23 @@ select.ui.dropdown {
|
|
|
27842
27852
|
border: 4px solid #e0e0e0;
|
|
27843
27853
|
border-top: 4px solid #0077b6;
|
|
27844
27854
|
border-radius: 50%;
|
|
27855
|
+
-webkit-animation: sdk-spin 1s linear infinite;
|
|
27845
27856
|
animation: sdk-spin 1s linear infinite;
|
|
27846
27857
|
margin-bottom: 20px;
|
|
27858
|
+
-webkit-transform: translateZ(0);
|
|
27859
|
+
transform: translateZ(0);
|
|
27860
|
+
will-change: transform;
|
|
27847
27861
|
}
|
|
27848
27862
|
.sdk-loader-text {
|
|
27849
27863
|
color: #0077b6;
|
|
27850
27864
|
font-size: 1.1rem;
|
|
27851
27865
|
font-weight: 500;
|
|
27852
27866
|
letter-spacing: 0.5px;
|
|
27867
|
+
-webkit-animation: sdk-pulse 1.5s ease-in-out infinite;
|
|
27853
27868
|
animation: sdk-pulse 1.5s ease-in-out infinite;
|
|
27869
|
+
-webkit-transform: translateZ(0);
|
|
27870
|
+
transform: translateZ(0);
|
|
27871
|
+
will-change: opacity;
|
|
27854
27872
|
}
|
|
27855
27873
|
.sdk-loader-subtext {
|
|
27856
27874
|
color: #666;
|
|
@@ -27858,10 +27876,18 @@ select.ui.dropdown {
|
|
|
27858
27876
|
margin-top: 8px;
|
|
27859
27877
|
opacity: 0.7;
|
|
27860
27878
|
}
|
|
27879
|
+
@-webkit-keyframes sdk-spin {
|
|
27880
|
+
0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); }
|
|
27881
|
+
100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); }
|
|
27882
|
+
}
|
|
27861
27883
|
@keyframes sdk-spin {
|
|
27862
27884
|
0% { transform: rotate(0deg); }
|
|
27863
27885
|
100% { transform: rotate(360deg); }
|
|
27864
27886
|
}
|
|
27887
|
+
@-webkit-keyframes sdk-pulse {
|
|
27888
|
+
0%, 100% { opacity: 1; }
|
|
27889
|
+
50% { opacity: 0.5; }
|
|
27890
|
+
}
|
|
27865
27891
|
@keyframes sdk-pulse {
|
|
27866
27892
|
0%, 100% { opacity: 1; }
|
|
27867
27893
|
50% { opacity: 0.5; }
|
|
@@ -27922,14 +27948,20 @@ select.ui.dropdown {
|
|
|
27922
27948
|
<div id="formio-cmt" style="margin-bottom: 20px;"></div>
|
|
27923
27949
|
</div>
|
|
27924
27950
|
<div id="sticky-footer">
|
|
27925
|
-
<div class="build-version">SDK v1.0.
|
|
27951
|
+
<div class="build-version">SDK v1.0.29</div>
|
|
27926
27952
|
<button class="ui button primary dataGrid-addRow" id="saveBtn" disabled="true" onclick="FormOnSave()">
|
|
27927
27953
|
<i class="icon save large"></i>Save
|
|
27928
27954
|
</button>
|
|
27955
|
+
<button class="ui button secondary dataGrid-addRow" id="prevBtn" style="display:none" onclick="FormOnPrevious()">
|
|
27956
|
+
<i class="icon arrow left"></i>Previous
|
|
27957
|
+
</button>
|
|
27958
|
+
<button class="ui button primary dataGrid-addRow" id="nextBtn" style="display:none" onclick="FormOnNext()">
|
|
27959
|
+
Next<i class="icon arrow right"></i>
|
|
27960
|
+
</button>
|
|
27929
27961
|
<button class="ui button primary dataGrid-addRow" id="submitBtn" style="display:none" onclick="FormOnSubmit()">
|
|
27930
27962
|
<i class="icon save large"></i>Submit
|
|
27931
27963
|
</button>
|
|
27932
|
-
|
|
27964
|
+
|
|
27933
27965
|
<!-- Quick Action Buttons -->
|
|
27934
27966
|
<div id="quick-actions" style="display: flex; align-items: center;">
|
|
27935
27967
|
<i id="quickCompleteBtn" class="icon clipboard check large" style="display:none; cursor: pointer; margin: 0 10px;" onclick="FormOnSubmit()" title="Complete"></i>
|
|
@@ -28078,6 +28110,16 @@ select.ui.dropdown {
|
|
|
28078
28110
|
window.formOnSubmitFunction();
|
|
28079
28111
|
}
|
|
28080
28112
|
};
|
|
28113
|
+
window.FormOnNext = window.FormOnNext || function() {
|
|
28114
|
+
if (typeof window.formOnNextFunction === "function") {
|
|
28115
|
+
window.formOnNextFunction();
|
|
28116
|
+
}
|
|
28117
|
+
};
|
|
28118
|
+
window.FormOnPrevious = window.FormOnPrevious || function() {
|
|
28119
|
+
if (typeof window.formOnPreviousFunction === "function") {
|
|
28120
|
+
window.formOnPreviousFunction();
|
|
28121
|
+
}
|
|
28122
|
+
};
|
|
28081
28123
|
const scriptContents = `
|
|
28082
28124
|
// Global variable initialization
|
|
28083
28125
|
window.form = window.form || {};
|
|
@@ -63598,6 +63640,11 @@ class SignatureComponent extends InputComponentForSignature {
|
|
|
63598
63640
|
}
|
|
63599
63641
|
if (this.refs.clicktoSign) {
|
|
63600
63642
|
this.refs.clicktoSign.disabled = true;
|
|
63643
|
+
this.refs.clicktoSign.style.pointerEvents = 'none';
|
|
63644
|
+
this.refs.clicktoSign.style.display = 'none';
|
|
63645
|
+
|
|
63646
|
+
const clickBox = this.refs.clicktoSign.closest('.click-to-sign-box');
|
|
63647
|
+
if(clickBox) clickBox.style.display = 'none';
|
|
63601
63648
|
}
|
|
63602
63649
|
if (this.refs.signatureImage && this.dataValue) {
|
|
63603
63650
|
this.refs.signatureImage.setAttribute('src', this.dataValue);
|
|
@@ -63609,6 +63656,12 @@ class SignatureComponent extends InputComponentForSignature {
|
|
|
63609
63656
|
}
|
|
63610
63657
|
if (this.refs.clicktoSign) {
|
|
63611
63658
|
this.refs.clicktoSign.disabled = false;
|
|
63659
|
+
this.refs.clicktoSign.style.pointerEvents = 'auto';
|
|
63660
|
+
if (this.component.isEnableClicktoSign) {
|
|
63661
|
+
this.refs.clicktoSign.style.display = 'inline-flex';
|
|
63662
|
+
const clickBox = this.refs.clicktoSign.closest('.click-to-sign-box');
|
|
63663
|
+
if(clickBox) clickBox.style.display = '';
|
|
63664
|
+
}
|
|
63612
63665
|
}
|
|
63613
63666
|
}
|
|
63614
63667
|
}
|
|
@@ -63680,6 +63733,11 @@ class SignatureComponent extends InputComponentForSignature {
|
|
|
63680
63733
|
this.refs.refresh.classList.add('disabled');
|
|
63681
63734
|
if (this.refs.clicktoSign) {
|
|
63682
63735
|
this.refs.clicktoSign.disabled = true;
|
|
63736
|
+
this.refs.clicktoSign.style.pointerEvents = 'none';
|
|
63737
|
+
this.refs.clicktoSign.style.display = 'none';
|
|
63738
|
+
|
|
63739
|
+
const clickBox = this.refs.clicktoSign.closest('.click-to-sign-box');
|
|
63740
|
+
if(clickBox) clickBox.style.display = 'none';
|
|
63683
63741
|
}
|
|
63684
63742
|
}
|
|
63685
63743
|
|
|
@@ -66192,16 +66250,13 @@ function showDynamicModal(
|
|
|
66192
66250
|
.custom-modal.show, .custom-modal-backdrop.show {
|
|
66193
66251
|
display: flex;
|
|
66194
66252
|
}
|
|
66195
|
-
/*
|
|
66253
|
+
/* Flexbox on the parent handles centering */
|
|
66196
66254
|
.custom-modal-dialog {
|
|
66197
66255
|
width: 100%;
|
|
66198
66256
|
max-width: 500px;
|
|
66199
|
-
margin:
|
|
66257
|
+
margin: auto;
|
|
66200
66258
|
box-sizing: border-box;
|
|
66201
66259
|
position: relative;
|
|
66202
|
-
top: 50%;
|
|
66203
|
-
left: 50%;
|
|
66204
|
-
transform: translate(-50%, -50%);
|
|
66205
66260
|
}
|
|
66206
66261
|
.custom-modal-content {
|
|
66207
66262
|
background: #fff;
|
|
@@ -66253,9 +66308,7 @@ function showDynamicModal(
|
|
|
66253
66308
|
@media (max-width: 600px) {
|
|
66254
66309
|
.custom-modal-dialog {
|
|
66255
66310
|
max-width: 95vw;
|
|
66256
|
-
|
|
66257
|
-
top: 40%;
|
|
66258
|
-
transform: translate(-50%, -40%);
|
|
66311
|
+
margin: 1rem auto;
|
|
66259
66312
|
}
|
|
66260
66313
|
.custom-modal-content {
|
|
66261
66314
|
border-radius: 0.15rem;
|
|
@@ -66567,6 +66620,8 @@ function FormOnBackNavigation() {
|
|
|
66567
66620
|
function initialButtonSetup(privateExternal, permission) {
|
|
66568
66621
|
const saveBtn = document.getElementById("saveBtn");
|
|
66569
66622
|
const submitBtn = document.getElementById("submitBtn");
|
|
66623
|
+
const prevBtn = document.getElementById("prevBtn");
|
|
66624
|
+
const nextBtn = document.getElementById("nextBtn");
|
|
66570
66625
|
const completeOption = document.getElementById("completeOption");
|
|
66571
66626
|
const saveOption = document.getElementById("saveOption");
|
|
66572
66627
|
const completeDivider = document.getElementById("completeDivider");
|
|
@@ -66672,6 +66727,7 @@ function initialButtonSetup(privateExternal, permission) {
|
|
|
66672
66727
|
}
|
|
66673
66728
|
}
|
|
66674
66729
|
|
|
66730
|
+
|
|
66675
66731
|
function onChangeButtonSetup(
|
|
66676
66732
|
completionPercentage,
|
|
66677
66733
|
formData,
|
|
@@ -66680,6 +66736,8 @@ function onChangeButtonSetup(
|
|
|
66680
66736
|
) {
|
|
66681
66737
|
const saveBtn = document.getElementById("saveBtn");
|
|
66682
66738
|
const submitBtn = document.getElementById("submitBtn");
|
|
66739
|
+
const prevBtn = document.getElementById("prevBtn");
|
|
66740
|
+
const nextBtn = document.getElementById("nextBtn");
|
|
66683
66741
|
if (!saveBtn || !submitBtn) return;
|
|
66684
66742
|
|
|
66685
66743
|
const isPrivate = privateExternal === true || privateExternal === "true";
|
|
@@ -67042,6 +67100,11 @@ async function loadRNform(
|
|
|
67042
67100
|
.then(() => {
|
|
67043
67101
|
console.log("[FormIO] \u{1F680} formReady.then() triggered");
|
|
67044
67102
|
|
|
67103
|
+
// Handle Navigation and Button Hiding (Wizard-specific logic separated)
|
|
67104
|
+
if (typeof window.initializeWizardLogic === "function") {
|
|
67105
|
+
window.initializeWizardLogic(formObj, privateExternal, permission);
|
|
67106
|
+
}
|
|
67107
|
+
|
|
67045
67108
|
if (formPreviousData) {
|
|
67046
67109
|
console.log("[FormIO] \u{1F4E6} Previous form data found:", formPreviousData);
|
|
67047
67110
|
|
|
@@ -67063,7 +67126,7 @@ async function loadRNform(
|
|
|
67063
67126
|
console.log("[FormIO] \u2705 Progress calculation completed");
|
|
67064
67127
|
|
|
67065
67128
|
// Hide FormIO submit button component and wizard buttons in readOnly mode
|
|
67066
|
-
if (mode == "readOnly") {
|
|
67129
|
+
if (mode == "readOnly" || permission == "read") {
|
|
67067
67130
|
console.log("[FormIO] \u{1F512} ReadOnly mode detected");
|
|
67068
67131
|
|
|
67069
67132
|
const submitComponents = document.querySelectorAll(
|
|
@@ -67078,41 +67141,17 @@ async function loadRNform(
|
|
|
67078
67141
|
console.log(\`[FormIO] Hidden submit component \${index + 1}\`);
|
|
67079
67142
|
});
|
|
67080
67143
|
|
|
67081
|
-
|
|
67082
|
-
|
|
67083
|
-
|
|
67084
|
-
|
|
67085
|
-
|
|
67086
|
-
|
|
67087
|
-
|
|
67088
|
-
|
|
67089
|
-
|
|
67090
|
-
|
|
67091
|
-
}
|
|
67092
|
-
|
|
67093
|
-
const wizardSubmitBtns = document.querySelectorAll(
|
|
67094
|
-
".btn-wizard-nav-submit"
|
|
67095
|
-
);
|
|
67096
|
-
console.log(
|
|
67097
|
-
\`[FormIO] Found \${wizardSubmitBtns.length} wizard submit buttons\`
|
|
67098
|
-
);
|
|
67099
|
-
|
|
67100
|
-
wizardSubmitBtns.forEach((btn, index) => {
|
|
67101
|
-
btn.style.display = "none";
|
|
67102
|
-
console.log(\`[FormIO] Hidden wizard submit button \${index + 1}\`);
|
|
67103
|
-
});
|
|
67104
|
-
|
|
67105
|
-
const wizardPrevBtns = document.querySelectorAll(
|
|
67106
|
-
".btn-wizard-nav-previous"
|
|
67107
|
-
);
|
|
67108
|
-
console.log(
|
|
67109
|
-
\`[FormIO] Found \${wizardPrevBtns.length} wizard previous buttons\`
|
|
67110
|
-
);
|
|
67111
|
-
|
|
67112
|
-
wizardPrevBtns.forEach((btn, index) => {
|
|
67113
|
-
btn.style.display = "none";
|
|
67114
|
-
console.log(\`[FormIO] Hidden wizard previous button \${index + 1}\`);
|
|
67115
|
-
});
|
|
67144
|
+
// Disable signature components robustly via CSS
|
|
67145
|
+
if (!document.getElementById("readonly-signature-style")) {
|
|
67146
|
+
const style = document.createElement("style");
|
|
67147
|
+
style.id = "readonly-signature-style";
|
|
67148
|
+
style.innerHTML = \`
|
|
67149
|
+
.formio-component-signature { pointer-events: none !important; }
|
|
67150
|
+
.formio-component-signature [ref="clicktoSign"],
|
|
67151
|
+
.formio-component-signature .click-to-sign-box { display: none !important; }
|
|
67152
|
+
\`;
|
|
67153
|
+
document.head.appendChild(style);
|
|
67154
|
+
}
|
|
67116
67155
|
} else {
|
|
67117
67156
|
console.log("[FormIO] \u{1F513} Editable mode detected");
|
|
67118
67157
|
}
|
|
@@ -67257,6 +67296,11 @@ function buildMandatoryFieldsCache() {
|
|
|
67257
67296
|
cacheMandatoryFields(comp.components, fieldPath);
|
|
67258
67297
|
}
|
|
67259
67298
|
|
|
67299
|
+
// Nested forms
|
|
67300
|
+
if (comp.type === 'form' && comp.subForm && Array.isArray(comp.subForm.components)) {
|
|
67301
|
+
cacheMandatoryFields(comp.subForm.components, fieldPath ? \`\${fieldPath}.data\` : 'data');
|
|
67302
|
+
}
|
|
67303
|
+
|
|
67260
67304
|
// Columns component handles children differently in instances?
|
|
67261
67305
|
// Usually comp.columns is an array of objects which contain .components (instances)
|
|
67262
67306
|
if (Array.isArray(comp.columns)) {
|
|
@@ -67290,13 +67334,16 @@ function buildMandatoryFieldsCache() {
|
|
|
67290
67334
|
return cache;
|
|
67291
67335
|
}
|
|
67292
67336
|
|
|
67293
|
-
function
|
|
67337
|
+
window.executeProgressCalculation = function(privateExternal, permission) {
|
|
67294
67338
|
if (!formObj) return;
|
|
67295
67339
|
|
|
67296
67340
|
const data = formObj.data || {};
|
|
67297
67341
|
const dataHash = JSON.stringify(data);
|
|
67342
|
+
const isWizard = formObj && !!formObj.wizard;
|
|
67298
67343
|
|
|
67299
|
-
if
|
|
67344
|
+
// For wizards, we must always proceed even if data is same,
|
|
67345
|
+
// because button visibility depends on the current page.
|
|
67346
|
+
if (!isWizard && dataHash === lastDataHash) return;
|
|
67300
67347
|
lastDataHash = dataHash;
|
|
67301
67348
|
|
|
67302
67349
|
const mandatoryFields = buildMandatoryFieldsCache();
|
|
@@ -67398,6 +67445,11 @@ function executeProgressCalculation(privateExternal, permission) {
|
|
|
67398
67445
|
permission
|
|
67399
67446
|
);
|
|
67400
67447
|
|
|
67448
|
+
// After setting up standard button visibility, override with wizard rules if applicable
|
|
67449
|
+
if (typeof window.updateWizardNav === "function") {
|
|
67450
|
+
window.updateWizardNav(formObj);
|
|
67451
|
+
}
|
|
67452
|
+
|
|
67401
67453
|
// Update progress bar
|
|
67402
67454
|
const progressBar = document.getElementById("progress-bar");
|
|
67403
67455
|
if (progressBar) {
|
|
@@ -67678,6 +67730,12 @@ function FormOnSave() {
|
|
|
67678
67730
|
}
|
|
67679
67731
|
|
|
67680
67732
|
function FormOnBack() {
|
|
67733
|
+
// Do not ask for confirmation in read-only mode
|
|
67734
|
+
if (formObj && formObj.options && formObj.options.readOnly) {
|
|
67735
|
+
FormOnBackNavigation();
|
|
67736
|
+
return;
|
|
67737
|
+
}
|
|
67738
|
+
|
|
67681
67739
|
let currentData;
|
|
67682
67740
|
try {
|
|
67683
67741
|
currentData = formObj ? formObj.getValue().data : null;
|
|
@@ -67685,10 +67743,10 @@ function FormOnBack() {
|
|
|
67685
67743
|
currentData = null;
|
|
67686
67744
|
}
|
|
67687
67745
|
|
|
67688
|
-
const
|
|
67746
|
+
const noChanges =
|
|
67689
67747
|
JSON.stringify(currentData) === JSON.stringify(initialFormData);
|
|
67690
67748
|
|
|
67691
|
-
if (
|
|
67749
|
+
if (noChanges) {
|
|
67692
67750
|
FormOnBackNavigation();
|
|
67693
67751
|
} else {
|
|
67694
67752
|
showDynamicModal(
|
|
@@ -67740,18 +67798,19 @@ window.checkMoreButtonVisibility = function () {
|
|
|
67740
67798
|
// For documentsOption, its display is managed by logic.
|
|
67741
67799
|
// For comments/help, they are often just static items toggled.
|
|
67742
67800
|
|
|
67743
|
-
const isVisible = (el) =>
|
|
67744
|
-
|
|
67745
|
-
|
|
67746
|
-
|
|
67747
|
-
|
|
67801
|
+
const isVisible = (el, optionKey) => {
|
|
67802
|
+
if (!el) return false;
|
|
67803
|
+
// If it's a static item like Help or Comments, check the options as well
|
|
67804
|
+
if (optionKey && options[optionKey] === true) return true;
|
|
67805
|
+
return el.style.display !== "none";
|
|
67806
|
+
};
|
|
67748
67807
|
|
|
67749
67808
|
const hasVisibleItems =
|
|
67750
67809
|
isVisible(completeOption) ||
|
|
67751
67810
|
isVisible(saveOption) ||
|
|
67752
67811
|
isVisible(documentsOption) ||
|
|
67753
|
-
isVisible(commentsItem) ||
|
|
67754
|
-
isVisible(helpItem); // Simplified: check actual DOM state
|
|
67812
|
+
isVisible(commentsItem, "showComments") ||
|
|
67813
|
+
isVisible(helpItem, "showHelp"); // Simplified: check actual DOM state + options
|
|
67755
67814
|
|
|
67756
67815
|
// If ANY item is visible, show the button. Otherwise hide.
|
|
67757
67816
|
if (hasVisibleItems) {
|
|
@@ -67769,6 +67828,28 @@ window.FormOnSave = FormOnSave;
|
|
|
67769
67828
|
window.FormOnBack = FormOnBack;
|
|
67770
67829
|
window.setImageData = setImageData;
|
|
67771
67830
|
window.FormOnSubmit = FormOnSubmit;
|
|
67831
|
+
window.FormOnNext = function () {
|
|
67832
|
+
if (formObj && typeof formObj.nextPage === "function") {
|
|
67833
|
+
formObj.nextPage().then(() => {
|
|
67834
|
+
if (typeof window.updateWizardNav === "function") {
|
|
67835
|
+
window.updateWizardNav(formObj);
|
|
67836
|
+
}
|
|
67837
|
+
});
|
|
67838
|
+
}
|
|
67839
|
+
};
|
|
67840
|
+
|
|
67841
|
+
window.FormOnPrevious = function () {
|
|
67842
|
+
if (formObj && typeof formObj.prevPage === "function") {
|
|
67843
|
+
formObj.prevPage().then(() => {
|
|
67844
|
+
if (typeof window.updateWizardNav === "function") {
|
|
67845
|
+
window.updateWizardNav(formObj);
|
|
67846
|
+
}
|
|
67847
|
+
});
|
|
67848
|
+
}
|
|
67849
|
+
};
|
|
67850
|
+
|
|
67851
|
+
window.formOnSubmitFunction = FormOnSubmit;
|
|
67852
|
+
|
|
67772
67853
|
window.resetFormCache = resetFormCache;
|
|
67773
67854
|
|
|
67774
67855
|
// Notify that loadRNform is ready (for event-based coordination)
|
|
@@ -67778,6 +67859,174 @@ document.dispatchEvent(new CustomEvent('LoadRNformReady'));
|
|
|
67778
67859
|
|
|
67779
67860
|
// === SCRIPT_SEPARATOR ===
|
|
67780
67861
|
|
|
67862
|
+
(function(){
|
|
67863
|
+
/**
|
|
67864
|
+
* Wizard Navigation Logic for Unvired Forms
|
|
67865
|
+
* This file handles all logic specific to Form.io wizard forms,
|
|
67866
|
+
* including navigation button visibility and event handling.
|
|
67867
|
+
*/
|
|
67868
|
+
|
|
67869
|
+
/**
|
|
67870
|
+
* Updates the visibility of navigation buttons (Next, Previous, Submit)
|
|
67871
|
+
* based on the current wizard page and form type.
|
|
67872
|
+
*
|
|
67873
|
+
* @param {Object} formObj - The Form.io form instance
|
|
67874
|
+
*/
|
|
67875
|
+
function updateWizardNav(formObj) {
|
|
67876
|
+
if (!formObj) return;
|
|
67877
|
+
|
|
67878
|
+
// 1. Hide default navigation and buttons (Next, Previous, Cancel, Submit)
|
|
67879
|
+
// This ensures that we only use our own footer buttons
|
|
67880
|
+
const selectorsToHide = [
|
|
67881
|
+
'.formio-component-wizard_nav',
|
|
67882
|
+
'.btn-wizard-nav-next',
|
|
67883
|
+
'.btn-wizard-nav-previous',
|
|
67884
|
+
'.btn-wizard-nav-cancel',
|
|
67885
|
+
'.btn-wizard-nav-submit'
|
|
67886
|
+
];
|
|
67887
|
+
|
|
67888
|
+
selectorsToHide.forEach(selector => {
|
|
67889
|
+
const elements = formObj.element.querySelectorAll(selector);
|
|
67890
|
+
elements.forEach(el => {
|
|
67891
|
+
el.style.display = "none";
|
|
67892
|
+
});
|
|
67893
|
+
});
|
|
67894
|
+
|
|
67895
|
+
// 2. Hide components from JSON that match navigation actions
|
|
67896
|
+
if (typeof formObj.eachComponent === 'function') {
|
|
67897
|
+
formObj.eachComponent((component) => {
|
|
67898
|
+
if (component.type === 'button') {
|
|
67899
|
+
const action = (component.component.action || '').toLowerCase();
|
|
67900
|
+
const label = (component.component.label || '').toLowerCase();
|
|
67901
|
+
|
|
67902
|
+
if (action === 'next' || action === 'previous' || action === 'cancel' ||
|
|
67903
|
+
label === 'next' || label === 'previous' || label === 'cancel') {
|
|
67904
|
+
// Hide both the component instance and its DOM element
|
|
67905
|
+
component.visible = false;
|
|
67906
|
+
if (component.element) {
|
|
67907
|
+
component.element.style.display = 'none';
|
|
67908
|
+
}
|
|
67909
|
+
}
|
|
67910
|
+
}
|
|
67911
|
+
});
|
|
67912
|
+
}
|
|
67913
|
+
|
|
67914
|
+
// 3. Handle Footer Navigation Toggling (Only for Wizards)
|
|
67915
|
+
if (!formObj.wizard) return;
|
|
67916
|
+
|
|
67917
|
+
const prevBtn = document.getElementById("prevBtn");
|
|
67918
|
+
const nextBtn = document.getElementById("nextBtn");
|
|
67919
|
+
const submitBtn = document.getElementById("submitBtn");
|
|
67920
|
+
const saveBtn = document.getElementById("saveBtn");
|
|
67921
|
+
|
|
67922
|
+
const currentPage = formObj.page || 0;
|
|
67923
|
+
const numPages = (formObj.pages && formObj.pages.length) || 0;
|
|
67924
|
+
const isLastPage = (currentPage >= numPages - 1);
|
|
67925
|
+
|
|
67926
|
+
console.log(\`[WizardLogic] \u{1F9ED} Page: \${currentPage + 1}/\${numPages}, isLastPage: \${isLastPage}\`);
|
|
67927
|
+
|
|
67928
|
+
if (prevBtn) {
|
|
67929
|
+
prevBtn.style.display = currentPage > 0 ? "inline-block" : "none";
|
|
67930
|
+
}
|
|
67931
|
+
|
|
67932
|
+
if (nextBtn) {
|
|
67933
|
+
nextBtn.style.display = currentPage < numPages - 1 ? "inline-block" : "none";
|
|
67934
|
+
}
|
|
67935
|
+
|
|
67936
|
+
// If it's a wizard, we only want the save and submit buttons on the last page.
|
|
67937
|
+
// If it's NOT the last page, we force hide them.
|
|
67938
|
+
// If it IS the last page, we let the normal logic (onChangeButtonSetup) decide.
|
|
67939
|
+
if (!isLastPage) {
|
|
67940
|
+
console.log("[WizardLogic] \u{1F512} Intermediate page: Hiding save/complete actions");
|
|
67941
|
+
if (submitBtn) submitBtn.style.display = "none";
|
|
67942
|
+
if (saveBtn) saveBtn.style.display = "none";
|
|
67943
|
+
|
|
67944
|
+
// Hide dropdown options as well
|
|
67945
|
+
const completeOption = document.getElementById("completeOption");
|
|
67946
|
+
const saveOption = document.getElementById("saveOption");
|
|
67947
|
+
const completeDivider = document.getElementById("completeDivider");
|
|
67948
|
+
const saveDivider = document.getElementById("saveDivider");
|
|
67949
|
+
|
|
67950
|
+
if (completeOption) completeOption.style.display = "none";
|
|
67951
|
+
if (saveOption) saveOption.style.display = "none";
|
|
67952
|
+
if (completeDivider) completeDivider.style.display = "none";
|
|
67953
|
+
if (saveDivider) saveDivider.style.display = "none";
|
|
67954
|
+
|
|
67955
|
+
// Also hide quick action buttons if they exist
|
|
67956
|
+
const quickCompleteBtn = document.getElementById("quickCompleteBtn");
|
|
67957
|
+
const quickSaveBtn = document.getElementById("quickSaveBtn");
|
|
67958
|
+
if (quickCompleteBtn) quickCompleteBtn.style.display = "none";
|
|
67959
|
+
if (quickSaveBtn) quickSaveBtn.style.display = "none";
|
|
67960
|
+
|
|
67961
|
+
// Re-check More button visibility after hiding items
|
|
67962
|
+
if (typeof window.checkMoreButtonVisibility === "function") {
|
|
67963
|
+
window.checkMoreButtonVisibility();
|
|
67964
|
+
}
|
|
67965
|
+
} else {
|
|
67966
|
+
console.log("[WizardLogic] \u{1F513} Last page: Allowing normal button logic to take over");
|
|
67967
|
+
// On the last page, we MUST ensure the More button visibility is re-evaluated
|
|
67968
|
+
// because it might have been hidden on the previous page.
|
|
67969
|
+
if (typeof window.checkMoreButtonVisibility === "function") {
|
|
67970
|
+
window.checkMoreButtonVisibility();
|
|
67971
|
+
}
|
|
67972
|
+
}
|
|
67973
|
+
}
|
|
67974
|
+
|
|
67975
|
+
/**
|
|
67976
|
+
* Sets up event listeners for wizard-specific events like page changes.
|
|
67977
|
+
*
|
|
67978
|
+
* @param {Object} formObj - The Form.io form instance
|
|
67979
|
+
* @param {Boolean} privateExternal - Private/External flag
|
|
67980
|
+
* @param {String} permission - User permission level
|
|
67981
|
+
*/
|
|
67982
|
+
function setupWizardEvents(formObj, privateExternal, permission) {
|
|
67983
|
+
if (!formObj) return;
|
|
67984
|
+
|
|
67985
|
+
if (formObj.wizard) {
|
|
67986
|
+
formObj.on('nextPage', () => {
|
|
67987
|
+
updateWizardNav(formObj);
|
|
67988
|
+
// Trigger progress calculation on page change
|
|
67989
|
+
if (typeof window.executeProgressCalculation === 'function') {
|
|
67990
|
+
window.executeProgressCalculation(privateExternal, permission);
|
|
67991
|
+
}
|
|
67992
|
+
});
|
|
67993
|
+
formObj.on('prevPage', () => {
|
|
67994
|
+
updateWizardNav(formObj);
|
|
67995
|
+
// Trigger progress calculation on page change
|
|
67996
|
+
if (typeof window.executeProgressCalculation === 'function') {
|
|
67997
|
+
window.executeProgressCalculation(privateExternal, permission);
|
|
67998
|
+
}
|
|
67999
|
+
});
|
|
68000
|
+
}
|
|
68001
|
+
|
|
68002
|
+
// Always handle render event to ensure buttons stay hidden
|
|
68003
|
+
formObj.on('render', () => {
|
|
68004
|
+
updateWizardNav(formObj);
|
|
68005
|
+
});
|
|
68006
|
+
}
|
|
68007
|
+
|
|
68008
|
+
window.updateWizardNav = updateWizardNav;
|
|
68009
|
+
|
|
68010
|
+
/**
|
|
68011
|
+
* Main initialization function for wizard logic.
|
|
68012
|
+
* Should be called after the Form.io form is created.
|
|
68013
|
+
*/
|
|
68014
|
+
window.initializeWizardLogic = function(formObj, privateExternal, permission) {
|
|
68015
|
+
console.log("[WizardLogic] \u{1F9D9} Initializing wizard-specific logic...");
|
|
68016
|
+
setupWizardEvents(formObj, privateExternal, permission);
|
|
68017
|
+
|
|
68018
|
+
// Also listen for change events to update nav (e.g. if pages are conditionally hidden)
|
|
68019
|
+
formObj.on('change', () => {
|
|
68020
|
+
updateWizardNav(formObj);
|
|
68021
|
+
});
|
|
68022
|
+
|
|
68023
|
+
updateWizardNav(formObj);
|
|
68024
|
+
};
|
|
68025
|
+
|
|
68026
|
+
})();
|
|
68027
|
+
|
|
68028
|
+
// === SCRIPT_SEPARATOR ===
|
|
68029
|
+
|
|
67781
68030
|
(function(){
|
|
67782
68031
|
async function loadCommentsform(
|
|
67783
68032
|
template,
|
|
@@ -68040,19 +68289,28 @@ window.CommentOnBack = CommentOnBack;
|
|
|
68040
68289
|
window.__unviredSdkScriptsLoading = false;
|
|
68041
68290
|
throw error;
|
|
68042
68291
|
}
|
|
68043
|
-
|
|
68044
|
-
|
|
68045
|
-
|
|
68046
|
-
|
|
68047
|
-
|
|
68048
|
-
|
|
68292
|
+
if (options.showComments) {
|
|
68293
|
+
for (let i = 1; i <= 2; i++) {
|
|
68294
|
+
if (scriptContents[i] && scriptContents[i].trim()) {
|
|
68295
|
+
const scriptElement = document.createElement("script");
|
|
68296
|
+
scriptElement.textContent = scriptContents[i];
|
|
68297
|
+
scriptElement.setAttribute("data-unvired-script", `recogito-${i}`);
|
|
68298
|
+
document.head.appendChild(scriptElement);
|
|
68299
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
68300
|
+
}
|
|
68049
68301
|
}
|
|
68302
|
+
} else {
|
|
68303
|
+
console.log("[SDK:10.3] \u26A1 Skipping Recogito (comments disabled, optimized load)");
|
|
68050
68304
|
}
|
|
68051
|
-
|
|
68305
|
+
const hasThemeOverrides = options.themeData && Object.keys(options.themeData).length > 0;
|
|
68306
|
+
if (hasThemeOverrides && scriptContents[3] && scriptContents[3].trim()) {
|
|
68052
68307
|
const lessScript = document.createElement("script");
|
|
68053
68308
|
lessScript.textContent = scriptContents[3];
|
|
68054
68309
|
lessScript.setAttribute("data-unvired-script", "less");
|
|
68055
68310
|
document.head.appendChild(lessScript);
|
|
68311
|
+
} else {
|
|
68312
|
+
console.log("[SDK:10.4] \u26A1 Skipping LESS.js (no theme overrides, optimized load)");
|
|
68313
|
+
window.less = window.less || { modifyVars: () => Promise.resolve() };
|
|
68056
68314
|
}
|
|
68057
68315
|
window.form = window.form || {};
|
|
68058
68316
|
window.platform = window.platform || {};
|
|
@@ -68075,6 +68333,9 @@ window.CommentOnBack = CommentOnBack;
|
|
|
68075
68333
|
scriptElement.textContent = scriptContent;
|
|
68076
68334
|
scriptElement.setAttribute("data-unvired-script", `script-${i}`);
|
|
68077
68335
|
document.head.appendChild(scriptElement);
|
|
68336
|
+
if (i % 5 === 0) {
|
|
68337
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
68338
|
+
}
|
|
68078
68339
|
}
|
|
68079
68340
|
}
|
|
68080
68341
|
window.__unviredSdkScriptsLoaded = true;
|
|
@@ -68300,7 +68561,7 @@ window.deleteAppDocument = async function(id) {
|
|
|
68300
68561
|
window.getAllDocuments = getAllDocuments;
|
|
68301
68562
|
window.hasDocuments = hasDocuments;
|
|
68302
68563
|
function getBuildVersion() {
|
|
68303
|
-
return "1.0.
|
|
68564
|
+
return "1.0.29";
|
|
68304
68565
|
}
|
|
68305
68566
|
export {
|
|
68306
68567
|
getBuildVersion,
|
package/package.json
CHANGED