Skip to content

Commit a9586b8

Browse files
author
Reece Browne
committed
Validation and bug fixes
1 parent d263e85 commit a9586b8

File tree

3 files changed

+105
-72
lines changed

3 files changed

+105
-72
lines changed

src/main/resources/static/js/draggable-utils-form.js

+53-39
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ const DraggableUtils = {
180180
window.latestId = input.getAttribute('id');
181181
window.populateEditForm(input.getAttribute('type'), {
182182
'id': input.getAttribute('id'), 'height': input.style.height, 'width': input.style.width,
183-
'backgroundPalette': input.style.backgroundColor, 'textPalette': input.style.color, fontSize: parseInt(input.style.fontSize)
183+
'backgroundPalette': input.getAttribute('backgroundColor'), 'textPalette': input.getAttribute('textColor'), fontSize: parseInt(input.style.fontSize),
184+
'font': input.style.fontFamily, 'dropdownValues': input.getAttribute("data-value"), 'value': input.value, 'optionListValues': input.getAttribute("data-value")
184185
});
185186
});
186187
canvasContainer.appendChild(createdCanvas);
@@ -217,6 +218,12 @@ const DraggableUtils = {
217218
// rotationInput.addEventListener('input', this.handleRotationInputChange);
218219
//this.showRotationControls(canvasContainer);
219220
this.lastInteracted = canvasContainer;
221+
window.latestId = element.getAttribute('id');
222+
window.populateEditForm(element.getAttribute('type'), {
223+
'id': element.getAttribute('id'), 'height': element.style.height, 'width': element.style.width,
224+
'backgroundPalette': element.getAttribute('backgroundColor'), 'textPalette': element.getAttribute('textColor'), fontSize: parseInt(element.style.fontSize),
225+
'font': element.style.fontFamily, 'dropdownValues': element.getAttribute("data-value"), 'value': element.value, 'optionListValues': element.getAttribute("data-value")
226+
});
220227
resolve(canvasContainer);
221228
});
222229
},
@@ -682,18 +689,20 @@ const DraggableUtils = {
682689
const elementType = input.getAttribute('type');
683690
const fieldKey = input.getAttribute('name');
684691
const fieldStyle = input.getAttribute('style');
685-
const fontMatch = fieldStyle.match(/font-size:\s*([\w-]+)/);
686-
const fontSize = parseInt(fontMatch ? fontMatch[1] : '12px');
692+
const fontSizeMatch = fieldStyle.match(/font-size:\s*([\w-]+)/);
693+
const fontSize = parseInt(fontSizeMatch ? fontSizeMatch[1] : '12');
694+
const fontFamilyMatch = fieldStyle.match(/font-family:\s*([^;]+)/);
695+
const fontFamily = fontFamilyMatch ? fontFamilyMatch[1].trim().replace(/['"]/g, '') : 'Helvetica';
687696

688-
const font = await pdfDocModified.embedFont(PDFLib.StandardFonts.Helvetica);
697+
const embeddedFont = await pdfDocModified.embedFont(PDFLib.StandardFonts[fontFamily]);
689698
const backgroundColor = rgbStringToPdfLib(input.style.backgroundColor) || PDFLib.rgb(1, 1, 1);
690699
const textColor = rgbStringToPdfLib(input.style.color) || PDFLib.rgb(0, 0, 0);
691700
const translatedPositions = this.rescaleForPage(
692701
page,
693702
draggableData,
694703
offsetWidth,
695704
offsetHeight,
696-
font,
705+
embeddedFont,
697706
fontSize,
698707
backgroundColor,
699708
textColor
@@ -706,41 +715,46 @@ const DraggableUtils = {
706715
const [r, g, b] = match.map((num) => parseInt(num) / 255);
707716
return PDFLib.rgb(r, g, b);
708717
}
709-
710-
if (elementType === 'checkbox') {
711-
// Handle Checkboxes
712-
const field = form.createCheckBox(fieldKey);
713-
714-
field.addToPage(page, translatedPositions);
715-
} else if (elementType === 'radio') {
716-
// Handle Radio Buttons
717-
const buttonValue = input.getAttribute('buttonValue');
718-
var radioGroup = radioGroups.get(fieldKey);
719-
if (!radioGroup) {
720-
radioGroup = form.createRadioGroup(fieldKey);
721-
radioGroups.set(fieldKey, radioGroup);
718+
try {
719+
if (elementType === 'checkbox') {
720+
// Handle Checkboxes
721+
const field = form.createCheckBox(fieldKey);
722+
723+
field.addToPage(page, translatedPositions);
724+
} else if (elementType === 'radio') {
725+
// Handle Radio Buttons
726+
const buttonValue = input.getAttribute('buttonValue');
727+
var radioGroup = radioGroups.get(fieldKey);
728+
if (!radioGroup) {
729+
radioGroup = form.createRadioGroup(fieldKey);
730+
radioGroups.set(fieldKey, radioGroup);
731+
}
732+
radioGroup.addOptionToPage(buttonValue, page, translatedPositions);
733+
} else if (elementType === 'dropdown') {
734+
// Handle Dropdowns
735+
const fieldValues = input.getAttribute('data-value')?.split(',').map(v => v.trim());
736+
const field = form.createDropdown(fieldKey);
737+
field.addOptions(fieldValues);
738+
field.addToPage(page, translatedPositions);
739+
field.setFontSize(fontSize);
740+
field.updateAppearances(embeddedFont);
741+
} else if (elementType === 'optionList') {
742+
// Handle Multi-Select Option List
743+
const fieldValues = JSON.parse(input.getAttribute('values'));
744+
const field = form.createOptionList(fieldKey);
745+
field.addOptions(fieldValues);
746+
field.addToPage(page, translatedPositions);
747+
field.updateAppearances(embeddedFont);
748+
field.setFontSize(fontSize);
749+
} else if (elementType === 'textarea' || elementType === 'text') {
750+
// Handle Text Fields (Single-line or Multi-line)
751+
const field = form.createTextField(fieldKey);
752+
field.addToPage(page, translatedPositions);
722753
}
723-
radioGroup.addOptionToPage(buttonValue, page, translatedPositions);
724-
} else if (elementType === 'dropdown') {
725-
// Handle Dropdowns
726-
const fieldValues = JSON.parse(input.getAttribute('values') || '[]');
727-
const field = form.createDropdown(fieldKey);
728-
field.addOptions(fieldValues);
729-
field.addToPage(page, translatedPositions);
730-
field.updateAppearances(font);
731-
field.setFontSize(fontSize);
732-
} else if (elementType === 'optionList') {
733-
// Handle Multi-Select Option List
734-
const fieldValues = JSON.parse(input.getAttribute('values'));
735-
const field = form.createOptionList(fieldKey);
736-
field.addOptions(fieldValues);
737-
field.addToPage(page, translatedPositions);
738-
field.updateAppearances(font);
739-
field.setFontSize(fontSize);
740-
} else if (elementType === 'textarea' || elementType === 'text') {
741-
// Handle Text Fields (Single-line or Multi-line)
742-
const field = form.createTextField(fieldKey);
743-
field.addToPage(page, translatedPositions);
754+
} catch (err) {
755+
alert(err);
756+
this.loadPageContents();
757+
return;
744758
}
745759
}
746760
}

src/main/resources/static/js/pages/forms.js

+46-24
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const dropdownConfig = {
2626
fields: [
2727
{ id: 'id', label: 'Dropdown ID', type: 'text', placeholder: 'Enter ID' },
2828
{ id: 'dropdownValues', label: 'Dropdown Options', type: 'text', placeholder: 'Comma-separated values' },
29-
{ id: 'font', label: 'Font', type: 'select', options: ['Arial', 'Verdana', 'Times New Roman'] },
29+
{ id: 'font', label: 'Font', type: 'select', options: ['Courier', 'Helvetica', 'TimesRoman'] },
3030
{ id: 'fontSize', label: 'Font Size', type: 'number', value: '12' },
3131
{ id: 'backgroundPalette', label: 'Background Color', type: 'color', value: '#ffffff' },
3232
{ id: 'textPalette', label: 'Text Color', type: 'color', value: '#000000' }
@@ -119,7 +119,7 @@ document.querySelector('input[name=pdf-upload]').addEventListener('change', asyn
119119

120120
document.addEventListener('DOMContentLoaded', () => {
121121
document.querySelectorAll('.show-on-file-selected').forEach((el) => {
122-
//el.style.cssText = 'display:none !important';
122+
el.style.cssText = 'display:none !important';
123123
});
124124
document.addEventListener('keydown', (e) => {
125125
if (e.key === 'Delete') {
@@ -160,31 +160,54 @@ window.createForm = (configString) => {
160160
input.appendChild(option);
161161
});
162162
} else if (field.type === 'color') {
163-
input = document.createElement('input');
163+
// Create label
164+
const label = document.createElement('label');
165+
label.classList.add('form-check-label');
166+
label.setAttribute('for', field.id);
167+
label.textContent = field.label;
168+
169+
// Create color input
170+
const input = document.createElement('input');
164171
input.classList.add('palette');
165172
input.setAttribute('type', 'color');
166173
input.setAttribute('id', field.id);
167174
input.setAttribute('name', field.id);
168175
input.setAttribute('value', field.value || '#000000');
169176

177+
// Create color picker button
170178
const paletteContainer = document.createElement('button');
171179
paletteContainer.classList.add('colour-picker', 'btn-primary');
172180
paletteContainer.setAttribute('id', `${field.id}Container`);
173181
paletteContainer.setAttribute('th:title', '#{redact.colourPicker}');
174182

183+
// Create label for color picker
175184
const paletteLabel = document.createElement('label');
176185
paletteLabel.setAttribute('id', `${field.id}Label`);
177186
paletteLabel.setAttribute('for', field.id);
178187
paletteLabel.classList.add('material-symbols-rounded', 'palette-color', 'text-center');
179188
paletteLabel.style.setProperty('--palette-color', field.value || '#000000');
180189
paletteLabel.textContent = 'palette';
181190

191+
// Append input to label
182192
paletteLabel.appendChild(input);
183193
paletteContainer.appendChild(paletteLabel);
184-
formContainer.appendChild(label);
185-
formContainer.appendChild(paletteContainer);
194+
195+
// Find or create the color group flex container
196+
let colorGroup = formContainer.querySelector('.color-group');
197+
if (!colorGroup) {
198+
colorGroup = document.createElement('div');
199+
colorGroup.classList.add('color-group');
200+
colorGroup.style.display = 'flex';
201+
colorGroup.style.gap = '10px'; // Space between color inputs
202+
colorGroup.style.marginTop = '10px'; // Space above first color input
203+
formContainer.appendChild(colorGroup);
204+
}
205+
colorGroup.appendChild(label);
206+
colorGroup.appendChild(paletteContainer);
207+
186208
return;
187-
} else {
209+
}
210+
else {
188211
input = document.createElement('input');
189212
input.classList.add('form-control');
190213
input.setAttribute('type', field.type);
@@ -225,7 +248,6 @@ function validateUniqueId(id) {
225248
function attachDynamicListeners(fields) {
226249
fields.forEach(field => {
227250
document.addEventListener("change", function (event) {
228-
console.log("hit");
229251
if (event.target && event.target.id === field.id) {
230252
if (field.type === 'color') {
231253
document.getElementById(`${field.id}Label`).style.setProperty('--palette-color', event.target.value);
@@ -235,27 +257,32 @@ function attachDynamicListeners(fields) {
235257
if (field.type === 'color') {
236258
if (field.id.toLowerCase().includes('background')) {
237259
targetElement.style.background = event.target.value;
260+
targetElement.setAttribute('backgroundColor', event.target.value)
238261
} else {
239262
targetElement.style.color = event.target.value;
263+
targetElement.setAttribute('textColor', event.target.value)
240264
}
241265
} else if (field.id === 'fontSize') {
242266
targetElement.style.fontSize = event.target.value + "px";
267+
} else if (field.id === 'font') {
268+
targetElement.style.fontFamily = event.target.value;
243269
} else if (field.id === 'value') {
244270
targetElement.value = event.target.value;
245271
} else if (field.id === 'id') {
246272
targetElement.id = event.target.value;
273+
targetElement.name = event.target.value;
247274
} else if (field.id === 'dropdownValues') {
248-
while (targetElement.firstChild) {
275+
while (targetElement?.firstChild) {
249276
targetElement.removeChild(targetElement.firstChild);
250277
}
251-
252278
const values = event.target.value.split(',').map(v => v.trim());
253279
values.forEach(value => {
254280
const option = document.createElement("option");
255281
option.value = value;
256282
option.textContent = value;
257283
targetElement.appendChild(option);
258284
});
285+
targetElement.setAttribute("data-value", values)
259286
}
260287
}
261288
}
@@ -279,6 +306,8 @@ function addDraggableFromForm(config) {
279306
element.setAttribute('id', id);
280307
element.setAttribute('name', id);
281308
element.setAttribute('type', config.type);
309+
element.style.fontFamily = 'Helvetica'
310+
element.style.fontSize = '12';
282311
element.classList.add('form-input')
283312

284313
if (config.styles) {
@@ -288,7 +317,6 @@ function addDraggableFromForm(config) {
288317
}
289318

290319
DraggableUtils.addDraggableElement(element, true);
291-
showTab(0);
292320
}
293321

294322
document.getElementById('save').addEventListener('click', function () {
@@ -332,21 +360,14 @@ document.getElementById('save').addEventListener('click', function () {
332360
});
333361
});
334362

335-
const showTab = (index) => {
336-
const tabs = document.querySelectorAll(".tab-container");
337-
tabs.forEach((tab, i) => {
338-
// tab.style.display = i === index ? "block" : "none";
339-
});
340-
}
363+
341364
document.addEventListener("DOMContentLoaded", function () {
342-
const tabs = document.querySelectorAll(".tab-container");
343365
const addNewFormContainer = document.getElementById("addNewForm");
344366
const formOptionsContainer = document.getElementById("formOptions");
345367
function createDropdown() {
346368
const dropdown = document.createElement("select");
347369
dropdown.classList.add("form-control");
348370
dropdown.id = "formTypeSelector";
349-
350371
const defaultOption = document.createElement("option");
351372
defaultOption.textContent = "Select Form Type";
352373
defaultOption.value = "";
@@ -360,6 +381,9 @@ document.addEventListener("DOMContentLoaded", function () {
360381
});
361382

362383
addNewFormContainer.prepend(dropdown);
384+
dropdown.addEventListener('change', async (event) => {
385+
// populateEditForm(event.target.value, { id: generateUniqueId(event.target.value) });
386+
})
363387
}
364388

365389
window.populateEditForm = (type, existingValues) => {
@@ -370,16 +394,14 @@ document.addEventListener("DOMContentLoaded", function () {
370394
const input = document.getElementById(key);
371395
if (input) {
372396
input.value = existingValues[key];
397+
if (input.type === "color") {
398+
document.getElementById(`${input.id}Label`).style.setProperty('--palette-color', existingValues[key]);
399+
}
373400
}
401+
374402
});
375403

376-
showTab(0);
377404
}
378405

379-
document.getElementById("save").addEventListener("click", function () {
380-
showTab(0);
381-
});
382-
383406
createDropdown();
384-
showTab(1);
385407
});

src/main/resources/templates/forms.html

+6-9
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,14 @@
4141
th:replace="~{fragments/common :: fileSelector(name='pdf-upload', multipleInputsForSingleRequest=false, disableMultipleFiles=true, accept='application/pdf')}">
4242
</div>
4343
<script type="module" th:src="@{'/pdfjs-legacy/pdf.mjs'}"></script>
44-
<div class="tab-group show-on-file-selected">
45-
<div class="tab-container" th:data-title="#{add-elements.editForm}">
46-
<div id="editForm"></div>
47-
<div id="formOptions"></div>
48-
</div>
49-
<div class="tab-container" th:data-title="#{add-elements.addNew}">
50-
<div id="addNewForm"></div>
51-
<div class="margin-auto-parent">
52-
<button id="save" class="btn btn-outline-success mt-2 margin-center" th:text="#{sign.add}"></button>
44+
<div class="show-on-file-selected">
45+
<div style="display: flex;">
46+
<div class="margin-auto-parent" style="margin-bottom: 1rem;margin-top: 0.5rem;">
47+
<div style="margin-right: 2rem; width:100%" id="addNewForm"></div>
48+
<button id="save" class="btn btn-outline-success" th:text="#{sign.add}"></button>
5349
</div>
5450
</div>
51+
<div id="formOptions"></div>
5552
</div>
5653
<!-- draggables box -->
5754
<div class="draggable-buttons-box ignore-rtl">

0 commit comments

Comments
 (0)