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>
|
||||||