diff --git a/Sprint-3/quote-generator/app.js b/Sprint-3/quote-generator/app.js new file mode 100644 index 000000000..734f7a486 --- /dev/null +++ b/Sprint-3/quote-generator/app.js @@ -0,0 +1,96 @@ +/* globals quotes, pickFromArray */ + +// Use a constant for the auto-play time to make it easy to change later. +const AUTO_PLAY_INTERVAL_MS = 5000; + +// Defines variables to track the state of the app. +// Uses 'let' because the timer ID will change when we start/stop auto-play. +let autoPlayIntervalId = null; + +// DOM Elements (fetched once to keep the code efficient) +const quoteElement = document.getElementById("quote"); +const authorElement = document.getElementById("author"); +const newQuoteButton = document.getElementById("new-quote"); +const autoPlaySwitch = document.getElementById("auto-play-switch"); +const autoPlayStatus = document.getElementById("auto-play-status"); + +/** + * Selects and displays a new random quote from the quote list. + * This function changes the text on the screen. + */ +function displayNewQuote() { + // Selects a random quote object from the global 'quotes' array. + const randomQuote = pickFromArray(quotes); + + // Updates the HTML elements with the new quote text and author name. + quoteElement.innerText = randomQuote.quote; + authorElement.innerText = randomQuote.author; +} + +/** + * Starts the auto-play feature. + * This sets up a timer to automatically change the quote every few seconds. + */ +function startAutoPlay() { + // Clears any existing timer first to prevent multiple timers running at once. + if (autoPlayIntervalId) { + clearInterval(autoPlayIntervalId); + } + + // Shows the "auto-play: ON" status text to inform the user it is active. + autoPlayStatus.classList.add("active"); + + // Sets a repeating timer that calls 'displayNewQuote' every 5000 milliseconds (5 seconds). + autoPlayIntervalId = setInterval(function () { + displayNewQuote(); + }, AUTO_PLAY_INTERVAL_MS); +} + +/** + * Stops the auto-play feature. + * This cancels the timer so the quotes stop changing automatically. + */ +function stopAutoPlay() { + // Checks if a timer exists, and if so, stops it. + if (autoPlayIntervalId) { + clearInterval(autoPlayIntervalId); + autoPlayIntervalId = null; + } + + // Hides the "auto-play: ON" status text. + autoPlayStatus.classList.remove("active"); +} + +/** + * Handles the change event when the user toggles the auto-play switch. + * Decides whether to start or stop auto-play based on the switch position. + * + * @param {Event} event - The event object from the click. + */ +function handleAutoPlayToggle(event) { + // Checks if the toggle switch is currently 'checked' (on). + if (event.target.checked) { + startAutoPlay(); + } else { + stopAutoPlay(); + } +} + +// Adds an event listener to the "New Quote" button. +// When clicked, it shows a new quote and resets the auto-play timer if it's running. +newQuoteButton.addEventListener("click", function () { + displayNewQuote(); + + // If auto-play is turned on, restarts the timer. + // This prevents the quote from changing immediately after the user manually clicks. + if (autoPlaySwitch.checked) { + startAutoPlay(); + } +}); + +// Adds an event listener to the auto-play toggle switch. +// When changed, it triggers the handleAutoPlayToggle function. +autoPlaySwitch.addEventListener("change", handleAutoPlayToggle); + +// Displays a random quote immediately when the page loads so it isn't empty. +displayNewQuote(); diff --git a/Sprint-3/quote-generator/index.html b/Sprint-3/quote-generator/index.html index 30b434bcf..a954aa9f5 100644 --- a/Sprint-3/quote-generator/index.html +++ b/Sprint-3/quote-generator/index.html @@ -3,13 +3,38 @@ - Title here + Quote generator app + + + + + + + -

hello there

-

-

- +
+

Quote generator app

+

+

+ +
+ + +
+ Auto-play + +
+ +
auto-play: ON
+
+
diff --git a/Sprint-3/quote-generator/style.css b/Sprint-3/quote-generator/style.css index 63cedf2d2..3d445ed20 100644 --- a/Sprint-3/quote-generator/style.css +++ b/Sprint-3/quote-generator/style.css @@ -1 +1,175 @@ /** Write your CSS in here **/ + +:root { + --primary-color: #f5ac2d; + --text-color: #f5ac2d; + --bg-color: #f5ac2d; + --card-bg: #ffffff; + --transition-speed: 0.3s; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + font-family: Georgia, 'Times New Roman', Times, serif; + background-color: var(--bg-color); + min-height: 100vh; + display: flex; + justify-content: center; + align-items: center; + padding: 1rem; +} + +.container { + background: var(--card-bg); + padding: 3rem 4rem; + width: 100%; + max-width: 700px; + text-align: center; + position: relative; + /* Simple crisp shadow or none based on flat design of example, keeping slight shadow for visibility */ + box-shadow: 0 4px 6px rgba(0,0,0,0.1); +} + +h1 { + display: none; /* The example image doesn't show a visible title inside the card */ +} + +#quote { + font-size: 1.8rem; + line-height: 1.4; + color: var(--text-color); + margin-bottom: 1.5rem; + position: relative; + padding-left: 3rem; /* Space for the quote icon */ + text-align: left; +} + +#quote::before { + content: '“'; /* Large quote mark using curved quotes */ + font-size: 6rem; + color: var(--primary-color); + position: absolute; + top: -1.5rem; + left: -1rem; + line-height: 1; + font-family: sans-serif; /* Quote marks often look better in sans-serif or specific fonts */ + opacity: 1; /* Solid colour in example */ +} + +#author { + font-size: 1.1rem; + color: var(--text-color); + margin-bottom: 2.5rem; + text-align: right; + font-style: italic; /* Authors are often italicized in this style */ +} + +/* Add dash before author if not present in JS, but here we style assuming content */ +#author::before { + content: '- '; +} + +.controls { + display: flex; + flex-direction: column; + align-items: flex-end; /* Button aligned to right in some designs, or center. Example shows right or center. Let's align right to match typical 'next' flows or keep center if safer. Example looks right-aligned for button. */ +} + +button { + background-color: var(--primary-color); + color: white; + border: none; + padding: 0.8rem 1.5rem; + font-size: 1rem; + font-family: Arial, sans-serif; + cursor: pointer; + transition: opacity var(--transition-speed) ease; + font-weight: bold; +} + +button:hover { + opacity: 0.9; +} + +/* Auto-play Switch - adjusting to fit the new theme */ +.auto-play-container { + display: flex; + align-items: center; + gap: 1rem; + margin-top: 1rem; /* Separate from main button */ + align-self: flex-end; +} + +.switch-label { + font-weight: normal; + font-size: 0.9rem; + color: var(--text-color); + font-family: Arial, sans-serif; +} + +.switch { + position: relative; + display: inline-block; + width: 50px; + height: 26px; +} + +.switch input { + opacity: 0; + width: 0; + height: 0; +} + +.slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #e4e4e4; /* Light grey for off */ + transition: .4s; + border-radius: 0; /* Square/Rectangular look or keep rounded? Let's keep rounded for standard UI toggle */ +} + +.slider:before { + position: absolute; + content: ""; + height: 20px; + width: 20px; + left: 3px; + bottom: 3px; + background-color: white; + transition: .4s; +} + +input:checked + .slider { + background-color: var(--primary-color); +} + +input:focus + .slider { + box-shadow: 0 0 1px var(--primary-color); +} + +input:checked + .slider:before { + transform: translateX(24px); +} + +.status-indicator { + font-size: 0.8rem; + font-weight: bold; + color: var(--primary-color); + opacity: 0; + margin-top: 0.5rem; + align-self: flex-end; + font-family: Arial, sans-serif; +} + +.status-indicator.active { + opacity: 1; +}