Baby’s First Module

Baby’s First Module

Modules are self contained scripts with their own distinct functionality. This allows for the addition or removal of modules as neccessary. It is easy enough to require modules using Node.js, but in the browser they behave very weirdly based on what browser you’re using. One of the quirks of JavaScripts!

A book is organized into chapters, a good program is divided into modules.

In my blockly big picture post I used an inelegant hack within the CreateDataSet block to include the stringified class code into the block itself. This is the perfect use case for a module!

Our Goal:

Rather than include the class script inside the CreateDataSet block, create a seperate module

Workflow

  • Create the Analysis class in a file called myModule.js and export it
  • Import Analysis within our index.html file
  • Change the CreateDataSet block to only contain the string new Analysis()
  • Cross fingers, see if it works??

Before we even begin, I’m still a little confused why each browser has their own errors but in order to run and debug any html code locally download lite-server [npm install lite-server] then serve your site in the directory where your html is located using lite-server index.html. This worked far better than using Chrome directly!

myModule.js

I’ve created a file called myModule.js where I’ve defined the Analysis class and I’m exporting it to be used in our html file. The only line that’s changed here from the code in the prior post is the first line, be sure to export this as default

// rather than const PREFIX = 
// we will export Analysis as a module
export default class Analysis {
    constructor () { 
        this.value = 0 
    }
    increment () { 
        this.value += 1; 
        return this 
    }
    display () {
    return this.value 
    }
}

Import

Back inside our html file we add

import Analysis from "myModule.js";

This was the trickiest part. This script needs to be contained within a type=module script tag, but in order for the blockly code to access the module we have to make Analysis a global class. The simplist way to do this is by using window.Analysis:

<script type="module">
import Analysis from "myModule.js";
window.Analysis = Analysis
</script>

example_blocks.js

Now we get elegant. Rather than include the Analysis class defintion within our block, we can simply point to our newly created module

Blockly.JavaScript['example_CreateDataSet'] = function(block) {
    return "new Analysis()"
}

Whew! With A LOT of help from Evan Schultz, I successfully loaded my first module!

BONUS

I had to include window.Analysis = Analysis because in my current framework I created two buttons with event handlers ABOVE the module.

While this works, it’s not good code ettiquite. Instead, we can create the button elements with IDs, then assign the event handlers BELOW the module script tag. That way we create buttons, then specify what those buttons actually DO after our module is loaded. This way, our two buttons show JavaScript and run JavaScript will work without needing to specify Analysis at the global scope.

Rather than having buttons with their functions at the top of the html

<button onclick="showCode()">Show JavaScript</button>
<button onclick="runCode()">Run JavaScript</button>

Declare button elements and have the specifications of what they actually DO after the module is loaded.

<button id="showCode">Show JavaScript</button>
<button id="runCode">Run JavaScript</button>

Now, BELOW our loaded module we can assign the function runCode [which evaluates the JavaScript within our blocks] to the button with the id above. This lets us look for the button in the UI - and then attach a click event to it. Below the runCode function we can now add the lines:

document.getElementById("runCode").addEventListener('click', runCode)
document.getElementById("showCode").addEventListener('click', showCode)

document looks within the entire html, and getElementById() grabs the proper element associated with the specified id [here the buttons that we get the IDs “runCode” and “showCode”]. .addEventListener allows us to attach multipule handlers to a single element: clicking the button should initiate (1) a click and (2) the function runCode or showCode.

It’s easy to see now that having multiple modules each contained within their own script tags in our index.html (and thus individually loading) could get cumbersome. Up next, exploring module bundling [read: concatenation] and minification [read: removal of unnecessary characters]!

Avatar
Maya Gans
Data Scientist

Maya’s work as a Master’s student was focused in quantitative biology. She loves coding and is extremely passionate about data science and data visualization.

Related