Skip to content

Commit c1db081

Browse files
author
Reece Browne
committed
Handle resizing with input
1 parent 0ea2f43 commit c1db081

File tree

2 files changed

+144
-53
lines changed

2 files changed

+144
-53
lines changed

Diff for: src/main/resources/static/js/draggable-utils-form.js

+75-12
Original file line numberDiff line numberDiff line change
@@ -173,17 +173,7 @@ const DraggableUtils = {
173173
canvasContainer.setAttribute('data-bs-y', y);
174174
canvasContainer.setAttribute('data-angle', angle);
175175

176-
canvasContainer.addEventListener('click', () => {
177-
this.lastInteracted = canvasContainer;
178-
//this.showRotationControls(canvasContainer);
179-
const input = canvasContainer.querySelector('.form-input');
180-
window.latestId = input.getAttribute('id');
181-
window.populateEditForm(input.getAttribute('type'), {
182-
'id': input.getAttribute('id'), 'height': input.style.height, 'width': input.style.width,
183-
'backgroundPalette': input.getAttribute('backgroundColor'), 'textPalette': input.getAttribute('textColor'), fontSize: parseInt(input.style.fontSize) || "12",
184-
'font': input.style.fontFamily, 'dropdownValues': input.getAttribute("data-value"), 'value': input.value, 'optionListValues': input.getAttribute("data-value")
185-
});
186-
});
176+
187177
canvasContainer.appendChild(createdCanvas);
188178
this.boxDragContainer.appendChild(canvasContainer);
189179

@@ -210,6 +200,17 @@ const DraggableUtils = {
210200

211201
canvasContainer.style.width = `${boundingWidth + 2 * padding}px`;
212202
canvasContainer.style.height = `${boundingHeight + 2 * padding}px`;
203+
canvasContainer.addEventListener('click', () => {
204+
this.lastInteracted = canvasContainer;
205+
//this.showRotationControls(canvasContainer);
206+
const input = canvasContainer.querySelector('.form-input');
207+
window.latestId = input.getAttribute('id');
208+
window.populateEditForm(input.getAttribute('type'), {
209+
'id': input.getAttribute('id'), 'height': parseInt(canvasContainer.firstChild.style.height), 'width': parseInt(canvasContainer.firstChild.style.width),
210+
'backgroundPalette': input.getAttribute('backgroundColor'), 'textPalette': input.getAttribute('textColor'), fontSize: parseInt(input.style.fontSize) || "12",
211+
'font': input.style.fontFamily, 'dropdownValues': input.getAttribute("data-value"), 'value': input.value, 'optionListValues': input.getAttribute("data-value")
212+
});
213+
});
213214
createdCanvas.appendChild(element);
214215
// const rotationControls = document.getElementById('rotation-controls');
215216
// const rotationInput = document.getElementById('rotation-input');
@@ -220,7 +221,7 @@ const DraggableUtils = {
220221
this.lastInteracted = canvasContainer;
221222
window.latestId = element.getAttribute('id');
222223
window.populateEditForm(element.getAttribute('type'), {
223-
'id': element.getAttribute('id'), 'height': element.style.height, 'width': element.style.width,
224+
'id': element.getAttribute('id'), 'height': parseInt(element.style.height), 'width': parseInt(element.style.width),
224225
'backgroundPalette': element.getAttribute('backgroundColor'), 'textPalette': element.getAttribute('textColor'), fontSize: parseInt(element.style.fontSize) || "12",
225226
'font': element.style.fontFamily, 'dropdownValues': element.getAttribute("data-value"), 'value': element.value, 'optionListValues': element.getAttribute("data-value")
226227
});
@@ -890,3 +891,65 @@ const DraggableUtils = {
890891
document.addEventListener('DOMContentLoaded', () => {
891892
DraggableUtils.init();
892893
});
894+
895+
window.resize = (target, newWidth, newHeight, maintainRatioEnabled, change) => {
896+
const MAX_CHANGE = 60;
897+
const padding = this.padding || 60;
898+
let x = parseFloat(target.getAttribute('data-bs-x')) || 0;
899+
let y = parseFloat(target.getAttribute('data-bs-y')) || 0;
900+
newWidth = parseInt(newWidth);
901+
newHeight = parseInt(newHeight);
902+
const canvas = target.querySelector('.display-canvas');
903+
if (!canvas) return;
904+
905+
const originalWidth = parseFloat(canvas.style.width) || parseInt(canvas.width);
906+
const originalHeight = parseFloat(canvas.style.height) || parseInt(canvas.height);
907+
const angle = parseFloat(target.getAttribute('data-angle')) || 0;
908+
909+
const aspectRatio = originalWidth / originalHeight;
910+
911+
if (maintainRatioEnabled) {
912+
if (change === "width") {
913+
newHeight = newWidth / aspectRatio;
914+
} else {
915+
newWidth = newHeight * aspectRatio;
916+
}
917+
}
918+
919+
const widthChange = newWidth - originalWidth;
920+
const heightChange = newHeight - originalHeight;
921+
922+
if (Math.abs(widthChange) > MAX_CHANGE || Math.abs(heightChange) > MAX_CHANGE) {
923+
const scale = MAX_CHANGE / Math.max(Math.abs(widthChange), Math.abs(heightChange));
924+
newWidth = originalWidth + widthChange * scale;
925+
newHeight = originalHeight + heightChange * scale;
926+
}
927+
928+
const cosAngle = Math.abs(Math.cos(angle));
929+
const sinAngle = Math.abs(Math.sin(angle));
930+
const boundingWidth = newWidth * cosAngle + newHeight * sinAngle;
931+
const boundingHeight = newWidth * sinAngle + newHeight * cosAngle;
932+
933+
934+
// Apply width and height
935+
target.style.width = `${boundingWidth + 2 * padding}px`;
936+
target.style.height = `${boundingHeight + 2 * padding}px`;
937+
938+
// Update inner canvas
939+
canvas.style.width = `${newWidth}px`;
940+
canvas.style.height = `${newHeight}px`;
941+
//canvas.style.transform = `translate(${(boundingWidth - newWidth) / 2}px, ${(boundingHeight - newHeight) / 2}px) rotate(${angle}rad)`;
942+
943+
// Update form input inside canvas
944+
const input = canvas.querySelector('.form-input');
945+
if (input) {
946+
input.style.width = `${newWidth}px`;
947+
input.style.height = `${newHeight}px`;
948+
}
949+
950+
window.populateEditForm(input.getAttribute('type'), {
951+
'id': input.getAttribute('id'), 'height': newHeight, 'width': newWidth,
952+
'backgroundPalette': input.getAttribute('backgroundColor'), 'textPalette': input.getAttribute('textColor'), fontSize: parseInt(input.style.fontSize) || "12",
953+
'font': input.style.fontFamily, 'dropdownValues': input.getAttribute("data-value"), 'value': input.value, 'optionListValues': input.getAttribute("data-value")
954+
});
955+
}

Diff for: src/main/resources/static/js/pages/forms.js

+69-41
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ const textConfig = {
77
height: '30px',
88
fields: [
99
{ id: 'id', label: 'Text ID', type: 'text', placeholder: 'Enter ID' },
10+
{ id: 'height', label: 'Height(px)', type: 'number' },
11+
{ id: 'width', label: 'Width(px)', type: 'number' },
1012
{ id: 'value', label: 'Text Value', type: 'text', placeholder: 'Enter Value' },
1113
{ id: 'color', label: 'Text Color', type: 'color', value: '#000000' }
1214
]
@@ -17,6 +19,8 @@ const checkboxConfig = {
1719
height: '20px',
1820
fields: [
1921
{ id: 'id', label: 'Check box ID', type: 'text', placeholder: 'Enter ID' },
22+
{ id: 'height', label: 'Height(px)', type: 'number' },
23+
{ id: 'width', label: 'Width(px)', type: 'number' },
2024
]
2125
};
2226
const dropdownConfig = {
@@ -26,6 +30,8 @@ const dropdownConfig = {
2630
fields: [
2731
{ id: 'id', label: 'Dropdown ID', type: 'text', placeholder: 'Enter ID' },
2832
{ id: 'dropdownValues', label: 'Dropdown Options', type: 'text', placeholder: 'Comma-separated values' },
33+
{ id: 'height', label: 'Height(px)', type: 'number' },
34+
{ id: 'width', label: 'Width(px)', type: 'number' },
2935
{ id: 'font', label: 'Font', type: 'select', options: ['Courier', 'Helvetica', 'TimesRoman'] },
3036
{ id: 'fontSize', label: 'Font Size', type: 'number', value: '12' },
3137
{ id: 'backgroundPalette', label: 'Background Color', type: 'color', value: '#ffffff' },
@@ -39,6 +45,8 @@ const optionListConfig = {
3945
fields: [
4046
{ id: 'id', label: 'Option List ID', type: 'text', placeholder: 'Enter ID' },
4147
{ id: 'optionListValues', label: 'Option List Values', type: 'text', placeholder: 'Comma-separated values' },
48+
{ id: 'height', label: 'Height(px)', type: 'number' },
49+
{ id: 'width', label: 'Width(px)', type: 'number' },
4250
{ id: 'fontSize', label: 'Font Size', type: 'number', value: '12' },
4351
{ id: 'backgroundPalette', label: 'Background Color', type: 'color', value: '#ffffff' },
4452
{ id: 'textPalette', label: 'Text Color', type: 'color', value: '#000000' }
@@ -51,6 +59,8 @@ const radioButtonConfig = {
5159
height: '20px',
5260
fields: [
5361
{ id: 'id', label: 'Radio ID', type: 'text', placeholder: 'Enter ID' },
62+
{ id: 'height', label: 'Height(px)', type: 'number' },
63+
{ id: 'width', label: 'Width(px)', type: 'number' },
5464
]
5565
};
5666
const textBoxConfig = {
@@ -60,6 +70,8 @@ const textBoxConfig = {
6070
fields: [
6171
{ id: 'id', label: 'Text Box ID', type: 'text', placeholder: 'Enter ID' },
6272
{ id: 'value', label: 'Placeholder', type: 'text', placeholder: '' },
73+
{ id: 'height', label: 'Height(px)', type: 'number' },
74+
{ id: 'width', label: 'Width(px)', type: 'number' },
6375
{ id: 'fontSize', label: 'Font Size', type: 'number', value: '12' },
6476
{ id: 'backgroundPalette', label: 'Background Color', type: 'color', value: '#ffffff' },
6577
{ id: 'textPalette', label: 'Text Color', type: 'color', value: '#000000' }
@@ -243,49 +255,65 @@ function validateUniqueId(id) {
243255
return !document.getElementById(id);
244256
}
245257

246-
247258
function attachDynamicListeners(fields) {
248-
fields.forEach(field => {
249-
document.addEventListener("change", function (event) {
250-
if (event.target && event.target.id === field.id) {
251-
if (field.type === 'color') {
252-
document.getElementById(`${field.id}Label`).style.setProperty('--palette-color', event.target.value);
253-
}
254-
if (window.latestId) {
255-
const targetElement = document.getElementById(window.latestId);
256-
if (field.type === 'color') {
257-
if (field.id.toLowerCase().includes('background')) {
258-
targetElement.style.background = event.target.value;
259-
targetElement.setAttribute('backgroundColor', event.target.value)
260-
} else {
261-
targetElement.style.color = event.target.value;
262-
targetElement.setAttribute('textColor', event.target.value)
263-
}
264-
} else if (field.id === 'fontSize') {
265-
targetElement.style.fontSize = event.target.value + "px";
266-
} else if (field.id === 'font') {
267-
targetElement.style.fontFamily = event.target.value;
268-
} else if (field.id === 'value') {
269-
targetElement.value = event.target.value;
270-
} else if (field.id === 'id') {
271-
targetElement.id = event.target.value;
272-
targetElement.name = event.target.value;
273-
} else if (field.id === 'dropdownValues') {
274-
while (targetElement?.firstChild) {
275-
targetElement.removeChild(targetElement.firstChild);
276-
}
277-
const values = event.target.value.split(',').map(v => v.trim());
278-
values.forEach(value => {
279-
const option = document.createElement("option");
280-
option.value = value;
281-
option.textContent = value;
282-
targetElement.appendChild(option);
283-
});
284-
targetElement.setAttribute("data-value", values)
259+
document.addEventListener("change", function (event) {
260+
const target = event.target;
261+
const field = fields.find(f => f.id === target.id); // Match the field
262+
263+
if (!field) return; // Ignore irrelevant changes
264+
265+
if (field.type === 'color') {
266+
document.getElementById(`${field.id}Label`).style.setProperty('--palette-color', target.value);
267+
}
268+
269+
if (window.latestId) {
270+
const targetElement = document.getElementById(window.latestId);
271+
if (!targetElement) return;
272+
273+
switch (field.id) {
274+
case 'backgroundColor':
275+
targetElement.style.background = target.value;
276+
targetElement.setAttribute('backgroundColor', target.value);
277+
break;
278+
case 'textColor':
279+
targetElement.style.color = target.value;
280+
targetElement.setAttribute('textColor', target.value);
281+
break;
282+
case 'height':
283+
window.resize(targetElement.parentElement.parentElement, document.getElementById('width').value, target.value, true, "height");
284+
break;
285+
case 'width':
286+
window.resize(targetElement.parentElement.parentElement, target.value, document.getElementById('height').value, true, "width");
287+
break;
288+
case 'fontSize':
289+
targetElement.style.fontSize = target.value + "px";
290+
break;
291+
case 'font':
292+
targetElement.style.fontFamily = target.value;
293+
break;
294+
case 'value':
295+
targetElement.value = target.value;
296+
break;
297+
case 'id':
298+
targetElement.name = target.value;
299+
targetElement.id = target.value;
300+
window.latestId = target.value;
301+
break;
302+
case 'dropdownValues':
303+
while (targetElement.firstChild) {
304+
targetElement.removeChild(targetElement.firstChild);
285305
}
286-
}
306+
const values = target.value.split(',').map(v => v.trim());
307+
values.forEach(value => {
308+
const option = document.createElement("option");
309+
option.value = value;
310+
option.textContent = value;
311+
targetElement.appendChild(option);
312+
});
313+
targetElement.setAttribute("data-value", values);
314+
break;
287315
}
288-
});
316+
}
289317
});
290318
}
291319

@@ -392,7 +420,7 @@ document.addEventListener("DOMContentLoaded", function () {
392420
Object.keys(existingValues).forEach(key => {
393421
const input = document.getElementById(key);
394422
if (input) {
395-
input.value = existingValues[key];
423+
input.defaultValue = existingValues[key];
396424
if (input.type === "color") {
397425
document.getElementById(`${input.id}Label`).style.setProperty('--palette-color', existingValues[key]);
398426
}

0 commit comments

Comments
 (0)