JavaScript and Jupyter references
JavaScript is the most important language you need to learn as a frontend developer. Jupyter Notebooks is a convenient way to learn the language without the overhead of creating a full Website. Jupyter Notebooks had ChatGPT plugins to assist with design and troubleshooting problems. This Notebook has colors on HTML pages that were designed with a dark mode background.
JavaScript / Jupyter General References
- W3Schools JS Reference - ChatGPT AI assistant for Chrome/Jupyter
- Theme setup for Jupyter Article. Or do these commands from shell...
- Install pip: pip install jupyterthemes
- Revert to original theme: jt -r
- List themes: jt -l
- Install with Theme, Name, Logo: jt -t onedork -T -N -kl
- Chrome Dev Tools
Coding with jQuery
- Jupyter Notebook GitHub, wget: https://raw.githubusercontent.com/nighthawkcoders/APCSP/master/_notebooks/2022-09-19-PBL-javascript_tutorial.ipynb
- Markdown Fetch example in GitHub project for APCSP
- HTML Static example in GitHub project for flask_portfolio
%%js
// Class representing a Formula One driver
class F1Driver {
// Constructor to initialize driver data
constructor(name, team, number, nationality) {
this.name = name;
this.team = team;
this.number = number;
this.nationality = nationality;
}
// Method to get the driver's name
getName() {
return this.name;
}
// Method to get the driver's team
getTeam() {
return this.team;
}
// Method to get the driver's number
getNumber() {
return this.number;
}
// Method to get the driver's nationality
getNationality() {
return this.nationality;
}
// Method to update the driver's team
setTeam(newTeam) {
this.team = newTeam;
}
}
// Example usage of the F1Driver class
const driver = new F1Driver("Lewis Hamilton", "Mercedes", 44, "British");
console.log(driver.getName()); // Output: Lewis Hamilton
console.log(driver.getTeam()); // Output: Mercedes
console.log(driver.getNumber()); // Output: 44
console.log(driver.getNationality()); // Output: British
driver.setTeam("Red Bull Racing");
console.log(driver.getTeam()); // Output: Red Bull Racing
%%html
<div id="table-container">
</div>
<script>
// Class representing a Formula One driver
class F1Driver {
// Constructor to initialize driver data
constructor(name, team, number, nationality) {
this.name = name;
this.team = team;
this.number = number;
this.nationality = nationality;
}
// Method to get the driver's name
getName() {
return this.name;
}
// Method to get the driver's team
getTeam() {
return this.team;
}
// Method to get the driver's number
getNumber() {
return this.number;
}
// Method to get the driver's nationality
getNationality() {
return this.nationality;
}
// Method to update the driver's team
setTeam(newTeam) {
this.team = newTeam;
}
}
// Function to fetch data from the API
async function fetchData() {
const url = 'https://f1-live-motorsport-data.p.rapidapi.com/drivers/2020';
const options = {
method: 'GET',
headers: {
'X-RapidAPI-Key': '9275b62a1fmsh3b832340dafb492p1abc77jsn58ef554feee6',
'X-RapidAPI-Host': 'f1-live-motorsport-data.p.rapidapi.com'
}
};
try {
const response = await fetch(url, options);
const result = await response.json();
console.log(result["results"])
return result["results"]
} catch (error) {
console.error(error);
}
}
// Function to create driver objects from the fetched data
async function createDriverObjects() {
const data = await fetchData();
if (data && data.length > 0) {
let drivers = [];
// Iterate over the data and create driver objects
for (const item of data) {
const driver = new F1Driver(
item["driver_name"],
item["team_name"],
item["driver_id"],
item["nationality"],
);
drivers.push(driver);
}
return drivers;
}
}
// Function to generate an HTML table from the driver objects
async function generateTable() {
const drivers = await createDriverObjects();
if (drivers && drivers.length > 0) {
const table = document.createElement("table");
// Create table header
const headerRow = table.insertRow();
const headers = ["Name", "Team", "Number", "Nationality"];
// Create sorting buttons and column headers
for (const header of headers) {
const th = document.createElement("th");
const button = document.createElement("button");
button.textContent = header;
button.addEventListener("click", sortTable.bind(null, header.toLowerCase()));
th.appendChild(button);
headerRow.appendChild(th);
}
// Create table rows with driver data
for (const driver of drivers) {
const row = table.insertRow();
const rowData = [
driver.getName(),
driver.getTeam(),
driver.getNumber(),
driver.getNationality(),
];
for (const data of rowData) {
const cell = row.insertCell();
cell.textContent = data;
}
}
// Append the table to a container element
const container = document.getElementById("table-container");
container.appendChild(table);
}
}
// Function to sort the table based on the selected column
function sortTable(column) {
const table = document.querySelector("table");
const rows = Array.from(table.rows).slice(1); // Exclude the header row
const columnIndex = ["name", "team", "number", "nationality"].indexOf(column);
// Sort the rows based on the selected column
rows.sort((a, b) => {
const aValue = a.cells[columnIndex].textContent;
const bValue = b.cells[columnIndex].textContent;
return aValue.localeCompare(bValue, undefined, { numeric: true, sensitivity: "base" });
});
// Remove existing rows from the table
while (table.rows.length > 1) {
table.deleteRow(1);
}
// Reinsert sorted rows into the table
for (const row of rows) {
table.appendChild(row);
}
}
// Example usage
generateTable();
</script>
%%html
<body>
<div style="display: flex; align-items: center; justify-content: center; flex-direction: column;">
<canvas id="container" width="200" height="200">
</canvas>
<h1 id="pressure-header">
P
</h1>
<input type="range" min="1" max="100" value="50" class="slider" id="pressure">
<h1 id="volume-header">
V
</h1>
<input type="range" min="1" max="100" value="50" class="slider" id="volume">
<h1 id="collisions">
# of Border Collisions:
</h1>
</div>
<style>
#container {
background-color: black;
border-style: solid;
border-width: 5px;
border-color: white;
}
.slider {
width: 500px;
height: 25px;
opacity: 0.7;
}
</style>
<script>
let container = document.getElementById("container")
let pressure = document.getElementById("pressure")
let volume = document.getElementById("volume")
let collisions = document.getElementById("volume")
let context = container.getContext("2d")
let borderCollisions = 0
let scaling = 200
let particles = [],
radius = 5,
boundaryX = 200,
boundaryY = 200,
numberOfParticles = 10
init()
volume.oninput = () => { calculatePressure() }
pressure.oninput = () => { calculateVolume() }
// calculate the new volume & scale
function calculateVolume() {
let newVolume = (50 * 50) / pressure.value
volume.value = newVolume
scale()
}
// calculate the new pressure & scale
function calculatePressure() {
let newPressure = (50 * 50) / volume.value
pressure.value = newPressure
scale()
}
// find the scale factor & set the values
function scale() {
scaling = 200*volume.value/50
context.clearRect(0, 0, 200, 200)
container.width = scaling
container.height = scaling
boundaryX = scaling
boundaryY = scaling
}
function init() {
for (let i = 0; i < numberOfParticles; i++) {
createParticle()
}
animate()
}
function createParticle() {
let particle = {}, vx2, vy2
particle.x = Math.random() * boundaryX
particle.y = Math.random() * boundaryY
particle.vx = 4 * Math.random()
particle.vy = 4 * Math.random()
particles.push(particle)
}
function drawParticle(x, y) {
context.beginPath()
context.arc(x, y, radius, 0, 2 * Math.PI, false)
context.fillStyle = 'red'
context.fill()
}
function resetVelocity(particle, axis) {
// invert x or y velocity
if (axis == 'x') {
particle.vx = -1 * particle.vx
} else {
particle.vy = -1 * particle.vy
}
borderCollisions++
}
function draw() {
for (let i = 0, l = particles.length; i < l; i++) {
let particle = particles[i]
// change particle position
particle.x += particle.vx
particle.y += particle.vy
drawParticle(particle.x, particle.y)
// reset velocity in the instance of a boundary contact
if (particle.x < 0 + radius) {
resetVelocity(particle, 'x')
} else if (particle.x > boundaryX - radius) {
resetVelocity(particle, 'x')
} else if (particle.y < 0 + radius) {
resetVelocity(particle, 'y')
} else if (particle.y > boundaryY - radius) {
resetVelocity(particle, 'y')
}
}
}
function animate() {
context.clearRect(0, 0, scaling, scaling)
draw()
requestAnimationFrame(animate)
}
function update() {
document.getElementById("pressure-header").innerHTML = "P1=50 | P2=" + pressure.value
document.getElementById("volume-header").innerHTML = "V1=50 | V2=" + volume.value
document.getElementById("collisions").innerHTML = "# of Border Collisions: " + borderCollisions
}
setInterval(update, 500)
</script>
</body>
Hacks
One key to these hacks is to build confidence with me going into final grade, I would like to see each student adapt this frontend work in their final project. Second key is the finished work can serve as review for the course, notes for the future in relationship to frontend.
- Adapt this tutorial to your own work
- Consider what you need to work on to be stronger developer
- Show something creative or unique, no cloning
- Be ready to talk to Teacher for 5 to 10 minutes. Individually!!!
- Show in Jupyter Notebook during discussion, show Theme and ChatGPT
- Have a runtime final in GithHub Pages (or Fastpage)