2024-07-02 14:20:55 +00:00
|
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
|
|
// Function to load a script into the DOM
|
|
|
|
function loadScript(url, integrity, crossorigin) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const script = document.createElement("script");
|
|
|
|
script.src = url;
|
|
|
|
script.integrity = integrity;
|
|
|
|
script.crossOrigin = crossorigin;
|
|
|
|
script.onload = () => resolve(script);
|
|
|
|
script.onerror = () => reject(new Error(`Failed to load script: ${url}`));
|
|
|
|
document.head.appendChild(script);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function to get URL parameters
|
|
|
|
function getUrlParameter(name) {
|
2024-08-05 10:10:33 +00:00
|
|
|
const url = document.location.href;
|
|
|
|
const urlobj = new URL(url);
|
2024-07-02 15:31:28 +00:00
|
|
|
return urlobj.searchParams.get(name);
|
2024-07-02 14:20:55 +00:00
|
|
|
}
|
|
|
|
|
2024-08-05 10:10:33 +00:00
|
|
|
// Function to wait until a global variable is defined
|
|
|
|
function waitForGlobalVariable(variableName) {
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
const checkVariable = setInterval(() => {
|
|
|
|
if (window[variableName]) {
|
|
|
|
clearInterval(checkVariable);
|
|
|
|
resolve();
|
|
|
|
}
|
|
|
|
}, 100);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-07-02 14:20:55 +00:00
|
|
|
// Check if the 'embed' parameter is set to '1'
|
|
|
|
if (getUrlParameter("embed") === "1") {
|
|
|
|
// Apply custom CSS to hide Moodle interface elements
|
2024-08-05 10:10:33 +00:00
|
|
|
const style = document.createElement("style");
|
2024-07-02 14:20:55 +00:00
|
|
|
style.innerHTML = `
|
2024-08-05 10:10:33 +00:00
|
|
|
body.path-mod {
|
|
|
|
#header, #footer, .breadcrumb, .navbar, .side-pre, .side-post, .drawer, .drawer-toggler, .footer-popover, .navigation {
|
|
|
|
display: none !important;
|
|
|
|
}
|
|
|
|
#region-main {
|
|
|
|
margin: 0;
|
|
|
|
padding: 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`;
|
2024-07-02 14:20:55 +00:00
|
|
|
document.head.appendChild(style);
|
|
|
|
|
2024-08-05 10:10:33 +00:00
|
|
|
// Load jQuery if not already defined
|
|
|
|
const jQueryPromise = window.jQuery
|
|
|
|
? Promise.resolve()
|
|
|
|
: loadScript(
|
|
|
|
"https://code.jquery.com/jquery-3.7.1.min.js",
|
|
|
|
"sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=",
|
|
|
|
"anonymous"
|
|
|
|
).then(() => waitForGlobalVariable("$"));
|
|
|
|
|
|
|
|
jQueryPromise
|
2024-07-02 14:20:55 +00:00
|
|
|
.then(() => {
|
|
|
|
console.log("jQuery loaded successfully");
|
2024-08-05 10:10:33 +00:00
|
|
|
|
|
|
|
// Load Bootstrap if not already defined
|
|
|
|
const bootstrapPromise = window.bootstrap
|
|
|
|
? Promise.resolve()
|
|
|
|
: loadScript(
|
|
|
|
"https://stackpath.bootstrapcdn.com/bootstrap/5.3.3/js/bootstrap.bundle.min.js",
|
|
|
|
"sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz",
|
|
|
|
"anonymous"
|
|
|
|
).then(() => waitForGlobalVariable("bootstrap"));
|
|
|
|
|
|
|
|
return bootstrapPromise;
|
2024-07-02 14:20:55 +00:00
|
|
|
})
|
|
|
|
.then(() => {
|
|
|
|
console.log("Bootstrap loaded successfully");
|
2024-08-05 10:10:33 +00:00
|
|
|
|
2024-07-02 14:20:55 +00:00
|
|
|
$(document).ready(function () {
|
2024-08-05 10:10:33 +00:00
|
|
|
$(".btn-secondary:contains('Back')").hide();
|
2024-07-05 08:10:58 +00:00
|
|
|
|
2024-08-05 10:10:33 +00:00
|
|
|
const embedded = getUrlParameter("embed");
|
|
|
|
const inModal = getUrlParameter("modal");
|
|
|
|
const page = getUrlParameter("page") ? getUrlParameter("page") : 0;
|
2024-07-02 15:43:06 +00:00
|
|
|
|
2024-07-02 14:20:55 +00:00
|
|
|
// Set required attribute on inputs associated with labels containing <i title="Required field">
|
|
|
|
$('label:has(i[title="Required field"])').each(function () {
|
2024-08-05 10:10:33 +00:00
|
|
|
const inputId = $(this).attr("for");
|
2024-07-02 14:20:55 +00:00
|
|
|
$("#" + inputId).attr("required", "required");
|
|
|
|
});
|
|
|
|
|
|
|
|
// Hide the modal if the 'cancel' button is clicked
|
|
|
|
$("[name=cancel]").click(function () {
|
|
|
|
hideContent();
|
|
|
|
});
|
|
|
|
|
|
|
|
$("form").each(function () {
|
2024-08-05 10:10:33 +00:00
|
|
|
const form = $(this);
|
|
|
|
|
|
|
|
// Check if the form has a button where the text contains "Finish attempt"
|
|
|
|
let isLast = false;
|
|
|
|
const finishButton = form.find('input[type="submit"][value*="Finish attempt"]');
|
|
|
|
if (finishButton.length) {
|
|
|
|
isLast = true;
|
|
|
|
}
|
2024-07-02 14:20:55 +00:00
|
|
|
|
|
|
|
form.submit(function (event) {
|
|
|
|
event.preventDefault(); // Prevent the default form submission
|
|
|
|
|
|
|
|
// Check if the form is valid
|
|
|
|
if (!form[0].checkValidity()) {
|
|
|
|
form[0].reportValidity();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Serialize the form data
|
2024-08-05 10:10:33 +00:00
|
|
|
let formData = form.serialize();
|
2024-07-02 14:20:55 +00:00
|
|
|
|
|
|
|
// Add the submit button's data to formData
|
2024-08-05 10:10:33 +00:00
|
|
|
const submitButton = form.find(
|
2024-07-02 14:20:55 +00:00
|
|
|
'input[type="submit"][name="savevalues"]'
|
|
|
|
);
|
|
|
|
if (submitButton.length) {
|
|
|
|
formData +=
|
|
|
|
"&" +
|
|
|
|
encodeURIComponent(submitButton.attr("name")) +
|
|
|
|
"=" +
|
|
|
|
encodeURIComponent(submitButton.val());
|
|
|
|
}
|
|
|
|
|
2024-08-05 10:10:33 +00:00
|
|
|
const sesskey = form.find('input[name=sesskey]').val();
|
|
|
|
const attempt = form.find('input[name=attempt]').val();
|
2024-07-05 08:10:58 +00:00
|
|
|
|
2024-07-02 14:20:55 +00:00
|
|
|
// Perform the AJAX request
|
|
|
|
$.ajax({
|
|
|
|
url: form.attr("action"), // Use the form's action attribute
|
|
|
|
type: form.attr("method"), // Use the form's method attribute
|
|
|
|
data: formData,
|
2024-08-05 10:10:33 +00:00
|
|
|
success: function (response, status, xhr) {
|
2024-07-05 08:10:58 +00:00
|
|
|
if (form.attr("action").includes("/quiz/")) {
|
2024-08-05 10:10:33 +00:00
|
|
|
// Check if the quiz has a next page by calling the attempt.php page
|
|
|
|
let nextUrl = form.attr("action").replace("processattempt", "attempt");
|
|
|
|
nextUrl += "&page=" + (parseInt(page) + 1) + "&attempt=" + attempt + "&sesskey=" + sesskey;
|
|
|
|
|
|
|
|
if (isLast) {
|
|
|
|
nextUrl = "https://invalid.invalid";
|
|
|
|
}
|
|
|
|
|
|
|
|
$.get(nextUrl, function (response) {
|
|
|
|
console.log(nextUrl + " seems to be a valid URL, redirecting...");
|
|
|
|
nextUrl = nextUrl + "&embed=1";
|
|
|
|
|
2024-07-05 08:10:58 +00:00
|
|
|
if (inModal === "1") {
|
2024-08-05 10:10:33 +00:00
|
|
|
nextUrl += "&modal=1";
|
2024-07-05 08:10:58 +00:00
|
|
|
}
|
2024-08-05 10:10:33 +00:00
|
|
|
|
|
|
|
document.location.href = nextUrl;
|
|
|
|
|
|
|
|
return;
|
|
|
|
})
|
|
|
|
.fail(function () {
|
|
|
|
console.log("No next page found at " + nextUrl + ", finalizing attempt...");
|
|
|
|
|
|
|
|
const finalize = "/mod/quiz/processattempt.php";
|
|
|
|
const data = {
|
|
|
|
attempt: attempt,
|
|
|
|
finishattempt: 1,
|
|
|
|
sesskey: sesskey,
|
|
|
|
};
|
|
|
|
$.post(finalize, data, function (response) {
|
|
|
|
console.log(response);
|
|
|
|
// Close the modal if `modal=1` is set
|
|
|
|
if (inModal === "1") {
|
|
|
|
window.top.closeQuizModal();
|
|
|
|
} else {
|
|
|
|
// Else call the nextContent function
|
|
|
|
window.top.nextContent();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2024-07-02 15:43:06 +00:00
|
|
|
} else {
|
2024-07-05 08:10:58 +00:00
|
|
|
// Close the modal if `modal=1` is set
|
|
|
|
if (inModal === "1") {
|
|
|
|
window.top.closeQuizModal();
|
|
|
|
} else {
|
|
|
|
// Else call the nextContent function
|
|
|
|
window.top.nextContent();
|
|
|
|
}
|
2024-07-02 15:43:06 +00:00
|
|
|
}
|
2024-07-02 14:20:55 +00:00
|
|
|
},
|
|
|
|
error: function (xhr, status, error) {
|
|
|
|
// Handle any errors that occur during the AJAX request
|
|
|
|
console.error(
|
|
|
|
"Form submission failed: " + status + " - " + error
|
|
|
|
);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch((error) => {
|
2024-08-05 10:10:33 +00:00
|
|
|
console.error(error.message);
|
2024-07-02 14:20:55 +00:00
|
|
|
});
|
|
|
|
}
|
2024-08-05 10:10:33 +00:00
|
|
|
});
|