Friday 6 November 2020

PyBloom coding project part 12: A little JavaScript magic

Here's an extra little something for PyBloom. In part 12 I look at how to transfer data from the Python code into the CSS of the website - not as hard as it first seems.

Colour picker utility

My stretch target was to display a table of all the colours of the Bloom lamp on a page in the website. As we've seen, the colours are in a persistent SQLite table, so all I have to do is to extract from the table, and somehow get the CSS to read the colour information. Except CSS is not an interactive language, so I needed another technology. Step forward JavaScript.

The technologies

  • HTML

  • JavaScript

  • Jinja2

The code

{% extends "base.html" %}


We put all the main styling into the base page, which means as before, we simply need to extend it here.


{% block app_content %}


This HTML section will be inserted into the base.html template at the position marked app_content.


<table class="table">


We’re making use of the Bootstrap formatting for tables to make things pretty. 


<tr>

  <th scope="col">Temperature</th>

  <th scope="col">Colour</th>

</tr>


The table consists of two columns: one for Temperature and one for the corresponding Bloom colour.


{% for row in rows %}


This is our familiar Jinja2 loop, which we want to repeat for every row in the temperature conversion lookup table.


<tr>

  <td>{{row[1]}}</td>


The first cell in the row is simply the value of temperature from the lookup table.


  <td id="{{row[2]}}">{{row[2]}}</td>

</tr>


The second cell is the value of the colour, a hex string. This same string is also used to identify the cell. Each cell will have its own background colour, so needs to be uniquely identified. We’ll implement this logic with a small bit of JavaScript, so let’s jump straight into it.


{% block app_js %}


As with the inserted HTML, this identifies where the custom JavaScript goes. Order is important in placing JavaScript; as this overrides the Bootstrap JavaScript, the block is after the statement that pulls Bootstrap from the CDN.


<script>

  "use strict";


This is the normal preamble for JavaScript. Unlike CSS, as of HTML5 there’s no need to define type="text/javascript" as no other types are allowed. The second "use strict" command instructs the browser to use the modern (ECMAScript5 from 2009) interpreter. This is important as some commands will not work in an older interpreter, and some commands will work differently. 


{% for row in rows %}

  document.getElementById("{{row[2]}}").style.background = "#"+"{{row[2]}}";


We can use the same Jinja2 loop structure to set the background for each hex value cell in our table. But because each iteration of the loop creates another persistent row in the JavaScript, we need to be careful not to use variables as these would simply overwrite the previous. That’s why we have this complicated command that chains a lot of functions. Let’s pick it apart.

  • document.getElementById(): We assigned a unique ID for each table cell containing a hex value

  • "{{row[2]}}": This unique ID is the hex value string

  • style.background: JavaScript accesses the cell colour using this method (which is slightly different to the CSS attribute of background-color)

  • = "#"+"{{row[2]}}": The colour is the hex value from the lookup table, which is a string (as accepted by the SQLite database), but has to be prefixed with a hash to identify it as a hex string

  • ; Don’t forget to finish every JavaScript statement with a semicolon - which isn’t required in Python or CSS or SQLite


The table now pulls the Hue bloom colour data from the external SQLite table and displays on a web page.

Putting it together

{% extends "base.html" %}



{% block app_content %}

  <h1>Colour key</h1>

  <div>

    <table class="table">

      <tr>

        <th scope="col">Temperature</th>

        <th scope="col">Colour</th>

      </tr>

      {% for row in rows %}

      <tr>

        <td>{{row[1]}}</td>

        <td id="{{row[2]}}">{{row[2]}}</td>

      </tr>

      {% endfor %}

    </table>

  </div>

{% endblock %}



{% block app_js %}

  <script>

    "use strict";

    {% for row in rows %}

      document.getElementById("{{row[2]}}").style.background = "#"+"{{row[2]}}";

    {% endfor %}

  </script>

{% endblock %}



This colour picker page combines a lot of technologies to achieve something that seemed quite simple, but turned out to require a bit of thought. And that's the theme for this entire project! In the next section, I'll look back at the project and draw out some conclusions. Also visit https://github.com/Schmoiger/pybloom for the full story.

No comments:

Post a Comment

It's always great to hear what you think. Please leave a comment, and start a conversation!