JavaScript Tutorial
Quick launch into Variables, Functions, Arrays, Classes, HTML.
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
Build a Person object and JSON
JavaScript and other languages have special properties and syntax to store and represent data. In fact, a class in JavaScript is a special function.
- Definition of class allows for a collection of data, the "class Person" allows programmer to retain name, github id, and class of a Person.
- Instance of a class, the "const teacher = new Person("Mr M", "jm1021", 1977)" makes an object "teacher" which is an object representation of "class Person".
- Setting and Getting properties After creating teacher and student objects, observe that properties can be changed/muted or extracted/accessed.
%%html
<!-- load jQuery and tablesorter scripts -->
<html>
<head>
<!-- load jQuery and tablesorter scripts -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.31.3/js/jquery.tablesorter.min.js"></script>
<style>
/* CSS-style selector maps to table id or other id's in HTML */
#jsonTable, #flaskTable {
background-color: #353b45;
padding: 10px;
border: 3px solid #ccc;
box-shadow: 0.8em 0.4em 0.4em blue;
}
</style>
</head>
<body>
<!-- Table for writing and extracting jsonText -->
<table id="jsonTable">
<thead>
<tr>
<th>Question JSON Data</th>
</tr>
</thead>
<tbody>
<tr>
<td id="jsonText">{"subject":[{"id":"Q","question":"...?","isImage":"true","answer":"answerChoice","solution":"solutionDescr","score": 1, "choices":{"choice1", "choice2", "choice3", "choice4"}}]}</td>
</tr>
</tbody>
</table>
</body>
</html>
%%js
console.log("Question objects");
/* class: Question
* Description: A collection of Person data
*/
class Question {
/* method: constructor
* parameters: subject, id - id number
* description: returns object when "new Question()" is called with matching parameters
* assignment: this.subject, this.id, ... are properties retained in the returned object
* default: isImage uses a default property, it is set to "Student"
*/
constructor(subject, id, question, isImage, answer, solution, score, choices) {
this.subject = subject;
this.id = id;
this.question = question;
this.isImage = isImage;
this.answer = answer;
this.solution = solution;
this.score = 1;
this.choices = choices;
}
/* method: setter
* parameters: id - id in subject
* description: this.id is updated from default value to value contained in id parameter
*/
setid(id) {
this.id = id;
}
/* method: getter
* description: turns properties of object into JSON object
* return value: JSON object
*/
getJSON() {
const obj = {subject: this.subject, id: this.id, question: this.question, isImage: this.isImage, answer = this.answer, solution: this.solution, score: this.score, choices: this.choices,};
const json = JSON.stringify(obj);
return json;
}
/* method: logIT
* description: "this" Question object is logged to console
*/
logIt() {
//Question Object
console.info(this);
//Log to Jupter
element.append("Question object in JSON <br>");
element.append(this.getJSON() + "<br>");
//alert(this.getJSON());
}
}
// make a new Question Object
const newQuestion = new Question("APStats", "q9", "questoistoin", "false", "answererer", "solutionsdnsj", 1, "choices"); // object type is easy to work with in JavaScript
newQuestion.logIt(); // log to console
Build a Classroom Array/List of Persons and JSON
Many key elements are shown again. New elements include...
- Building an Array, "var students" is an array of many persons
- Building a Classroom, this show forEach iteration through an array and .push adding to an array. These are key concepts in all programming languages.
%%js
console.log("Question objects");
/* class: Question
* Description: A collection of Person data
*/
class Question {
/* method: constructor
* parameters: subject, id - id number
* description: returns object when "new Question()" is called with matching parameters
* assignment: this.subject, this.id, ... are properties retained in the returned object
* default: isImage uses a default property, it is set to "Student"
*/
constructor(subject, id, question, isImage, answer, solution, score, choices) {
this.subject = subject;
this.id = id;
this.question = question;
this.isImage = isImage;
this.answer = answer;
this.solution = solution;
this.score = 1;
this.choices = choices;
}
/* method: setter
* parameters: id - id in subject
* description: this.id is updated from default value to value contained in id parameter
*/
setid(id) {
this.id = id;
}
/* method: getter
* description: turns properties of object into JSON object
* return value: JSON object
*/
getJSON() {
const obj = {subject: this.subject, id: this.id, question: this.question, isImage: this.isImage, answer = this.answer, solution: this.solution, score: this.score, choices: this.choices,};
const json = JSON.stringify(obj);
return json;
}
/* method: logIT
* description: "this" Question object is logged to console
*/
logIt() {
//Question Object
console.info(this);
//Log to Jupter
element.append("Question object in JSON <br>");
element.append(this.getJSON() + "<br>");
//alert(this.getJSON());
}
}
/* function: constructNewQuestions
* Description: Create data for Classroom and Question objects
* Returns: A Classroom Object
*/
function constructNewQuestions() {
// define a Question object
const newQuestion = new Question("APStats", "q9", "questoistoin", "false", "answererer", "solutionsdnsj", 1, "choice1"); // object type is easy to work with in JavaScript
// define a question Array of Question objects
const questions = [
new Question("APCalc", "q10", "questoistoin", "true", "answererer", "solutionsdnsj", 1, "choice1"),
new Question("ApCalc", "q11", "questoistoin", "false", "answererer", "solutionsdnsj", 1, "choice2",),
new Question("APPsyc", "q9", "questoistoin", "false", "answererer", "solutionsdnsj", 1, "choice1"),
new Question("APPsyc", "q10", "questoistoin", "true", "answererer", "solutionsdnsj", 1, "choice3"),
new Question("APStats", "Rebecca-123", "questoistoin", "false", "answererer", "solutionsdnsj", 1, "choice3"),
new Question("ApStats", "VidhiKulkarni", "questoistoin", "false", "answererer", "solutionsdnsj", 1, "choice1")
];
// make a CompSci classroom from formerly defined teacher and student objects
return new Question(question); // returns object
}
// assigns "question" to the object returned by "constructNewQuestions()" function
const createQuestions = constructNewQuestions();
// output of Objects and JSON in CompSci classroom
question.logIt();
// enable sharing of data across jupyter cells
$('#jsonText').text(question.json); // posts/embeds/writes compsci.json to HTML DOM element called jsonText
for loop to generate Table Rows in HTML output
This code extracts JSON text from HTML, that was placed in DOM in an earlier JavaScript cell, then it parses text into a JavaScript object. In addition, there is a for loop that iterates over the extracted object generating formated rows and columns in an HTML table.
- Table generation is broken into parts...
- table data is obtained from a classroom array inside of the extracted object.
- the JavaScript for loop allows the construction of a new row of data for each Person hash object inside of the the Array.
- in the loop a table row
<tr> ... </tr>
is created for each Hash object in the Array. - in the loop table data, a table column,
<td> ... </td>
is created for name, ghID, question, and role within the Hash object.
%%js
console.log("Question Web Page");
// extract JSON text from HTML page
const jsonText = document.getElementById("jsonText").innerHTML;
console.log(jsonText);
element.append("Raw jsonText element embedded in HTML<br>");
element.append( jsonText + "<br>");
// convert JSON text to Object
const question = JSON.parse(jsonText).question;
console.log(question);
// from classroom object creates rows and columns in HTML table
element.append("<br>Formatted data sample from jsonText <br>");
for (var row of question) {
element.append(row.id + " " + row.subject + '<br>');
// tr for each row, a new line
$('#question').append('<tr>')
// td for each column of data
$('#question').append('<td>' + row.subject + '</td>')
$('#question').append('<td>' + row.id + '</td>')
$('#question').append('<td>' + row.question + '</td>')
$('#question').append('<td>' + row.isImage + '</td>')
$('#question').append('<td>' + row.answer + '</td>')
$('#question').append('<td>' + row.solution + '</td>')
$('#question').append('<td>' + row.score + '</td>')
$('#question').append('<td>' + row.choices + '</td>')
// tr to end row
$('#question').append('</tr>');
}
id =
def sortQuestions(id):
n = len(id)
for i in range(n):
min_index = i
for j in range(i + 1, n):
if id[j] < id[min_index]:
min_index = j
id[i], id[min_index] = id[min_index], id[i]
sortQuestions(id)
print(id)
%%html
<head>
<!-- load jQuery and DataTables syle and scripts -->
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.25/css/jquery.dataTables.min.css">
<script type="text/javascript" language="javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript" language="javascript" src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js"></script>
</head>
<table id="flaskTable" class="table" style="width:100%">
<thead id="flaskHead">
<tr>
<th>Subject</th>
<th>ID</th>
<th>Question</th>
<th>Answer</th>
</tr>
</thead>
<tbody id="flaskBody"></tbody>
</table>
<script>
$(document).ready(function() {
subj = 'Physics';
totalQs=10;
const fetchQuizUrl = `/${subj}/${totalQs}`;
fetch('http://localhost:5000/api/quiz/questions', { mode: 'cors' })
.then(response => {
if (!response.ok) {
throw new Error('API response failed');
}
return response.json();
})
.then(data => {
for (const row of data) {
// BUG warning/resolution - DataTable requires row to be single append
$('#flaskBody').append('<tr><td>' +
row.subject + '</td><td>' +
row.qid + '</td><td>' +
row.question + '</td><td>' +
row.answer + '</td></tr>');
}
// BUG warning - Jupyter does not show Datatable controls, works on deployed GitHub pages
$("#flaskTable").DataTable();
})
.catch(error => {
console.error('Error:', error);
});
});
</script>
%%html
<head>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.25/css/jquery.dataTables.min.css">
<script type="text/javascript" language="javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript" language="javascript" src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js"></script>
</head>
<table id="flaskTable" class="table cell-border stripe" style="width:80%; border:thick solid blue;background-color:#D9F1FF;">
<thead id="flaskHead">
<tr>
<th>Subject</th>
<th>ID</th>
<th>Question</th>
<th>Answer</th>
<th>Pinned</th>
</tr>
</thead>
<tbody id="flaskBody"></tbody>
</table>
<script>
// prepare fetch GET options
const options = {
method: 'GET', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, *cors, same-origin
cache: 'default', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'omit', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
},
};
$(document).ready(function() {
dataX = {};
refresh();
function createPinnedColumn(id, isPinned) {
label = '' ; // isPinned ? 'pinned' : 'unpinned';
checked = (isPinned >= 1) ? 'checked' : '';
b = '<td><input id="' + id + '" ' + isPinned +
'" type="checkbox" name="pinner" value="' +
label + '" ' + checked +
' onclick="handlePinEvent(event)">' + '<span style="margin-left:5px;">' + label + '</span>' +
'</td>';
return b;
}
function handlePinEvent(event) {
pinned = event.target.checked;
rec = dataX[event.target.id];
savePin(event.target.id, pinned);
}
function savePin(qNo, pinValue) {
const post_options = {
...options,
method: 'PUT'
};
url = 'http://localhost:5000/api/quiz/questions/' + qNo + '/' + pinValue;
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error('API response failed');
}
return 1;
})
.then(data => {
})
.catch(error => {
console.error('Error:', error);
});
}
function refresh() {
fetch('http://localhost:5000/api/quiz/questions', { mode: 'cors' })
.then(response => {
if (!response.ok) {
throw new Error('API response failed');
}
return response.json();
})
.then(data => {
for (const row of data) {
dataX[row.id] = row;
$('#flaskBody').append('<tr><td>' +
row.subject + '</td><td>' +
row.qid + '</td><td>' +
row.question + '</td><td>' +
row.answer + '</td>' +
createPinnedColumn(row.id, row.pinned)
+ '</tr>'
);
}
$("#flaskTable").DataTable();
const pinb = document.getElementById('pinner');
if (pinb != undefined) {
pinb.addEventListener("click", handlePinEvent);
}
})
.catch(error => {
console.error('Error:', error);
});
}
});
</script>
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)