forked from UKSOURCE/cms.lams
Adding backend of Student Support, Contact, Request
This commit is contained in:
@@ -0,0 +1,481 @@
|
||||
<div class="container">
|
||||
<div class="d-flex justify-content-between align-items-center mt-4 mb-4 flex-wrap gap-2">
|
||||
<div>
|
||||
<h1 class="h3 mb-0" style="color: var(--primary-dark);"><%= title %></h1>
|
||||
<p class="text-muted mb-0">Edit the public Request Information page: hero, value props, and form configuration.</p>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<% if (frontendUrl) { %>
|
||||
<a href="<%= frontendUrl %>/request" class="btn btn-outline-primary" target="_blank" rel="noopener">
|
||||
<i class="fas fa-external-link-alt me-2"></i>View Request Info Page
|
||||
</a>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="POST" class="content-with-fixed-buttons" id="requestInfoForm" action="/admin/request-info/update">
|
||||
<input type="hidden" name="metadata" id="metadataJson">
|
||||
<input type="hidden" name="hero" id="heroJson">
|
||||
<input type="hidden" name="form" id="formJson">
|
||||
|
||||
<div class="card shadow-sm border-0 mb-4">
|
||||
<div class="card-header bg-white border-bottom">
|
||||
<ul class="nav nav-tabs card-header-tabs" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-bs-toggle="tab" href="#tab-meta" role="tab">
|
||||
<i class="fas fa-tags me-2"></i>Metadata
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-bs-toggle="tab" href="#tab-hero" role="tab">
|
||||
<i class="fas fa-star me-2"></i>Hero
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-bs-toggle="tab" href="#tab-form" role="tab">
|
||||
<i class="fas fa-wpforms me-2"></i>Form Config
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="tab-content">
|
||||
|
||||
<%# ── TAB: Metadata ──────────────────────────────────────────── %>
|
||||
<div class="tab-pane fade show active" id="tab-meta" role="tabpanel">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-medium" for="metaTitle">Title (SEO)</label>
|
||||
<input type="text" class="form-control" id="metaTitle" value="<%= data.metadata?.title || '' %>">
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-medium" for="metaDescription">Description (SEO)</label>
|
||||
<textarea class="form-control" id="metaDescription" rows="3"><%= data.metadata?.description || '' %></textarea>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-medium" for="metaKeywords">Keywords (SEO)</label>
|
||||
<input type="text" class="form-control" id="metaKeywords" value="<%= data.metadata?.keywords || '' %>" placeholder="keyword1, keyword2, ...">
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-medium" for="metaOgImage">OG Image path</label>
|
||||
<input type="text" class="form-control" id="metaOgImage" value="<%= data.metadata?.ogImage || '' %>" placeholder="/images/og-request.jpg">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%# ── TAB: Hero ──────────────────────────────────────────────── %>
|
||||
<div class="tab-pane fade" id="tab-hero" role="tabpanel">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-medium" for="heroBadge">Badge</label>
|
||||
<input type="text" class="form-control" id="heroBadge" value="<%= data.hero?.badge || '' %>">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-medium" for="heroTitleHighlight">Title — Highlight word</label>
|
||||
<input type="text" class="form-control" id="heroTitleHighlight" value="<%= data.hero?.titleHighlight || '' %>">
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-medium" for="heroTitleMain">Title — Main text (before highlight)</label>
|
||||
<input type="text" class="form-control" id="heroTitleMain" value="<%= data.hero?.titleMain || '' %>" placeholder="Take the Next Step in Your ">
|
||||
<small class="text-muted">The highlight word will appear after this text, rendered in accent colour on the frontend.</small>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-medium" for="heroDescription">Description</label>
|
||||
<textarea class="form-control" id="heroDescription" rows="3"><%= data.hero?.description || '' %></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%# Value Props %>
|
||||
<hr class="my-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h6 class="mb-0 fw-semibold">Value Props</h6>
|
||||
<button type="button" class="btn btn-sm btn-primary" id="addValuePropBtn">
|
||||
<i class="fas fa-plus me-1"></i>Add value prop
|
||||
</button>
|
||||
</div>
|
||||
<div id="valuePropsContainer" class="vstack gap-3">
|
||||
<% const vps = data.hero?.valueProps || []; %>
|
||||
<% vps.forEach(function(vp, index) { %>
|
||||
<div class="card vp-row border">
|
||||
<div class="card-body">
|
||||
<div class="row g-2 align-items-end">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label small">Icon</label>
|
||||
<select class="form-select vp-icon-select">
|
||||
<% iconOptions.forEach(function(opt) { %>
|
||||
<option value="<%= opt.value %>" <%= (vp.icon === opt.value) ? 'selected' : '' %>><%= opt.label %></option>
|
||||
<% }); %>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<label class="form-label small">Title</label>
|
||||
<input type="text" class="form-control vp-title" value="<%= vp.title || '' %>">
|
||||
</div>
|
||||
<div class="col-md-1 d-flex align-items-end justify-content-end">
|
||||
<button type="button" class="btn btn-outline-danger btn-sm remove-vp"><i class="fas fa-trash"></i></button>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="form-label small">Description</label>
|
||||
<textarea class="form-control vp-description" rows="2"><%= vp.description || '' %></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }); %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%# ── TAB: Form Config ───────────────────────────────────────── %>
|
||||
<div class="tab-pane fade" id="tab-form" role="tabpanel">
|
||||
<% const fm = data.form || {}; const fld = fm.fields || {}; %>
|
||||
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-medium" for="formHeading">Form Heading</label>
|
||||
<input type="text" class="form-control" id="formHeading" value="<%= fm.heading || '' %>">
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-medium" for="formDescription">Form Description</label>
|
||||
<textarea class="form-control" id="formDescription" rows="2"><%= fm.description || '' %></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6 class="text-uppercase text-muted small mb-3">Fields</h6>
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">First Name — label</label>
|
||||
<input type="text" class="form-control" id="fld_firstName_label" value="<%= fld.firstName?.label || '' %>">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">First Name — placeholder</label>
|
||||
<input type="text" class="form-control" id="fld_firstName_ph" value="<%= fld.firstName?.placeholder || '' %>">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">Last Name — label</label>
|
||||
<input type="text" class="form-control" id="fld_lastName_label" value="<%= fld.lastName?.label || '' %>">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">Last Name — placeholder</label>
|
||||
<input type="text" class="form-control" id="fld_lastName_ph" value="<%= fld.lastName?.placeholder || '' %>">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">Email — label</label>
|
||||
<input type="text" class="form-control" id="fld_email_label" value="<%= fld.email?.label || '' %>">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">Email — placeholder</label>
|
||||
<input type="text" class="form-control" id="fld_email_ph" value="<%= fld.email?.placeholder || '' %>">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">Phone — label</label>
|
||||
<input type="text" class="form-control" id="fld_phone_label" value="<%= fld.phone?.label || '' %>">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">Phone — placeholder</label>
|
||||
<input type="text" class="form-control" id="fld_phone_ph" value="<%= fld.phone?.placeholder || '' %>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6 class="text-uppercase text-muted small mb-3">Program of Interest (dropdown options)</h6>
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">Field label</label>
|
||||
<input type="text" class="form-control" id="fld_program_label" value="<%= fld.program?.label || '' %>">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">Placeholder</label>
|
||||
<input type="text" class="form-control" id="fld_program_ph" value="<%= fld.program?.placeholder || '' %>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<span class="small fw-medium">Program options</span>
|
||||
<button type="button" class="btn btn-sm btn-secondary" id="addProgramBtn">
|
||||
<i class="fas fa-plus me-1"></i>Add option
|
||||
</button>
|
||||
</div>
|
||||
<div id="programOptionsContainer" class="vstack gap-2 mb-4">
|
||||
<% (fld.program?.options || []).forEach(function(opt) { %>
|
||||
<div class="input-group program-opt-row">
|
||||
<input type="text" class="form-control prog-label" placeholder="Label" value="<%= opt.label || '' %>">
|
||||
<input type="text" class="form-control prog-value" placeholder="Value (e.g. bs-cs)" value="<%= opt.value || '' %>">
|
||||
<button type="button" class="btn btn-outline-danger remove-prog-opt"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
<% }); %>
|
||||
</div>
|
||||
|
||||
<h6 class="text-uppercase text-muted small mb-3">Start Timeline (dropdown options)</h6>
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-12">
|
||||
<label class="form-label small">Field label</label>
|
||||
<input type="text" class="form-control" id="fld_timeline_label" value="<%= fld.timeline?.label || '' %>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<span class="small fw-medium">Timeline options</span>
|
||||
<button type="button" class="btn btn-sm btn-secondary" id="addTimelineBtn">
|
||||
<i class="fas fa-plus me-1"></i>Add option
|
||||
</button>
|
||||
</div>
|
||||
<div id="timelineOptionsContainer" class="vstack gap-2 mb-4">
|
||||
<% (fld.timeline?.options || []).forEach(function(opt) { %>
|
||||
<div class="input-group timeline-opt-row">
|
||||
<input type="text" class="form-control tl-label" placeholder="Label" value="<%= opt.label || '' %>">
|
||||
<input type="text" class="form-control tl-value" placeholder="Value (e.g. immediate)" value="<%= opt.value || '' %>">
|
||||
<button type="button" class="btn btn-outline-danger remove-tl-opt"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
<% }); %>
|
||||
</div>
|
||||
|
||||
<h6 class="text-uppercase text-muted small mb-3">Form texts</h6>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-12">
|
||||
<label class="form-label small">Consent text</label>
|
||||
<textarea class="form-control" id="formConsentText" rows="3"><%= fm.consentText || '' %></textarea>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">Submit label</label>
|
||||
<input type="text" class="form-control" id="formSubmitLabel" value="<%= fm.submitLabel || '' %>">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">Footer text (security note)</label>
|
||||
<input type="text" class="form-control" id="formFooterText" value="<%= fm.footerText || '' %>">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">Success message</label>
|
||||
<input type="text" class="form-control" id="formSuccessMsg" value="<%= fm.successMessage || '' %>">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">Error message</label>
|
||||
<input type="text" class="form-control" id="formErrorMsg" value="<%= fm.errorMessage || '' %>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fixed-bottom-buttons">
|
||||
<button type="button" class="btn btn-secondary" onclick="resetRequestInfoForm()">
|
||||
<i class="fas fa-undo me-2"></i>Reset
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary" id="submitBtn">
|
||||
<i class="fas fa-save me-2"></i>Save Changes
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function resetRequestInfoForm() {
|
||||
if (confirm('Are you sure you want to reset all changes? Unsaved edits will be lost.')) {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
window.REQUEST_INFO_ICON_OPTIONS = <%- JSON.stringify(iconOptions) %>;
|
||||
|
||||
function escapeHtml(s) {
|
||||
return String(s || '')
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"');
|
||||
}
|
||||
|
||||
function iconOptionsHtml(selected) {
|
||||
var opts = window.REQUEST_INFO_ICON_OPTIONS || [];
|
||||
var html = '';
|
||||
for (var i = 0; i < opts.length; i++) {
|
||||
var o = opts[i];
|
||||
var sel = (o.value === selected) ? ' selected' : '';
|
||||
html += '<option value="' + escapeHtml(o.value) + '"' + sel + '>' + escapeHtml(o.label) + '</option>';
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
function buildValuePropRow(vp) {
|
||||
vp = vp || {};
|
||||
var iconSel = '<select class="form-select vp-icon-select">' + iconOptionsHtml(vp.icon) + '</select>';
|
||||
return (
|
||||
'<div class="card vp-row border"><div class="card-body">' +
|
||||
'<div class="row g-2 align-items-end">' +
|
||||
'<div class="col-md-4"><label class="form-label small">Icon</label>' + iconSel + '</div>' +
|
||||
'<div class="col-md-7"><label class="form-label small">Title</label>' +
|
||||
'<input type="text" class="form-control vp-title" value="' + escapeHtml(vp.title) + '"></div>' +
|
||||
'<div class="col-md-1 d-flex align-items-end justify-content-end">' +
|
||||
'<button type="button" class="btn btn-outline-danger btn-sm remove-vp"><i class="fas fa-trash"></i></button>' +
|
||||
'</div>' +
|
||||
'<div class="col-md-12"><label class="form-label small">Description</label>' +
|
||||
'<textarea class="form-control vp-description" rows="2">' + escapeHtml(vp.description) + '</textarea></div>' +
|
||||
'</div></div></div>'
|
||||
);
|
||||
}
|
||||
|
||||
function buildProgramOptRow(opt) {
|
||||
opt = opt || {};
|
||||
return (
|
||||
'<div class="input-group program-opt-row">' +
|
||||
'<input type="text" class="form-control prog-label" placeholder="Label" value="' + escapeHtml(opt.label) + '">' +
|
||||
'<input type="text" class="form-control prog-value" placeholder="Value (e.g. bs-cs)" value="' + escapeHtml(opt.value) + '">' +
|
||||
'<button type="button" class="btn btn-outline-danger remove-prog-opt"><i class="fas fa-times"></i></button>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
|
||||
function buildTimelineOptRow(opt) {
|
||||
opt = opt || {};
|
||||
return (
|
||||
'<div class="input-group timeline-opt-row">' +
|
||||
'<input type="text" class="form-control tl-label" placeholder="Label" value="' + escapeHtml(opt.label) + '">' +
|
||||
'<input type="text" class="form-control tl-value" placeholder="Value (e.g. immediate)" value="' + escapeHtml(opt.value) + '">' +
|
||||
'<button type="button" class="btn btn-outline-danger remove-tl-opt"><i class="fas fa-times"></i></button>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
|
||||
function syncHiddenJson() {
|
||||
// Metadata
|
||||
document.getElementById('metadataJson').value = JSON.stringify({
|
||||
title: document.getElementById('metaTitle').value.trim(),
|
||||
description: document.getElementById('metaDescription').value.trim(),
|
||||
keywords: document.getElementById('metaKeywords').value.trim(),
|
||||
ogImage: document.getElementById('metaOgImage').value.trim(),
|
||||
});
|
||||
|
||||
// ValueProps
|
||||
var valueProps = [];
|
||||
document.querySelectorAll('#valuePropsContainer .vp-row').forEach(function(row) {
|
||||
valueProps.push({
|
||||
icon: row.querySelector('.vp-icon-select').value,
|
||||
title: row.querySelector('.vp-title').value.trim(),
|
||||
description: row.querySelector('.vp-description').value.trim(),
|
||||
});
|
||||
});
|
||||
|
||||
// Hero
|
||||
document.getElementById('heroJson').value = JSON.stringify({
|
||||
badge: document.getElementById('heroBadge').value.trim(),
|
||||
titleMain: document.getElementById('heroTitleMain').value.trim(),
|
||||
titleHighlight: document.getElementById('heroTitleHighlight').value.trim(),
|
||||
description: document.getElementById('heroDescription').value.trim(),
|
||||
valueProps: valueProps,
|
||||
});
|
||||
|
||||
// Program options
|
||||
var programOptions = [];
|
||||
document.querySelectorAll('#programOptionsContainer .program-opt-row').forEach(function(row) {
|
||||
var label = row.querySelector('.prog-label').value.trim();
|
||||
var value = row.querySelector('.prog-value').value.trim();
|
||||
if (label || value) programOptions.push({ label: label, value: value });
|
||||
});
|
||||
|
||||
// Timeline options
|
||||
var timelineOptions = [];
|
||||
document.querySelectorAll('#timelineOptionsContainer .timeline-opt-row').forEach(function(row) {
|
||||
var label = row.querySelector('.tl-label').value.trim();
|
||||
var value = row.querySelector('.tl-value').value.trim();
|
||||
if (label || value) timelineOptions.push({ label: label, value: value });
|
||||
});
|
||||
|
||||
// Form
|
||||
document.getElementById('formJson').value = JSON.stringify({
|
||||
heading: document.getElementById('formHeading').value.trim(),
|
||||
description: document.getElementById('formDescription').value.trim(),
|
||||
fields: {
|
||||
firstName: {
|
||||
name: 'first_name',
|
||||
label: document.getElementById('fld_firstName_label').value.trim(),
|
||||
placeholder: document.getElementById('fld_firstName_ph').value.trim(),
|
||||
required: true,
|
||||
},
|
||||
lastName: {
|
||||
name: 'last_name',
|
||||
label: document.getElementById('fld_lastName_label').value.trim(),
|
||||
placeholder: document.getElementById('fld_lastName_ph').value.trim(),
|
||||
required: true,
|
||||
},
|
||||
email: {
|
||||
name: 'email_address',
|
||||
label: document.getElementById('fld_email_label').value.trim(),
|
||||
placeholder: document.getElementById('fld_email_ph').value.trim(),
|
||||
required: true,
|
||||
},
|
||||
phone: {
|
||||
name: 'phone_number',
|
||||
label: document.getElementById('fld_phone_label').value.trim(),
|
||||
placeholder: document.getElementById('fld_phone_ph').value.trim(),
|
||||
required: false,
|
||||
},
|
||||
program: {
|
||||
name: 'program_id',
|
||||
label: document.getElementById('fld_program_label').value.trim(),
|
||||
placeholder: document.getElementById('fld_program_ph').value.trim(),
|
||||
required: true,
|
||||
options: programOptions,
|
||||
},
|
||||
timeline: {
|
||||
name: 'start_timeline',
|
||||
label: document.getElementById('fld_timeline_label').value.trim(),
|
||||
options: timelineOptions,
|
||||
},
|
||||
},
|
||||
consentText: document.getElementById('formConsentText').value.trim(),
|
||||
submitLabel: document.getElementById('formSubmitLabel').value.trim(),
|
||||
footerText: document.getElementById('formFooterText').value.trim(),
|
||||
successMessage: document.getElementById('formSuccessMsg').value.trim(),
|
||||
errorMessage: document.getElementById('formErrorMsg').value.trim(),
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var form = document.getElementById('requestInfoForm');
|
||||
form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var btn = document.getElementById('submitBtn');
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Saving...';
|
||||
try {
|
||||
syncHiddenJson();
|
||||
form.submit();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
alert('Could not prepare form data. Please try again.');
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = '<i class="fas fa-save me-2"></i>Save Changes';
|
||||
}
|
||||
});
|
||||
|
||||
// Value props
|
||||
document.getElementById('addValuePropBtn').addEventListener('click', function () {
|
||||
document.getElementById('valuePropsContainer').insertAdjacentHTML('beforeend',
|
||||
buildValuePropRow({ icon: 'fa-solid fa-circle-info' })
|
||||
);
|
||||
});
|
||||
document.getElementById('valuePropsContainer').addEventListener('click', function (e) {
|
||||
if (e.target.closest('.remove-vp')) {
|
||||
e.target.closest('.vp-row').remove();
|
||||
}
|
||||
});
|
||||
|
||||
// Program options
|
||||
document.getElementById('addProgramBtn').addEventListener('click', function () {
|
||||
document.getElementById('programOptionsContainer').insertAdjacentHTML('beforeend', buildProgramOptRow());
|
||||
});
|
||||
document.getElementById('programOptionsContainer').addEventListener('click', function (e) {
|
||||
if (e.target.closest('.remove-prog-opt')) {
|
||||
e.target.closest('.program-opt-row').remove();
|
||||
}
|
||||
});
|
||||
|
||||
// Timeline options
|
||||
document.getElementById('addTimelineBtn').addEventListener('click', function () {
|
||||
document.getElementById('timelineOptionsContainer').insertAdjacentHTML('beforeend', buildTimelineOptRow());
|
||||
});
|
||||
document.getElementById('timelineOptionsContainer').addEventListener('click', function (e) {
|
||||
if (e.target.closest('.remove-tl-opt')) {
|
||||
e.target.closest('.timeline-opt-row').remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user