Search code examples
javascripthtmlcanvasgraph

How to make a graph show up in an HTML document


I am trying to make a chart show up in an HTML file that is being generated programatically. What I'm trying to do, is to place a canvas in the HTML early on, and then have a java script actually place the chart data. But it's not working for me, and I'm not sure how to fix it.

The following is a scrubbed and condensed version of the actual HTML showing the problem.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Active chats</title>
    <meta charset="utf-8">
    <style>
        body {
            background-attachment: fixed;
            }
        .twoTables {
            margin-left:-5px;
            margin-right:-5px;
            }
        .tableLeft {
            float:left ;
            padding: 5px ;
            }
        .tableRight {
                float:left ;
                padding: 5px ;
                }
        .twoTables::after {
            content: "";
            clear: both;
            display: table;
            }
        headingLink {
            color: white; text-decoration: none ;
            }
        .dummyRow {
            line-height: 1px;
            visibility: hidden;
            }
        .freeze-table {
            border-spacing: 0;
            border-collapse: collapse;
            padding: 0;
            }
        thead th {
            top: 0;
            position: sticky;
            background-color: #666 ;
            color: #fff ;
            z-index: 20 ;
            min-height: 30px ;
            height: 30px ;
            text-align: left ;
            }
        tr:nth-child(even) {
            background-color: #f2f2f2 ;
            }
        xth, xtd { 
            padding: 0 5px;
            border-collapse: collapse;
            font-size: 100% ;
            outline: 1px solid #ccc ;
            border: none ;
            outline-offset: -1px ;
            padding-left: 5px ;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            }
        th, td {
            padding: 0 0px;
            border-collapse: collapse;
            font-size: 100% ;
            border: none ;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            padding-left: 5px;
            }
        tr {
            min-height: 25px ;
            height: 25px ;
            background-color: #ffffff
            }
        pageElement {
            display:flex; flex-wrap: nowrap; align-items: center
            }
        a:link {
            color: white ;
            text-decoration: none ;
            }
        * { padding: 0;
            margin: 0;
            }
        .fit { /* set relative picture size */
            max-width: 100%;
            max-height: 100%;
            }
        .center {
            display: block;
            margin: auto;
            }
        .imgbox {
            display: grid;
            width: 100%;
            }
        .center-fit {
            max-width: 100%;
            max-height: 100vh;
            margin: auto;
            }
        @media screen and (max-width: 100px) {
        .tableLeft {
            <!-- width: 40%; <-- ->
            }
        .tableRight {
            <!-- width:100%; <!-- ->
            }
        }
      </style>
    </head>
  <body><form method = 'POST' action = /YouTube/latestChats.php >
   <table style='border-collapse:collapse;'>
      <tr>
         <td><input type = 'checkbox' name='highlightMsg' id='highlightMsg'  checked >
            <label for='highlightMsg'>Highlight messages</label></td>
         <td><input type = 'checkbox' name = 'msgUseRegEx' id = 'msgUseRegEx' checked >
            <label for='msgUseRegEx'>Use REGEX</label></td>
         <td>Message filter</td>
         <td><input type = 'text' name = 'msgFilter' value='[@#]*request' size=30 ></td>
      </tr>
      <tr>
         <td><input type='checkbox' name='invertOrder' id='invertOrder' checked >
            <label for='invertOrder'>Latest first</label></td>
         <td>&nbsp;</td>
         <td>&nbsp;</td>
         <td>&nbsp;</td>
      </tr>
      <tr>
         <td>
            <input type='radio' name='emoteMgmt'  value='text'>&nbsp;Emoticons&nbsp;as&nbsp;text&nbsp;&nbsp;&nbsp;&nbsp;
            <input type='radio' name='emoteMgmt' checked value='icon'>&nbsp;Emoticons&nbsp;as&nbsp;image&nbsp;&nbsp;&nbsp;&nbsp;
            <input type='radio' name='emoteMgmt'  value='strip'>&nbsp;Strip&nbsp;emoticons&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                </td>
         <td>&nbsp;</td>
         <td>&nbsp;</td>
         <td>&nbsp;</td>
     </tr>
   </table>
   <br>
   <input type='submit' name='submit' value='Submit'>
   &nbsp;&nbsp;&nbsp;<input type='submit' name=backToYouTubeStuff value='Go Back'>
   &nbsp;&nbsp;&nbsp;<input type='submit' name=buttonCheckLivestream value='Check for new'>
   <br>
</form>
<br><script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div class='twoTables'>
<div id='watchers' class='tableLeft'><table>
  <tr>
    <th colspan=2>Watcher</th><th>Joined</th><th>Latest</th>
  </tr>
<tr><td style='text-align:right;'>26</td><td><span>John RC</span></td><td>07:32</td><td style='text-align:right;'>0.0m</td></tr>
<tr><td style='text-align:right;'>25</td><td><span>Carolyn Free</span></td><td>07:31</td><td style='text-align:right;'>4.2m</td></tr>
<tr><td style='text-align:right;'>24</td><td><span>Johnny Flyer</span></td><td>07:31</td><td style='text-align:right;'>3.4m</td></tr>
</table><br><br>
<div style="width: 200px;">
  <canvas id="concurrentChart">
<script>
  const ctx = document.getElementById('concurrentChart') ;
  new Chart(ctx
          , type: 'line'
          , data: {
                labels: ["07:08","07:09","07:10","07:11","07:12","07:13","07:14","07:15","07:16","07:17","07:18","07:19","07:20","07:21","07:22","07:23","07:24","07:25","07:26","07:27","07:28","07:29","07:30","07:31","07:32","07:33","07:34","07:35"]
              , datasets: [{
                  label: 'Concurrent Chat Viewers'
                  , data: [0,8,8,9,6,8,8,3,5,7,4,4,1,3,8,8,6,6,4,7,11,16,14,9,7,9,6,9]
                  , fill:false
                  , borderColor: 'rgb(75, 192, 192)'
                  , tension: 0.1
              }]
            }
        );
</script>
  </canvas>
</div></div><div id='chats' class='tableRight'><table style='border-collapse:collapse;border:0px solid white;'>
    <tr style='color:white; border:0px;'>
    <th colspan=3 style='text-align:center;background-color:darkblue;color:white;font-size:115%;font-weight:bold;border:solid white;'>2023-09-17</th>
    <td           style='background-color:darkblue;color:white;font-size:115%;font-weight:bold;border:solid white;word-wrap:break-word;'><a href='https://youtu.be/-unZO__WJuo'>2023-09-17 Atlanta timeline (23-080) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background-color:lightblue;color:black;font-size:100%;font-weight:bold;">&nbsp;(16 max)&nbsp;</span></a></td>
</tr>
<tr>
  <td style='text-align:right;color:Blue;'>1</td>
  <td style='text-align:center;color:Blue;'>07:36</td>
  <td style='text-align:left;color:Blue;'>John RC</td>
  <td style='text-align:left;color:Blue;'>
    <a style='color:blue;text-decoration:none;word-wrap:break-word;wicth:100%;' href='https://youtu.be/-unZO__WJuo?t=1690' target='_blank'>_&nbsp;
        I think he gave up</a></td>
</tr><tr>
  <td style='text-align:right;color:Blue;'>2</td>
  <td style='text-align:center;color:Blue;'>07:35</td>
  <td style='text-align:left;color:Blue;'>Blessing</td>
  <td style='text-align:left;color:Blue;'>
    <a style='color:blue;text-decoration:none;word-wrap:break-word;wicth:100%;' href='https://youtu.be/-unZO__WJuo?t=1624' target='_blank'>_&nbsp;
        <span style='background-color:red; color:black;'>@request</span> Sorry you’re having technical difficulties Dennis.</a></td>
</tr><tr>
  <td style='text-align:right;color:Blue;'>3</td>
  <td style='text-align:center;color:Blue;'>07:35</td>
  <td style='text-align:left;color:Blue;'>Buying Space</td>
  <td style='text-align:left;color:Blue;'>
    <a style='color:blue;text-decoration:none;word-wrap:break-word;wicth:100%;' href='https://youtu.be/-unZO__WJuo?t=1623' target='_blank'>_&nbsp;
        Warren, the Blood, Sweat and Tears version?</a></td>
</tr><tr>
  <td style='text-align:right;color:Blue;'>4</td>
  <td style='text-align:center;color:Blue;'>07:35</td>
  <td style='text-align:left;color:Blue;'>Sky Flier</td>
  <td style='text-align:left;color:Blue;'>
    <a style='color:blue;text-decoration:none;word-wrap:break-word;wicth:100%;' href='https://youtu.be/-unZO__WJuo?t=1619' target='_blank'>_&nbsp;
        lol @Blessing</a></td>
</tr><tr>
  <td style='text-align:right;color:Blue;'>5</td>
  <td style='text-align:center;color:Blue;'>07:35</td>
  <td style='text-align:left;color:Blue;'>TeeJ Giggles n Drones</td>
  <td style='text-align:left;color:Blue;'>
    <a style='color:blue;text-decoration:none;word-wrap:break-word;wicth:100%;' href='https://youtu.be/-unZO__WJuo?t=1590' target='_blank'>_&nbsp;
        Right Ronnie 😂😂😂</a></td>
</tr>
<tr><th colspan=5 style='background-color: #666 ;color: #fff ;z-index: 20 ;min-height: 30px ;height: 30px ;text-align: left ;'>End of data.</th>
</tr>
</table>
</div>
</div>
</body>
</html>

What should be seen, depending upon window size, is a table on the left and a chart below it, and a separate table on the right. But the chart is missing.

Is the approach incorrect here? Is it not possible to have javascript update the canvas?


Solution

  • Yes, you can absolutely use JavaScript to update a canvas in your HTML. The problem you're encountering is primarily due to the way you've structured your script and HTML.

    Here are some issues with the current structure:

    1. Script Inside Canvas: Your <script> tag is placed inside the <canvas> tag. It should be outside.
    2. Invalid JavaScript Syntax: In your new Chart() instantiation, there's an issue with the JavaScript syntax. You need {} to wrap the configuration object.

    Here's how to fix it:

    1. Move the script out of the <canvas> tag.
    2. Use the correct syntax for creating a new Chart.

    Here's a corrected version of the relevant part of your HTML:

    <div style="width: 200px;">
      <canvas id="concurrentChart"></canvas>
    </div>
    <script>
      const ctx = document.getElementById('concurrentChart').getContext('2d');
      new Chart(ctx, {
          type: 'line',
          data: {
              labels: ["07:08","07:09","07:10","07:11","07:12","07:13","07:14","07:15","07:16","07:17","07:18","07:19","07:20","07:21","07:22","07:23","07:24","07:25","07:26","07:27","07:28","07:29","07:30","07:31","07:32","07:33","07:34","07:35"],
              datasets: [{
                  label: 'Concurrent Chat Viewers',
                  data: [0,8,8,9,6,8,8,3,5,7,4,4,1,3,8,8,6,6,4,7,11,16,14,9,7,9,6,9],
                  fill: false,
                  borderColor: 'rgb(75, 192, 192)',
                  tension: 0.1
              }]
          }
      });
    </script>