Teacher's Guide: Script Recycling!
POTENTIAL CHANGE TO THIS LESSON
Perhaps don't use CoffeeScript.load, but rather CoffeeScript compile. And have students do it as a multi-program effort, rather than doing it all in one program. For example...
CustomLibrary: Create your own external JavaScript file from an existing CoffeeScript program, ideally as one that defines some useful, reusable functions. Then incorporate this custom script into an additional program:
- In your source CoffeeScript file, prepend any variable you want accessible after it load can be accessible with
window.
. This is necessary to make variables available to the rest of the program that loads this script. - Create a second program ConvertToJS to convert your source CoffeeScript file to JavaScript (this conversion process formally known as compiling). Use
load
to read in the source file; pass the output fromload
CoffeeScript.compile
; and pass this compiled code to a new file with a.js
extension usingsave
. - Reference this script in a <script> tag of a new program of your choice.
- In your source CoffeeScript file, prepend any variable you want accessible after it load can be accessible with
Overview
This lesson extends the ability to load and run scripts. The focus of the lesson is twofold: introducing the Pencil Code loadscript
function, which simplifies (in particular) the process of running scripts written in CoffeeScript; and introducing the concept of modular writing of code. For the latter, the specific goal is reading in user-defined functions that are are executable anywhere in the current script. This exercise illustrates the importance of the issue of variable scope, and formally introduces the window
object.
More about the lesson
The goal of this lesson is to enable students greater opportunities for code reuse. this becomes increasingly important as tasks get more complicated. For example, when we define functions that add the ability to siliently toggle the pen (see lesson XXX) or to add text labels directly to canvas elements (lesson YYY). (Additional Activities here go back and pull some previously-coded solutions out and turn into modules... if they haven't done them, students would benefit from the practice of those prior activities!)
Before proceeding too far, it is important to clear up some terminology. This lesson defines a module is a file that includes pre-written code that simplifies the completion of common and/or complicated tasks. A module is a unit of software. This refers - depending on the context - to a self-contained part of source code, to the file that the former is found in, or to the module object (data structure) said code declares (or generates when executed).
CoffeeScript variables are file-scoped by default (visible only in the .coffee file where they are defined.)Reusable code / Modules
When we say an application is modular, we generally mean it's composed of a set of highly decoupled, distinct pieces of functionality stored in modules. As you probably know, loose coupling facilitates easier maintainability of apps by removing dependencies where possible. When this is implemented efficiently, its quite easy to see how changes to one part of a system may affect another.
Terms for "reusable code"
The distinction between modules, packages, and libraries is blurred; there are various definitions, and can differ across languages. Modules typically refer to a piece of coe perfoming a very specific functionality, a library is reusable code that provides well-tested functionality through a well-defined interface. A package is the copiled form of the library for distribution, i.e., an installable library. A package mostly contains the source code, distribution code, documentation, examples, executables, test suite, meta-data (such as version number) etc.
stuff
Teacher notes: this lesson is limited to running a single external script. It gets complicated because of the use of nested callbacks... The next lesson shows how to create libraries which contain functions (and potentially other content) that can be imported and used in the local script just as jQuery functions are... (the next lesson starts with importing public libraries, and then shows how to create your own)
Defining our own utilities
Taken from "Return_Notes":
The usefulness of such utility functions will become more evident once students learn to create and access separate source code files. Then utilities files that store functions that can be accessed from any program. While this is easy to do when running programs directly accessing a browser's JavaScript, it is more challenging to read in external scripts in the Pencil Code environment, because features of the environment that usually facilitate student coding (such as not having to write the HTML compenents of each program or to compile CoffeeScript files to Javascript) in this context end up getting in the way. There is a workaround, but it requires use of callbacks. This topic will therefore be revisited after the Callbacks! lesson, in the External Files! lesson.
Asynchronous processes
loadscript
functions asynronously. One option is to use continuation passing style, i.e., put all code that should run after loadscript
in the callback or in a function called from that callback. But while this works fine for short programs, it is cumbersome for bigger programs (especially if we want to make more than one call to loadscript
)Notes to activities
There is a
AnnotatedShape: Note the fact that the path to the module includes /home/rather than /edit/. As discussed in the Notes to the I/O lessons, this is essential for the Pencil Code server to serve up the expected file type. (I DON'T THINK THEY NEED TO ADD /proxy/... DOUBLE CHECK!)
CrazyLetters: the key is for students to remember to define their function as window.jiggle rather than just jiggle.
The ArtShow activity is designed to emphasize the need to have a .coffee extension on the source file, as well as to give practice with previously-learned I/O functions. Note that if students choose scripts with embedded calls to await/defer, the programs are unlikely to function correctly. (The lesson intentionally does not mention this pitfall, as it tends to stick more if they stumble across it first themselves.) The lesson does not mention the other way to solve the problem, i.e., replace /edit/ in the path with /code/. ) Also, this activity highlights timing issues between the loaded script and script that calls it. await done defer(), in the absense of a.d.d. inside the loaded script, will force the calling script to wait. But any other needs to pause the program (i.e., at the end, so it shows the picture before the calling script erases it) need to be done inside the loaded script (otherwise it is guesswork... unless we set up some complicated events to signal completion of the program on the inside.)
Additional activities
Beyond the lesson
Namespace concerns
Typically in pencil code, we add variables to the ?? scope. But they are not window.
When we create our .coffee files, first create an object, then add all necessary resources to that object. For example, in the CrazyLetter program, window.cl = {}
, then subsequently make all references properties of this object, e.g., window.cl.print = ...
External scripts: modules, packages, libraries, frameworks
khan academy's "what is a js library?"
Pencil Code is provided as a javascript library, jQuery-turtle.js. You can see the code yourself, from a link at https://pencilcode.net/license.html
There are many additional libraries, which can help us get our work done...
We use the term "library" here rather loosely for an external resource containing functions that can be accessed for use in our current program. (python has a hierarchy, of modules which contain python functions and variables; a package is a namespace (folder??) that contains multiple modules. And a library is a collection of one or more packages ("package or library is a set of modules"). To be more precise, a library is a collection of related functionality, whereas a module only provides a single piece of functionality. Which means that, if you have a system with both modules and libraries, a library will typically contain multiple modules.
A package is a special type of module that contains many other modules in a way that makes it straightforward to import from. This shields each module from having to worry about the naming schemes of other modules conflicting with theirs.
From MDN (https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Introduction):
JavaScript libraries — Usually one or more JavaScript files containing custom functions that you can attach to your web page to speed up or enable writing common functionality. Examples include jQuery, Mootools and React.
looks like the concept of modules has been evolving in JS: https://javascript.info/modules-intro
.coffee
extension. (Etc)
(3rd Party) JavaScript Libraries
I've got a few picked out as examples that are fun.. confetti, etc. They are easily read in using loadscript (which reads in JavaScript too) in conjunction with await/defer.
jQuery plugins
plugins are a special kind of library/package for jQuery.
jQuery-turtle is a jQuery plugin for turtle graphics. A plug-in is piece of code written in a standard JavaScript file. These files provide useful jQuery methods which can be used along with jQuery library methods. There are plenty of jQuery plug-in available. They used to be available at for download from repository link at https://jquery.com/plugins. But now use the npm registry. jQuery-turtle.js is available via github.
Libraries vs. APIs
An API is an Application Programming Interface. This is a piece of software that allows other software to interact. For example, businesses often use the Google Maps API to include/integrate a map of their locations or directions on their own Website. Instead of writing all of the code to create their own map, they write code that connects to the Google Maps API and then pulls information from Google Maps.
The general explanation is that when two softwares communicate with each other through an interface, that interface is called API. For example, rules that allow you to write browser-based javascript that can interact with features of the underlying operating system on your computer; or to connect to servers (google maps api); or features of the browser (Web APIs such as Canvas API for drawing; File API for loading files from the computer; XMLHttpRequest API that underlies the load and save functions...
What can go wrong
File does not have .coffee
extension
We get an Uncaught SyntaxError, with a message to screen "Oops, the computer got confused. It says: "reserved word "function"".
As noted in (???) and seen in https://hacker.pencilcode.net/edit/44-ScriptRecycling/ArtShow2, we don't actually have to have the .coffee extension, that is a Pencil Code server issue...
calls to await within source files...
(include a section somewhere on "initui")
Pedagogy
Stear clear of libraries...
Libraries can be a lot of fun, and useful to quickly enhance student work. But they are a shortcut, and much time can get lost learning the syntax etc of the library, rather than on fundamental, underlying coding concepts. Students benefit from knowing that libraries are there (for later use...) but don't let them go down those rabbit holes...
Technicalities
Browser.coffee documentation
source code and descriptions for CoffeeScript.run, .load, http://coffee-script.org/documentation/docs/browser.html
Other ways to load scripts
"If you’d like to create top-level variables for other scripts to use, attach them as properties on window; attach them as properties on the exports object in CommonJS; or use an export statement. "
Content Security Policy
see https://web.dev/csp/; originally came across this in the Khan Academy lesson Where are JS libraries hosted? It also discusses content delivery networks (CDN).
(potentially link this topic back to same-ooriginal policy / discussion of Cross-site scripting (XSS) attacks, which was maybe mentioned in earlier lessons too(?).
<