diff --git a/_sources/lectures/TWP52_en.rst b/_sources/lectures/TWP52_en.rst index e19079513c..518fd3b8c2 100644 --- a/_sources/lectures/TWP52_en.rst +++ b/_sources/lectures/TWP52_en.rst @@ -305,7 +305,11 @@ Review + OptionMenu() +.. raw:: html + <iframe src="https://dev.python.org.ar/mod/scorm/player.php?a=7&scoid=16" width="100%" height="600px"> + Your browser does not support iframes. + </iframe> .. disqus:: :shortname: pyzombis diff --git a/_static/APIWrapper.js b/_static/APIWrapper.js new file mode 100644 index 0000000000..b37d2f2daa --- /dev/null +++ b/_static/APIWrapper.js @@ -0,0 +1,59 @@ +// SCORM API Wrapper +var findAPITries = 0; +var API = null; + +function findAPI(win) { + while ((win.API == null) && (win.parent != null) && (win.parent != win)) { + findAPITries++; + if (findAPITries > 7) { + return null; + } + win = win.parent; + } + return win.API; +} + +function getAPI() { + var theAPI = findAPI(window); + if ((theAPI == null) && (window.opener != null) && (typeof(window.opener) != "undefined")) { + theAPI = findAPI(window.opener); + } + if (theAPI == null) { + alert("Unable to find an API adapter"); + } + return theAPI; +} + +function initializeAPI() { + API = getAPI(); + if (API != null) { + API.LMSInitialize(""); + } +} + +function terminateAPI() { + if (API != null) { + API.LMSFinish(""); + } +} + +function setProgress(progress) { + if (API != null) { + API.LMSSetValue("cmi.core.lesson_status", progress); + API.LMSCommit(""); + } +} + +function setSuspendData(data) { + if (API != null) { + API.LMSSetValue("cmi.suspend_data", data); + API.LMSCommit(""); + } +} + +function getSuspendData() { + if (API != null) { + return API.LMSGetValue("cmi.suspend_data"); + } + return ""; +} diff --git a/_static/SCORMFunctions.js b/_static/SCORMFunctions.js new file mode 100644 index 0000000000..30f1f62fa8 --- /dev/null +++ b/_static/SCORMFunctions.js @@ -0,0 +1,62 @@ +// SCORM Functions + +function loadPage() { + initializeAPI(); + console.log("SCORM API initialized."); +} + +function unloadPage() { + saveTextBoxData(); // Save data when the page is unloaded + terminateAPI(); + console.log("SCORM API terminated."); +} + +function loadChapter(chapter) { + loadPage(); + + var suspendData = getSuspendData(); + if (suspendData) { + console.log("Suspend data retrieved:", suspendData); + // Restore the text data in the textbox + document.getElementById("chapter-textbox").value = suspendData; + } + + var completionStatus = API.LMSGetValue("cmi.core.lesson_status"); + + if (completionStatus === "completed") { + document.getElementById("completion-status").innerText = "This chapter has been completed."; + document.getElementById("complete-button").style.display = "none"; + } else { + document.getElementById("completion-status").innerText = "This chapter has not been completed."; + document.getElementById("reset-button").style.display = "none"; + } +} + +function completeChapter(chapter) { + setProgress("completed"); + alert(chapter + " completed! Progress recorded."); + document.getElementById("completion-status").innerText = "This chapter has been completed."; + document.getElementById("complete-button").style.display = "none"; + document.getElementById("reset-button").style.display = "block"; + + // Optionally save some suspend data when the chapter is completed + setSuspendData(document.getElementById("chapter-textbox").value); +} + +function resetChapter(chapter) { + setProgress("incomplete"); + alert(chapter + " reset to incomplete."); + document.getElementById("completion-status").innerText = "This chapter has not been completed."; + document.getElementById("complete-button").style.display = "block"; + document.getElementById("reset-button").style.display = "none"; + + // Clear the suspend data if the chapter is reset + setSuspendData(""); + document.getElementById("chapter-textbox").value = ""; // Clear the textbox as well +} + +function saveTextBoxData() { + // Save the current state of the textbox into suspend data + var textBoxData = document.getElementById("chapter-textbox").value; + setSuspendData(textBoxData); +} diff --git a/_static/auth.js b/_static/auth.js new file mode 100644 index 0000000000..1b478cfddf --- /dev/null +++ b/_static/auth.js @@ -0,0 +1,52 @@ +// auth.js + +function registerUser() { + const username = document.getElementById('newUsername').value; + const password = document.getElementById('newPassword').value; + + // Store the new user in local storage + localStorage.setItem('username', username); + localStorage.setItem('password', password); + + alert('Registration successful! Please log in.'); + window.location.href = '../scorm_package/login.html'; + return false; +} + +function loginUser() { + const username = document.getElementById('username').value; + const password = document.getElementById('password').value; + const rememberMe = document.getElementById('rememberMe').checked; + + const storedUsername = localStorage.getItem('username'); + const storedPassword = localStorage.getItem('password'); + + if (username === storedUsername && password === storedPassword) { + if (rememberMe) { + localStorage.setItem('loggedInUser', username); + } + sessionStorage.setItem('loggedInUser', username); + alert('Login successful!'); + window.location.href = '../scorm_package/chapter1.html'; // Redirect to the first chapter + } else { + alert('Invalid username or password!'); + } + return false; +} + +function logoutUser() { + sessionStorage.removeItem('loggedInUser'); + alert('You have been logged out.'); + window.location.href = '../scorm_package/login.html'; +} + +function checkLogin() { + const loggedInUser = sessionStorage.getItem('loggedInUser') || localStorage.getItem('loggedInUser'); + + if (!loggedInUser) { + alert('You are not logged in. Please log in first.'); + window.location.href = '../scorm_package/login.html'; + } +} + +window.onload = checkLogin; diff --git a/_templates/layout.html b/_templates/layout.html index 00a8807a4f..68b4225437 100644 --- a/_templates/layout.html +++ b/_templates/layout.html @@ -275,6 +275,8 @@ {% endraw %} {% endif %} +<script src="../scorm_package/scripts/scorm_functions.js"></script> + {% endblock %} {# Silence the sidebar's, relbar's #} diff --git a/scorm_package/chapter1.html b/scorm_package/chapter1.html new file mode 100644 index 0000000000..6d51ab2a9a --- /dev/null +++ b/scorm_package/chapter1.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Chapter 1</title> + <script src="../_static/APIWrapper.js"></script> + <script src="../_static/SCORMFunctions.js"></script> + <script src="../_static/auth.js"></script> +</head> +<body onload="loadChapter('chapter1')" onunload="unloadPage()"> + <h1>Chapter 1: Introduction</h1> + <button onclick="logoutUser()">Logout</button> + <p id="completion-status">Checking completion status...</p> + <button id="complete-button" onclick="completeChapter('chapter1')">Mark this Chapter as Completed</button> + <button id="reset-button" onclick="resetChapter('chapter1')">Reset Progress</button> + + <!-- Textbox for user to write and save data --> + <textarea id="chapter-textbox" rows="10" cols="50" placeholder="Write your notes here..."></textarea> +</body> +</html> diff --git a/scorm_package/chapter2.html b/scorm_package/chapter2.html new file mode 100644 index 0000000000..f3e3f9f554 --- /dev/null +++ b/scorm_package/chapter2.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Chapter 2</title> + <script src="../_static/APIWrapper.js"></script> + <script src="../_static/SCORMFunctions.js"></script> + <script src="../_static/auth.js"></script> +</head> +<body onload="loadChapter('chapter2')" onunload="unloadPage()"> + <h1>Chapter 2: Uff</h1> + <button onclick="logoutUser()">Logout</button> + <p id="completion-status">Checking completion status...</p> + <button id="complete-button" onclick="completeChapter('chapter2')">Mark this Chapter as Completed</button> + <button id="reset-button" onclick="resetChapter('chapter2')">Reset Progress</button> + + <!-- Textbox for user to write and save data --> + <textarea id="chapter-textbox" rows="10" cols="50" placeholder="Write your notes here..."></textarea> +</body> +</html> diff --git a/scorm_package/imsmanifest.xml b/scorm_package/imsmanifest.xml new file mode 100644 index 0000000000..59ef4aba7c --- /dev/null +++ b/scorm_package/imsmanifest.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<manifest identifier="com.example.scormminimal" version="1.2" + xmlns="http://www.imsproject.org/xsd/imscp_rootv1p1p2" + xmlns:adlcp="http://www.adlnet.org/xsd/adlcp_rootv1p2" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.imsproject.org/xsd/imscp_rootv1p1p2 imscp_rootv1p1p2.xsd + http://www.adlnet.org/xsd/adlcp_rootv1p2 adlcp_rootv1p2.xsd"> + <metadata> + <schema>ADL SCORM</schema> + <schemaversion>1.2</schemaversion> + <adlcp:location>metadata.xml</adlcp:location> + </metadata> + <organizations default="org"> + <organization identifier="org"> + <title>Your Course Title</title> + <item identifier="item1" identifierref="resource1"> + <title>Chapter 1</title> + </item> + <item identifier="item2" identifierref="resource2"> + <title>Chapter 2</title> + </item> + <!-- Add more items for additional chapters --> + </organization> + </organizations> + <resources> + <resource identifier="resource1" type="webcontent" adlcp:scormtype="sco" href="chapter1.html"> + <file href="chapter1.html"/> + <file href="../_static/SCORMFunctions.js"/> + <file href="../_static/APIWrapper.js"/> + <file href="../_static/auth.js"/> + </resource> + <resource identifier="resource2" type="webcontent" adlcp:scormtype="sco" href="chapter2.html"> + <file href="chapter2.html"/> + <file href="../_static/SCORMFunctions.js"/> + <file href="../_static/APIWrapper.js"/> + <file href="../_static/auth.js"/> + </resource> + <resource identifier="loginResource" type="webcontent" adlcp:scormtype="sco" href="login.html"> + <file href="login.html"/> + <file href="../_static/auth.js"/> + </resource> + <resource identifier="signupResource" type="webcontent" adlcp:scormtype="sco" href="signup.html"> + <file href="signup.html"/> + <file href="../_static/auth.js"/> + </resource> + <!-- Add more resources as needed --> +</resources> +</manifest> \ No newline at end of file diff --git a/scorm_package/login.html b/scorm_package/login.html new file mode 100644 index 0000000000..5c1416ca4c --- /dev/null +++ b/scorm_package/login.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Login</title> + <script src="../_static/auth.js"></script> +</head> +<body> + <h1>Login</h1> + <form onsubmit="return loginUser()"> + <label for="username">Username:</label><br> + <input type="text" id="username" name="username" required><br> + <label for="password">Password:</label><br> + <input type="password" id="password" name="password" required><br> + <input type="checkbox" id="rememberMe" name="rememberMe"> Remember Me<br><br> + <input type="submit" value="Login"> + </form> + <p>Don't have an account? <a href="signup.html">Sign Up</a></p> +</body> +</html> diff --git a/scorm_package/scorm_package.zip b/scorm_package/scorm_package.zip new file mode 100644 index 0000000000..2fde218991 Binary files /dev/null and b/scorm_package/scorm_package.zip differ diff --git a/scorm_package/signup.html b/scorm_package/signup.html new file mode 100644 index 0000000000..43f2e7651e --- /dev/null +++ b/scorm_package/signup.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Sign Up</title> + <script src="../_static/auth.js"></script> +</head> +<body> + <h1>Sign Up</h1> + <form onsubmit="return registerUser()"> + <label for="newUsername">Username:</label><br> + <input type="text" id="newUsername" name="newUsername" required><br> + <label for="newPassword">Password:</label><br> + <input type="password" id="newPassword" name="newPassword" required><br><br> + <input type="submit" value="Sign Up"> + </form> + <p>Already have an account? <a href="login.html">Login</a></p> +</body> +</html>