"something happened here"
BIN
Murach/.DS_Store
vendored
@ -1,22 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Die Roller</title>
|
|
||||||
<link rel="stylesheet" href="main.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>
|
|
||||||
<script>
|
|
||||||
// get a random number between 0 and 6
|
|
||||||
const randNum = Math.random() * 6;
|
|
||||||
|
|
||||||
// round up to get a number from 1 to 6.
|
|
||||||
const dieRoll = Math.ceil(randNum);
|
|
||||||
|
|
||||||
// write some text and the number to the web page
|
|
||||||
document.write("Die Roll: " + dieRoll);
|
|
||||||
</script>
|
|
||||||
</h1>
|
|
||||||
<p>Click Reload to roll again!</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 600px;
|
|
||||||
padding: 0 2em 0;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Join Email List</title>
|
|
||||||
<link rel="stylesheet" href="email_list.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Thanks for joining our email list!</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
// define a function that gets an HTML element
|
|
||||||
function getElement(selector) {
|
|
||||||
return document.querySelector(selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
// define a function that handles the click event of the Join button
|
|
||||||
function joinButtonClick(event) {
|
|
||||||
// get user entries from text boxes
|
|
||||||
const email1 = getElement("#email_1").value;
|
|
||||||
const email2 = getElement("#email_2").value;
|
|
||||||
|
|
||||||
// check user entries
|
|
||||||
let invalid = false;
|
|
||||||
if (email1 == "") {
|
|
||||||
getElement("#email_1_error").textContent = "Email is required.";
|
|
||||||
invalid = true;
|
|
||||||
} else {
|
|
||||||
getElement("#email_1_error").textContent = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (email1 != email2) {
|
|
||||||
getElement("#email_2_error").textContent = "Emails must match.";
|
|
||||||
invalid = true;
|
|
||||||
} else {
|
|
||||||
getElement("#email_2_error").textContent = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// cancel form submit if any user entries are invalid
|
|
||||||
if (invalid) {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// add code that's run when the web page is loaded
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
// specify the function that's run when the Join button is clicked
|
|
||||||
getElement("#join_button").addEventListener("click", joinButtonClick);
|
|
||||||
});
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Email List</title>
|
|
||||||
<link rel="stylesheet" href="main.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Email List</h1>
|
|
||||||
<form id="email_form" name="email_form"
|
|
||||||
action="add.html" method="post">
|
|
||||||
<div>
|
|
||||||
<label for="email_1">Enter email:</label>
|
|
||||||
<input type="text" id="email_1" name="email_1">
|
|
||||||
<span id="email_1_error">*</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label for="email_2">Confirm email:</label>
|
|
||||||
<input type="text" id="email_2" name="email_2">
|
|
||||||
<span id="email_2_error">*</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label> </label>
|
|
||||||
<input type="submit" id="join_button" value="Join">
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<script src="email_list.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 600px;
|
|
||||||
padding: 0 2em 0;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
}
|
|
||||||
div {
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
display: inline-block;
|
|
||||||
width: 11em;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
input {
|
|
||||||
margin-left: 1em;
|
|
||||||
margin-right: 0.5em;
|
|
||||||
}
|
|
||||||
span {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Welcome</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Welcome to Modern JavaScript</h1>
|
|
||||||
<script>
|
|
||||||
// call a method that displays a dialog
|
|
||||||
alert("Hi");
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 0 2em 1em;
|
|
||||||
width: 600px;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Miles to Kilometers</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script src="miles_to_kms.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
// get miles from user
|
|
||||||
const miles = parseFloat(prompt("Miles:", 120));
|
|
||||||
|
|
||||||
// calculate kilometers
|
|
||||||
const kilometers = miles * 1.60934;
|
|
||||||
|
|
||||||
// display results
|
|
||||||
const results = "Miles: " + miles + "\n" +
|
|
||||||
"Kilometers: " + kilometers.toFixed(2);
|
|
||||||
|
|
||||||
alert(results);
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Test Scores</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script src="test_scores.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
// initialize total variable
|
|
||||||
let total = 0;
|
|
||||||
|
|
||||||
//get 3 scores from user and add them together
|
|
||||||
const score1 = parseInt(prompt("Enter first test score"));
|
|
||||||
total += score1;
|
|
||||||
|
|
||||||
const score2 = parseInt(prompt("Enter second test score"));
|
|
||||||
total += score2;
|
|
||||||
|
|
||||||
const score3 = parseInt(prompt("Enter third test score"));
|
|
||||||
total += score3;
|
|
||||||
|
|
||||||
//calculate the average
|
|
||||||
const average = Math.round(total/3);
|
|
||||||
|
|
||||||
// display the scores
|
|
||||||
const result = "Score 1 = " + score1 + "\n" +
|
|
||||||
"Score 2 = " + score2 + "\n" +
|
|
||||||
"Score 3 = " + score3 + "\n" +
|
|
||||||
"Average score = " + average;
|
|
||||||
|
|
||||||
alert(result);
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
// get investment amount - loop until user enters a number
|
|
||||||
let investment = NaN;
|
|
||||||
while (isNaN(investment)) {
|
|
||||||
investment = parseFloat(
|
|
||||||
prompt("Enter investment amount", 10000));
|
|
||||||
}
|
|
||||||
|
|
||||||
// get interest rate - loop until user enters a number
|
|
||||||
let rate = NaN;
|
|
||||||
while (isNaN(rate)) {
|
|
||||||
rate = parseFloat(prompt("Enter interest rate", 4.5));
|
|
||||||
}
|
|
||||||
|
|
||||||
// get number of years - loop until user enters a number
|
|
||||||
let years = NaN;
|
|
||||||
while (isNaN(years)) {
|
|
||||||
years = parseInt(prompt("Enter years", 10));
|
|
||||||
}
|
|
||||||
|
|
||||||
// calulate future value
|
|
||||||
let futureValue = investment;
|
|
||||||
for (let i = 0; i < years; i++) {
|
|
||||||
futureValue += futureValue * rate / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
// display results
|
|
||||||
alert("Investment amount: $" + investment + "\n" +
|
|
||||||
"Interest rate: " + rate + "%\n" +
|
|
||||||
"Years: " + years + "\n" +
|
|
||||||
"Future Value: $" + futureValue.toFixed(2));
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Future Value Calculator</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script src="future_value.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
// get a random number between 1 and 20
|
|
||||||
const num = Math.ceil(Math.random() * 20);
|
|
||||||
|
|
||||||
// get the computer's guess
|
|
||||||
const computerGuess = Math.ceil(Math.random() * 20);
|
|
||||||
|
|
||||||
// get the user's guess
|
|
||||||
const userGuess = parseInt(prompt("Enter a number between 1 and 20"));
|
|
||||||
|
|
||||||
if (isNaN(userGuess)) {
|
|
||||||
alert("Not a valid number. Computer wins.")
|
|
||||||
} else if (userGuess < 1 || userGuess > 20) {
|
|
||||||
alert("Not a number between 1 and 20. Computer wins.");
|
|
||||||
} else {
|
|
||||||
let message = "The number is " + num + ".\n" +
|
|
||||||
"You guessed " + userGuess +
|
|
||||||
" and the computer guessed " + computerGuess + ".\n";
|
|
||||||
|
|
||||||
// compute the difference between the guesses and the number
|
|
||||||
const computerDiff = Math.abs(num - computerGuess);
|
|
||||||
const userDiff = Math.abs(num - userGuess);
|
|
||||||
|
|
||||||
// determine the winner
|
|
||||||
if (userDiff === computerDiff) {
|
|
||||||
message += "It's a tie!";
|
|
||||||
} else if (userDiff < computerDiff) {
|
|
||||||
message += "You WIN!";
|
|
||||||
} else {
|
|
||||||
message += "Computer wins.";
|
|
||||||
}
|
|
||||||
|
|
||||||
alert(message);
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Guess the Number</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>The Guess the Number App</h1>
|
|
||||||
<p>Click Reload to play again.</p>
|
|
||||||
<script src="guess_number.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Magic Eightball</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Magic Eightball</h1>
|
|
||||||
<p>Click Reload to ask another question.</p>
|
|
||||||
<script src="magic_eight_ball.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
// get user's question
|
|
||||||
const question = prompt("Please enter a yes or no question.")
|
|
||||||
|
|
||||||
if (question) {
|
|
||||||
let answer = "";
|
|
||||||
|
|
||||||
// get a random number between 1 and 9
|
|
||||||
const num = Math.ceil(Math.random() * 9);
|
|
||||||
|
|
||||||
switch (num) {
|
|
||||||
case 1:
|
|
||||||
answer = "It is certain.";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
answer = "Reply hazy, try again.";
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
answer = "Don't count on it.";
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
answer = "It is decidedly so.";
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
answer = "Without a doubt.";
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
answer = "Ask again later.";
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
answer = "My sources say no.";
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
answer = "Most likely.";
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
answer = "Signs point to yes.";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
answer = "Something went wrong.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
alert(question + "\n" +
|
|
||||||
answer);
|
|
||||||
} else {
|
|
||||||
alert("You didn't enter a question.");
|
|
||||||
}
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
// get name, dob, and colors and split into arrays
|
|
||||||
const names = prompt("Enter your full name").split(" ");
|
|
||||||
const dob = prompt("Enter your DOB in mm-dd-yyyy format").split("-");
|
|
||||||
const colors = prompt("Enter your favorite colors, separated by commas")
|
|
||||||
.split(",");
|
|
||||||
|
|
||||||
// capitalize each name
|
|
||||||
for (let i in names) {
|
|
||||||
const firstLetter = names[i].substring(0, 1).toUpperCase();
|
|
||||||
const restOfName = names[i].substring(1).toLowerCase();
|
|
||||||
names[i] = firstLetter + restOfName;
|
|
||||||
}
|
|
||||||
|
|
||||||
// trim any spaces from colors
|
|
||||||
for (let i in colors) {
|
|
||||||
colors[i] = colors[i].trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a display string for the colors
|
|
||||||
const firstColors = colors.slice(0, -1);
|
|
||||||
const lastColor = colors.at(-1);
|
|
||||||
const colorString = `${firstColors.join(", ")} and ${lastColor}`;
|
|
||||||
|
|
||||||
// display bio
|
|
||||||
alert(`Hello, my name is ${names.join(" ")}.
|
|
||||||
I was born in ${dob[2]}.
|
|
||||||
I have ${colors.length} favorite colors: ${colorString}.`);
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>The Bio App</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script src="bio.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
let isValid = false;
|
|
||||||
while (!isValid) {
|
|
||||||
const email = prompt("Enter your email address:");
|
|
||||||
if (email.startsWith("_") || email.startsWith(".")) {
|
|
||||||
alert("Email address may not start with a period or underscore.");
|
|
||||||
} else if (!email.includes("@")) {
|
|
||||||
alert("Email address must contain an @ symbol.");
|
|
||||||
} else if (!email.includes(".")) {
|
|
||||||
alert("Email address must contain a period.");
|
|
||||||
} else if (!email.includes(".", email.indexOf("@"))) {
|
|
||||||
alert("The period must come after the @ symbol.");
|
|
||||||
} else {
|
|
||||||
alert(`You entered: ${email}.\nThis is a valid email address.`);
|
|
||||||
isValid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>The Email Check App</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script src="email_check.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Average Test Scores</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<main>
|
|
||||||
<h1>The Test Scores App</h1>
|
|
||||||
<script src="test_scores.js"></script>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const scores = [];
|
|
||||||
|
|
||||||
// get scores from the user
|
|
||||||
while (true) {
|
|
||||||
const entry = prompt("Enter a test score. Or, enter 'x' to exit.");
|
|
||||||
if (entry === 'x' || entry === null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const score = parseInt(entry);
|
|
||||||
if (score >= 0 && score <= 100) {
|
|
||||||
scores[scores.length] = score;
|
|
||||||
} else {
|
|
||||||
alert("Score must by a valid number from 0 through 100.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there are no scores, notify user
|
|
||||||
if (scores.length === 0) {
|
|
||||||
alert("You didn't enter any scores.");
|
|
||||||
} else { // otherwise, calculate the total and create a display string
|
|
||||||
let total = 0;
|
|
||||||
let scoresString = "";
|
|
||||||
for (let i in scores) {
|
|
||||||
total += scores[i];
|
|
||||||
scoresString += `Score ${parseInt(i) + 1}: ${scores[i]}\n`;
|
|
||||||
}
|
|
||||||
const average = total/scores.length;
|
|
||||||
|
|
||||||
// display the scores and their average
|
|
||||||
alert(`${scoresString}Average score: ${average.toFixed(2)}`);
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Average Test Scores</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<main>
|
|
||||||
<h1>The Test Scores App</h1>
|
|
||||||
<script src="test_scores.js"></script>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const scores = [];
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
const entry = prompt("Enter a test score. Or, enter 'x' to exit.");
|
|
||||||
if (entry === 'x' || entry === null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const score = parseInt(entry);
|
|
||||||
if (score >= 0 && score <= 100) {
|
|
||||||
scores.push(score);
|
|
||||||
} else {
|
|
||||||
alert("Score must by a valid number from 0 through 100.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const len = scores.length;
|
|
||||||
if (len === 0) {
|
|
||||||
alert("You didn't enter any scores.");
|
|
||||||
} else {
|
|
||||||
// calculate total and average
|
|
||||||
let total = 0;
|
|
||||||
for (let score of scores) {
|
|
||||||
total += score;
|
|
||||||
}
|
|
||||||
const average = total/len;
|
|
||||||
|
|
||||||
// get the last 3 scores in reverse order
|
|
||||||
const lastScores = (len <= 3) ? scores.slice() : scores.slice(len - 3, len);
|
|
||||||
lastScores.reverse();
|
|
||||||
|
|
||||||
// display score data
|
|
||||||
alert("Scores: " + scores.join(", ") + "\n" +
|
|
||||||
"Total: " + total + "\n" +
|
|
||||||
"Average: " + average.toFixed(2) + "\n" +
|
|
||||||
"Last 3: " + lastScores.join(", "));
|
|
||||||
}
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
function getAsArray(promptMsg, separator = " ") {
|
|
||||||
return prompt(promptMsg).split(separator);
|
|
||||||
}
|
|
||||||
|
|
||||||
// use rest operator for the following functions so can accept either a
|
|
||||||
// comma-separated list of arguments or an array with a spread operator
|
|
||||||
function capitalize(...words) {
|
|
||||||
const capitalizedWords = [];
|
|
||||||
for (let word of words) {
|
|
||||||
const firstLetter = word.substring(0,1).toUpperCase();
|
|
||||||
const restOfWord = word.substring(1).toLowerCase();
|
|
||||||
capitalizedWords.push(firstLetter + restOfWord);
|
|
||||||
}
|
|
||||||
return capitalizedWords;
|
|
||||||
}
|
|
||||||
|
|
||||||
function trim(...items) {
|
|
||||||
const trimmedItems = [];
|
|
||||||
for (let item of items) {
|
|
||||||
trimmedItems.push(item.trim());
|
|
||||||
}
|
|
||||||
return trimmedItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getColorsString(...items) {
|
|
||||||
const firstItems = items.slice(0, -1);
|
|
||||||
const lastItem = items.at(-1);
|
|
||||||
return `${firstItems.join(", ")} and ${lastItem}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function displayBio(names, dob, colors) {
|
|
||||||
alert("Hello, my name is " + names.join(" ") + ".\n" +
|
|
||||||
"I was born in " + dob.at(-1) + ".\n" +
|
|
||||||
"I have " + colors.length + " favorite colors: " +
|
|
||||||
getColorsString(...colors) + ".");
|
|
||||||
}
|
|
||||||
|
|
||||||
const names = capitalize(...getAsArray("Enter your full name"));
|
|
||||||
const dob = getAsArray("Enter your DOB in mm-dd-yyyy format", "-");
|
|
||||||
|
|
||||||
const msg = "Enter your favorite colors, separated by commas";
|
|
||||||
const colors = trim(...getAsArray(msg, ","));
|
|
||||||
|
|
||||||
displayBio(names, dob, colors);
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>The Bio App</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script src="bio.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
function getNumber(promptMsg, defaultValue) {
|
|
||||||
let num = NaN;
|
|
||||||
while (isNaN(num)) {
|
|
||||||
num = parseFloat(prompt(promptMsg, defaultValue));
|
|
||||||
}
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
function calcFutureValue(investment, rate, years) {
|
|
||||||
let futureValue = investment;
|
|
||||||
for (let i = 0; i < years; i++) {
|
|
||||||
futureValue += futureValue * rate / 100;
|
|
||||||
}
|
|
||||||
return futureValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
function displayResults(investment, rate, years, futureValue) {
|
|
||||||
alert("Investment amount: $" + investment + "\n" +
|
|
||||||
"Interest rate: " + rate + "%\n" +
|
|
||||||
"Years: " + years + "\n" +
|
|
||||||
"Future Value: $" + futureValue.toFixed(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
const investment = getNumber("Enter investment amount as xxxxx.xx", 10000);
|
|
||||||
const rate = getNumber("Enter interest rate as xx.x", 7.5);
|
|
||||||
const years = getNumber("Enter number of years", 10);
|
|
||||||
const futureValue = calcFutureValue(investment, rate, years);
|
|
||||||
displayResults(investment, rate, years, futureValue);
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Future Value Calculator</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>The Future Value Calculator</h1>
|
|
||||||
<script src="future_value.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
// global variables
|
|
||||||
let randomNum = 0;
|
|
||||||
let tries = 0;
|
|
||||||
|
|
||||||
// helper function
|
|
||||||
const getRandomInt = (max = 100) => {
|
|
||||||
let num = Math.random() * max; // get a random number between 0 and max
|
|
||||||
num = Math.ceil(num); // round up to nearest integer
|
|
||||||
return num;
|
|
||||||
};
|
|
||||||
|
|
||||||
// event handler functions
|
|
||||||
const guessClick = () => {
|
|
||||||
const guess = parseInt(document.querySelector("#number").value);
|
|
||||||
|
|
||||||
let message = "";
|
|
||||||
if (isNaN(guess)) {
|
|
||||||
message = "Not a valid number. Please enter a valid number."
|
|
||||||
} else if (guess < 1 || guess > 10) {
|
|
||||||
message = "Invalid number. Enter a number between 1 and 10.";
|
|
||||||
} else if (guess < randomNum) {
|
|
||||||
message = "Too small. Try again.";
|
|
||||||
tries++;
|
|
||||||
} else if (guess > randomNum) {
|
|
||||||
message = "Too big. Try again.";
|
|
||||||
tries++;
|
|
||||||
} else if (guess === randomNum) {
|
|
||||||
tries++;
|
|
||||||
const lastWord = (tries === 1) ? "try" : "tries";
|
|
||||||
message = `You guessed it in ${tries} ${lastWord}!`;
|
|
||||||
}
|
|
||||||
document.querySelector("#message").textContent = message;
|
|
||||||
};
|
|
||||||
|
|
||||||
const playAgainClick = () => {
|
|
||||||
randomNum = getRandomInt(10);
|
|
||||||
tries = 0;
|
|
||||||
document.querySelector("#number").value = "";
|
|
||||||
document.querySelector("#message").textContent = "";
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
playAgainClick(); // initial a new game
|
|
||||||
|
|
||||||
document.querySelector("#guess").addEventListener(
|
|
||||||
"click", guessClick);
|
|
||||||
document.querySelector("#play_again").addEventListener(
|
|
||||||
"click", playAgainClick);
|
|
||||||
});
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Guess the Number</title>
|
|
||||||
<link rel="stylesheet" href="main.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Guess the Number</h1>
|
|
||||||
<p>It's between 1 and 10.</p>
|
|
||||||
|
|
||||||
<input type="text" id="number">
|
|
||||||
<button id="guess">Guess</button>
|
|
||||||
<button id="play_again">Play again</button><br>
|
|
||||||
<label id="message"></label>
|
|
||||||
|
|
||||||
<script src="guess.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 600px;
|
|
||||||
padding: 0 2em 1em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
}
|
|
||||||
input, button {
|
|
||||||
margin: 0 0.5em 1em 0;
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>My Typewriter App</title>
|
|
||||||
<link rel="stylesheet" href="typewriter.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>My Typewriter App</h1>
|
|
||||||
<pre id="text"></pre>
|
|
||||||
<script src="typewriter.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em;
|
|
||||||
padding: 0 2em 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
}
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
|
|
||||||
document.addEventListener("keydown", event => {
|
|
||||||
const pre = document.querySelector("#text");
|
|
||||||
|
|
||||||
const validChars = `abcdefghijklmnopqrstuvwxyz
|
|
||||||
ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
|
||||||
1234567890~!@#$%^&*()_+-=\;:'",.`;
|
|
||||||
|
|
||||||
if (validChars.includes(event.key)) {
|
|
||||||
pre.textContent += event.key;
|
|
||||||
}
|
|
||||||
else if (event.key.toLowerCase() === "enter") {
|
|
||||||
pre.textContent += "\n";
|
|
||||||
}
|
|
||||||
else if (event.key.toLowerCase() === "backspace") {
|
|
||||||
// remove last character
|
|
||||||
pre.textContent = pre.textContent.slice(0, -1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 500px;
|
|
||||||
padding: 0 2em 1em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
font-size: 150%;
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
font-size: 120%;
|
|
||||||
padding: 0 0 0 1.5em;
|
|
||||||
cursor: pointer;
|
|
||||||
background: url(images/plus.png) no-repeat left center;
|
|
||||||
}
|
|
||||||
h2.minus {
|
|
||||||
background: url(images/minus.png) no-repeat left center;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: black;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
a:focus, a:hover {
|
|
||||||
color: blue;
|
|
||||||
}
|
|
||||||
div {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
div.open {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
li {
|
|
||||||
padding-bottom: .25em;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
padding-bottom: .25em;
|
|
||||||
padding-left: 2em;
|
|
||||||
}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
// the event handler for the click event of each <h2> element
|
|
||||||
const toggleVisibility = evt => {
|
|
||||||
const h2 = evt.currentTarget; // get the <h2> element
|
|
||||||
const div = h2.nextElementSibling; // get the <div> element
|
|
||||||
|
|
||||||
h2.classList.toggle("minus");
|
|
||||||
div.classList.toggle("open");
|
|
||||||
|
|
||||||
evt.preventDefault(); // cancel default action of child <a> element
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
// get the <h2> elements
|
|
||||||
const h2s = document.querySelectorAll("#faqs h2");
|
|
||||||
|
|
||||||
// attach event handler for each <h2> tag
|
|
||||||
for (let h2 of h2s) {
|
|
||||||
h2.addEventListener("click", toggleVisibility);
|
|
||||||
}
|
|
||||||
// set focus on first <a> tag
|
|
||||||
h2s[0].firstChild.focus();
|
|
||||||
});
|
|
||||||
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 48 KiB |
@ -1,35 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>FAQs</title>
|
|
||||||
<link rel="stylesheet" href="faqs.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body id="faqs">
|
|
||||||
<h1>JavaScript FAQs</h1>
|
|
||||||
|
|
||||||
<h2><a href="#">What is JavaScript?</a></h2>
|
|
||||||
<div>
|
|
||||||
<p>JavaScript is a scripting language that you can use to make websites
|
|
||||||
interactive.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2><a href="#">Why use JavaScript?</a></h2>
|
|
||||||
<div>
|
|
||||||
<ul>
|
|
||||||
<li>It has simple syntax that's easy to learn.</li>
|
|
||||||
<li>It's versatile.</li>
|
|
||||||
<li>It's one of the most popular programming languages.</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2><a href="#">Which browsers support JavaScript?</a></h2>
|
|
||||||
<div>
|
|
||||||
<p>All the major modern browsers support JavaScript.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="faqs.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 550px;
|
|
||||||
padding: 0 1em 1em 0;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
h1, h2 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
}
|
|
||||||
li {
|
|
||||||
display: inline;
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const getElement = selector => document.querySelector(selector);
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
// get the main image and caption elements
|
|
||||||
const mainImage = getElement("#main_image");
|
|
||||||
const caption = getElement("#caption");
|
|
||||||
|
|
||||||
// get all the <a> elements in the <ul> element
|
|
||||||
const imageLinks = document.querySelectorAll("#image_list a");
|
|
||||||
|
|
||||||
// process image links
|
|
||||||
for ( let link of imageLinks ) {
|
|
||||||
|
|
||||||
// preload image
|
|
||||||
const image = new Image();
|
|
||||||
image.src = link.href;
|
|
||||||
|
|
||||||
// attach event handler for click event of <a> element
|
|
||||||
link.addEventListener("click", evt => {
|
|
||||||
mainImage.src = link.href;
|
|
||||||
mainImage.alt = link.title;
|
|
||||||
caption.textContent = link.title;
|
|
||||||
|
|
||||||
evt.preventDefault(); // cancel the default action of the link
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// set focus on first image link
|
|
||||||
imageLinks[0].focus();
|
|
||||||
});
|
|
||||||
|
Before Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 73 KiB |
@ -1,30 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Fishing Images Viewer</title>
|
|
||||||
<link rel="stylesheet" href="image_swap.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Fishing Images</h1>
|
|
||||||
<p>Click on an image to enlarge.</p>
|
|
||||||
|
|
||||||
<ul id="image_list">
|
|
||||||
<li><a href="images/release.jpg" title="Catch and Release">
|
|
||||||
<img src="thumbnails/release.jpg" alt="release fish"></a></li>
|
|
||||||
<li><a href="images/deer.jpg" title="Deer at Play">
|
|
||||||
<img src="thumbnails/deer.jpg" alt="deer"></a></li>
|
|
||||||
<li><a href="images/hero.jpg" title="The Big One!">
|
|
||||||
<img src="thumbnails/hero.jpg" alt="big fish"></a></li>
|
|
||||||
<li><a href="images/bison.jpg" title="Roaming Bison">
|
|
||||||
<img src="thumbnails/bison.jpg" alt="Bison"></a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="caption">Catch and Release</h2>
|
|
||||||
<p><img id="main_image" src="images/release.jpg"
|
|
||||||
alt="Catch and Release"></p>
|
|
||||||
|
|
||||||
<script src="image_swap.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
@ -1,17 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Registration</title>
|
|
||||||
<link rel="stylesheet" href="register.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<main>
|
|
||||||
<h1>Thanks for registering with us!</h1>
|
|
||||||
<p>You should get a confirmation email shortly.</p>
|
|
||||||
<p><a href="index.html">Go back</a></p>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Registration</title>
|
|
||||||
<link rel="stylesheet" href="register.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<main>
|
|
||||||
<h1>Register for an Account</h1>
|
|
||||||
<form action="confirm.html" method="post">
|
|
||||||
<div>
|
|
||||||
<label for="email_address">E-Mail:</label>
|
|
||||||
<input type="text" name="email_address" id="email_address">
|
|
||||||
<span>*</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="phone">Mobile Phone:</label>
|
|
||||||
<input type="text" name="phone" id="phone">
|
|
||||||
<span>*</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="country">Country:</label>
|
|
||||||
<select name="country" id="country">
|
|
||||||
<option value="">Select a country</option>
|
|
||||||
<option>USA</option>
|
|
||||||
<option>Canada</option>
|
|
||||||
<option>Mexico</option>
|
|
||||||
</select>
|
|
||||||
<span>*</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Contact me by:</label>
|
|
||||||
<input type="radio" name="contact" id="text"
|
|
||||||
value="text" checked>Text
|
|
||||||
<input type="radio" name="contact" id="email"
|
|
||||||
value="email">Email
|
|
||||||
<input type="radio" name="contact" id="none"
|
|
||||||
value="none">Don't contact me
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Terms of Service:</label>
|
|
||||||
<input type="checkbox" name="terms" id="terms"
|
|
||||||
value="yes">I accept
|
|
||||||
<span>*</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label> </label>
|
|
||||||
<input type="button" id="register" value="Register">
|
|
||||||
<input type="button" id="reset_form" value="Reset">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
</main>
|
|
||||||
<script src="register.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 600px;
|
|
||||||
padding: 0 2em 1em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: slategray;
|
|
||||||
padding-left: 1em;
|
|
||||||
}
|
|
||||||
div {
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
display: inline-block;
|
|
||||||
width: 11em;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
input, select {
|
|
||||||
margin-left: 1em;
|
|
||||||
margin-right: 0.5em;
|
|
||||||
padding: 0.25em;
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
width: 13em;
|
|
||||||
}
|
|
||||||
span {
|
|
||||||
color: red;
|
|
||||||
margin-left: 0.25em;
|
|
||||||
}
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const getElement = selector => document.querySelector(selector);
|
|
||||||
|
|
||||||
const processEntries = () => {
|
|
||||||
// get form controls to check for validity
|
|
||||||
const email = getElement("#email_address");
|
|
||||||
const phone = getElement("#phone");
|
|
||||||
const country = getElement("#country");
|
|
||||||
const terms = getElement("#terms");
|
|
||||||
|
|
||||||
// check user entries for validity
|
|
||||||
let isValid = true;
|
|
||||||
if (email.value == "") {
|
|
||||||
email.nextElementSibling.textContent = "This field is required.";
|
|
||||||
isValid = false;
|
|
||||||
} else {
|
|
||||||
email.nextElementSibling.textContent = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (phone.value == "") {
|
|
||||||
phone.nextElementSibling.textContent = "This field is required.";
|
|
||||||
isValid = false;
|
|
||||||
} else {
|
|
||||||
phone.nextElementSibling.textContent = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (country.value == "") {
|
|
||||||
country.nextElementSibling.textContent = "Please select a country.";
|
|
||||||
isValid = false;
|
|
||||||
} else {
|
|
||||||
country.nextElementSibling.textContent = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!terms.checked) {
|
|
||||||
terms.nextElementSibling.textContent = "This box must be checked.";
|
|
||||||
isValid = false;
|
|
||||||
} else {
|
|
||||||
terms.nextElementSibling.textContent = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// submit the form if all fields are valid
|
|
||||||
if (isValid) {
|
|
||||||
getElement("form").submit();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const resetForm = () => {
|
|
||||||
getElement("form").reset();
|
|
||||||
getElement("#email_address").nextElementSibling.textContent = "*";
|
|
||||||
getElement("#phone").nextElementSibling.textContent = "*";
|
|
||||||
getElement("#country").nextElementSibling.textContent = "*";
|
|
||||||
getElement("#terms").nextElementSibling.textContent = "*";
|
|
||||||
getElement("#email_address").focus();
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
getElement("#register").addEventListener("click", processEntries);
|
|
||||||
getElement("#reset_form").addEventListener("click", resetForm);
|
|
||||||
getElement("#email_address").focus();
|
|
||||||
});
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Registration</title>
|
|
||||||
<link rel="stylesheet" href="register.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<main>
|
|
||||||
<h1>Thanks for registering with us!</h1>
|
|
||||||
<p>You should get a confirmation email shortly.</p>
|
|
||||||
<p><a href="index.html">Go back</a></p>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Registration</title>
|
|
||||||
<link rel="stylesheet" href="register.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<main>
|
|
||||||
<h1>Register for an Account</h1>
|
|
||||||
<form action="confirm.html" method="post">
|
|
||||||
<div>
|
|
||||||
<label for="email_address">E-Mail:</label>
|
|
||||||
<input type="text" name="email_address" id="email_address">
|
|
||||||
<span>*</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="phone">Mobile Phone:</label>
|
|
||||||
<input type="text" name="phone" id="phone">
|
|
||||||
<span>*</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="country">Country:</label>
|
|
||||||
<select name="country" id="country">
|
|
||||||
<option value="">Select a country</option>
|
|
||||||
<option>USA</option>
|
|
||||||
<option>Canada</option>
|
|
||||||
<option>Mexico</option>
|
|
||||||
</select>
|
|
||||||
<span>*</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Contact me by:</label>
|
|
||||||
<input type="radio" name="contact" id="text"
|
|
||||||
value="text" checked>Text
|
|
||||||
<input type="radio" name="contact" id="email"
|
|
||||||
value="email">Email
|
|
||||||
<input type="radio" name="contact" id="none"
|
|
||||||
value="none">Don't contact me
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Terms of Service:</label>
|
|
||||||
<input type="checkbox" name="terms" id="terms"
|
|
||||||
value="yes">I accept
|
|
||||||
<span>*</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label> </label>
|
|
||||||
<input type="button" id="register" value="Register">
|
|
||||||
<input type="button" id="reset_form" value="Reset">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
</main>
|
|
||||||
<script src="register.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 600px;
|
|
||||||
padding: 0 2em 1em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: slategray;
|
|
||||||
padding-left: 1em;
|
|
||||||
}
|
|
||||||
div {
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
display: inline-block;
|
|
||||||
width: 11em;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
input, select {
|
|
||||||
margin-left: 1em;
|
|
||||||
margin-right: 0.5em;
|
|
||||||
padding: 0.25em;
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
width: 13em;
|
|
||||||
}
|
|
||||||
span {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
.messages {
|
|
||||||
color: red;
|
|
||||||
padding: 1em 2em;
|
|
||||||
margin-bottom: 2em;
|
|
||||||
border: 2px solid red;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
@ -1,79 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const getElement = selector => document.querySelector(selector);
|
|
||||||
|
|
||||||
const displayErrorMsgs = msgs => {
|
|
||||||
// create a new ul element
|
|
||||||
const ul = document.createElement("ul");
|
|
||||||
ul.classList.add("messages");
|
|
||||||
|
|
||||||
// create a new li element for each error message, add to ul
|
|
||||||
for (let msg of msgs) {
|
|
||||||
const li = document.createElement("li");
|
|
||||||
const text = document.createTextNode(msg);
|
|
||||||
li.appendChild(text);
|
|
||||||
ul.appendChild(li);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if ul node isn't in document yet, add it
|
|
||||||
const node = getElement("ul");
|
|
||||||
if (node == null) {
|
|
||||||
// get the form element
|
|
||||||
const form = getElement("form");
|
|
||||||
|
|
||||||
// add ul to parent of form, before the form
|
|
||||||
form.parentNode.insertBefore(ul, form);
|
|
||||||
} else {
|
|
||||||
// replace existing ul node
|
|
||||||
node.parentNode.replaceChild(ul, node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const processEntries = () => {
|
|
||||||
// get form controls to check for validity
|
|
||||||
const email = getElement("#email_address");
|
|
||||||
const phone = getElement("#phone");
|
|
||||||
const country = getElement("#country");
|
|
||||||
const terms = getElement("#terms");
|
|
||||||
|
|
||||||
// create array for error messages
|
|
||||||
const msgs = [];
|
|
||||||
|
|
||||||
// check user entries for validity
|
|
||||||
if (email.value === "") {
|
|
||||||
msgs.push("Please enter an email address.");
|
|
||||||
}
|
|
||||||
if (phone.value === "") {
|
|
||||||
msgs.push("Please enter a mobile phone number.");
|
|
||||||
}
|
|
||||||
if (country.value === "") {
|
|
||||||
msgs.push("Please select a country.");
|
|
||||||
}
|
|
||||||
if (!terms.checked) {
|
|
||||||
msgs.push("You must agree to the terms of service.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// submit the form or notify user of errors
|
|
||||||
if (msgs.length === 0) { // no error messages
|
|
||||||
getElement("form").submit();
|
|
||||||
} else {
|
|
||||||
displayErrorMsgs(msgs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const resetForm = () => {
|
|
||||||
getElement("form").reset();
|
|
||||||
|
|
||||||
// remove error messages if any
|
|
||||||
const ul = getElement("ul");
|
|
||||||
if (ul !== null) ul.remove();
|
|
||||||
|
|
||||||
getElement("#email_address").focus();
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
getElement("#register").addEventListener("click", processEntries);
|
|
||||||
getElement("#reset_form").addEventListener("click", resetForm);
|
|
||||||
|
|
||||||
getElement("#email_address").focus();
|
|
||||||
});
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 600px;
|
|
||||||
padding: 0 2em 0;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
}
|
|
||||||
div {
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
display: inline-block;
|
|
||||||
width: 11em;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
input {
|
|
||||||
width: 15em;
|
|
||||||
margin-left: 1em;
|
|
||||||
}
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
function getElement(selector) {
|
|
||||||
return document.querySelector(selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isNotValid(val) {
|
|
||||||
/*
|
|
||||||
if (isNaN(val)) {
|
|
||||||
console.error("Value is not a number");
|
|
||||||
} else if (val <= 0) {
|
|
||||||
console.warn(`Value ${val} is not greater than zero.`);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return isNaN(val) || val <= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function calcFutureValue(investment, rate, years) {
|
|
||||||
// console.log("calcFutureValue() has started");
|
|
||||||
// console.trace();
|
|
||||||
let futureValue = investment;
|
|
||||||
for (let i = 1; i <= years; i++) {
|
|
||||||
futureValue += futureValue * rate / 100;
|
|
||||||
// console.log(`year ${i} future value is ${futureValue}`);
|
|
||||||
}
|
|
||||||
return futureValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
function calcButtonClick() {
|
|
||||||
// clear any previous calculation
|
|
||||||
getElement("#future_value").value = "";
|
|
||||||
|
|
||||||
// get values user entered in text boxes
|
|
||||||
const investment = parseFloat(getElement("#investment").value);
|
|
||||||
const rate = parseFloat(getElement("#rate").value);
|
|
||||||
const years = parseInt(getElement("#years").value);
|
|
||||||
|
|
||||||
// check user entries and set error message
|
|
||||||
let errorMsg = "";
|
|
||||||
if (isNotValid(investment)) {
|
|
||||||
errorMsg += "Investment amount must be a positive number.\n";
|
|
||||||
getElement("#investment").focus();
|
|
||||||
}
|
|
||||||
if (isNotValid(rate)) {
|
|
||||||
errorMsg += "Interest rate must be a positive number.\n";
|
|
||||||
getElement("#rate").focus();
|
|
||||||
}
|
|
||||||
if (isNotValid(years)) {
|
|
||||||
errorMsg += "Number of years must be a positive number.";
|
|
||||||
getElement("#years").focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
// if user entries are valid, calculate and display future value
|
|
||||||
if (errorMsg == "") {
|
|
||||||
const futureValue = calcFutureValue(investment, rate, years);
|
|
||||||
getElement("#future_value").value = futureValue.toFixed(2);
|
|
||||||
} else {
|
|
||||||
alert(errorMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
// attach the button click event handler
|
|
||||||
getElement("#calculate").addEventListener("click", calcButtonClick);
|
|
||||||
|
|
||||||
// set focus on first text box on initial load
|
|
||||||
getElement("#investment").focus();
|
|
||||||
});
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Future Value Calculator</title>
|
|
||||||
<link rel="stylesheet" href="future_value.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>The Future Value Calculator</h1>
|
|
||||||
<div>
|
|
||||||
<label for="investment">Total investment:</label>
|
|
||||||
<input type="text" id="investment" value="1000">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="rate">Annual interest rate:</label>
|
|
||||||
<input type="text" id="rate" value="3.5">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="years">Number of years</label>
|
|
||||||
<input type="text" id="years" value="10">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Future value:</label>
|
|
||||||
<input type="text" id="future_value" disabled>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label> </label>
|
|
||||||
<input type="button" id="calculate" value="Calculate">
|
|
||||||
</div>
|
|
||||||
<script src="future_value.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 600px;
|
|
||||||
padding: 0 2em 1em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
}
|
|
||||||
div {
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
display: inline-block;
|
|
||||||
width: 11em;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
input {
|
|
||||||
margin-left: 1em;
|
|
||||||
margin-right: 0.5em;
|
|
||||||
width: 15em;
|
|
||||||
}
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
function getElement(selector) {
|
|
||||||
return document.querySelector(selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isNotValid(val) {
|
|
||||||
return isNaN(val) || val <= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function calcFutureValue(investment, rate, years) {
|
|
||||||
let futureValue = investment;
|
|
||||||
for (let i = 0; i < years; i++) {
|
|
||||||
futureValue += futureValue * rate / 100;
|
|
||||||
}
|
|
||||||
return futureValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
function calcButtonClick() {
|
|
||||||
// clear any previous calculation
|
|
||||||
getElement("#future_value").value = "";
|
|
||||||
|
|
||||||
// get values user entered in textboxes
|
|
||||||
const investment = parseFloat(getElement("#investment").value);
|
|
||||||
const rate = parseFloat(getElement("#rate").value);
|
|
||||||
const years = parseInt(getElement("#years").value);
|
|
||||||
|
|
||||||
// check user entries and set error message
|
|
||||||
let errorMsg = "";
|
|
||||||
if (isNotValid(investment)) {
|
|
||||||
errorMsg += "Investment amount must be a positive number.\n";
|
|
||||||
getElement("#investment").focus();
|
|
||||||
}
|
|
||||||
if (isNotValid(rate)) {
|
|
||||||
errorMsg += "Interest rate must be a positive number.\n";
|
|
||||||
getElement("#rate").focus();
|
|
||||||
}
|
|
||||||
if (isNotValid(years)) {
|
|
||||||
errorMsg += "Number of years must be a positive number.";
|
|
||||||
getElement("#years").focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
// if user entries are valid, calculate and display future value
|
|
||||||
if (errorMsg == "") {
|
|
||||||
const futureValue = calcFutureValue(investment, rate, years);
|
|
||||||
getElement("#future_value").value = futureValue.toFixed(2);
|
|
||||||
} else {
|
|
||||||
alert(errorMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
// attach the event handler
|
|
||||||
getElement("#calculate").addEventListener("click", calcButtonClick);
|
|
||||||
|
|
||||||
// set focus on first text box on initial load
|
|
||||||
getElement("#investment").focus();
|
|
||||||
});
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Future Value Calculator</title>
|
|
||||||
<link rel="stylesheet" href="future_value.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>The Future Value Calculator</h1>
|
|
||||||
<div>
|
|
||||||
<label for="investment">Total investment:</label>
|
|
||||||
<input type="text" id="investment" value="1000">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="Rate">Annual interest rate:</label>
|
|
||||||
<input type="text" id="rate" value="3.5">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="years">Number of years</label>
|
|
||||||
<input type="text" id="years" value="10">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Future value:</label>
|
|
||||||
<input type="text" id="future_value" value="" disabled>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label> </label>
|
|
||||||
<input type="button" id="calculate" value="Calculate">
|
|
||||||
</div>
|
|
||||||
<script src="future_value.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const getElement = selector => document.querySelector(selector);
|
|
||||||
|
|
||||||
const padValue = value => value.toString().padStart(2, "0");
|
|
||||||
|
|
||||||
const displayClock = () => {
|
|
||||||
const now = new Date();
|
|
||||||
const ampm = (now.getHours() >= 12) ? "PM" : "AM";
|
|
||||||
const hours = (now.getHours() > 12) ? now.getHours() - 12 : now.getHours();
|
|
||||||
const minutes = padValue(now.getMinutes());
|
|
||||||
const seconds = padValue(now.getSeconds());
|
|
||||||
|
|
||||||
getElement("#time").textContent = `${hours}:${minutes}:${seconds} ${ampm}`;
|
|
||||||
getElement("#date").textContent = now.toDateString();
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
// set initial clock time and then start interval for clock
|
|
||||||
displayClock();
|
|
||||||
setInterval(displayClock, 1000);
|
|
||||||
});
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Clock</title>
|
|
||||||
<link rel="stylesheet" href="main.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>My Clock</h1>
|
|
||||||
<p id="time"></p>
|
|
||||||
<p id="date"></p>
|
|
||||||
<script src="clock.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 150px;
|
|
||||||
padding: 0 2em 1em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
font-size: large;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 450px;
|
|
||||||
padding: 0 1em 0 2em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
}
|
|
||||||
div {
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
display: inline-block;
|
|
||||||
width: 6em;
|
|
||||||
}
|
|
||||||
input {
|
|
||||||
height: 1.5em;
|
|
||||||
width: 20em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 0.25em;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
height: 2em;
|
|
||||||
width: 10em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 0.25em;
|
|
||||||
}
|
|
||||||
#message {
|
|
||||||
color: red;
|
|
||||||
font-weight: bold;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const getElement = selector => document.querySelector(selector);
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
|
|
||||||
getElement("#countdown").addEventListener("click", () => {
|
|
||||||
const eventName = getElement("#event").value;
|
|
||||||
const eventDateString = getElement("#date").value;
|
|
||||||
const messageLbl = getElement("#message");
|
|
||||||
|
|
||||||
// make sure user entered event and date
|
|
||||||
if (eventName == "" || eventDateString == "") {
|
|
||||||
messageLbl.textContent = "Please enter both a name and a date.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert event date string to Date object and check for validity
|
|
||||||
const eventDate = new Date(eventDateString);
|
|
||||||
if (eventDate.toString() == "Invalid Date") {
|
|
||||||
messageLbl.textContent = "Please enter a valid date.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate days
|
|
||||||
const today = new Date();
|
|
||||||
const msFromToday = eventDate.getTime() - today.getTime();
|
|
||||||
const msForOneDay = 24 * 60 * 60 * 1000; // hrs * mins * secs * milliseconds
|
|
||||||
const daysToDate = Math.ceil( msFromToday / msForOneDay );
|
|
||||||
|
|
||||||
// create and display message
|
|
||||||
const displayDate = eventDate.toDateString();
|
|
||||||
let msg = "";
|
|
||||||
if (daysToDate == 0) {
|
|
||||||
msg = `Hooray! Today is ${eventName}! (${displayDate})`;
|
|
||||||
} else if (daysToDate > 0) {
|
|
||||||
msg = `${daysToDate} day(s) until ${eventName}! (${displayDate})`;
|
|
||||||
} else if (daysToDate < 0) {
|
|
||||||
msg = `${eventName} happened ${Math.abs(daysToDate)}
|
|
||||||
day(s) ago. (${displayDate})`;
|
|
||||||
}
|
|
||||||
messageLbl.textContent = msg;
|
|
||||||
});
|
|
||||||
|
|
||||||
// set focus on first text box
|
|
||||||
getElement("#event").focus();
|
|
||||||
});
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Countdown</title>
|
|
||||||
<link rel="stylesheet" href="countdown.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Countdown To...</h1>
|
|
||||||
<div>
|
|
||||||
<label for="event">Event Name:</label>
|
|
||||||
<input type="text" id="event">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="date">Event Date:</label>
|
|
||||||
<input type="text" id="date"><br>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label> </label>
|
|
||||||
<button id="countdown">Countdown!</button>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label id="message"></label>
|
|
||||||
</div>
|
|
||||||
<script src="countdown.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
Before Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 73 KiB |
@ -1,21 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Fishing Slide Show</title>
|
|
||||||
<link rel="stylesheet" href="slide_show.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Fishing Slide Show</h1>
|
|
||||||
<ul id="image_list">
|
|
||||||
<li><a href="images/release.jpg" title="Catch and Release"></a></li>
|
|
||||||
<li><a href="images/deer.jpg" title="Deer at Play"></a></li>
|
|
||||||
<li><a href="images/hero.jpg" title="The Big One!"></a></li>
|
|
||||||
<li><a href="images/bison.jpg" title="Roaming Bison"></a></li>
|
|
||||||
</ul>
|
|
||||||
<p><img id="main_image"></p>
|
|
||||||
<h2 id="caption"></h2>
|
|
||||||
<script src="slide_show.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 500px;
|
|
||||||
padding: 0 2em 1em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
h1, h2 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
}
|
|
||||||
ul {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const getElement = selector => document.querySelector(selector);
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
// get elements for the image and caption
|
|
||||||
const mainImage = getElement("#main_image"); // the img element for the show
|
|
||||||
const caption = getElement("#caption"); // the h2 element for the caption
|
|
||||||
|
|
||||||
// get all the <a> elements in the <ul> element
|
|
||||||
const links = document.querySelectorAll("#image_list a");
|
|
||||||
|
|
||||||
// Process images
|
|
||||||
const imageCache = [];
|
|
||||||
let image = null;
|
|
||||||
|
|
||||||
for (let link of links) {
|
|
||||||
// Preload image
|
|
||||||
image = new Image();
|
|
||||||
image.src = link.href;
|
|
||||||
image.alt = link.title;
|
|
||||||
// add image to array
|
|
||||||
imageCache.push(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set initial image and caption
|
|
||||||
mainImage.src = imageCache[0].src;
|
|
||||||
mainImage.alt = imageCache[0].alt;
|
|
||||||
caption.textContent = imageCache[0].alt;
|
|
||||||
|
|
||||||
// start slide show
|
|
||||||
let imageCounter = 0;
|
|
||||||
setInterval(() => { // first parameter – anonymous function
|
|
||||||
// calculate the index for the current image
|
|
||||||
imageCounter = (imageCounter + 1) % imageCache.length;
|
|
||||||
|
|
||||||
// get image object from array
|
|
||||||
image = imageCache[imageCounter];
|
|
||||||
|
|
||||||
// set image and caption with values from image object
|
|
||||||
mainImage.src = image.src;
|
|
||||||
mainImage.alt = image.alt;
|
|
||||||
caption.textContent = image.alt;
|
|
||||||
},
|
|
||||||
2000); // second parameter - 2 second interval
|
|
||||||
});
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Timer</title>
|
|
||||||
<link rel="stylesheet" href="main.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>My Timer</h1>
|
|
||||||
<p id="display_timer"></p>
|
|
||||||
<button id="start_timer">Start Timer</button>
|
|
||||||
<script src="timer.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 150px;
|
|
||||||
padding: 0 2em 1em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
font-size: large;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
height: 3em;
|
|
||||||
min-width: 10em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 0.5em;
|
|
||||||
}
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
let timer = null;
|
|
||||||
let endTime = null;
|
|
||||||
|
|
||||||
const getElement = selector => document.querySelector(selector);
|
|
||||||
|
|
||||||
const padValue = value => value.toString().padStart(2, "0");
|
|
||||||
|
|
||||||
const displayTimer = () => {
|
|
||||||
const now = new Date();
|
|
||||||
const diff = endTime.getTime() - now.getTime();
|
|
||||||
if (diff <= 0) {
|
|
||||||
clearInterval(timer);
|
|
||||||
getElement("#display_timer").textContent = "";
|
|
||||||
alert("Time's up!!");
|
|
||||||
} else {
|
|
||||||
const timerDate = new Date(diff);
|
|
||||||
const minutes = padValue(timerDate.getMinutes());
|
|
||||||
const seconds = padValue(timerDate.getSeconds());
|
|
||||||
getElement("#display_timer").textContent = `${minutes}:${seconds}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const startTimer = () => {
|
|
||||||
let minutes = NaN;
|
|
||||||
while (!(minutes > 0 && minutes < 10)) {
|
|
||||||
minutes = parseInt(prompt("Please enter 1 to 10 minutes."));
|
|
||||||
}
|
|
||||||
endTime = new Date();
|
|
||||||
endTime.setMinutes(endTime.getMinutes() + minutes);
|
|
||||||
|
|
||||||
// display timer and then start interval for timer
|
|
||||||
displayTimer();
|
|
||||||
timer = setInterval(displayTimer, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
// attach event handler for timer button
|
|
||||||
getElement("#start_timer").addEventListener("click", startTimer);
|
|
||||||
});
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>My Trivia</title>
|
|
||||||
<link href="main.css" rel="stylesheet">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>My Trivia</h1>
|
|
||||||
<div id="question">
|
|
||||||
<p>You have <span id="seconds">10</span> seconds to answer.</p>
|
|
||||||
<label>What is the capitol of Vermont? </label>
|
|
||||||
<input type="radio" name="city" id="bur" value="Burlington">Burlington
|
|
||||||
<input type="radio" name="city" id="mont" value="Montpelier">Montpelier
|
|
||||||
<input type="radio" name="city" id="con" value="Concord">Concord
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
let timer = null;
|
|
||||||
const div = document.querySelector("#question");
|
|
||||||
|
|
||||||
const updateTime = () => {
|
|
||||||
const span = document.querySelector("#seconds");
|
|
||||||
const seconds = parseInt(span.textContent) - 1;
|
|
||||||
|
|
||||||
if (seconds == 0) {
|
|
||||||
clearInterval(timer);
|
|
||||||
div.textContent = "Time's up!!";
|
|
||||||
} else {
|
|
||||||
span.textContent = seconds;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const processAnswer = evt => {
|
|
||||||
clearInterval(timer);
|
|
||||||
if (evt.currentTarget.value === "Montpelier") {
|
|
||||||
div.textContent = "Correct!! The capitol of Vermont is Montpelier.";
|
|
||||||
} else {
|
|
||||||
div.textContent = "Sorry - the capitol of Vermont is Montpelier.";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
timer = setInterval(updateTime, 1000);
|
|
||||||
|
|
||||||
const options = div.querySelectorAll("input");
|
|
||||||
for (let opt of options) {
|
|
||||||
opt.addEventListener("click", processAnswer);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 520px;
|
|
||||||
padding: 0 2em 1em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
}
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
// function that simulates an external service that is sometimes down
|
|
||||||
function getCurrentInterestRate() {
|
|
||||||
const random = Math.ceil(Math.random() * 10);
|
|
||||||
if (random === 1) {
|
|
||||||
throw new Error("Interest Rate API is down.");
|
|
||||||
} else {
|
|
||||||
return 3.9;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function calcFutureValue(investment, years) {
|
|
||||||
// convert to numeric values
|
|
||||||
investment = parseFloat(investment);
|
|
||||||
years = parseInt(years);
|
|
||||||
|
|
||||||
// throw error if investment and years aren't numbers greater than zero
|
|
||||||
if (isNaN(investment) || investment <= 0) {
|
|
||||||
throw new Error("Investment amount must be a number greater than zero.");
|
|
||||||
}
|
|
||||||
if (isNaN(years) || years <= 0) {
|
|
||||||
throw new Error("Years must be a number greater than zero.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// get interest rate - throw error if service returns an error
|
|
||||||
let rate = 0;
|
|
||||||
try {
|
|
||||||
rate = getCurrentInterestRate();
|
|
||||||
} catch(e) {
|
|
||||||
throw new Error("Unable to calculate future value. " + e.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if no errors, calculate and return future value
|
|
||||||
let futureValue = investment;
|
|
||||||
for (let i = 1; i <= years; i++) {
|
|
||||||
futureValue += futureValue * rate / 100;
|
|
||||||
}
|
|
||||||
return Number(futureValue.toFixed(2));
|
|
||||||
};
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
padding-left: 1em;
|
|
||||||
width: 600px;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
display: inline-block;
|
|
||||||
width: 8em;
|
|
||||||
}
|
|
||||||
input {
|
|
||||||
height: 1.5em;
|
|
||||||
width: 10em;
|
|
||||||
margin: 0 0.5em 1em 0;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 0.25em;
|
|
||||||
}
|
|
||||||
input[type="submit"], input[type="reset"] {
|
|
||||||
height: 2em;
|
|
||||||
width: 6em;
|
|
||||||
}
|
|
||||||
span, #message {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const getElement = selector => document.querySelector(selector);
|
|
||||||
|
|
||||||
const clearMessages = () => {
|
|
||||||
getElement("#investment").nextElementSibling.textContent = "*";
|
|
||||||
getElement("#years").nextElementSibling.textContent = "*";
|
|
||||||
getElement("#message").textContent = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
const form = getElement("form");
|
|
||||||
form.noValidate = true;
|
|
||||||
|
|
||||||
for (let element of form.elements) {
|
|
||||||
element.addEventListener("invalid", evt => {
|
|
||||||
const elem = evt.currentTarget;
|
|
||||||
const span = elem.nextElementSibling;
|
|
||||||
if (span) span.textContent = elem.validationMessage;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
form.addEventListener("submit", evt => {
|
|
||||||
clearMessages();
|
|
||||||
evt.preventDefault(); // prevent form submission in all cases
|
|
||||||
|
|
||||||
// get future value text box and clear any previous value
|
|
||||||
const fv = getElement("#future_value");
|
|
||||||
fv.value = "";
|
|
||||||
|
|
||||||
// if form is valid, display future value or error message
|
|
||||||
if (form.checkValidity()) {
|
|
||||||
try {
|
|
||||||
const investment = getElement("#investment").value;
|
|
||||||
const years = getElement("#years").value;
|
|
||||||
fv.value = calcFutureValue(investment, years);
|
|
||||||
} catch(e) {
|
|
||||||
const msg = `${e.name}: ${e.message}`;
|
|
||||||
getElement("#message").textContent = msg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
getElement("#clear").addEventListener("click", () => {
|
|
||||||
clearMessages();
|
|
||||||
getElement("#investment").focus();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Future Value Calculator</title>
|
|
||||||
<link rel="stylesheet" href="future_value.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<form action="#" method="get">
|
|
||||||
<h1>The Future Value Calculator</h1>
|
|
||||||
|
|
||||||
<label for="investment">Total investment:</label>
|
|
||||||
<input type="number" id="investment"
|
|
||||||
min="0" max="1000" step="100" required autofocus>
|
|
||||||
<span>*</span><br>
|
|
||||||
|
|
||||||
<label for="years">Number of years:</label>
|
|
||||||
<input type="number" id="years" min="0" max="10" step="1" required>
|
|
||||||
<span>*</span><br>
|
|
||||||
|
|
||||||
<label>Future value:</label>
|
|
||||||
<input type="text" id="future_value" disabled><br>
|
|
||||||
|
|
||||||
<label></label>
|
|
||||||
<input type="submit" id="calculate" value="Calculate">
|
|
||||||
<input type="reset" id="clear" value="Clear">
|
|
||||||
|
|
||||||
<p id="message"></p>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<script src="calc_future_value.js"></script>
|
|
||||||
<script src="future_value.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Registration</title>
|
|
||||||
<link rel="stylesheet" href="register.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<main>
|
|
||||||
<h1>Thanks for registering with us!</h1>
|
|
||||||
<p>You should get a confirmation email shortly.</p>
|
|
||||||
<p><a href="index.html">Go back</a></p>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Registration</title>
|
|
||||||
<link rel="stylesheet" href="register.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<main>
|
|
||||||
<h1>Register for an Account</h1>
|
|
||||||
<form action="confirm.html" method="post">
|
|
||||||
<label for="email_address">E-Mail:</label>
|
|
||||||
<input type="email" name="email_address" id="email_address"
|
|
||||||
placeholder="name@domain.com" autocomplete="off"
|
|
||||||
autofocus required>
|
|
||||||
<span>*</span><br>
|
|
||||||
|
|
||||||
<label for="dob">DOB:</label>
|
|
||||||
<input type="date" name="dob" id="dob" required>
|
|
||||||
<span>*</span><br>
|
|
||||||
|
|
||||||
<label for="phone">Mobile Phone:</label>
|
|
||||||
<input type="tel" name="phone" id="phone"
|
|
||||||
autocomplete="off"
|
|
||||||
pattern="\d{3}[\-]\d{3}[\-]\d{4}"
|
|
||||||
title="Must be nnn-nnn-nnnn" required>
|
|
||||||
<span>*</span><br>
|
|
||||||
|
|
||||||
<label for="country">Country:</label>
|
|
||||||
<select name="country" id="country" required>
|
|
||||||
<option value="">Select a country</option>
|
|
||||||
<option>USA</option>
|
|
||||||
<option>Canada</option>
|
|
||||||
<option>Mexico</option>
|
|
||||||
</select>
|
|
||||||
<span>*</span><br>
|
|
||||||
|
|
||||||
<label>Contact me by:</label>
|
|
||||||
<input type="radio" name="contact" id="text"
|
|
||||||
value="text" checked>Text
|
|
||||||
<input type="radio" name="contact" id="email"
|
|
||||||
value="email">Email
|
|
||||||
<input type="radio" name="contact" id="none"
|
|
||||||
value="none">Don't contact me<br>
|
|
||||||
|
|
||||||
<label>Terms of Service:</label>
|
|
||||||
<input type="checkbox" name="terms" id="terms"
|
|
||||||
value="yes" required>I accept
|
|
||||||
<span>*</span><br>
|
|
||||||
|
|
||||||
<label> </label>
|
|
||||||
<input type="submit" id="register" value="Register">
|
|
||||||
<input type="reset" id="reset_form" value="Reset">
|
|
||||||
</form>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 600px;
|
|
||||||
padding: 0 2em 1em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
padding-left: 1em;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
display: inline-block;
|
|
||||||
width: 11em;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
input, select {
|
|
||||||
margin: 0 0.5em 1em 1em;
|
|
||||||
padding: 0.25em;
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
width: 13em;
|
|
||||||
}
|
|
||||||
span {
|
|
||||||
color: red;
|
|
||||||
margin-left: 0.25em;
|
|
||||||
}
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Registration</title>
|
|
||||||
<link rel="stylesheet" href="register.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<main>
|
|
||||||
<h1>Thanks for registering with us!</h1>
|
|
||||||
<p>You should get a confirmation email shortly.</p>
|
|
||||||
<p><a href="index.html">Go back</a></p>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Registration</title>
|
|
||||||
<link rel="stylesheet" href="register.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<main>
|
|
||||||
<h1>Register for an Account</h1>
|
|
||||||
<form action="confirm.html" method="post">
|
|
||||||
<label for="email_address">E-Mail:</label>
|
|
||||||
<input type="email" name="email_address" id="email_address"
|
|
||||||
placeholder="name@domain.com" autocomplete="off"
|
|
||||||
autofocus required>
|
|
||||||
<span>*</span><br>
|
|
||||||
|
|
||||||
<label for="dob">DOB:</label>
|
|
||||||
<input type="date" name="dob" id="dob"
|
|
||||||
title="You must be at least 13 years old." required>
|
|
||||||
<span>*</span><br>
|
|
||||||
|
|
||||||
<label for="phone">Mobile Phone:</label>
|
|
||||||
<input type="tel" name="phone" id="phone"
|
|
||||||
placeholder="nnn-nnn-nnnn" autocomplete="off"
|
|
||||||
pattern="\d{3}[\-]\d{3}[\-]\d{4}"
|
|
||||||
title="Must be nnn-nnn-nnnn format." required>
|
|
||||||
<span>*</span><br>
|
|
||||||
|
|
||||||
<label for="country">Country:</label>
|
|
||||||
<select name="country" id="country"
|
|
||||||
title="Please select a country." required>
|
|
||||||
<option value="">Select a country</option>
|
|
||||||
<option>USA</option>
|
|
||||||
<option>Canada</option>
|
|
||||||
<option>Mexico</option>
|
|
||||||
</select>
|
|
||||||
<span>*</span><br>
|
|
||||||
|
|
||||||
<label>Contact me by:</label>
|
|
||||||
<input type="radio" name="contact" id="text"
|
|
||||||
value="text" checked>Text
|
|
||||||
<input type="radio" name="contact" id="email"
|
|
||||||
value="email">Email
|
|
||||||
<input type="radio" name="contact" id="none"
|
|
||||||
value="none">Don't contact me<br>
|
|
||||||
|
|
||||||
<label>Terms of Service:</label>
|
|
||||||
<input type="checkbox" name="terms" id="terms" required
|
|
||||||
title="Please accept the terms of service.">I accept
|
|
||||||
<span>*</span><br>
|
|
||||||
|
|
||||||
<label> </label>
|
|
||||||
<input type="submit" id="register" value="Register">
|
|
||||||
<input type="reset" id="reset_form" value="Reset">
|
|
||||||
</form>
|
|
||||||
</main>
|
|
||||||
<script src="register.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 640px;
|
|
||||||
padding: 0 2em 1em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
padding-left: 1em;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
display: inline-block;
|
|
||||||
width: 11em;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
input, select {
|
|
||||||
margin: 0 0.5em 1em 1em;
|
|
||||||
padding: 0.25em;
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
width: 13em;
|
|
||||||
}
|
|
||||||
span {
|
|
||||||
color: red;
|
|
||||||
margin-left: 0.25em;
|
|
||||||
}
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const getElement = selector => document.querySelector(selector);
|
|
||||||
|
|
||||||
const clearMessages = form => {
|
|
||||||
for (let element of form.elements) {
|
|
||||||
const span = element.nextElementSibling;
|
|
||||||
if (span) span.textContent = "*";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
const form = getElement("form");
|
|
||||||
|
|
||||||
// turn off default HTML validation messages
|
|
||||||
form.noValidate = true;
|
|
||||||
|
|
||||||
// attach invalid event handler for form controls
|
|
||||||
for (let element of form.elements) {
|
|
||||||
element.addEventListener("invalid", evt => {
|
|
||||||
const elem = evt.currentTarget;
|
|
||||||
const msg = elem.title ? elem.title : elem.validationMessage;
|
|
||||||
|
|
||||||
const span = elem.nextElementSibling;
|
|
||||||
if (span) span.textContent = msg;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
form.addEventListener("submit", evt => {
|
|
||||||
clearMessages(form);
|
|
||||||
|
|
||||||
// do custom age validation
|
|
||||||
const dobElement = getElement("#dob");
|
|
||||||
const dob = new Date(dobElement.value);
|
|
||||||
|
|
||||||
const limit = new Date();
|
|
||||||
limit.setFullYear(limit.getFullYear() - 13);
|
|
||||||
|
|
||||||
const msg = (dob > limit) ? dobElement.title: "";
|
|
||||||
dobElement.setCustomValidity(msg);
|
|
||||||
|
|
||||||
// validate form
|
|
||||||
if (!form.checkValidity()) {
|
|
||||||
evt.preventDefault();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
getElement("#reset_form").addEventListener("click", () => {
|
|
||||||
clearMessages(form);
|
|
||||||
getElement("#email_address").focus();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
margin: 1em auto;
|
|
||||||
width: 600px;
|
|
||||||
padding: 0 2em 1em;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 1em;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: cornflowerblue;
|
|
||||||
}
|
|
||||||
div {
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
display: inline-block;
|
|
||||||
width: 11em;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
input {
|
|
||||||
margin-left: 1em;
|
|
||||||
margin-right: 0.5em;
|
|
||||||
width: 15em;
|
|
||||||
}
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
function getElement(selector) {
|
|
||||||
return document.querySelector(selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isNotValid(val) {
|
|
||||||
if (isNaN(val) || val <= 0) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function calcFutureValue(investment, rate, years) {
|
|
||||||
let futureValue = investment;
|
|
||||||
for (let i = 0; i < years; i++) {
|
|
||||||
futureValue += futureValue * rate / 100;
|
|
||||||
}
|
|
||||||
return futureValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
function calcButtonClick() {
|
|
||||||
// clear any previous calculation
|
|
||||||
getElement("#future_value").value = "";
|
|
||||||
|
|
||||||
// get values user entered in textboxes
|
|
||||||
const investment = parseFloat(getElement("#investment").value);
|
|
||||||
const rate = parseFloat(getElement("#rate").value);
|
|
||||||
const years = parseInt(getElement("#years").value);
|
|
||||||
|
|
||||||
// check user entries and set error message
|
|
||||||
let errorMsg = "";
|
|
||||||
if (isNotValid(investment)) {
|
|
||||||
errorMsg += "Investment amount must be a positive number.\n";
|
|
||||||
getElement("#investment").focus();
|
|
||||||
}
|
|
||||||
if (isNotValid(rate)) {
|
|
||||||
errorMsg += "Interest rate must be a positive number.\n";
|
|
||||||
getElement("#rate").focus();
|
|
||||||
}
|
|
||||||
if (isNotValid(years)) {
|
|
||||||
errorMsg += "Number of years must be a positive number.";
|
|
||||||
getElement("#years").focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
// if user entries are valid
|
|
||||||
if (errorMsg == "") {
|
|
||||||
// save user entries
|
|
||||||
localStorage.investment = investment;
|
|
||||||
localStorage.rate = rate;
|
|
||||||
localStorage.years = years;
|
|
||||||
|
|
||||||
// calculate and display future value
|
|
||||||
const futureValue = calcFutureValue(investment, rate, years);
|
|
||||||
getElement("#future_value").value = futureValue.toFixed(2);
|
|
||||||
} else {
|
|
||||||
// display error message
|
|
||||||
alert(errorMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
// load user entries
|
|
||||||
getElement("#investment").value = localStorage.investment ?? "";
|
|
||||||
getElement("#rate").value = localStorage.rate ?? "";
|
|
||||||
getElement("#years").value = localStorage.years ?? "";
|
|
||||||
|
|
||||||
// attach the event handler
|
|
||||||
getElement("#calculate").addEventListener("click", calcButtonClick);
|
|
||||||
|
|
||||||
// set focus on first text box on initial load
|
|
||||||
getElement("#investment").focus();
|
|
||||||
});
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Future Value Calculator</title>
|
|
||||||
<link rel="stylesheet" href="future_value.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>The Future Value Calculator</h1>
|
|
||||||
<div>
|
|
||||||
<label for="investment">Total investment:</label>
|
|
||||||
<input type="text" id="investment">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="Rate">Annual interest rate:</label>
|
|
||||||
<input type="text" id="rate">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="years">Number of years</label>
|
|
||||||
<input type="text" id="years">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Future value:</label>
|
|
||||||
<input type="text" id="future_value" disabled>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label> </label>
|
|
||||||
<input type="button" id="calculate" value="Calculate">
|
|
||||||
</div>
|
|
||||||
<script src="future_value.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const getElement = selector => document.querySelector(selector);
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
|
|
||||||
// add to existing hits
|
|
||||||
let localHits = localStorage.hits ?? "0"; // get hits
|
|
||||||
localHits = Number(localHits) + 1; // increment by 1
|
|
||||||
localStorage.hits = localHits; // set hits
|
|
||||||
|
|
||||||
let sessionHits = sessionStorage.hits ?? "0";
|
|
||||||
sessionHits = Number(sessionHits) + 1;
|
|
||||||
sessionStorage.hits = sessionHits;
|
|
||||||
|
|
||||||
// display hits
|
|
||||||
console.log("Hits for this browser: " + localStorage.hits);
|
|
||||||
console.log("Hits for this session: " + sessionStorage.hits);
|
|
||||||
|
|
||||||
// display hits
|
|
||||||
getElement("#browser_hits").textContent = localStorage.hits ?? "1";
|
|
||||||
getElement("#session_hits").textContent = sessionStorage.hits ?? "1";
|
|
||||||
|
|
||||||
});
|
|
||||||