Introduction

coding.js and web-worker-interpreters make it possible for you to make your tutorial, blog post or textbook interactive. Writing code fragments that your users can edit and run is as easy as calling the prompt function with the id of the div element your code lives in.



(+ 137 349)
<div id="scheme-plus-1">
(+ 137 349)
</div>

<script>
  c.prompt("scheme-plus-1");
</script>

try editing the (+ 137 349), then press Ctrl-Enter and watch the evaluated answer (originally 486) change.

Including coding.js

To use coding.js on your own website, simply clone the coding-js github project and include the coding.js file. We can create a CodingJS object, which by default to a scheme interpreter.

<script src="coding.js"> </script>
<script>
  c = CodingJS();
</script>

In this example, the language is set to scheme, so coding.js invokes a scheme interpreter behind the scenes whenever your user edits your code. The interpreter path is the relative path to the directory coding.js lives in and is used to load additional files (as the files are loaded relative to this page and not coding.js). For instance if you place coding.js in a js/ext/ subdirectory, and want to use the language logic, do this instead.

<script src="js/ext/coding.js"> </script>
<script>
  c = CodingJS("js/ext", "logic");
</script>

Dependency management

Often, code fragments depend on each other. We have a prompt with a function definition:



(define (factorial n) (if (= n 0) 1 (* n (factorial (- n 1)))))
<div id="scheme-define-factorial">
(define (factorial n)
  (if (= n 0)
      1
      (* n (factorial (- n 1)))))
</div>

<script>
  c.prompt("scheme-define-factorial");
</script>

We can reuse this definition of factorial in other code fragments:


(factorial 10)
<div id="scheme-factorial">
(factorial 10);
</div>

<script>
  c.prompt("scheme-factorial", ["scheme-define-factorial"]);
</script>

This is done by passing an additional argument to prompt, an array which lists the id's of all the dependencies. When a dependency is updated, everything that depends on it is changed as well; try modifying the definition of factorial and watch the call to (factorial 10) change.

Related functions

prompt is part of a family of functions designed to be used "as-is". The other functions in the family introduce slight variations on prompt. They include frozen_prompt, no_output_prompt, no_output_frozen_prompt and hidden_prompt.

frozen_prompt makes a prompt that is not editable. Useful for exercise where users must wirte some definition for a function to be true.


(define x 10)
(* x x)
<div id="scheme-define-x-10">
(define x 10)
</div>

<div id="scheme-square-x">
(define x 10)
(* x x);
</div>

<script>
  c.prompt("scheme-define-x-10");
  c.frozen_prompt("scheme-square-x", ["scheme-define-x-10"]);
</script>

no_output_prompt suppresses the output, so only the code is visible. It is not very useful.

no_output_frozen_prompt is a frozen prompt that suppresses output. It is useful for showing off language features as it suppresses error messages.


(if <predicate> <consequent> <alternative>)
<div id="scheme-factorial">
(if <predicate> <consequent> <alternative>)
</div>
<script>
  c.no_output_frozen_prompt("scheme-if-syntax");
</script>

Lastly, hidden_prompt makes both the code and the output invisible, and can be used for exercise scaffolding, black-box functions, etc.

Internals

This example demonstrates using some internal functions. make_editable causes a div to be converted into a CodeMirror editor instance, preloaded with the code it contained.

486

the compute function calls a scheme (or language of your choice) interpreter, and in fact we can get all our functionality by binding it to the onBlur event listener that CodeMirror gives us.