First commit
255
Lab 10/storadons.html
Executable file
@@ -0,0 +1,255 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Storadons</title>
|
||||
<link rel="icon" href="https://fav.farm/🦕">
|
||||
<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=Open+Sans:wght@800&family=Roboto&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
/* JMU Slate Gray: #333333 Ice Blue: #8EE4D7 JMU Purple: #450084 Teal: #009698 JMU Light Gold: #F4EFE1 */
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
font-family: Roboto;
|
||||
}
|
||||
|
||||
main {
|
||||
background-color: #F4EFE1;
|
||||
color: #333;
|
||||
flex-grow: 1;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
aside {
|
||||
border-inline-start: 1rem solid #009698;
|
||||
background-color: #450084;
|
||||
color: #8EE4D7;
|
||||
max-width: 33vw;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
main,
|
||||
aside {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
aside a {
|
||||
color: #F4EFE1;
|
||||
}
|
||||
|
||||
aside a:visited {
|
||||
color: #009698;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#downloads {
|
||||
display: none;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #00000099;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main>
|
||||
<header>
|
||||
<h1>🦕 Storadons</h1>
|
||||
<button id="share" type="button">Get Sharable URL</button>
|
||||
<button id="export" type="button">Export</button>
|
||||
<form action="#" id="import-form">
|
||||
<input type="file" name="import-file" id="import-file" required>
|
||||
<button id="import" type="submit">Import</button>
|
||||
</form>
|
||||
</header>
|
||||
<form id="new-item-form" action="#">
|
||||
<label for="item">New todo item</label>
|
||||
<input type="text" name="item" id="item">
|
||||
<button type="submit">Add</button>
|
||||
</form>
|
||||
<ol id="items"></ol>
|
||||
<div id="downloads"></div>
|
||||
</main>
|
||||
<aside>
|
||||
<section>
|
||||
<h2>Overview</h2>
|
||||
<p>Look at this excellent little TODO app! 🤩 The code as provided implements these features:</p>
|
||||
<ul>
|
||||
<li>adding items to the todo list</li>
|
||||
<li>listing the new item at the end of the existing to do list items</li>
|
||||
</ul>
|
||||
</section>
|
||||
<hr>
|
||||
<section>
|
||||
<p>Know what might be neato? I think it needs MOAR ... 🔔</p>
|
||||
<h2>Part 1: Persistodon</h2>
|
||||
<p>It'd be nice if we could close the window and not lose all of our data.</p>
|
||||
<h3>TODO (Part 1)</h3>
|
||||
<p>There are <code>// TODO (Part 1)</code> comments in the JavaScript code to guide your way while you add
|
||||
these features:</p>
|
||||
<ol>
|
||||
<li><em>persist</em> the todo items to <code>localStorage</code> as they are added to the to do list</li>
|
||||
<li><em>load any todo items from <code>localStorage</code> when the page loads </em></li>
|
||||
</ol>
|
||||
<h2>Part 2: Sharasaurus</h2>
|
||||
<p>How could we view the same list on our phone as we are viewing on our laptop? Share the list with a friend?
|
||||
</p>
|
||||
<h3>TODO (Part 2)</h3>
|
||||
<p>There are <code>// TODO (Part 2)</code> comments in the JavaScript to guide you in your way while you add these
|
||||
features:</p>
|
||||
<ol>
|
||||
<li>notice if the page was passed a query string and to populate <code>localStorage</code>
|
||||
initially with the items in the query string</li>
|
||||
<li>modify the <code>Get Sharable URL</code> button so that it updates the url so that all of the todo
|
||||
items currently stored in <code>localStorage</code> are encoded in the <code>query string</code> in the
|
||||
browser's address bar</li>
|
||||
</ol>
|
||||
</section>
|
||||
<hr>
|
||||
<section>
|
||||
<h2>Part 3: Transportodon</h2>
|
||||
<p>URLs have a pretty short length limit. What if we add too much stuff to fit into the URL? How can we share a
|
||||
file version?</p>
|
||||
<h3>TODO (Part 3)</h3>
|
||||
<p>There are <code>// TODO (Part 3)</code> comments in the JavaScript to guide you to add these features:</p>
|
||||
<ol>
|
||||
<li>modify the <code>Export</code> button so that it creates a Blob containing the items from
|
||||
<code>localStorage</code>
|
||||
</li>
|
||||
<li>modify the <code>Import</code> button to replace the items in <code>localStorage</code> with the file's text
|
||||
content</li>
|
||||
</ol>
|
||||
</section>
|
||||
</aside>
|
||||
<script>
|
||||
// get the DOM elements
|
||||
const form = document.getElementById('new-item-form');
|
||||
const input = document.getElementById('item');
|
||||
const list = document.getElementById('items');
|
||||
|
||||
function addItemToList(item) {
|
||||
const newLi = document.createElement('li')
|
||||
newLi.textContent = item;
|
||||
list.append(newLi);
|
||||
}
|
||||
|
||||
function populateFromLocalStorage() {
|
||||
// TODO (Part 1)
|
||||
// Retrieve the stored items from localStorage. Parse the returned string using JSON.parse
|
||||
// and pass each item in the array to addItemToList.
|
||||
const todosString = localStorage.getItem('todos')
|
||||
if (!todosString) return
|
||||
|
||||
const todos = JSON.parse(todosString)
|
||||
todos.forEach(addItemToList)
|
||||
}
|
||||
|
||||
form.addEventListener('submit', (ev) => {
|
||||
// TODO (Part 1)
|
||||
// Get the new item from the input field and pass it to addItemToList. Get the array of
|
||||
// items currently stored in localStorage and add the new item to the end of the list.
|
||||
// If there aren't any items in localStorage (because the page was just loaded for the
|
||||
// first time), make an array of just the new item. P.S. don't forget to prevent the
|
||||
// page from reloading when the form is submitted and clear the input field.
|
||||
ev.preventDefault()
|
||||
const newTodo = input.value
|
||||
|
||||
const todosString = localStorage.getItem('todos')
|
||||
const todos = todosString ? JSON.parse(todosString) : []
|
||||
|
||||
todos.push(newTodo)
|
||||
localStorage.setItem('todos', JSON.stringify(todos))
|
||||
addItemToList(newTodo)
|
||||
})
|
||||
|
||||
function populateLocalStorageFromURLSearch() {
|
||||
// TODO (Part 2)
|
||||
// Given the URL index.html?first&second, the query string is ?first&second and can be
|
||||
// accessed as location.search. If a query string is passed as part of the URL, replace
|
||||
// the localStorage items with an array created by splitting the query string. In the
|
||||
// previous example, the new array should be [ 'first', 'second' ].
|
||||
const queryParams = new URLSearchParams(location.search)
|
||||
if (queryParams.size == 0) return
|
||||
|
||||
localStorage.setItem('todos', JSON.stringify(Array.from(queryParams.keys())))
|
||||
}
|
||||
|
||||
// get url
|
||||
document.getElementById('share').addEventListener('click', (ev) => {
|
||||
// TODO (Part 2)
|
||||
// Generate a sharable link of the current items. The URL should consist of the
|
||||
// current location (window.location), but add on '?' and a string version of the
|
||||
// items with an '&' between each. For instance, if the URL is http://foo.com/index.html
|
||||
// and the list consists of [ 'first', 'second' ], the sharable URL should be
|
||||
// http://foo.com/index.html?first&second
|
||||
// Update window.location to this URL so you can copy and paste from the browser's
|
||||
// URL bar.
|
||||
// CAUTION: If the URL already has a query string, that should NOT be included in
|
||||
// this new version. As a hint, use console.log to print out the window.location
|
||||
// object and see what parts you actually need.
|
||||
const sharableURL = new URL(location.toString())
|
||||
const todosString = localStorage.getItem('todos')
|
||||
todosString ? sharableURL.search = `?${JSON.parse(todosString).join('&')}` : ''
|
||||
window.location = sharableURL.toString()
|
||||
});
|
||||
|
||||
// export blob
|
||||
document.getElementById('export').addEventListener('click', (ev) => {
|
||||
// TODO (Part 3)
|
||||
// Generate a Blob of the localStorage items. See Week 11 slides for creating
|
||||
// a blob, a link, and a download action. You'll create the Blob from the
|
||||
// items in localStorage.
|
||||
const blob = new Blob([localStorage.getItem('todos')], { type: 'text/plain' })
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = 'data.json'
|
||||
link.click()
|
||||
|
||||
window.URL.revokeObjectURL(url)
|
||||
link.remove()
|
||||
});
|
||||
|
||||
// import from file
|
||||
let importForm = document.getElementById('import-form');
|
||||
importForm.addEventListener('submit', (ev) => {
|
||||
// TODO (Part 3)
|
||||
// Get files[0] from the import-file input when the form is submitted.
|
||||
// Use .text() on the file to get a Promise that resolves to the file
|
||||
// contents. Store the resolved data as the items in localStorage, then
|
||||
// use populateFromLocalStorage() to load the items. Do not forget to
|
||||
// stop the page from reloading.
|
||||
ev.preventDefault()
|
||||
const file = importForm['import-file'].files[0]
|
||||
file.text().then((text) => {
|
||||
localStorage.setItem('todos', text)
|
||||
populateFromLocalStorage()
|
||||
})
|
||||
});
|
||||
|
||||
// initialize the page
|
||||
(function () {
|
||||
populateLocalStorageFromURLSearch();
|
||||
populateFromLocalStorage();
|
||||
})();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
BIN
Lab 11/JMU-Logo-RGB-horiz-purple.png
Executable file
|
After Width: | Height: | Size: 15 KiB |
131
Lab 11/bootstrap.html
Executable file
@@ -0,0 +1,131 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="author" content="Nicholas Tamassia">
|
||||
<title>CSP Test</title>
|
||||
<!-- Insert your CSP policies here. Do not change anything else in this file. Well, okay,
|
||||
you can change your name as the author just above this comment. -->
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; frame-src 'self'; style-src https:;">
|
||||
|
||||
<link rel="stylesheet" href="https://w3.cs.jmu.edu/kirkpams/343/labs/lab11/styles.css">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<nav class="nav">
|
||||
<a class="nav-link border bg-light" href="local.html">Local</a>
|
||||
<a class="nav-link border bg-light" href="bootstrap.html">Bootstrap</a>
|
||||
<a class="nav-link border bg-light" href="noframe.html">No frame</a>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
<div class="row my-4">
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Inline CSS</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p style="font-size: 2em;">Large text</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Local CSS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="h5">Level 5 heading</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Remote CSS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="h6">Level 6 heading</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Inline JavaScript</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<script>document.write('This is inline scripting');</script>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Local JS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<script src="local.js"></script>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Remote JS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<script src="https://w3.cs.jmu.edu/kirkpams/343/labs/lab11/remote.js"></script>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Display an image</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<img src="https://w3.cs.jmu.edu/kirkpams/images/JMU-Logo-RGB-horiz-purple.png" width="100%" height="50px"
|
||||
alt="Image should not load due to CSP">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Local image in iframe</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<iframe src="JMU-Logo-RGB-horiz-purple.png" width="100%" height="50px"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Remote image in iframe</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<iframe src="https://w3.cs.jmu.edu/kirkpams/images/JMU-Logo-RGB-horiz-purple.png" width="100%"
|
||||
height="50px"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
130
Lab 11/index.html
Executable file
@@ -0,0 +1,130 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="author" content="Nicholas Tamassia">
|
||||
<title>CSP Test</title>
|
||||
<!-- Insert your CSP policies here. Do not change anything else in this file. Well, okay,
|
||||
you can change your name as the author just above this comment. -->
|
||||
|
||||
<link rel="stylesheet" href="https://w3.cs.jmu.edu/kirkpams/343/labs/lab11/styles.css">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<nav class="nav">
|
||||
<a class="nav-link border bg-light" href="local.html">Local</a>
|
||||
<a class="nav-link border bg-light" href="bootstrap.html">Bootstrap</a>
|
||||
<a class="nav-link border bg-light" href="noframe.html">No frame</a>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
<div class="row my-4">
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Inline CSS</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p style="font-size: 2em;">Large text</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Local CSS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="h5">Level 5 heading</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Remote CSS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="h6">Level 6 heading</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Inline JavaScript</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<script>document.write('This is inline scripting');</script>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Local JS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<script src="local.js"></script>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Remote JS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<script src="https://w3.cs.jmu.edu/kirkpams/343/labs/lab11/remote.js"></script>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Display an image</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<img src="https://w3.cs.jmu.edu/kirkpams/images/JMU-Logo-RGB-horiz-purple.png" width="100%" height="50px"
|
||||
alt="Image should not load due to CSP">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Local image in iframe</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<iframe src="JMU-Logo-RGB-horiz-purple.png" width="100%" height="50px"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Remote image in iframe</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<iframe src="https://w3.cs.jmu.edu/kirkpams/images/JMU-Logo-RGB-horiz-purple.png" width="100%"
|
||||
height="50px"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
131
Lab 11/local.html
Executable file
@@ -0,0 +1,131 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="author" content="Nicholas Tamassia">
|
||||
<title>CSP Test</title>
|
||||
<!-- Insert your CSP policies here. Do not change anything else in this file. Well, okay,
|
||||
you can change your name as the author just above this comment. -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline'; frame-src 'self' https:;">
|
||||
|
||||
<link rel="stylesheet" href="https://w3.cs.jmu.edu/kirkpams/343/labs/lab11/styles.css">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<nav class="nav">
|
||||
<a class="nav-link border bg-light" href="local.html">Local</a>
|
||||
<a class="nav-link border bg-light" href="bootstrap.html">Bootstrap</a>
|
||||
<a class="nav-link border bg-light" href="noframe.html">No frame</a>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
<div class="row my-4">
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Inline CSS</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p style="font-size: 2em;">Large text</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Local CSS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="h5">Level 5 heading</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Remote CSS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="h6">Level 6 heading</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Inline JavaScript</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<script>document.write('This is inline scripting');</script>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Local JS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<script src="local.js"></script>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Remote JS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<script src="https://w3.cs.jmu.edu/kirkpams/343/labs/lab11/remote.js"></script>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Display an image</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<img src="https://w3.cs.jmu.edu/kirkpams/images/JMU-Logo-RGB-horiz-purple.png" width="100%" height="50px"
|
||||
alt="Image should not load due to CSP">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Local image in iframe</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<iframe src="JMU-Logo-RGB-horiz-purple.png" width="100%" height="50px"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Remote image in iframe</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<iframe src="https://w3.cs.jmu.edu/kirkpams/images/JMU-Logo-RGB-horiz-purple.png" width="100%"
|
||||
height="50px"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
7
Lab 11/local.js
Executable file
@@ -0,0 +1,7 @@
|
||||
(function() {
|
||||
let scripts = document.getElementsByTagName('script');
|
||||
let script = scripts[scripts.length - 1];
|
||||
let parent = script.parentNode;
|
||||
|
||||
parent.textContent = 'This is locally generated';
|
||||
})();
|
||||
131
Lab 11/noframe.html
Executable file
@@ -0,0 +1,131 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="author" content="Nicholas Tamassia">
|
||||
<title>CSP Test</title>
|
||||
<!-- Insert your CSP policies here. Do not change anything else in this file. Well, okay,
|
||||
you can change your name as the author just above this comment. -->
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' https:; frame-src 'none'; img-src 'none';">
|
||||
|
||||
<link rel="stylesheet" href="https://w3.cs.jmu.edu/kirkpams/343/labs/lab11/styles.css">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<nav class="nav">
|
||||
<a class="nav-link border bg-light" href="local.html">Local</a>
|
||||
<a class="nav-link border bg-light" href="bootstrap.html">Bootstrap</a>
|
||||
<a class="nav-link border bg-light" href="noframe.html">No frame</a>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
<div class="row my-4">
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Inline CSS</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p style="font-size: 2em;">Large text</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Local CSS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="h5">Level 5 heading</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Remote CSS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="h6">Level 6 heading</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Inline JavaScript</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<script>document.write('This is inline scripting');</script>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Local JS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<script src="local.js"></script>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Remote JS file</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<script src="https://w3.cs.jmu.edu/kirkpams/343/labs/lab11/remote.js"></script>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Display an image</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<img src="https://w3.cs.jmu.edu/kirkpams/images/JMU-Logo-RGB-horiz-purple.png" width="100%" height="50px"
|
||||
alt="Image should not load due to CSP">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Local image in iframe</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<iframe src="JMU-Logo-RGB-horiz-purple.png" width="100%" height="50px"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 my-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="h4">Remote image in iframe</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<iframe src="https://w3.cs.jmu.edu/kirkpams/images/JMU-Logo-RGB-horiz-purple.png" width="100%"
|
||||
height="50px"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
3
Lab 11/styles.css
Executable file
@@ -0,0 +1,3 @@
|
||||
.h5 {
|
||||
font-style: italic;
|
||||
}
|
||||
BIN
Lab 2/JMU-Logo-RGB-horiz-purple.png
Executable file
|
After Width: | Height: | Size: 15 KiB |
109
Lab 2/index.html
Executable file
@@ -0,0 +1,109 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="author" content="Nicholas Tamassia">
|
||||
<meta name="description" content="Lab 2 submission">
|
||||
<title>CS 343 Lab 2</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
let header1 = 'Course Information', header2 = 'Detailed Course Objectives', header3 = 'Course Catalog Description'
|
||||
let showFooter = true
|
||||
</script>
|
||||
|
||||
<header>
|
||||
<h1>CS 343: Application Development</h1>
|
||||
<h2>Fall 2023</h2>
|
||||
<blockquote cite="https://uxdworld.com">
|
||||
<p>"A user interface is like a joke. If you have to explain it, it’s not that good."</p>
|
||||
<p>- Martin LeBlanc</p>
|
||||
</blockquote>
|
||||
</header>
|
||||
|
||||
<hr>
|
||||
|
||||
<section>
|
||||
<h3 id="header1"></h3>
|
||||
<p>
|
||||
Learning to work with the tools and technologies that are used to build and
|
||||
create web sites is both empowering and fun. With these tools, you can build
|
||||
your own web sites and customize the experience of those you visit. You can
|
||||
also create interactive applications for storing and manipulating personal or
|
||||
enterprise data. And you can dynamically generate images and graphics to help
|
||||
visualize data sets.
|
||||
</p>
|
||||
<p>
|
||||
The goal of this course is to explore these technologies - HTML, CSS, and
|
||||
Javascript - that define the structure, presentation, and interactions for
|
||||
modern web development. In addition to covering the basics of how to use these
|
||||
tools, we will explore guidelines to ensure the sites we create are accessible
|
||||
for a variety of users, including users with disabilities. After completing
|
||||
this course, you will have a solid foundation to continue learning more
|
||||
advanced web development techniques.
|
||||
</p>
|
||||
<ul>
|
||||
<li><strong>Website: </strong><a>https://w3.cs.jmu.edu/kirkpams/343</a></li>
|
||||
<li><strong>Time: </strong>M/W/F 9:10 - 10:00 AM</li>
|
||||
<li><strong>Location: </strong>King Hall 243</li>
|
||||
<li><strong>Textbook: </strong><cite>Fundamentals of Web Development, 3rd Edition</cite></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<hr>
|
||||
|
||||
<section>
|
||||
<h3 id="header2"></h3>
|
||||
<p>
|
||||
Following the successful completion of this course, students will be able to:
|
||||
</p>
|
||||
<ol type="1">
|
||||
<li>Summarize the key steps and processes for retrieving and displaying a web page.</li>
|
||||
<li>Structure text documents as HTML and publish them on a server.</li>
|
||||
<li>Apply accessibility standards to web documents.</li>
|
||||
<li>Create and adapt CSS style sheets for consistent web site presentation and styling.</li>
|
||||
<li>Use a web framework to create a modern, responsive web site.</li>
|
||||
<li>Generate HTML content dynamically with Javascript.</li>
|
||||
<li>Create handlers to detect and respond to user input events.</li>
|
||||
<li>Store and retrieve data in client-side storage.</li>
|
||||
<li>Build images dynamically using provided data.</li>
|
||||
<li>Learn to consult a web framework documentation and tutorials for additional help.</li>
|
||||
</ol>
|
||||
</section>
|
||||
|
||||
<hr>
|
||||
|
||||
<section>
|
||||
<h3 id="header3"></h3>
|
||||
<p>
|
||||
Projects or topics in computer science which are of interest to the lower
|
||||
division student. May be repeated for credit when course content changes.
|
||||
Topics may vary. Prerequisite: Fully admitted Computer Science majors or
|
||||
minors only and students should consult the instructor prior to enrolling
|
||||
for the course.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<hr>
|
||||
|
||||
<footer id="footer"></footer>
|
||||
|
||||
<script>
|
||||
document.querySelector('#header1').innerText = header1
|
||||
document.querySelector('#header2').innerText = header2
|
||||
document.querySelector('#header3').innerText = header3
|
||||
|
||||
const footer = document.querySelector('#footer')
|
||||
|
||||
if (showFooter) {
|
||||
footer.innerHTML = '<img src="./JMU-Logo-RGB-horiz-purple.png" alt="James Madison University logo in purple" />'
|
||||
} else {
|
||||
footer.innerText = 'JMU logo is not shown'
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
104
Lab 2/lab2.txt
Executable file
@@ -0,0 +1,104 @@
|
||||
# CONVERT # LINES TO COMMENTS (DELETE THIS ONE AND THE HORIZONTAL LINES)
|
||||
|
||||
# Create an HTML header using the author (your name), description
|
||||
# ("Lab 2 submission"), and charset ("UTF-8") meta tags. Add a title of
|
||||
# "CS 343 Lab 2".
|
||||
|
||||
# Define 4 JavaScript variables here:
|
||||
# One is a Boolean that controls whether or not the footer image is shown.
|
||||
# The Boolean MUST be named showFooter for testing purposes.
|
||||
# The other three are the level-3 headings, including both the <h3> tag
|
||||
# and the associated text. The names are not important.
|
||||
|
||||
# Wrap the title, subtitle, and blockquote inside a <header> element
|
||||
|
||||
# Page title and subtitle (should both be bigger than section headers)
|
||||
CS 343: Application Development
|
||||
Fall 2023
|
||||
|
||||
# Block quotation. Use an attribute to add the citation "https://uxdworld.com".
|
||||
# The quote and the name should be two paragraphs.
|
||||
"A user interface is like a joke. If you have to explain it, it’s not that good."
|
||||
- Martin LeBlanc
|
||||
|
||||
# End of the <header>
|
||||
|
||||
|
||||
# HORIZONTAL LINE
|
||||
|
||||
# Section header - MUST BE WRITTEN BY JAVASCRIPT
|
||||
Course Information
|
||||
|
||||
# Two separate paragraphs
|
||||
Learning to work with the tools and technologies that are used to build and
|
||||
create web sites is both empowering and fun. With these tools, you can build
|
||||
your own web sites and customize the experience of those you visit. You can
|
||||
also create interactive applications for storing and manipulating personal or
|
||||
enterprise data. And you can dynamically generate images and graphics to help
|
||||
visualize data sets.
|
||||
|
||||
The goal of this course is to explore these technologies - HTML, CSS, and
|
||||
Javascript - that define the structure, presentation, and interactions for
|
||||
modern web development. In addition to covering the basics of how to use these
|
||||
tools, we will explore guidelines to ensure the sites we create are accessible
|
||||
for a variety of users, including users with disabilities. After completing
|
||||
this course, you will have a solid foundation to continue learning more
|
||||
advanced web development techniques.
|
||||
|
||||
# Make this a bullet-point list. Format the text as shown in the sample
|
||||
# solution image. Note that <b> is NOT allowed for bold text. For the book
|
||||
# title, use the <cite> tag to mark it as a citation.
|
||||
|
||||
* Website: https://w3.cs.jmu.edu/kirkpams/343
|
||||
* Time: M/W/F 9:10 - 10:00 AM
|
||||
* Location: King Hall 243
|
||||
* Textbook: Fundamentals of Web Development, 3rd Edition
|
||||
|
||||
|
||||
# HORIZONTAL LINE
|
||||
|
||||
# Section header - MUST BE WRITTEN BY JAVASCRIPT
|
||||
Detailed Course Objectives
|
||||
|
||||
# Paragraph
|
||||
Following the successful completion of this course, students will be able to:
|
||||
|
||||
# Make this a numbered list and do NOT hard-code the numbers
|
||||
1. Summarize the key steps and processes for retrieving and displaying a web page.
|
||||
2. Structure text documents as HTML and publish them on a server.
|
||||
3. Apply accessibility standards to web documents.
|
||||
4. Create and adapt CSS style sheets for consistent web site presentation and styling.
|
||||
5. Use a web framework to create a modern, responsive web site.
|
||||
6. Generate HTML content dynamically with Javascript.
|
||||
7. Create handlers to detect and respond to user input events.
|
||||
8. Store and retrieve data in client-side storage.
|
||||
9. Build images dynamically using provided data.
|
||||
10. Learn to consult a web framework documentation and tutorials for additional help.
|
||||
|
||||
|
||||
# HORIZONTAL LINE
|
||||
|
||||
# Section header - MUST BE WRITTEN BY JAVASCRIPT
|
||||
Course Catalog Description
|
||||
|
||||
# Paragraph
|
||||
Projects or topics in computer science which are of interest to the lower
|
||||
division student. May be repeated for credit when course content changes.
|
||||
Topics may vary. Prerequisite: Fully admitted Computer Science majors or
|
||||
minors only and students should consult the instructor prior to enrolling
|
||||
for the course.
|
||||
|
||||
# HORIZONTAL LINE
|
||||
|
||||
# Wrap the following image inside a <footer> element
|
||||
|
||||
# If the Boolean variable at the top is set to tru:
|
||||
|
||||
# Embed the JMU-Logo-RGB-horiz-purple.png image. Add the following text as its
|
||||
# description: "James Madison University logo in purple"
|
||||
|
||||
# Otherwise:
|
||||
|
||||
# Show the text "JMU logo is not shown"
|
||||
|
||||
# End of the <footer>
|
||||
125
Lab 3/index.html
Executable file
@@ -0,0 +1,125 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Bootstrap demo</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
<link rel="icon" href="https://fav.farm/🕸️">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-md bg-body-primary">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="#">Navbar</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo02"
|
||||
aria-controls="navbarTogglerDemo02" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarTogglerDemo02">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" aria-current="page" href="#">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Link</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link disabled" aria-disabled="true">Disabled</a>
|
||||
</li>
|
||||
</ul>
|
||||
<form class="d-flex" role="search" data-bs-theme="light">
|
||||
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
|
||||
<button class="btn btn-light" type="submit">Search</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<main class="col-md-8">
|
||||
<h1>Bootstrap demo</h1>
|
||||
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet asperiores neque quis ut ipsa
|
||||
nostrum
|
||||
repellat itaque, ullam delectus recusandae eum repellendus necessitatibus, corporis deleniti
|
||||
placeat. Ipsam
|
||||
rerum nihil enim.</p>
|
||||
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsa possimus dolorum aliquam nisi
|
||||
praesentium
|
||||
adipisci aliquid. Provident quasi, unde dignissimos, repellat eaque voluptas id sapiente porro
|
||||
necessitatibus pariatur, eum culpa?</p>
|
||||
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil assumenda velit, repudiandae nulla
|
||||
excepturi
|
||||
ea voluptatibus odit at temporibus nam beatae perferendis non corporis! Nam error fugiat earum
|
||||
commodi
|
||||
similique.</p>
|
||||
</main>
|
||||
<aside class="col-md-4 d-none d-sm-block">
|
||||
<div class="accordion" id="accordionExample">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
|
||||
Accordion Item #1
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseOne" class="accordion-collapse collapse show"
|
||||
data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body">
|
||||
<strong>This is the first item's accordion body.</strong> It is shown by default, until
|
||||
the collapse plugin adds the appropriate classes that we use to style each element.
|
||||
These classes control the overall appearance, as well as the showing and hiding via CSS
|
||||
transitions. You can modify any of this with custom CSS or overriding our default
|
||||
variables. It's also worth noting that just about any HTML can go within the
|
||||
<code>.accordion-body</code>, though the transition does limit overflow.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
|
||||
Accordion Item #2
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseTwo" class="accordion-collapse collapse" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body">
|
||||
<strong>This is the second item's accordion body.</strong> It is hidden by default,
|
||||
until the collapse plugin adds the appropriate classes that we use to style each
|
||||
element. These classes control the overall appearance, as well as the showing and hiding
|
||||
via CSS transitions. You can modify any of this with custom CSS or overriding our
|
||||
default variables. It's also worth noting that just about any HTML can go within the
|
||||
<code>.accordion-body</code>, though the transition does limit overflow.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
|
||||
Accordion Item #3
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseThree" class="accordion-collapse collapse" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body">
|
||||
<strong>This is the third item's accordion body.</strong> It is hidden by default, until
|
||||
the collapse plugin adds the appropriate classes that we use to style each element.
|
||||
These classes control the overall appearance, as well as the showing and hiding via CSS
|
||||
transitions. You can modify any of this with custom CSS or overriding our default
|
||||
variables. It's also worth noting that just about any HTML can go within the
|
||||
<code>.accordion-body</code>, though the transition does limit overflow.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
|
||||
crossorigin="anonymous"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
79
Lab 4/basic.html
Executable file
@@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Fundamentals</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<h1>Lorem Ipsum</h1>
|
||||
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla
|
||||
vel leo sed ante vulputate porta id ac sapien. Nulla lacinia commodo
|
||||
augue. Ut risus mauris, consectetur sed neque quis, sollicitudin sodales
|
||||
nulla. Nullam eu porta arcu. Curabitur in erat sagittis, malesuada lorem
|
||||
ac, vehicula nulla. Praesent rhoncus magna eu elit lobortis, ac congue
|
||||
augue semper. Duis interdum consequat cursus. Morbi rutrum dapibus est
|
||||
vel volutpat. Pellentesque in malesuada ante.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="basic.html">Basic</a></li>
|
||||
<li><a href="spaces.html">Spacing</a></li>
|
||||
<li><a href="colors.html">Colorful</a></li>
|
||||
<li><a href="navs.html">Navigation</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<section>
|
||||
<h2>Part One <span>1</span></h2>
|
||||
|
||||
<p>
|
||||
Etiam euismod pretium risus quis venenatis. Fusce finibus lacinia urna
|
||||
sit amet pretium. Interdum et malesuada fames ac ante ipsum primis in
|
||||
faucibus. Etiam consectetur, justo ac ornare volutpat, ante mi vehicula
|
||||
quam, eget vehicula velit ex at orci. Pellentesque turpis est, convallis
|
||||
eget finibus eu, hendrerit non mauris. Sed at sapien eu erat iaculis
|
||||
porta nec sed ante. Nullam quis aliquam felis. Mauris gravida urna
|
||||
blandit nisl posuere, tristique accumsan nibh mollis. Sed faucibus
|
||||
malesuada arcu, et ultrices turpis laoreet lobortis. Mauris hendrerit
|
||||
commodo ex, vitae venenatis arcu volutpat ut. In in nisi rhoncus,
|
||||
fringilla risus ac, aliquet nunc. Fusce ut quam eleifend, fringilla
|
||||
ante sed, congue nisi. Sed ut est elit.
|
||||
</p>
|
||||
|
||||
<p>Back to <a href="basic.html">basic</a>.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Part Two <span>2</span></h2>
|
||||
|
||||
<p>
|
||||
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
|
||||
inceptos himenaeos. Quisque nec arcu eget eros fermentum efficitur non
|
||||
vitae ante. Suspendisse semper dapibus dui ac volutpat. Morbi consectetur
|
||||
mi a nunc posuere tristique. Vivamus interdum tincidunt arcu. Integer
|
||||
volutpat ipsum in pellentesque tempus. Nulla aliquet congue ex at
|
||||
elementum. Vestibulum imperdiet quam ac dui finibus, eget elementum erat
|
||||
aliquam. Sed erat neque, cursus vulputate consectetur et, vulputate sit
|
||||
amet orci. Duis fringilla aliquet mauris, nec semper nisl blandit ut.
|
||||
Fusce iaculis vestibulum pulvinar. Morbi facilisis, ligula non
|
||||
consectetur fringilla, elit magna auctor velit, at pretium magna lacus
|
||||
sit amet nulla.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="spaces.html">Lorem</a></li>
|
||||
<li><a href="color.html">Ipsum</a></li>
|
||||
<li><a href="navs.html">Dolor</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
BIN
Lab 4/colors-annot.png
Executable file
|
After Width: | Height: | Size: 282 KiB |
19
Lab 4/colors.css
Executable file
@@ -0,0 +1,19 @@
|
||||
/* colors.css -- Controlling the colors and borders for Lab 4
|
||||
* author: Nicholas Tamassia
|
||||
*/
|
||||
|
||||
header {
|
||||
background: #450084;
|
||||
color: #f5f5f5;
|
||||
border-bottom: solid #dacce6 1vh;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #dfd2aa;
|
||||
}
|
||||
|
||||
section {
|
||||
background: #f4efe1;
|
||||
border: solid black 3px;
|
||||
border-radius: 1vh;
|
||||
}
|
||||
81
Lab 4/colors.html
Executable file
@@ -0,0 +1,81 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Fundamentals</title>
|
||||
<link href="spaces.css" rel="stylesheet">
|
||||
<link href="colors.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<h1>Lorem Ipsum</h1>
|
||||
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla
|
||||
vel leo sed ante vulputate porta id ac sapien. Nulla lacinia commodo
|
||||
augue. Ut risus mauris, consectetur sed neque quis, sollicitudin sodales
|
||||
nulla. Nullam eu porta arcu. Curabitur in erat sagittis, malesuada lorem
|
||||
ac, vehicula nulla. Praesent rhoncus magna eu elit lobortis, ac congue
|
||||
augue semper. Duis interdum consequat cursus. Morbi rutrum dapibus est
|
||||
vel volutpat. Pellentesque in malesuada ante.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="basic.html">Basic</a></li>
|
||||
<li><a href="spaces.html">Spacing</a></li>
|
||||
<li><a href="colors.html">Colorful</a></li>
|
||||
<li><a href="navs.html">Navigation</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<section>
|
||||
<h2>Part One <span>1</span></h2>
|
||||
|
||||
<p>
|
||||
Etiam euismod pretium risus quis venenatis. Fusce finibus lacinia urna
|
||||
sit amet pretium. Interdum et malesuada fames ac ante ipsum primis in
|
||||
faucibus. Etiam consectetur, justo ac ornare volutpat, ante mi vehicula
|
||||
quam, eget vehicula velit ex at orci. Pellentesque turpis est, convallis
|
||||
eget finibus eu, hendrerit non mauris. Sed at sapien eu erat iaculis
|
||||
porta nec sed ante. Nullam quis aliquam felis. Mauris gravida urna
|
||||
blandit nisl posuere, tristique accumsan nibh mollis. Sed faucibus
|
||||
malesuada arcu, et ultrices turpis laoreet lobortis. Mauris hendrerit
|
||||
commodo ex, vitae venenatis arcu volutpat ut. In in nisi rhoncus,
|
||||
fringilla risus ac, aliquet nunc. Fusce ut quam eleifend, fringilla
|
||||
ante sed, congue nisi. Sed ut est elit.
|
||||
</p>
|
||||
|
||||
<p>Back to <a href="basic.html">basic</a>.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Part Two <span>2</span></h2>
|
||||
|
||||
<p>
|
||||
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
|
||||
inceptos himenaeos. Quisque nec arcu eget eros fermentum efficitur non
|
||||
vitae ante. Suspendisse semper dapibus dui ac volutpat. Morbi consectetur
|
||||
mi a nunc posuere tristique. Vivamus interdum tincidunt arcu. Integer
|
||||
volutpat ipsum in pellentesque tempus. Nulla aliquet congue ex at
|
||||
elementum. Vestibulum imperdiet quam ac dui finibus, eget elementum erat
|
||||
aliquam. Sed erat neque, cursus vulputate consectetur et, vulputate sit
|
||||
amet orci. Duis fringilla aliquet mauris, nec semper nisl blandit ut.
|
||||
Fusce iaculis vestibulum pulvinar. Morbi facilisis, ligula non
|
||||
consectetur fringilla, elit magna auctor velit, at pretium magna lacus
|
||||
sit amet nulla.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="spaces.html">Lorem</a></li>
|
||||
<li><a href="color.html">Ipsum</a></li>
|
||||
<li><a href="navs.html">Dolor</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
BIN
Lab 4/colors.png
Executable file
|
After Width: | Height: | Size: 414 KiB |
BIN
Lab 4/css.zip
Executable file
BIN
Lab 4/navs-annot.png
Executable file
|
After Width: | Height: | Size: 315 KiB |
34
Lab 4/navs.css
Executable file
@@ -0,0 +1,34 @@
|
||||
/* navs.css -- Styling the nav elements for Lab 4
|
||||
* author: Nicholas Tamassia
|
||||
*/
|
||||
|
||||
nav a {
|
||||
font-family: sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: 900;
|
||||
color: #450084;
|
||||
}
|
||||
|
||||
nav {
|
||||
border: solid black 2px;
|
||||
border-radius: 1vh;
|
||||
overflow: hidden;
|
||||
color: #dcdcdc;
|
||||
background: #dcdcdc;
|
||||
}
|
||||
|
||||
nav > ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
nav > ul li {
|
||||
padding: 8px 13px;
|
||||
background-color: #dcdcdc;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
nav > ul li:not(:last-child) {
|
||||
border-bottom: solid 2px #f5f5f5;
|
||||
}
|
||||
82
Lab 4/navs.html
Executable file
@@ -0,0 +1,82 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Fundamentals</title>
|
||||
<link href="spaces.css" rel="stylesheet">
|
||||
<link href="colors.css" rel="stylesheet">
|
||||
<link href="navs.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<h1>Lorem Ipsum</h1>
|
||||
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla
|
||||
vel leo sed ante vulputate porta id ac sapien. Nulla lacinia commodo
|
||||
augue. Ut risus mauris, consectetur sed neque quis, sollicitudin sodales
|
||||
nulla. Nullam eu porta arcu. Curabitur in erat sagittis, malesuada lorem
|
||||
ac, vehicula nulla. Praesent rhoncus magna eu elit lobortis, ac congue
|
||||
augue semper. Duis interdum consequat cursus. Morbi rutrum dapibus est
|
||||
vel volutpat. Pellentesque in malesuada ante.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="basic.html">Basic</a></li>
|
||||
<li><a href="spaces.html">Spacing</a></li>
|
||||
<li><a href="colors.html">Colorful</a></li>
|
||||
<li><a href="navs.html">Navigation</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<section>
|
||||
<h2>Part One <span>1</span></h2>
|
||||
|
||||
<p>
|
||||
Etiam euismod pretium risus quis venenatis. Fusce finibus lacinia urna
|
||||
sit amet pretium. Interdum et malesuada fames ac ante ipsum primis in
|
||||
faucibus. Etiam consectetur, justo ac ornare volutpat, ante mi vehicula
|
||||
quam, eget vehicula velit ex at orci. Pellentesque turpis est, convallis
|
||||
eget finibus eu, hendrerit non mauris. Sed at sapien eu erat iaculis
|
||||
porta nec sed ante. Nullam quis aliquam felis. Mauris gravida urna
|
||||
blandit nisl posuere, tristique accumsan nibh mollis. Sed faucibus
|
||||
malesuada arcu, et ultrices turpis laoreet lobortis. Mauris hendrerit
|
||||
commodo ex, vitae venenatis arcu volutpat ut. In in nisi rhoncus,
|
||||
fringilla risus ac, aliquet nunc. Fusce ut quam eleifend, fringilla
|
||||
ante sed, congue nisi. Sed ut est elit.
|
||||
</p>
|
||||
|
||||
<p>Back to <a href="basic.html">basic</a>.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Part Two <span>2</span></h2>
|
||||
|
||||
<p>
|
||||
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
|
||||
inceptos himenaeos. Quisque nec arcu eget eros fermentum efficitur non
|
||||
vitae ante. Suspendisse semper dapibus dui ac volutpat. Morbi consectetur
|
||||
mi a nunc posuere tristique. Vivamus interdum tincidunt arcu. Integer
|
||||
volutpat ipsum in pellentesque tempus. Nulla aliquet congue ex at
|
||||
elementum. Vestibulum imperdiet quam ac dui finibus, eget elementum erat
|
||||
aliquam. Sed erat neque, cursus vulputate consectetur et, vulputate sit
|
||||
amet orci. Duis fringilla aliquet mauris, nec semper nisl blandit ut.
|
||||
Fusce iaculis vestibulum pulvinar. Morbi facilisis, ligula non
|
||||
consectetur fringilla, elit magna auctor velit, at pretium magna lacus
|
||||
sit amet nulla.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="spaces.html">Lorem</a></li>
|
||||
<li><a href="color.html">Ipsum</a></li>
|
||||
<li><a href="navs.html">Dolor</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
BIN
Lab 4/navs.png
Executable file
|
After Width: | Height: | Size: 414 KiB |
BIN
Lab 4/spaces-annot.png
Executable file
|
After Width: | Height: | Size: 205 KiB |
38
Lab 4/spaces.css
Executable file
@@ -0,0 +1,38 @@
|
||||
/* basics.css -- Controlling the spacing for Lab 4
|
||||
* author: Nicholas Tamassia
|
||||
*/
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
header {
|
||||
padding: 1vh 2vw;
|
||||
}
|
||||
|
||||
nav {
|
||||
width: 10vw;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin: 1vh 2vw;
|
||||
}
|
||||
|
||||
main {
|
||||
width: 80vw;
|
||||
padding: 3vh 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
section {
|
||||
margin: 3vh 0 0;
|
||||
padding: 1vw;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
p {
|
||||
padding: 0 2vw;
|
||||
}
|
||||
80
Lab 4/spaces.html
Executable file
@@ -0,0 +1,80 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Fundamentals</title>
|
||||
<link href="spaces.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<h1>Lorem Ipsum</h1>
|
||||
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla
|
||||
vel leo sed ante vulputate porta id ac sapien. Nulla lacinia commodo
|
||||
augue. Ut risus mauris, consectetur sed neque quis, sollicitudin sodales
|
||||
nulla. Nullam eu porta arcu. Curabitur in erat sagittis, malesuada lorem
|
||||
ac, vehicula nulla. Praesent rhoncus magna eu elit lobortis, ac congue
|
||||
augue semper. Duis interdum consequat cursus. Morbi rutrum dapibus est
|
||||
vel volutpat. Pellentesque in malesuada ante.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="basic.html">Basic</a></li>
|
||||
<li><a href="spaces.html">Spacing</a></li>
|
||||
<li><a href="colors.html">Colorful</a></li>
|
||||
<li><a href="navs.html">Navigation</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<section>
|
||||
<h2>Part One <span>1</span></h2>
|
||||
|
||||
<p>
|
||||
Etiam euismod pretium risus quis venenatis. Fusce finibus lacinia urna
|
||||
sit amet pretium. Interdum et malesuada fames ac ante ipsum primis in
|
||||
faucibus. Etiam consectetur, justo ac ornare volutpat, ante mi vehicula
|
||||
quam, eget vehicula velit ex at orci. Pellentesque turpis est, convallis
|
||||
eget finibus eu, hendrerit non mauris. Sed at sapien eu erat iaculis
|
||||
porta nec sed ante. Nullam quis aliquam felis. Mauris gravida urna
|
||||
blandit nisl posuere, tristique accumsan nibh mollis. Sed faucibus
|
||||
malesuada arcu, et ultrices turpis laoreet lobortis. Mauris hendrerit
|
||||
commodo ex, vitae venenatis arcu volutpat ut. In in nisi rhoncus,
|
||||
fringilla risus ac, aliquet nunc. Fusce ut quam eleifend, fringilla
|
||||
ante sed, congue nisi. Sed ut est elit.
|
||||
</p>
|
||||
|
||||
<p>Back to <a href="basic.html">basic</a>.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Part Two <span>2</span></h2>
|
||||
|
||||
<p>
|
||||
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
|
||||
inceptos himenaeos. Quisque nec arcu eget eros fermentum efficitur non
|
||||
vitae ante. Suspendisse semper dapibus dui ac volutpat. Morbi consectetur
|
||||
mi a nunc posuere tristique. Vivamus interdum tincidunt arcu. Integer
|
||||
volutpat ipsum in pellentesque tempus. Nulla aliquet congue ex at
|
||||
elementum. Vestibulum imperdiet quam ac dui finibus, eget elementum erat
|
||||
aliquam. Sed erat neque, cursus vulputate consectetur et, vulputate sit
|
||||
amet orci. Duis fringilla aliquet mauris, nec semper nisl blandit ut.
|
||||
Fusce iaculis vestibulum pulvinar. Morbi facilisis, ligula non
|
||||
consectetur fringilla, elit magna auctor velit, at pretium magna lacus
|
||||
sit amet nulla.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="spaces.html">Lorem</a></li>
|
||||
<li><a href="color.html">Ipsum</a></li>
|
||||
<li><a href="navs.html">Dolor</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
BIN
Lab 4/spaces.png
Executable file
|
After Width: | Height: | Size: 344 KiB |
47
Lab 5/flex.js
Executable file
@@ -0,0 +1,47 @@
|
||||
const picsumBase = "https://picsum.photos/200";
|
||||
|
||||
let mainElement;
|
||||
|
||||
let addButton;
|
||||
let spreadButton;
|
||||
let rotateButton;
|
||||
|
||||
function spacing() {
|
||||
spreadButton.classList.toggle("active");
|
||||
mainElement.classList.toggle("spread");
|
||||
}
|
||||
|
||||
function rotate() {
|
||||
rotateButton.classList.toggle("active");
|
||||
mainElement.classList.toggle("vert");
|
||||
}
|
||||
|
||||
function addImg() {
|
||||
const randomNumber = document.getElementsByTagName("img").length + 1;
|
||||
|
||||
const newImg = document.createElement("img");
|
||||
newImg.src = `${picsumBase}?random=${randomNumber}`;
|
||||
newImg.alt = "random square image";
|
||||
newImg.addEventListener("click", removeImg.bind(null, newImg));
|
||||
mainElement.appendChild(newImg);
|
||||
}
|
||||
|
||||
function removeImg(element) {
|
||||
element.remove();
|
||||
}
|
||||
|
||||
(function () {
|
||||
mainElement = document.querySelector("main");
|
||||
|
||||
addButton = document.querySelector("#add");
|
||||
spreadButton = document.querySelector("#spread");
|
||||
rotateButton = document.querySelector("#rotate");
|
||||
|
||||
addButton.addEventListener("click", addImg);
|
||||
spreadButton.addEventListener("click", spacing);
|
||||
rotateButton.addEventListener("click", rotate);
|
||||
|
||||
document
|
||||
.querySelectorAll("img")
|
||||
.forEach((img) => img.addEventListener("click", removeImg.bind(null, img)));
|
||||
})();
|
||||
28
Lab 5/index.html
Executable file
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Flexbox Layout</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><button id="add">Add Image</button></li>
|
||||
<li><button id="spread">Spread Out</button></li>
|
||||
<li><button id="rotate">Rotate Direction</button></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<img src="https://picsum.photos/200?random=1" alt="random square image" />
|
||||
<img src="https://picsum.photos/200?random=2" alt="random square image" />
|
||||
</main>
|
||||
<script src="flex.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
79
Lab 5/styles.css
Executable file
@@ -0,0 +1,79 @@
|
||||
:root {
|
||||
--foreground-color: #343a40;
|
||||
--background-color: #f8f9fa;
|
||||
--nav-background-color: #ced4da;
|
||||
}
|
||||
|
||||
body {
|
||||
/* Do not change: <body> includes vertical margin only */
|
||||
margin: 2vh 0vw;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
header {
|
||||
background-color: var(--nav-background-color);
|
||||
top: 0;
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
main {
|
||||
height: 96vh;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
main.spread {
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
main.vert {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
nav > ul {
|
||||
list-style: none;
|
||||
margin-right: 5vw;
|
||||
}
|
||||
|
||||
nav > ul > li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
nav > ul > li > button {
|
||||
padding: 1vh 2vw;
|
||||
font-size: 1.2em;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
background-color: var(--background-color);
|
||||
color: var(--foreground-color);
|
||||
}
|
||||
|
||||
nav > ul > li > button:hover {
|
||||
outline: 3px solid var(--foreground-color);
|
||||
}
|
||||
|
||||
nav > ul > li > button.active {
|
||||
background-color: var(--foreground-color);
|
||||
color: var(--background-color);
|
||||
}
|
||||
|
||||
/* TODO: Define rules for the nav buttons:
|
||||
|
||||
* The coloring will be controlled dynamically:
|
||||
*
|
||||
* Start with the default background and foreground colors
|
||||
* If the mouse is hovering, add an outline using the foreground color
|
||||
* If the "active" class is present, reverse the colors
|
||||
*/
|
||||
|
||||
/* TODO: Define rules for the main flexbox:
|
||||
*
|
||||
* If the "spread" class is present, use space-around to space the images out
|
||||
* If the "vert" class is present, make the flexbox a column
|
||||
*/
|
||||
|
||||
/* BONUS: Make <img> tags show up in front of the header bar */
|
||||
100
Lab 6/cards.css
Executable file
@@ -0,0 +1,100 @@
|
||||
/* Use this file to control the layout of cards (articles) within the
|
||||
* main region of the page. */
|
||||
|
||||
/* TODO: Map the articles to grid areas */
|
||||
main > h2 {
|
||||
grid-area: heading;
|
||||
}
|
||||
main > article:nth-of-type(1) {
|
||||
grid-area: article1;
|
||||
}
|
||||
main > article:nth-of-type(2) {
|
||||
grid-area: article2;
|
||||
}
|
||||
main > article:nth-of-type(3) {
|
||||
grid-area: article3;
|
||||
}
|
||||
main > article:nth-of-type(4) {
|
||||
grid-area: article4;
|
||||
}
|
||||
main > article:nth-of-type(5) {
|
||||
grid-area: article5;
|
||||
}
|
||||
main > article:nth-of-type(6) {
|
||||
grid-area: article6;
|
||||
}
|
||||
|
||||
/* TODO: Make the main element into a grid to hold the cards */
|
||||
main {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
/* TODO: Tiny and small layouts:
|
||||
* All articles in a vertical column using grid-template-areas with
|
||||
* the main h2 title at the top. */
|
||||
|
||||
@media (max-width: 699px) {
|
||||
main {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-areas:
|
||||
"heading"
|
||||
"article1"
|
||||
"article2"
|
||||
"article3"
|
||||
"article4"
|
||||
"article5"
|
||||
"article6";
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Medium layouts:
|
||||
* Article cards are displayed 2 per row (articles 1 and 2 in the top row,
|
||||
* 3 and 4 in the second, 5 and 6 in the third). Use 1vh for row gaps and
|
||||
* 2vw for column gaps. Both columns should have the same width. Again,
|
||||
* place the main h2 title at the top. */
|
||||
@media (min-width: 700px) {
|
||||
main {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-areas:
|
||||
"heading heading"
|
||||
"article1 article2"
|
||||
"article3 article4"
|
||||
"article5 article6";
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Large layouts:
|
||||
* Article cards are now in 3 equal-width columns with the main h2 title
|
||||
* at the top. */
|
||||
@media (min-width: 1000px) {
|
||||
main {
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-template-areas:
|
||||
"heading heading heading"
|
||||
"article1 article2 article3"
|
||||
"article4 article5 article6";
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
article h3,
|
||||
p {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
main > h2 {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Print formatting:
|
||||
* Make the main content into a flex-box with the articles
|
||||
* in a column with space between the items vertically. Get rid
|
||||
* of the vertical padding on the p and h3 elements inside
|
||||
* the articles (keeping 1vw padding on the sides).
|
||||
* Remove the main h2 title from the display. */
|
||||
52
Lab 6/dark.css
Executable file
@@ -0,0 +1,52 @@
|
||||
:root {
|
||||
--dark: #333;
|
||||
--mid: #555;
|
||||
--light: #ddd;
|
||||
--white: #fff;
|
||||
}
|
||||
|
||||
/* Set default to light mode */
|
||||
body {
|
||||
background-color: var(--white);
|
||||
color: var(--dark);
|
||||
}
|
||||
|
||||
/* TODO: In light stealth mode, set font colors to light. This should
|
||||
* all text, including the buttons. */
|
||||
.stealth {
|
||||
color: var(--light);
|
||||
}
|
||||
|
||||
/* TODO: Dark mode:
|
||||
* Switch the background color to dark and switch the article
|
||||
* border to white. Any text on a gray background should become
|
||||
* dark while text on the new dark background becomes light.
|
||||
*/
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: var(--dark);
|
||||
color: var(--light);
|
||||
}
|
||||
article {
|
||||
border-color: var(--white);
|
||||
}
|
||||
main h2,
|
||||
main h3 {
|
||||
color: var(--dark);
|
||||
}
|
||||
|
||||
body.stealth {
|
||||
color: var(--mid);
|
||||
}
|
||||
|
||||
body.stealth > main h2,
|
||||
body.stealth > main h3,
|
||||
body.stealth > nav button {
|
||||
color: var(--light);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Stealth dark mode:
|
||||
* Set the font colors to mid, except for those that are on a gray
|
||||
* background. Make that text have a light font color.
|
||||
*/
|
||||
82
Lab 6/index.html
Executable file
@@ -0,0 +1,82 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Grids and Dark Mode</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap-reboot.css">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<link rel="stylesheet" href="layout.css">
|
||||
<link rel="stylesheet" href="cards.css">
|
||||
<link rel="stylesheet" href="dark.css">
|
||||
</head>
|
||||
|
||||
<!-- To check your layout, you can add class="debug" to the body element to
|
||||
add colors and borders to the major sections -->
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<h1>Header</h1>
|
||||
</header>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><button type="button" id="mode-print">Print Layout</button></li>
|
||||
<li><button type="button" id="theme-stealth">Stealth Mode</button></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<h2>Main Content</h2>
|
||||
<article id="article-1">
|
||||
<h3>Main</h3>
|
||||
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque dapibus mi sed
|
||||
facilisis finibus. Cras ut mollis eros. Aliquam commodo quis purus et tempus.
|
||||
</article>
|
||||
|
||||
<article id="article-2">
|
||||
<h3>Second</h3>
|
||||
<p>Fusce nisi enim, interdum efficitur magna quis, feugiat ornare sapien. Quisque
|
||||
molestie maximus diam, in egestas elit elementum vel. Morbi in faucibus odio.
|
||||
</article>
|
||||
|
||||
<article id="article-3">
|
||||
<h3>Third</h3>
|
||||
<p> In consectetur, odio id malesuada venenatis, diam dolor consequat erat, sed
|
||||
blandit nisi nunc ac libero.
|
||||
</article>
|
||||
|
||||
<article id="article-4">
|
||||
<h3>Fourth</h3>
|
||||
<p> Etiam consequat, sem sit amet volutpat tempus, justo mi dapibus erat, in
|
||||
maximus odio metus id ex. Pellentesque finibus eleifend tempor.
|
||||
</article>
|
||||
|
||||
<article id="article-5">
|
||||
<h3>Fifth</h3>
|
||||
<p> Morbi in imperdiet sem, at ultrices ligula. Curabitur bibendum quis leo non
|
||||
lacinia. In hac habitasse platea dictumst. Nullam malesuada consequat efficitur.
|
||||
</article>
|
||||
|
||||
<article id="article-6">
|
||||
<h3>Sixth</h3>
|
||||
<p> Nulla laoreet vestibulum hendrerit. Aenean ut velit eget lectus molestie
|
||||
bibendum. In ac elit a eros iaculis scelerisque dictum in nulla.
|
||||
</article>
|
||||
|
||||
</main>
|
||||
|
||||
<aside id="side">
|
||||
<h2>Sidebar</h2>
|
||||
</aside>
|
||||
<aside id="ad">
|
||||
<h2>Advertising</h2>
|
||||
</aside>
|
||||
<footer>
|
||||
<h2>The footer</h2>
|
||||
</footer>
|
||||
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
107
Lab 6/layout.css
Executable file
@@ -0,0 +1,107 @@
|
||||
/* Map the semantic elements to grid area names: */
|
||||
|
||||
header {
|
||||
grid-area: header;
|
||||
}
|
||||
main {
|
||||
grid-area: content;
|
||||
}
|
||||
nav {
|
||||
grid-area: nav;
|
||||
}
|
||||
#side {
|
||||
grid-area: sidebar;
|
||||
}
|
||||
#ad {
|
||||
grid-area: ad;
|
||||
}
|
||||
footer {
|
||||
grid-area: footer;
|
||||
}
|
||||
|
||||
/* Set default values for the body and list */
|
||||
body {
|
||||
display: grid;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
list-style: none;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
/* (Default) Tiny screen */
|
||||
@media (max-width: 499px) {
|
||||
body {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-areas:
|
||||
"header"
|
||||
"nav"
|
||||
"content"
|
||||
"footer";
|
||||
}
|
||||
#ad,
|
||||
#side {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
/* (Default) Tiny screen */
|
||||
|
||||
/* Small screen */
|
||||
@media (min-width: 500px) {
|
||||
body {
|
||||
padding-right: 2vw;
|
||||
grid-template-columns: 1fr 3fr;
|
||||
grid-template-areas:
|
||||
"header header"
|
||||
"nav nav"
|
||||
"sidebar content"
|
||||
"ad footer";
|
||||
}
|
||||
}
|
||||
/* Small screen */
|
||||
|
||||
/* Medium & Large screens */
|
||||
@media (min-width: 700px) {
|
||||
body {
|
||||
grid-template-columns: 1fr 4fr 1fr;
|
||||
grid-template-areas:
|
||||
"header header header"
|
||||
"nav content sidebar"
|
||||
"nav content ad"
|
||||
"footer footer footer";
|
||||
}
|
||||
nav ul {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
nav ul > li {
|
||||
margin-bottom: 3vh;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
body {
|
||||
grid-template-columns: 1fr 9fr;
|
||||
grid-template-areas:
|
||||
"header header"
|
||||
". content"
|
||||
"footer footer";
|
||||
}
|
||||
nav,
|
||||
#side,
|
||||
#ad {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Print formatting:
|
||||
* Make two columns with the right taking up 90% width.
|
||||
* The header and footer span both columns at the top and
|
||||
* bottom, respectively. The main content is only in the
|
||||
* right. Do not show the #side, #ad, or nav bar.
|
||||
*/
|
||||
31
Lab 6/script.js
Executable file
@@ -0,0 +1,31 @@
|
||||
(function () {
|
||||
const modePrint = document.querySelector("#mode-print");
|
||||
modePrint.addEventListener("click", () => window.print());
|
||||
|
||||
const themeStealth = document.querySelector("#theme-stealth");
|
||||
const header = document.querySelector("body > header > h1");
|
||||
const body = document.querySelector("body");
|
||||
themeStealth.addEventListener("click", () => {
|
||||
body.classList.toggle("stealth");
|
||||
if (body.classList.contains("stealth")) {
|
||||
header.innerText += "(Stealth Mode)";
|
||||
} else {
|
||||
header.innerText = "Header";
|
||||
}
|
||||
});
|
||||
|
||||
const articleH3s = document.querySelectorAll("article > h3");
|
||||
articleH3s.forEach((element) => {
|
||||
element.addEventListener("click", (event) => {
|
||||
event.target.nextElementSibling.hidden =
|
||||
!event.target.nextElementSibling.hidden;
|
||||
});
|
||||
});
|
||||
/* TODO: Add a click event listener to the article h3 titles. When
|
||||
* clicked, make the text of the associated p element hidden. HINT:
|
||||
* event listener callback functions receive an event parameter
|
||||
* object. event.target will refer to the object clicked (i.e., the
|
||||
* h3 title). If you print that element out to the console, you can
|
||||
* examine its fields to find how to access the p element that
|
||||
* follows. */
|
||||
})();
|
||||
52
Lab 6/styles.css
Executable file
@@ -0,0 +1,52 @@
|
||||
/* Create rounded-corner buttons */
|
||||
nav button {
|
||||
border: 2px black solid;
|
||||
border-radius: 5px;
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
/* Make the articles into cards */
|
||||
article {
|
||||
border: 1px solid black;
|
||||
border-radius: 5px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
article > h3, main > h2 {
|
||||
background: lightgray;
|
||||
padding: 1vh 1vw;
|
||||
font-size: 1.6em;
|
||||
}
|
||||
|
||||
article > p {
|
||||
padding: 1vh 1vw;
|
||||
}
|
||||
|
||||
/* Set the debug class on body to view outlines of the regions */
|
||||
.debug {
|
||||
header {
|
||||
background-color: red;
|
||||
border: 5px dashed #450085;
|
||||
}
|
||||
main {
|
||||
background-color: orange;
|
||||
border: 5px dashed #333333;
|
||||
}
|
||||
nav {
|
||||
background-color: yellow;
|
||||
border: 5px dashed #009698;
|
||||
}
|
||||
#side {
|
||||
background-color: green;
|
||||
border: 5px dashed #8EE4D7 ;
|
||||
}
|
||||
#ad {
|
||||
background-color: #F4EFE1;
|
||||
border: 5px dashed blue;
|
||||
}
|
||||
footer {
|
||||
background-color: #cbb677;
|
||||
border: 5px dashed #b599ce;
|
||||
}
|
||||
}
|
||||
|
||||
81
Lab 7/card-creator.html
Executable file
@@ -0,0 +1,81 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Card Creator</title>
|
||||
<link rel="stylesheet" href="cards.css">
|
||||
<link rel="stylesheet" href="modal.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<aside class="modal fade" tabindex="-1" role="dialog" id="user-modal">
|
||||
<div class="modal-dialog">
|
||||
<form class="modal-content card-form" id="user-form">
|
||||
<header class="modal-header">
|
||||
<h3>Add/Edit User</h3>
|
||||
</header>
|
||||
<section class="modal-body">
|
||||
<input name="guest-full" type="text" />
|
||||
<input name="guest-short" type="text" />
|
||||
<div class="invalid-feedback">Short name must be unique</div>
|
||||
<input name="old-short" type="hidden" />
|
||||
</section>
|
||||
<footer class="modal-footer">
|
||||
<button type="submit">Submit</button>
|
||||
</footer>
|
||||
</form>
|
||||
</div>
|
||||
</aside>
|
||||
<nav>
|
||||
<h1>Guest List</h1>
|
||||
<ul id="guest-list" class="card-list">
|
||||
<li id="alice">Alice <button class="btn-edit-guest" data-user="alice">Edit</button></li>
|
||||
<li id="bob">Bob <button class="btn-edit-guest" data-user="bob">Edit</button></li>
|
||||
<li id="charlie">Charlie <button class="btn-edit-guest" data-user="charlie">Edit</button></li>
|
||||
</ul>
|
||||
<button type="button" id="btn-add-guest">Add Guest</button>
|
||||
</nav>
|
||||
<main class="left-right pt-4">
|
||||
<section id="form-area">
|
||||
<h2>Invitation Details</h2>
|
||||
<form class="card-form" id="preview-form">
|
||||
<div class="form-group">
|
||||
<label for="host">Host</label>
|
||||
<input name="host" type="text" placeholder="Message sender">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="title">Title</label>
|
||||
<input name="title" type="text" placeholder="Message title">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="date">Party Date</label>
|
||||
<input name="date" type="date">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="message">Message</label>
|
||||
<textarea name="message" placeholder="Message content" rows="8"></textarea>
|
||||
</div>
|
||||
<div class="form-buttons">
|
||||
<button type="reset" id="reset-btn">Clear Form</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<section id="preview-area">
|
||||
<div class="card-display">
|
||||
<div class="card-page page-one">
|
||||
<div class="title"><span id="preview-title">TITLE</span></div>
|
||||
<div class="subtitle"><span id="preview-date">DATE</span></div>
|
||||
</div>
|
||||
<div class="card-page page-two">
|
||||
<div class="to">Dear <span id="preview-guest">GUEST</span>,</div>
|
||||
<div class="message"><span id="preview-message">YOUR MESSAGE HERE</span></div>
|
||||
<div class="from">Sincerely, <span id="preview-host">HOST</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<script src="createcard.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
214
Lab 7/cards.css
Executable file
@@ -0,0 +1,214 @@
|
||||
body {
|
||||
font-family: 'Trebuchet MS', sans-serif;
|
||||
background-color: #f0f0f0;
|
||||
display: grid;
|
||||
grid-template-rows: 1fr 9fr;
|
||||
}
|
||||
|
||||
button {
|
||||
border: 2px solid black;
|
||||
border-radius: 5px;
|
||||
padding: 0.2rem 0.2rem;
|
||||
}
|
||||
|
||||
nav {
|
||||
grid-row: 1;
|
||||
grid-column:1;
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
border:1px solid black;
|
||||
background: white;
|
||||
padding: 1vh 1vw;
|
||||
text-wrap: wrap;
|
||||
}
|
||||
|
||||
li.blank {
|
||||
border: none;
|
||||
background-color: #f0f0f0;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
li:not(.blank):hover {
|
||||
background: #c0c0b0;
|
||||
}
|
||||
|
||||
.btn-edit-guest {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#btn-add-guest {
|
||||
float: right;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.left-right {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
grid-row: 1;
|
||||
grid-column: 2;
|
||||
}
|
||||
|
||||
#card-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
[contenteditable] {
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
.card-form {
|
||||
margin: 20px;
|
||||
min-width: 500px;
|
||||
|
||||
.form-buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
align-items: baseline;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.form-buttons > button {
|
||||
margin: 0px 5px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin: 10px;
|
||||
width: auto;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 3fr;
|
||||
grid-template-rows: 1fr;
|
||||
grid-template-areas: "label input"
|
||||
". feedback";
|
||||
|
||||
& label {
|
||||
grid-area: label;
|
||||
text-align: right;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
& input,
|
||||
& textarea {
|
||||
grid-area: input;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-display {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: fit-content;
|
||||
background-color: white;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
font-size: 18px;
|
||||
font-family: 'Garamond', Times, serif;
|
||||
|
||||
.card-page {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr 2fr 2fr 1fr;
|
||||
width: 300px;
|
||||
height: 400px;
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.page-one {
|
||||
background: rgb(240, 240, 240);
|
||||
background: linear-gradient(270deg, rgba(240, 240, 240, 1) 0%, rgba(255, 255, 255, 1) 20%);
|
||||
|
||||
grid-template-areas:
|
||||
"delete"
|
||||
"title"
|
||||
"subtitle"
|
||||
".";
|
||||
|
||||
.title {
|
||||
grid-area: title;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
justify-self: center;
|
||||
align-self: center;
|
||||
font-family: "Lucida Handwriting", cursive;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
grid-area: subtitle;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
justify-self: center;
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
grid-area: delete;
|
||||
justify-self: center;
|
||||
align-self: start;
|
||||
}
|
||||
}
|
||||
|
||||
.page-two {
|
||||
background: rgb(230, 230, 230);
|
||||
background: linear-gradient(90deg, rgba(230, 230, 230, 1) 0%, rgba(255, 255, 255, 1) 5%);
|
||||
|
||||
grid-template-areas:
|
||||
"to"
|
||||
"message"
|
||||
"message"
|
||||
"from";
|
||||
|
||||
.to {
|
||||
grid-area: to;
|
||||
justify-self: start;
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
.message {
|
||||
grid-area: message;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.from {
|
||||
grid-area: from;
|
||||
justify-self: end;
|
||||
align-self: end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
form .invalid-feedback {
|
||||
color: red;
|
||||
font-size: 0.8em;
|
||||
grid-area: feedback;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
form .invalid {
|
||||
border-color: red;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
form .invalid ~ .invalid-feedback {
|
||||
visibility: visible;
|
||||
}
|
||||
154
Lab 7/createcard.js
Executable file
@@ -0,0 +1,154 @@
|
||||
/* Default users in the invitation list */
|
||||
let userList = [
|
||||
{ shortName: "Alice", fullName: "Alice N. Wonderland" },
|
||||
{ shortName: "Bob", fullName: "Bob Malooga" },
|
||||
{ shortName: "Charlie", fullName: "Charlie Bucket" },
|
||||
];
|
||||
|
||||
/* STEP 1:
|
||||
* Update a field of the card preview based on the current value of the
|
||||
* preview-form field. For the preview-form, use the field's .value field.
|
||||
* Find the corresponding preview-X field (i.e., for the preview-form host
|
||||
* field, you should update preview-host's textContent. */
|
||||
function updateField(field) {
|
||||
document.querySelector(`#preview-${field.name}`).textContent = field.value;
|
||||
}
|
||||
|
||||
/* STEP 1:
|
||||
* When the Clear Form button is clicked, set all of the preview-area's
|
||||
* fields back to the default values as given in the HTML file. */
|
||||
function defaultPreview() {
|
||||
document.querySelector("#preview-host").textContent = "HOST";
|
||||
document.querySelector("#preview-title").textContent = "TITLE";
|
||||
document.querySelector("#preview-message").textContent = "YOUR MESSAGE HERE";
|
||||
document.querySelector("#preview-date").textContent = "DATE";
|
||||
}
|
||||
|
||||
/* STEP 2:
|
||||
* Update the preview of the card to show the selected user. Use the
|
||||
* user parameter to search through the userList, trying to match the
|
||||
* shortName field. You should do a case-insensitive match, meaning
|
||||
* the shortName field should be passed to the toLowerCase() function.
|
||||
* Get the preview-guest field and set its textContent to the user's
|
||||
* fullName field. */
|
||||
function previewCard(user) {
|
||||
const guestPreview = document.querySelector("#preview-guest");
|
||||
const listUser = userList.find(
|
||||
(listUser) => listUser.shortName.toLowerCase() === user.id
|
||||
);
|
||||
guestPreview.textContent = listUser.fullName;
|
||||
}
|
||||
|
||||
(function () {
|
||||
// STEP 1:
|
||||
// Get the preview form. For each of the text fields (host, title, message),
|
||||
// add a keyup event listener to call updateField on that field name. For
|
||||
// the date field, use a change event listener to do the same.
|
||||
const form = document.querySelector("#preview-form");
|
||||
const { host, title, message, date } = form;
|
||||
host.addEventListener("keyup", updateField.bind(null, host));
|
||||
title.addEventListener("keyup", updateField.bind(null, title));
|
||||
message.addEventListener("keyup", updateField.bind(null, message));
|
||||
date.addEventListener("change", updateField.bind(null, date));
|
||||
|
||||
// STEP 1:
|
||||
// When the reset-btn button is clicked, call defaultPreview() to restore
|
||||
// the preview fields to their original values.
|
||||
document
|
||||
.querySelector("#reset-btn")
|
||||
.addEventListener("click", defaultPreview);
|
||||
|
||||
// STEP 2:
|
||||
// For each of the existing users in the invitation list, add a click
|
||||
// listener that will put their name into the card preview.
|
||||
// HINT: You can grab all of them and use .forEach:
|
||||
document
|
||||
.querySelectorAll("#guest-list > li")
|
||||
.forEach((userCard) =>
|
||||
userCard.addEventListener("click", previewCard.bind(null, userCard))
|
||||
);
|
||||
|
||||
// STEP 3:
|
||||
// Grab all elements with the "modal" class. When clicked, remove the
|
||||
// "show" class from the target element.
|
||||
const modal = document.querySelector(".modal");
|
||||
modal.addEventListener("click", (event) => {
|
||||
if (event.target === modal) {
|
||||
modal.classList.remove("show");
|
||||
}
|
||||
});
|
||||
|
||||
// STEP 3:
|
||||
// For each of the btn-edit-guest buttons, add a click event listener. When
|
||||
// clicked, get the data-user attribute from the clicked item and find the
|
||||
// guest from the userList with that shortName. Store the guest's fullName
|
||||
// and shortName into the user-form fields and show the modal. Also store
|
||||
// the shortName in the old-short field and stop the event propagation.
|
||||
const userForm = document.querySelector("#user-form");
|
||||
|
||||
document.querySelectorAll(".btn-edit-guest").forEach((btn) => {
|
||||
btn.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
|
||||
const dataUser = btn.dataset.user;
|
||||
const listUser = userList.find(
|
||||
(listUser) => listUser.shortName.toLowerCase() === dataUser
|
||||
);
|
||||
userForm["guest-full"].value = listUser.fullName;
|
||||
userForm["guest-short"].value = listUser.shortName;
|
||||
userForm["old-short"].value = listUser.shortName;
|
||||
|
||||
modal.classList.add("show");
|
||||
});
|
||||
});
|
||||
|
||||
// STEP 3:
|
||||
// When the modal form is submitted, user the user-form's old-short field
|
||||
// to find the user from the userList. Also look for the new short-name value
|
||||
// in the userList. If the new short-name is found and it is not the same
|
||||
// user as before (e.g., the new name conflicts with someone else), add the
|
||||
// "invalid" class to the guest-short input and return.
|
||||
//
|
||||
// If the short-name is valid, get the guest-short and guest-full values from
|
||||
// the form and update the user in the userList. Hide the modal.
|
||||
//
|
||||
// BONUS: Update the short name that appears in the guest-list item. Note
|
||||
// that you'll need to first get the item, then access its firstChild. Otherwise,
|
||||
// setting the textContent will accidentally remove the edit button.
|
||||
userForm.addEventListener("submit", (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
const guestFull = userForm["guest-full"].value;
|
||||
const guestShort = userForm["guest-short"].value;
|
||||
const oldShort = userForm["old-short"].value;
|
||||
|
||||
const newId = guestShort.toLowerCase();
|
||||
const oldId = oldShort.toLowerCase();
|
||||
|
||||
const listUserIndex = userList.findIndex(
|
||||
(listUser) => listUser.shortName.toLowerCase() === oldId
|
||||
);
|
||||
|
||||
for (let i = 0; i < userList.length; i++) {
|
||||
const shortNameMatches = userList[i].shortName.toLowerCase() === newId;
|
||||
if (i !== listUserIndex && shortNameMatches) {
|
||||
userForm["guest-short"].classList.add("invalid");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
userList[listUserIndex].fullName = guestFull;
|
||||
userList[listUserIndex].shortName = guestShort;
|
||||
|
||||
const oldListItem = document.querySelector(`#guest-list > li#${oldId}`);
|
||||
oldListItem.id = newId;
|
||||
|
||||
const newNode = document.createElement("div");
|
||||
newNode.textContent = guestShort;
|
||||
oldListItem.replaceChild(newNode.firstChild, oldListItem.firstChild);
|
||||
oldListItem.firstElementChild.dataset.user = newId;
|
||||
|
||||
userForm["guest-short"].classList.remove("invalid");
|
||||
modal.classList.remove("show");
|
||||
});
|
||||
})();
|
||||
95
Lab 7/modal.css
Executable file
@@ -0,0 +1,95 @@
|
||||
/* Modal interactions based on Bootstrap */
|
||||
|
||||
.modal {
|
||||
/* The modal covers the entire screent */
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
|
||||
/* The modal has a dark color */
|
||||
background-color: rgb(33, 37, 41, .5);
|
||||
}
|
||||
|
||||
.fade:not(.show) {
|
||||
/* When not shown, the modal is see-through and (important!) doesn't capture clicks */
|
||||
pointer-events: none;
|
||||
transition: opacity .15s linear;
|
||||
opacity: 0;
|
||||
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.fade {
|
||||
/* Controls the speed of the fade in/out transitions */
|
||||
transition: opacity .15s linear;
|
||||
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.show {
|
||||
/* When shown, make the dark gray (somewhat transparent) background solid */
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
/* Controls the drop-down motion of the dialog box */
|
||||
.modal-dialog {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* When the modal gets the show class added, drop down from 0 to 10vh from the top */
|
||||
.modal.show .modal-dialog {
|
||||
transition: transform .3s ease-out;
|
||||
transform: translate(0,10vh);
|
||||
}
|
||||
|
||||
/* When the modal is dismissed, raise it before making it disappear */
|
||||
.modal.fade:not(.show) .modal-dialog {
|
||||
transition: transform .3s ease-out;
|
||||
transform: translate(0,-10vh);
|
||||
}
|
||||
|
||||
/* Create the box around the modal content */
|
||||
.modal-content {
|
||||
pointer-events: auto;
|
||||
background: white;
|
||||
opacity: 1;
|
||||
min-height: 10vh;
|
||||
min-width: 30vw;
|
||||
border: 1px solid rgba(0,0,0,.2);
|
||||
border-radius: .3rem;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid gray;
|
||||
}
|
||||
|
||||
.modal-header * {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 0rem 1rem;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
border-top: 1px solid gray;
|
||||
padding: 1rem;
|
||||
}
|
||||
188
Lab 8/funs.js
Executable file
@@ -0,0 +1,188 @@
|
||||
/* STEP 1: Given a movie object, copy its title into a new field called
|
||||
* textContent and return the movie.
|
||||
*
|
||||
* @param {object} movie A movie object from the JSON data set
|
||||
*/
|
||||
function setTitleContent(movie) {
|
||||
movie.textContent = movie.title;
|
||||
return movie;
|
||||
}
|
||||
|
||||
/* STEP 2: Given a movie object, append the remaining fields into the
|
||||
* textContent field. Each function should append only the relevant field.
|
||||
* Chaining them together would create a textContent string such as the
|
||||
* following:
|
||||
* Mad Max: Fury Road (2015) - 120 minutes [8.1]
|
||||
* Make sure to include the correct spacing and punctuation marks.
|
||||
*
|
||||
* @param {object} movie A movie object from the JSON data set with the
|
||||
* title already copied into the movie.textContent field.
|
||||
*/
|
||||
function appendYear(movie) {
|
||||
movie.textContent = movie.textContent.concat(` (${movie.year})`);
|
||||
return movie;
|
||||
}
|
||||
|
||||
function appendRuntime(movie) {
|
||||
movie.textContent = movie.textContent.concat(` - ${movie.runtime} minutes`);
|
||||
return movie;
|
||||
}
|
||||
|
||||
function appendRating(movie) {
|
||||
movie.textContent = movie.textContent.concat(` [${movie.rating}]`);
|
||||
return movie;
|
||||
}
|
||||
|
||||
/* STEP 3: Return a closure (arrow function) that takes a movie argument
|
||||
* and compares its .rating field with this function's rating argument.
|
||||
* Return true if the movie's rating satisfies this minimum criterion.
|
||||
* Note that you need to call parseFloat on the movie.rating field because
|
||||
* JSON data defaults to a string type.
|
||||
*
|
||||
* @param {number} rating The minimum movie rating that will cause the
|
||||
* closure to return true for a movie.
|
||||
*/
|
||||
function setMinRating(rating) {
|
||||
// If the minimum rating value passed in the query string is NaN,
|
||||
// the closure should always evaluate to false.
|
||||
// Whether or not this is desireable is up to the designer
|
||||
|
||||
const minRating = Number.parseFloat(rating);
|
||||
return (movie) => Number.parseFloat(movie.rating) >= minRating;
|
||||
}
|
||||
|
||||
/* STEP 3: Complete the following functions just as you did setMinRating.
|
||||
* You'll need to use parseInt instead of parseFloat, because these are
|
||||
* all integer values.
|
||||
*/
|
||||
function setMinYear(year) {
|
||||
const minYear = Number.parseFloat(year);
|
||||
return (movie) => Number.parseFloat(movie.year) >= minYear;
|
||||
}
|
||||
|
||||
function setMaxYear(year) {
|
||||
const maxYear = Number.parseFloat(year);
|
||||
return (movie) => Number.parseFloat(movie.year) <= maxYear;
|
||||
}
|
||||
|
||||
function setMinTime(mins) {
|
||||
const minMins = Number.parseFloat(mins);
|
||||
return (movie) => Number.parseFloat(movie.runtime) >= minMins;
|
||||
}
|
||||
|
||||
function setMaxTime(mins) {
|
||||
const maxMins = Number.parseFloat(mins);
|
||||
return (movie) => Number.parseFloat(movie.runtime) <= maxMins;
|
||||
}
|
||||
|
||||
/* buildItem - Helper function that creates a DOM <li> element, adds the
|
||||
* list-group-item class, and inserts the movie's text content. Do not
|
||||
* modify.
|
||||
*
|
||||
* @param {object} movie The movie object to create as a list item
|
||||
* @param {object} list The <ul> to add the item to
|
||||
*/
|
||||
function buildItem(movie, list) {
|
||||
let item = document.createElement("li");
|
||||
item.classList.add("list-group-item");
|
||||
item.textContent = movie.textContent;
|
||||
list.append(item);
|
||||
}
|
||||
|
||||
(async function () {
|
||||
// STEP 1: Start your anonymous initialization function here. Be sure to
|
||||
// end the file with the needed syntax to call the function.
|
||||
|
||||
// FIRST CODE IN THE INITIALIZATION FUNCTION
|
||||
|
||||
// Get the <ul> object from the HTML (do not modify)
|
||||
let ul = document.querySelector("#target");
|
||||
|
||||
// Set default values (do not modify)
|
||||
let minYear = 0;
|
||||
let maxYear = 3000;
|
||||
let minTime = 0;
|
||||
let maxTime = 500;
|
||||
let minRating = 0.0;
|
||||
|
||||
// Get the query string and split it into an array of distinct queries.
|
||||
// (do not modify)
|
||||
// For example, given index.html?minyear=1990&minrating=9.0, the query
|
||||
// variable is the array [ 'minyear=1990', 'minrating=9.0' ]
|
||||
let query = window.location.search.substring(1); //.split('&');
|
||||
if (query !== "") {
|
||||
query = query.split("&");
|
||||
} else {
|
||||
query = undefined;
|
||||
}
|
||||
|
||||
// KEEP THIS HARD-CODED TO AVOID CORS ISSUES
|
||||
const hostname = "https://w3.cs.jmu.edu/kirkpams/343/labs/lab8";
|
||||
const url = `${hostname}/data.json`;
|
||||
|
||||
// STEP 1: Fetch the JSON data from the URL. If the query string is empty
|
||||
// (i.e., query is undefined), grab just the first 10 data entries. Given
|
||||
// this array, use .map to call setTitleContent on each entry and .forEach
|
||||
// to call buildItem for each. You may NOT use a traditional loop (e.g.,
|
||||
// for-of, while, etc.) for this lab.
|
||||
//
|
||||
// STEP 2: Extend the movie's textContent by using .map with the additional
|
||||
// functions to append the year, runtime, and rating values.
|
||||
//
|
||||
// STEP 3: If the query variable is defined, then the URL contains a query
|
||||
// string of criteria. Use the criteria specified in the query string to
|
||||
// filter the data. Each criterion would be of the form minyear=2000, with
|
||||
// the criteria being minyear, maxyear, mintime, maxtime, or minrating. Use
|
||||
// the values here to change the default minYear, etc., listed above. Note
|
||||
// that you will need to use parseInt or parseFloat to convert the query
|
||||
// string value into a number.
|
||||
//
|
||||
// Once you've processed all of the filter criteria, run the full JSON data
|
||||
// set through these using .filter, then use .map and .forEach as before to
|
||||
// generate the data.
|
||||
|
||||
// END OF THE INITIALIZATION FUNCTION
|
||||
|
||||
// ! Important caveat of this implementation, there is no specification for
|
||||
// ! how to handle situations where the same query param is passed multiple
|
||||
// ! times, or when query params contradict each other.
|
||||
// ! This implementation sequentially applies filters for every query param
|
||||
// ! regardless of the other conditions in list of query params.
|
||||
|
||||
let movieData = await fetch(url)
|
||||
.then((response) => response.json())
|
||||
.catch(() => null);
|
||||
if (!movieData) return;
|
||||
|
||||
// In order to constrain all current and potential future filter functions
|
||||
// to a singular interface all filter functions will accept a single string
|
||||
// parameter (the query value).
|
||||
// Any parsing of this string will be handled by the individual filter functions.
|
||||
|
||||
const filterMap = {
|
||||
minyear: setMinYear,
|
||||
maxyear: setMaxYear,
|
||||
mintime: setMinTime,
|
||||
maxtime: setMaxTime,
|
||||
minrating: setMinRating,
|
||||
};
|
||||
|
||||
query?.forEach((queryString) => {
|
||||
const [name, value] = queryString.split("=");
|
||||
|
||||
if (name in filterMap) {
|
||||
movieData = movieData.filter(filterMap[name](value));
|
||||
}
|
||||
});
|
||||
|
||||
if (!query) {
|
||||
movieData = movieData.slice(0, 10);
|
||||
}
|
||||
|
||||
movieData
|
||||
.map(setTitleContent)
|
||||
.map(appendYear)
|
||||
.map(appendRuntime)
|
||||
.map(appendRating)
|
||||
.forEach((movie) => buildItem(movie, ul));
|
||||
})();
|
||||
51
Lab 8/index.html
Executable file
@@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="author" content="Michael S. Kirkpatrick">
|
||||
<title>IMDb Demo</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Step 0: Create the nav bar in all files -->
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="index.html">Lab 9</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item"> <a class="nav-link active" href="index.html?minrating=8.5">High Rating</a>
|
||||
<li class="nav-item"> <a class="nav-link active" href="index.html?minyear=1970&maxyear=1979">The '70s</a>
|
||||
<li class="nav-item"> <a class="nav-link active" href="index.html?mintime=150">Long Movies</a>
|
||||
<li class="nav-item"> <a class="nav-link active" href="index.html?maxtime=100&minrating=8.0">Best Short Movies</a>
|
||||
<li class="nav-item"> <a class="nav-link active" href="index.html?minrating=8.0&minyear=1980&maxyear=1990&mintime=116&maxtime=120">Blade Runner</a>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<br>
|
||||
|
||||
<header class="container">
|
||||
<h1>IMDb Sample</h1>
|
||||
|
||||
<p>This page uses a small sample of records from IMDb's public web service.
|
||||
</header>
|
||||
|
||||
<main class="container">
|
||||
<ul class="list-group" id="target"></ul>
|
||||
</main>
|
||||
|
||||
</body>
|
||||
|
||||
<script src="funs.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
</html>
|
||||
88
Modals/modal.css
Executable file
@@ -0,0 +1,88 @@
|
||||
/* Start by styling the outermost element defining a modal. This element
|
||||
* should cover the entire screen with a dark but transparent background
|
||||
* color. It needs a z-index value to make sure it is placed over
|
||||
* everything else. */
|
||||
.modal {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgb(33, 37, 41, 0.5);
|
||||
|
||||
/* STEP 0: Initially, occupy only the bottom half of the screen. You'll
|
||||
* change this later to cover the whole thing. */
|
||||
top: 0;
|
||||
|
||||
/* STEP 1: Add an opacity value of 0 to make the modal initially
|
||||
* invisible (completely transparent). */
|
||||
opacity: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
/* Helper class for the modal. When the modal is activated, it "fades in"
|
||||
* over the course of .15 seconds, going from fully transparent (can't
|
||||
* be seen) to fully opaque (blocks out the background). This is optional,
|
||||
* but it makes for a nicer looking transition. */
|
||||
.fade {
|
||||
transition: opacity 0.15s linear;
|
||||
}
|
||||
|
||||
/* STEP 1a: Define a combined selector that applies to any element that has
|
||||
* the 'fade' class but doesn't have the 'show' class. HINT: There is a
|
||||
* :not pseudoclass where :not(...) means the rule applies when ... is not
|
||||
* true. */
|
||||
.fade:not(.show) {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.show {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* STEP 2: Define a descendant selector to grab any element with the
|
||||
* 'modal-dialog' class that is a descendant of a shown modal (has both
|
||||
* the 'modal' and 'show' classes). */
|
||||
TODO {
|
||||
/* The transform property is used to define a change to an element. */
|
||||
transition: transform 0.3s ease-out;
|
||||
transform: translate(0, 10vh);
|
||||
}
|
||||
|
||||
/* STEP 2a: Make the modal dialog a centered flexbox to add spacing to
|
||||
* center the modal content horizontally. */
|
||||
.modal-dialog {
|
||||
}
|
||||
|
||||
/* STEP 2a: As above, use a descendant selector to grab the 'modal-dialog'
|
||||
* that is a descendant of 'modal', but only if the 'modal' element doesn't
|
||||
* have the 'show' class. */
|
||||
TODO {
|
||||
transition: transform 0.3s ease-out;
|
||||
transform: translate(0, -10vh);
|
||||
}
|
||||
|
||||
/* Create the box around the modal content */
|
||||
.modal-content {
|
||||
background: white;
|
||||
min-height: 10vh;
|
||||
min-width: 30vw;
|
||||
border: 1px solid black;
|
||||
border-radius: 0.3rem;
|
||||
}
|
||||
|
||||
/* Basic styling - not part of the tutorial */
|
||||
body {
|
||||
background: lightgray;
|
||||
font-family: "Trebuchet MS", sans-serif;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
li {
|
||||
width: 15vw;
|
||||
background: white;
|
||||
border: 1px black solid;
|
||||
padding: 0.5vh 1vw;
|
||||
}
|
||||
63
Modals/modal.html
Executable file
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Modal Demo</title>
|
||||
<link rel="stylesheet" href="modal.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main>
|
||||
<h1>Modal demo</h1>
|
||||
<ul>
|
||||
<li id="modal-btn-1">Modal Step 1</li>
|
||||
<li id="modal-btn-2">Modal Step 2</li>
|
||||
<li id="modal-btn-3">Modal Step 3</li>
|
||||
</ul>
|
||||
</main>
|
||||
|
||||
<!-- STEP 1: add the modal fade classes -->
|
||||
<div id="modal-step-1" class="modal fade">
|
||||
<p style="background: blue; color: white">Modal Step 1</p>
|
||||
</div>
|
||||
|
||||
<!-- STEP 2: copy modal 1 and add a modal-dialog around the p -->
|
||||
<div id="modal-step-2" class="modal fade modal-dialog">
|
||||
<p style="background: blue; color: white">Modal Step 2</p>
|
||||
</div>
|
||||
|
||||
<!-- STEP 3: copy modal 2 and add a modal-content around the p -->
|
||||
|
||||
</body>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
/* STEP 1: Add a click event listener to modal-btn-1. When clicked,
|
||||
* add the 'show' class to modal-step-1. */
|
||||
//document.querySelector(???).addEventListener('click', () =>
|
||||
// document.querySelector(???).???);
|
||||
const modal = document.getElementById('modal-step-1')
|
||||
const modalBtn1 = document.getElementById('modal-btn-1')
|
||||
modalBtn1.addEventListener('click', () => modal.classList.add('show'))
|
||||
|
||||
modal.addEventListener('click', () => modal.classList.remove('show'))
|
||||
/* STEP 1: Add a click event listener to modal-step-1 (NOT the button).
|
||||
* When clicked, from the 'show' class from modal-step-1. */
|
||||
|
||||
/* STEP 2: Add click event listeners for modal-btn-2 and modal-step-2
|
||||
* similar to those above. */
|
||||
|
||||
/* STEP 3: Comment out the click event listeners above. Make a loop to
|
||||
* generate the modal-btn-n and modal-step-n values for n = 1, 2, 3. In
|
||||
* the loop, add click event listeners to add the 'show' class. */
|
||||
|
||||
/* STEP 3a: Instead of relying on a for loop on the indexes, use
|
||||
* document.querySelectorAll to grab all 'modal' elements. This function
|
||||
* returns an array. Loop through that array using .forEach and add an
|
||||
* event to remove the 'show' class from modal-step-N. */
|
||||
|
||||
})();
|
||||
</script>
|
||||
|
||||
</html>
|
||||
33
Prep 2/ch03-proj01.html
Executable file
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Chapter 03 Project 01</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Fundamentals of Web Development</h1>
|
||||
<p>
|
||||
<em>By Randy Connolly and Ricardo Hoar</em>
|
||||
</p>
|
||||
<a href="./funwebdev-3rd-ed-cover.jpg">
|
||||
<img src="./funwebdev-3rd-ed-cover-small.jpg" alt="funwebdev-3rd-ed-cover-small">
|
||||
</a>
|
||||
<p>
|
||||
This textbook covers a broad range of topics required for modern web development.
|
||||
</p>
|
||||
<p>
|
||||
<a href="http://www.funwebdev.com">Learn more</a>
|
||||
</p>
|
||||
<h2>First Chapters</h2>
|
||||
<ol>
|
||||
<li>Introduction to Web Development</li>
|
||||
<li>How the Web Works</li>
|
||||
<li>Introduction to HTML</li>
|
||||
<li>Introduction to CSS</li>
|
||||
</ol>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
30
Prep 2/codingjs-1.js
Executable file
@@ -0,0 +1,30 @@
|
||||
// s/o to https://the-winter.github.io/codingjs
|
||||
|
||||
// https://the-winter.github.io/codingjs/exercise.html?name=sleepIn&title=Warmup-1
|
||||
function sleepIn(weekday, vacation) {
|
||||
return !weekday || vacation
|
||||
}
|
||||
|
||||
// https://the-winter.github.io/codingjs/exercise.html?name=monkeyTrouble&title=Warmup-1
|
||||
function monkeyTrouble(aSmile, bSmile) {
|
||||
return (aSmile && bSmile) || (!aSmile && !bSmile)
|
||||
}
|
||||
|
||||
// https://the-winter.github.io/codingjs/exercise.html?name=sumDouble&title=Warmup-1
|
||||
function sumDouble(a, b){
|
||||
return a === b ? a * 4 : a + b
|
||||
}
|
||||
|
||||
// https://the-winter.github.io/codingjs/exercise.html?name=frontBack&title=Warmup-1
|
||||
function frontBack(str){
|
||||
const chars = str.split("")
|
||||
;[chars[0], chars[chars.length - 1]] = [chars[chars.length - 1], chars[0]];
|
||||
return chars.join("")
|
||||
}
|
||||
|
||||
// https://the-winter.github.io/codingjs/exercise.html?name=intMax&title=Warmup-1
|
||||
function intMax(a, b, c){
|
||||
// I'll assume Math.max(a, b, c) is cheating
|
||||
|
||||
return a > b && a > c ? a : b > c ? b : c
|
||||
}
|
||||
BIN
Prep 2/funwebdev-3rd-ed-cover-small.jpg
Executable file
|
After Width: | Height: | Size: 31 KiB |
BIN
Prep 2/funwebdev-3rd-ed-cover.jpg
Executable file
|
After Width: | Height: | Size: 200 KiB |
61
Prep 3/ch03-proj02.html
Executable file
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Share Your Travels</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<img src="images/share-logo.png" alt="logo" />
|
||||
<nav>
|
||||
<a href="#description">Description</a> | <a href="#related">Related</a> | <a href="#reviews">Reviews</a>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<h2>Venice - Grand Canal</h2>
|
||||
|
||||
<main>
|
||||
<section>
|
||||
<h3 id="description">Description</h3>
|
||||
<p>This view of the Grand Canal in
|
||||
<a href="https://en.wikipedia.org/wiki/Venice">Venice</a>
|
||||
was taken from the <strong>Ponte di Rialto</strong>.
|
||||
</p>
|
||||
<figure>
|
||||
<img src="images/venice.jpg" alt="Venice" />
|
||||
<figcaption>Photo by Randy Connolly</figcaption>
|
||||
</figure>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3 id="related">Related Images</h3>
|
||||
<img src="images/v1.jpg" alt="More Venice" />
|
||||
<img src="images/v2.jpg" alt="More Venice" />
|
||||
<img src="images/v3.jpg" alt="More Venice" />
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3 id="reviews">Reviews</h3>
|
||||
<article>
|
||||
<p>By Hypatia on <time>2019-10-23</time></p>
|
||||
<p>I love Venice in the morning.</p>
|
||||
</article>
|
||||
<hr>
|
||||
<article>
|
||||
<p>By Curia on <time>2019-12-11</time></p>
|
||||
<p>I want to visit Venice!</p>
|
||||
</article>
|
||||
<p>Copyright © 2020 Share Your Travels</p>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<p>
|
||||
<a href="#description">Description</a> | <a href="#related">Related</a> | <a href="#reviews">Reviews</a>
|
||||
</p>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
BIN
Prep 3/images/share-logo.png
Executable file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
Prep 3/images/v1.jpg
Executable file
|
After Width: | Height: | Size: 14 KiB |
BIN
Prep 3/images/v2.jpg
Executable file
|
After Width: | Height: | Size: 18 KiB |
BIN
Prep 3/images/v3.jpg
Executable file
|
After Width: | Height: | Size: 19 KiB |
BIN
Prep 3/images/venice.jpg
Executable file
|
After Width: | Height: | Size: 285 KiB |
101
Prep 4/arrays.html
Executable file
@@ -0,0 +1,101 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Array Champion 3000</title>
|
||||
<link rel="icon" href="https://fav.farm/🏆">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p><em>Psst: have a look at the JavaScript Console</em> 💁</p>
|
||||
<script>
|
||||
// It's time to work out those array muscles! 💪
|
||||
// Complete the following exercises to get your array game on point.
|
||||
// Become an array CHAMPION!!!1!! 🏆🏆🏆
|
||||
|
||||
// Some data we can work with
|
||||
const inventors = [
|
||||
{ first: 'Albert', last: 'Einstein', year: 1879, passed: 1955 },
|
||||
{ first: 'Isaac', last: 'Newton', year: 1643, passed: 1727 },
|
||||
{ first: 'Galileo', last: 'Galilei', year: 1564, passed: 1642 },
|
||||
{ first: 'Marie', last: 'Curie', year: 1867, passed: 1934 },
|
||||
{ first: 'Johannes', last: 'Kepler', year: 1571, passed: 1630 },
|
||||
{ first: 'Nicolaus', last: 'Copernicus', year: 1473, passed: 1543 },
|
||||
{ first: 'Max', last: 'Planck', year: 1858, passed: 1947 },
|
||||
{ first: 'Katherine', last: 'Blodgett', year: 1898, passed: 1979 },
|
||||
{ first: 'Ada', last: 'Lovelace', year: 1815, passed: 1852 },
|
||||
{ first: 'Sarah E.', last: 'Goode', year: 1855, passed: 1905 },
|
||||
{ first: 'Lise', last: 'Meitner', year: 1878, passed: 1968 },
|
||||
{ first: 'Hanna', last: 'Hammarström', year: 1829, passed: 1909 }
|
||||
];
|
||||
|
||||
const people = [
|
||||
'Bernhard, Sandra', 'Bethea, Erin', 'Becker, Carl', 'Bentsen, Lloyd', 'Beckett, Samuel', 'Blake, William', 'Berger, Ric', 'Beddoes, Mick', 'Beethoven, Ludwig',
|
||||
'Belloc, Hilaire', 'Begin, Menachem', 'Bellow, Saul', 'Benchley, Robert', 'Blair, Robert', 'Benenson, Peter', 'Benjamin, Walter', 'Berlin, Irving',
|
||||
'Benn, Tony', 'Benson, Leana', 'Bent, Silas', 'Berle, Milton', 'Berry, Halle', 'Biko, Steve', 'Beck, Glenn', 'Bergman, Ingmar', 'Black, Elk', 'Berio, Luciano',
|
||||
'Berne, Eric', 'Berra, Yogi', 'Berry, Wendell', 'Bevan, Aneurin', 'Ben-Gurion, David', 'Bevel, Ken', 'Biden, Joseph', 'Bennington, Chester', 'Bierce, Ambrose',
|
||||
'Billings, Josh', 'Birrell, Augustine', 'Blair, Tony', 'Beecher, Henry', 'Biondo, Frank'
|
||||
];
|
||||
|
||||
// Array.prototype.filter()
|
||||
// 1. Filter the list of inventors for those who were born in the 1500's
|
||||
// Store the result in a variable called 'fifteen'
|
||||
|
||||
const fifteen = inventors.filter((inventor) => inventor.year >= 1500 && inventor.year < 1600)
|
||||
|
||||
// Array.prototype.map()
|
||||
// 2. Give us an array of the inventors first and last names
|
||||
// Store the result in a variable called 'fullNames'
|
||||
|
||||
const fullNames = inventors.map((inventor) => `${inventor.first} ${inventor.last}`)
|
||||
|
||||
// Array.prototype.toSorted()
|
||||
// 3. Sort the inventors by birthdate, oldest to youngest
|
||||
// Store the result in a variable called 'ordered'
|
||||
|
||||
const ordered = inventors.toSorted((previous, current) => previous.year - current.year)
|
||||
|
||||
// Array.prototype.reduce()
|
||||
// 4. How many years did all the inventors live all together?
|
||||
// Store the result in a variable called 'totalYears'
|
||||
|
||||
const totalYears = inventors.reduce((previous, current) => previous + (current.passed - current.year), 0)
|
||||
|
||||
// 5. Sort the inventors by years lived
|
||||
// Store the result in a variable called 'oldest'
|
||||
|
||||
const oldest = inventors.toSorted((previous, current) => (current.passed - current.year) - (previous.passed - previous.year))
|
||||
|
||||
// 6. Create a list of Boulevards in Paris that contain 'de' anywhere in the name
|
||||
// https://en.wikipedia.org/wiki/Category:Boulevards_in_Paris
|
||||
// Store the result in a variable called 'category'
|
||||
const boulevards = [
|
||||
'Boulevards of Paris', 'City walls of Paris', 'Thiers wall', 'Wall of Charles V', 'Wall of Philip II Augustus', 'City gates of Paris',
|
||||
"Haussmann's renovation of Paris", 'Boulevards of the Marshals', 'Boulevard Auguste-Blanqui', 'Boulevard Barbès', 'Boulevard Beaumarchais',
|
||||
"Boulevard de l'Amiral-Bruix", 'Boulevard Mortier', 'Boulevard Poniatowski', 'Boulevard Soult', 'Boulevard des Capucines',
|
||||
'Boulevard de la Chapelle', 'Boulevard de Clichy', 'Boulevard du Crime', "Boulevard du Général-d'Armée-Jean-Simon", 'Boulevard Haussmann',
|
||||
"Boulevard de l'Hôpital", 'Boulevard des Italiens', 'Boulevard Lefebvre', 'Boulevard de la Madeleine', 'Boulevard de Magenta',
|
||||
'Boulevard Malesherbes', 'Boulevard Marguerite-de-Rochechouart', 'Boulevard Montmartre', 'Boulevard du Montparnasse', 'Boulevard Raspail',
|
||||
'Boulevard Richard-Lenoir', 'Boulevard Saint-Germain', 'Boulevard Saint-Michel', 'Boulevard de Sébastopol', 'Boulevard de Strasbourg',
|
||||
'Boulevard du Temple', 'Boulevard Voltaire', 'Boulevard de la Zone']
|
||||
|
||||
const category = boulevards.filter((boulevard) => /de/.test(boulevard))
|
||||
|
||||
// 7. Sorting exercise
|
||||
// Sort the people alphabetically by last name
|
||||
// Store the result in a variable called 'alpha'
|
||||
|
||||
const alpha = people.toSorted((previous, current) => previous.split(", ")[0].localeCompare(current.split(", ")[0]))
|
||||
|
||||
// 8. Reduce Exercise
|
||||
// Sum up the instances of each of these:
|
||||
const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car', 'truck'];
|
||||
// Store the result in a variable called 'transportation'
|
||||
// The result should be an object where the keys are the names of the transportation methods and the values are the number of instances
|
||||
|
||||
const transportation = data.reduce((obj, current) => Object.assign(obj, { [current]: (obj[current] ?? 0) + 1 }), {})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
BIN
Prep 6/Screenshots/Fluid Colums 400px.png
Executable file
|
After Width: | Height: | Size: 559 KiB |
BIN
Prep 6/Screenshots/Fluid Colums 600px.png
Executable file
|
After Width: | Height: | Size: 553 KiB |
BIN
Prep 6/Screenshots/Fluid Colums 700px.png
Executable file
|
After Width: | Height: | Size: 561 KiB |
BIN
Prep 6/Screenshots/Holy Grail.png
Executable file
|
After Width: | Height: | Size: 555 KiB |
72
Prep 6/fluid-columns.css
Executable file
@@ -0,0 +1,72 @@
|
||||
.wrapper {
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"header"
|
||||
"nav"
|
||||
"content"
|
||||
"sidebar"
|
||||
"ad"
|
||||
"footer";
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.wrapper > * {
|
||||
background-color: #ffec99;
|
||||
border-radius: 5px;
|
||||
border: 1px solid red;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.main-head {
|
||||
grid-area: header;
|
||||
}
|
||||
.content {
|
||||
grid-area: content;
|
||||
}
|
||||
.main-nav {
|
||||
grid-area: nav;
|
||||
}
|
||||
.side {
|
||||
grid-area: sidebar;
|
||||
}
|
||||
.ad {
|
||||
grid-area: ad;
|
||||
}
|
||||
.main-footer {
|
||||
grid-area: footer;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 500px) {
|
||||
.wrapper {
|
||||
grid-template-columns: 1fr 3fr;
|
||||
grid-template-areas:
|
||||
"header header"
|
||||
"nav nav"
|
||||
"sidebar content"
|
||||
"ad footer";
|
||||
}
|
||||
nav ul {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 700px) {
|
||||
.wrapper {
|
||||
grid-template-columns: 1fr 4fr 1fr;
|
||||
grid-template-areas:
|
||||
"header header header"
|
||||
"nav content sidebar"
|
||||
"nav content ad"
|
||||
"footer footer footer";
|
||||
}
|
||||
nav ul {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
35
Prep 6/fluid-columns.html
Executable file
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Fluid Columns</title>
|
||||
<link rel="stylesheet" href="fluid-columns.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<header class="main-head">The header</header>
|
||||
<nav class="main-nav">
|
||||
<ul>
|
||||
<li><a href="">Nav 1</a></li>
|
||||
<li><a href="">Nav 2</a></li>
|
||||
<li><a href="">Nav 3</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<article class="content">
|
||||
<h1>Main article area</h1>
|
||||
<p>
|
||||
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Animi deserunt placeat molestiae vitae
|
||||
voluptates modi distinctio repudiandae, expedita suscipit tenetur nesciunt magnam autem maxime ea libero
|
||||
totam soluta ipsa fuga.
|
||||
</p>
|
||||
</article>
|
||||
<aside class="side">Sidebar</aside>
|
||||
<div class="ad">Advertising</div>
|
||||
<footer class="main-footer">The footer</footer>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
34
Prep 6/holy-grail.css
Executable file
@@ -0,0 +1,34 @@
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
header,
|
||||
footer {
|
||||
background-color: sandybrown;
|
||||
}
|
||||
|
||||
.middler {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
aside {
|
||||
flex-basis: 150px;
|
||||
background-color: cornsilk;
|
||||
}
|
||||
|
||||
main {
|
||||
flex-grow: 1;
|
||||
flex-basis: 0;
|
||||
}
|
||||
|
||||
main,
|
||||
aside,
|
||||
header,
|
||||
footer {
|
||||
padding: 10px;
|
||||
}
|
||||
42
Prep 6/holy-grail.html
Executable file
@@ -0,0 +1,42 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Holy Grail</title>
|
||||
<link rel="stylesheet" href="holy-grail.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<h1>header</h1>
|
||||
</header>
|
||||
|
||||
<div class="middler">
|
||||
<aside class="lefter">
|
||||
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quibusdam sed, ad voluptas itaque quasi
|
||||
voluptatum ea iure doloremque reprehenderit et illo dolores cum magni odio consequatur id ab ipsa
|
||||
provident!</p>
|
||||
</aside>
|
||||
<main>
|
||||
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quibusdam sed, ad voluptas itaque quasi
|
||||
voluptatum ea iure doloremque reprehenderit et illo dolores cum magni odio consequatur id ab ipsa
|
||||
provident!</p>
|
||||
|
||||
</main>
|
||||
<aside class="righter">
|
||||
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quibusdam sed, ad voluptas itaque quasi
|
||||
voluptatum ea iure doloremque reprehenderit et illo dolores cum magni odio consequatur id ab ipsa
|
||||
provident!</p>
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<h2>footer</h2>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
61
Prep 7/index.html
Executable file
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Prep 7</title>
|
||||
<meta author="Nicholas Tamassia">
|
||||
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<form action="" id="number-form">
|
||||
<label for="number-input">Number of images:</label>
|
||||
<input id="number-input" name="image-number" type="number">
|
||||
<button type="submit">Generate</button>
|
||||
</form>
|
||||
|
||||
<form action="" id="color-form">
|
||||
<label for="color-input">Background color</label>
|
||||
<input id="color-input" name="background-color" type="color" />
|
||||
<button type="submit">Change background</button>
|
||||
</form>
|
||||
|
||||
<div id="wrapper"></div>
|
||||
|
||||
<script>
|
||||
const wrapper = document.getElementById('wrapper')
|
||||
const numberForm = document.getElementById('number-form')
|
||||
const colorForm = document.getElementById('color-form')
|
||||
|
||||
numberForm.onsubmit = (event) => {
|
||||
event.preventDefault()
|
||||
const imageCount = Number(new FormData(numberForm).get('image-number'))
|
||||
if (imageCount < 0) return
|
||||
|
||||
while (wrapper.firstChild) {
|
||||
wrapper.removeChild(wrapper.lastChild)
|
||||
}
|
||||
|
||||
for (let i = 0; i < imageCount; i++) {
|
||||
const img = new Image(200, 200)
|
||||
img.src = `https://picsum.photos/200/200?random=${Math.ceil(Math.random() * 100)}`
|
||||
wrapper.appendChild(img)
|
||||
}
|
||||
}
|
||||
|
||||
colorForm.onsubmit = (event) => {
|
||||
event.preventDefault()
|
||||
const formData = new FormData(colorForm)
|
||||
document.body.style.backgroundColor = formData.get('background-color')
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
34
Prep 8/load.html
Executable file
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Nicholas Tamassia - Prep 8 - Load</title>
|
||||
|
||||
<style>
|
||||
/* YOUR STYLE HERE */
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="name-display"></div>
|
||||
<div id="favorite-display"></div>
|
||||
<div id="quotes-display"></div>
|
||||
|
||||
<script>
|
||||
const nameDisplay = document.getElementById('name-display')
|
||||
const favoriteDisplay = document.getElementById('favorite-display')
|
||||
const quotesDisplay = document.getElementById('quotes-display')
|
||||
|
||||
nameDisplay.textContent = localStorage.getItem('fullname')
|
||||
favoriteDisplay.textContent = Number.parseFloat(localStorage.getItem('favnumber')) + 5
|
||||
|
||||
JSON.parse(localStorage.getItem('quotes')).forEach((quote) => {
|
||||
const listItem = document.createElement('li')
|
||||
listItem.textContent = quote
|
||||
quotesDisplay.appendChild(listItem)
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
33
Prep 8/save.html
Executable file
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Nicholas Tamassia - Prep 8 - Save</title>
|
||||
|
||||
<style>
|
||||
/* YOUR STYLE HERE */
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
Data saved!
|
||||
|
||||
<script>
|
||||
const items = {
|
||||
'fullname': 'Nicholas Tamassia',
|
||||
'favnumber': '28', // It's a Perfect Number! Literally.
|
||||
'quotes': [
|
||||
"Savior, conqueror, hero, villain. You are all things, Revan... and yet you are nothing. In the end, you belong to neither the light nor the darkness. You will forever stand alone.",
|
||||
"Do you know the difference between an error and a mistake? Anyone can make an error. But that error doesn't become a mistake until you refuse to correct it.",
|
||||
"It is said that one should keep one's allies within view, and one's enemies within reach"
|
||||
]
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(items)) {
|
||||
localStorage.setItem(key, typeof value === "string" ? value : JSON.stringify(value))
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||