Skip to content

Commit d8318d9

Browse files
committed
Modified JS for visualising the dropdown menus.
1 parent 45ead9f commit d8318d9

1 file changed

Lines changed: 107 additions & 60 deletions

File tree

  • FilmProductionManagementSystem/Wrap.FilmProductionManagementSystem.Web/wwwroot/js/production
Lines changed: 107 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
document.addEventListener('DOMContentLoaded', () => {
2+
// Optional debug fingerprint (can remove later)
3+
// console.log('production-create.js loaded', new Date().toISOString());
24

35
// ── Thumbnail preview ─────────────────────────────────────────
46
const thumbInput = document.getElementById('thumbnailInput');
@@ -7,81 +9,126 @@ document.addEventListener('DOMContentLoaded', () => {
79
const uploadLabel = document.getElementById('uploadLabel');
810
const clearBtn = document.getElementById('clearThumbnail');
911

10-
thumbInput?.addEventListener('change', e => {
11-
const file = e.target.files[0];
12-
if (!file) return;
13-
if (!file.type.startsWith('image/')) { alert('Please select an image file.'); thumbInput.value = ''; return; }
14-
if (file.size > 10 * 1024 * 1024) { alert('Max file size is 10 MB.'); thumbInput.value = ''; return; }
15-
const reader = new FileReader();
16-
reader.onload = ev => {
17-
thumbImg.src = ev.target.result;
18-
thumbPreview.style.display = '';
19-
uploadLabel.style.display = 'none';
20-
};
21-
reader.readAsDataURL(file);
22-
});
12+
if (thumbInput && thumbPreview && thumbImg && uploadLabel) {
13+
thumbInput.addEventListener('change', (e) => {
14+
const input = /** @type {HTMLInputElement} */ (e.target);
15+
const file = input.files && input.files[0];
16+
if (!file) return;
17+
18+
if (!file.type || !file.type.startsWith('image/')) {
19+
alert('Please select an image file.');
20+
input.value = '';
21+
return;
22+
}
2323

24-
clearBtn?.addEventListener('click', () => {
25-
thumbInput.value = '';
26-
thumbPreview.style.display = 'none';
27-
uploadLabel.style.display = '';
28-
});
24+
if (file.size > 10 * 1024 * 1024) {
25+
alert('Max file size is 10 MB.');
26+
input.value = '';
27+
return;
28+
}
29+
30+
const reader = new FileReader();
31+
reader.onload = (ev) => {
32+
const result = ev.target && ev.target.result;
33+
if (!result) return;
34+
35+
thumbImg.src = String(result);
36+
thumbPreview.style.display = '';
37+
uploadLabel.style.display = 'none';
38+
};
39+
reader.readAsDataURL(file);
40+
});
41+
42+
if (clearBtn) {
43+
clearBtn.addEventListener('click', () => {
44+
thumbInput.value = '';
45+
thumbPreview.style.display = 'none';
46+
uploadLabel.style.display = '';
47+
});
48+
}
49+
}
2950

3051
// ── Description counter ───────────────────────────────────────
3152
const descField = document.getElementById('descriptionTextarea');
3253
const descCounter = document.getElementById('descriptionCounter');
33-
descField?.addEventListener('input', () =>
34-
descCounter.textContent = descField.value.length);
54+
55+
if (descField && descCounter) {
56+
descField.addEventListener('input', () => {
57+
descCounter.textContent = String(descField.value.length);
58+
});
59+
// init if server pre-filled
60+
descCounter.textContent = String(descField.value.length);
61+
}
3562

3663
// ── Default start date ────────────────────────────────────────
3764
const startDate = document.querySelector('[name="StatusStartDate"]');
38-
if (startDate && !startDate.value)
65+
if (startDate && !startDate.value) {
66+
// YYYY-MM-DD (works for <input type="date">)
3967
startDate.value = new Date().toISOString().split('T')[0];
68+
}
4069

4170
// ── Cascading phase → status select ───────────────────────────
4271
const phaseSelect = document.getElementById('phaseSelect');
4372
const statusSelect = document.getElementById('statusTypeSelect');
44-
const optgroups = statusSelect.querySelectorAll('optgroup[data-phase]');
45-
46-
phaseSelect?.addEventListener('change', () => {
47-
const chosen = phaseSelect.value;
48-
49-
// Instead of toggling optgroup display (not reliable across browsers),
50-
// show/hide individual <option> elements. This ensures only options
51-
// relevant to the selected phase appear in the dropdown.
52-
const placeholder = statusSelect.querySelector('option[value=""]');
53-
54-
// Iterate optgroups and their options
55-
optgroups.forEach(og => {
56-
const match = og.dataset.phase === chosen;
57-
og.querySelectorAll('option').forEach(opt => {
58-
// Keep the placeholder option visible regardless
59-
if (opt.value === '') return;
60-
61-
// Use `hidden` and `disabled` so options are removed from the list
62-
// and cannot be selected in browsers that don't respect optgroup styling.
63-
opt.hidden = !match;
64-
opt.disabled = !match;
73+
74+
if (!phaseSelect || !statusSelect) {
75+
console.warn('CreateProduction: missing selects. phaseSelect/statusTypeSelect not found.');
76+
} else {
77+
const optgroups = statusSelect.querySelectorAll('optgroup[data-phase]');
78+
79+
const applyPhase = () => {
80+
const chosen = phaseSelect.value;
81+
const placeholder = statusSelect.querySelector('option[value=""]');
82+
83+
// If there are no optgroups, something is off in the markup
84+
if (!optgroups || optgroups.length === 0) {
85+
console.warn('CreateProduction: no optgroups[data-phase] found under statusTypeSelect.');
86+
}
87+
88+
optgroups.forEach((og) => {
89+
const match = og.dataset.phase === chosen;
90+
91+
// IMPORTANT: don't rely on optgroup display toggling; hide/disable options instead
92+
og.querySelectorAll('option').forEach((opt) => {
93+
if (opt.value === '') return; // keep placeholder visible
94+
opt.hidden = !match;
95+
opt.disabled = !match;
96+
});
6597
});
66-
});
6798

68-
if (!chosen) {
69-
// No phase chosen → disable status select and clear its value
70-
statusSelect.value = '';
71-
statusSelect.disabled = true;
72-
if (placeholder) placeholder.textContent = '— Select Phase first —';
73-
} else {
74-
statusSelect.disabled = false;
75-
statusSelect.value = ''; // reset to "please choose" state
76-
if (placeholder) placeholder.textContent = '— Select Status —';
77-
}
78-
});
99+
if (!chosen) {
100+
statusSelect.value = '';
101+
statusSelect.disabled = true;
102+
if (placeholder) placeholder.textContent = '— Select Phase first —';
103+
} else {
104+
statusSelect.disabled = false;
105+
statusSelect.value = ''; // reset selection on phase change
106+
if (placeholder) placeholder.textContent = '— Select Status —';
107+
}
108+
};
109+
110+
phaseSelect.addEventListener('change', applyPhase);
111+
112+
// Init state on load (handles browser autofill / preselected values)
113+
applyPhase();
114+
}
79115

80116
// ── Unsaved changes warning ───────────────────────────────────
81-
let dirty = false;
82-
document.querySelectorAll('#createProductionForm input, #createProductionForm textarea, #createProductionForm select')
83-
.forEach(el => el.addEventListener('change', () => dirty = true));
84-
window.addEventListener('beforeunload', e => { if (dirty) { e.preventDefault(); e.returnValue = ''; } });
85-
document.getElementById('createProductionForm')
86-
?.addEventListener('submit', () => dirty = false);
117+
const form = document.getElementById('createProductionForm');
118+
if (form) {
119+
let dirty = false;
120+
121+
form.querySelectorAll('input, textarea, select').forEach((el) => {
122+
el.addEventListener('change', () => (dirty = true));
123+
el.addEventListener('input', () => (dirty = true));
124+
});
125+
126+
window.addEventListener('beforeunload', (e) => {
127+
if (!dirty) return;
128+
e.preventDefault();
129+
e.returnValue = '';
130+
});
131+
132+
form.addEventListener('submit', () => (dirty = false));
133+
}
87134
});

0 commit comments

Comments
 (0)