Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions Sprint-3/quote-generator/app.js
Original file line number Diff line number Diff line change
@@ -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();
35 changes: 30 additions & 5 deletions Sprint-3/quote-generator/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,38 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Title here</title>
<title>Quote generator app</title>
<!-- Preconnect for fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;800&display=swap"
rel="stylesheet"
/>

<link rel="stylesheet" href="style.css" />
<script defer src="quotes.js"></script>
<script defer src="app.js"></script>
</head>
<body>
<h1>hello there</h1>
<p id="quote"></p>
<p id="author"></p>
<button type="button" id="new-quote">New quote</button>
<div class="container">
<h1>Quote generator app</h1>
<p id="quote"></p>
<p id="author"></p>

<div class="controls">
<button type="button" id="new-quote">New Quote</button>

<div class="auto-play-container">
<span class="switch-label">Auto-play</span>
<label class="switch">
<input type="checkbox" id="auto-play-switch" />
<span class="slider"></span>
</label>
</div>

<div id="auto-play-status" class="status-indicator">auto-play: ON</div>
</div>
</div>
</body>
</html>
174 changes: 174 additions & 0 deletions Sprint-3/quote-generator/style.css
Original file line number Diff line number Diff line change
@@ -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;
}
Loading