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.

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>
Question JSON Data
{"subject":[{"id":"Q","question":"...?","isImage":"true","answer":"answerChoice","solution":"solutionDescr","score": 1, "choices":{"choice1", "choice2", "choice3", "choice4"}}]}
%%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)
  Input In [22]
    id =
         ^
SyntaxError: invalid syntax
%%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>
Subject ID Question Answer
%%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>
Subject ID Question Answer Pinned

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)