├── README.md ├── examples ├── basic.html ├── basic_de.html ├── countries.js ├── data.html ├── drawing.html ├── drawing.js ├── drawing_animate.js ├── drawing_animate_de.js ├── drawing_code.js ├── drawing_de.js ├── drawing_function.js ├── drawing_function_de.js ├── drawing_if.js ├── drawing_if_de.js ├── drawing_loop.js ├── drawing_loop_de.js ├── drawing_tree.js ├── drawing_tree_de.js ├── event_code.js ├── interact.html ├── invaders.js ├── invaders_de.js ├── life_expectancy.js ├── life_expectancy_de.js ├── rainbow.js ├── transform.js ├── weather_report.js ├── weather_report_average.js └── weather_report_visualization.js ├── fonts.googleapis.com ├── css-family=Averia+Serif+Libre:300,400 ├── fdtF30xa_Erw0zAzOoG4BVVaXhodyZpwkPyKEugoMLo.woff2 └── yvITAdr5D1nlsdFswJAb8Vos2Pdf-dQN4tJmHAEs2hQ.woff2 ├── footprint.png ├── index.html ├── index_de.html ├── lib ├── README └── codemirror2 │ ├── LICENSE │ ├── lib │ ├── codemirror.css │ └── codemirror.js │ └── mode │ ├── css │ └── css.js │ ├── htmlmixed │ └── htmlmixed.js │ ├── javascript │ └── javascript.js │ └── xml │ └── xml.js ├── page1.html ├── page1_de.html ├── page2.html ├── page2_de.html ├── page3.html ├── page3_de.html ├── page4.html ├── page4_de.html ├── sandbox ├── index.html └── sandbox.js └── style.css /README.md: -------------------------------------------------------------------------------- 1 | Curriculum for the OpenTechSchool workshop "JavaScript for absolute beginners". 2 | 3 | It's mainly about basics of the JavaScript programming language. 4 | -------------------------------------------------------------------------------- /examples/basic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Our example page 4 | 5 | 6 | 10 | 11 |

This is a document. The text in angle brackets (tags) provides meta 12 | information about its structure. P stands for paragraph, for example. 13 | When preceded by a slash, it ends the tag.

14 | 15 |

Here is a button that runs some JavaScript when 16 | clicked:

17 | -------------------------------------------------------------------------------- /examples/basic_de.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Unsere Beispielseite 4 | 5 | 6 | 10 | 11 |

Dies ist ein Dokument. Der Text in den spitzen Klammern („Tags“) beschreibt 12 | die Struktur des Dokuments. „p“ z.B. steht für einen Absatz (englisch 13 | „paragraph“). Wenn ein Schrägstrich vorangestellt ist, bedeutet das, dass 14 | der Tag hier endet, also geschlossen wird.

15 | 16 |

Hier ist ein Button, der etwas JavaScript ausführt, wenn man ihn klickt: 17 |

18 | -------------------------------------------------------------------------------- /examples/data.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Graphics sandbox 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/drawing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Graphics sandbox 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/drawing.js: -------------------------------------------------------------------------------- 1 | // use_html: drawing.html 2 | // Below is a definition of a drawing. 3 | 4 | function drawing() { 5 | color("yellow"); 6 | circle(0, 0, 50); 7 | color("black"); 8 | circle(-20, 10, 7); 9 | circle(20, 10, 7); 10 | lineWidth(3); 11 | path("g -20 -10 q 20 -10 0 -50 c"); 12 | } 13 | 14 | // The following functions are available: 15 | // 16 | // color(string) - set the current color 17 | // lineWidth(number) - set the line width 18 | // box(x, y, width, height) - draw a box 19 | // circle(x, y, radius) - draw a circle 20 | // line(x1, y1, x2, y2) - draw a line 21 | // text(x, y, string) - draw text 22 | // clear() - clear the screen 23 | // path(string) - draw a complex line 24 | // In a line description, the following commands are valid: 25 | // g x y - go to point x,y without drawing 26 | // l x y - draw a line from the current point to point x,y 27 | // c - draw a line back to the start of the line 28 | // q x y cx cy - draw a curve to x,y, using cx,cy as 29 | // 'control point' to determine the curvature 30 | // 31 | // fill() - fill the current path with the current color 32 | // 33 | // Coordinates are interpreted as if 0,0 is the center of the 34 | // screen. x is the horizontal axis, and y the vertical. 35 | // Positive x goes to the right, positive y goes up. 36 | // These operations can transform the coordinate system: 37 | // 38 | // moveTo(x, y) - move the origin to x, y 39 | // rotate(degrees) - rotate subsequent drawing operations 40 | // by a number of degrees 41 | // scale(factor) - scale subsequent drawing operations 42 | // goBack() - undo one transformation 43 | -------------------------------------------------------------------------------- /examples/drawing_animate.js: -------------------------------------------------------------------------------- 1 | // use_html: drawing.html 2 | // The old smiley function from the previous step 3 | function smiley(x, y) { 4 | moveTo(x, y); 5 | color("yellow"); 6 | circle(0, 0, 50); 7 | color("black"); 8 | circle(-20, 10, 7); 9 | circle(20, 10, 7); 10 | lineWidth(3); 11 | path("g -20 -10 q 20 -10 0 -50 c"); 12 | goBack(); 13 | } 14 | 15 | function drawing() { 16 | // The angle variable stores the current rotation 17 | var angle = 0; 18 | // Draw twenty frames per second (20 * 50 = 1000 milliseconds) 19 | setInterval(frame, 50); 20 | function frame() { 21 | // Clear the screen 22 | clear(); 23 | // Update the angle 24 | angle = angle - 2; 25 | // Rotate what we are about to draw 26 | rotate(angle); 27 | // A stick... 28 | color("black"); 29 | box(-5, 100, 10, 150); 30 | // with a smiley on top 31 | smiley(0, 100); 32 | } 33 | } 34 | 35 | // The following functions are available: 36 | // 37 | // color(string) - set the current color 38 | // lineWidth(number) - set the line width 39 | // box(x, y, width, height) - draw a box 40 | // circle(x, y, radius) - draw a circle 41 | // line(x1, y1, x2, y2) - draw a line 42 | // text(x, y, string) - draw text 43 | // clear() - clear the screen 44 | // path(string) - draw a complex line 45 | // In a line description, the following commands are valid: 46 | // g x y - go to point x,y without drawing 47 | // l x y - draw a line from the current point to point x,y 48 | // c - draw a line back to the start of the line 49 | // q x y cx cy - draw a curve to x,y, using cx,cy as 50 | // 'control point' to determine the curvature 51 | // 52 | // fill() - fill the current path with the current color 53 | // 54 | // Coordinates are interpreted as if 0,0 is the center of the 55 | // screen. x is the horizontal axis, and y the vertical. 56 | // Positive x goes to the right, positive y goes up. 57 | // These operations can transform the coordinate system: 58 | // 59 | // moveTo(x, y) - move the origin to x, y 60 | // rotate(degrees) - rotate subsequent drawing operations 61 | // by a number of degrees 62 | // scale(factor) - scale subsequent drawing operations 63 | // goBack() - undo one transformation 64 | -------------------------------------------------------------------------------- /examples/drawing_animate_de.js: -------------------------------------------------------------------------------- 1 | // use_html: drawing.html 2 | // Die Smiley-Funktion vom vorherigen Schritt 3 | function smiley(x, y) { 4 | moveTo(x, y); 5 | color("yellow"); 6 | circle(0, 0, 50); 7 | color("black"); 8 | circle(-20, 10, 7); 9 | circle(20, 10, 7); 10 | lineWidth(3); 11 | path("g -20 -10 q 20 -10 0 -50 c"); 12 | goBack(); 13 | } 14 | 15 | function drawing() { 16 | // The angle variable stores the current rotation 17 | var angle = 0; 18 | // Draw twenty frames per second (20 * 50 = 1000 milliseconds) 19 | setInterval(frame, 50); 20 | function frame() { 21 | // Clear the screen 22 | clear(); 23 | // Update the angle 24 | angle = angle - 2; 25 | // Rotate what we are about to draw 26 | rotate(angle); 27 | // A stick... 28 | color("black"); 29 | box(-5, 100, 10, 150); 30 | // with a smiley on top 31 | smiley(0, 100); 32 | } 33 | } 34 | 35 | // Folgende Funktionen stehen zur Verfügung: 36 | // 37 | // color(string) - setzt die Farbe 38 | // lineWidth(number) - setzt die Dicke der Linie 39 | // box(x, y, width, height) - zeichnet einen Kasten 40 | // circle(x, y, radius) - zeichnet einen Kreis 41 | // line(x1, y1, x2, y2) - zeichnet eine Linie 42 | // text(x, y, string) - zeichnet einen Text 43 | // clear() - leert den Bildschirm 44 | // path(string) - zeichnet eine komplexe Linie (Pfad) 45 | // Für einen Pfad kann man folgende Anweisungen geben: 46 | // g x y - zum Punkt x,y bewegen, ohne zu zeichnen 47 | // l x y - zeichet eine Linie vom aktuellen Punkt bis zum Punkt x,y 48 | // c - zeichnet eine Linie, die zurückführt zum Anfang des Pfads 49 | // q x y cx cy - zeichnet eine Kurve zu x,y, wobei cx,cy als 50 | // „Kontrollpunkt“ zur Definition der Rundung dient 51 | // 52 | // fill() - fülle den Pfad mit der aktuellen Farbe 53 | // 54 | // Alle Koordinaten (Punkte) werden so interpretiert, dass 0,0 55 | // im Zentrum des Bildschirms liegt. x ist die horizontale Achse, y die vertikale. 56 | // Positive x-Werte bewegen sich nach rechts, positive y-Werte bewegen sich nach 57 | // oben. 58 | // Folgende Operationen können dieses Koordinatensystem verändern: 59 | // 60 | // moveTo(x, y) - bewegt den Ursprung nach x,y 61 | // rotate(degrees) - rotiert (dreht) alle nachfolgenden Zeichenoperationen 62 | // um die angegebene Gradzahl 63 | // scale(factor) - skaliert die nachfolgenden Zeichenoperationen 64 | // (größer/kleiner) 65 | // goBack() - macht eine Transformation rückgängig 66 | -------------------------------------------------------------------------------- /examples/drawing_code.js: -------------------------------------------------------------------------------- 1 | var _canvas, _ctx; 2 | 3 | window.onload = function() { 4 | setTimeout(function() { 5 | _canvas = document.getElementById("mycanvas"); 6 | _ctx = _canvas.getContext("2d"); 7 | clear(); 8 | drawing(); 9 | }, 20); 10 | }; 11 | 12 | function color(col) { 13 | _ctx.strokeStyle = _ctx.fillStyle = col; 14 | } 15 | 16 | function lineWidth(n) { 17 | _ctx.lineWidth = n; 18 | } 19 | 20 | var _pushDepth = 0, _centerX, _centerY; 21 | 22 | function clear() { 23 | for (var i = 0; i < _pushDepth; ++i) 24 | _ctx.restore(); 25 | var w = document.body.clientWidth - 5, h = document.body.clientHeight - 5; 26 | _canvas.width = w; 27 | _canvas.height = h; 28 | _ctx.clearRect(0, 0, w, h); 29 | _ctx.translate(_centerX = Math.round(w / 2), _centerY = Math.round(h / 2)); 30 | _ctx.scale(1, -1); 31 | _pushDepth = 2; 32 | } 33 | 34 | function box(x, y, w, h) { 35 | _ctx.fillRect(x, y - h, w, h); 36 | } 37 | 38 | function circle(x, y, r) { 39 | _ctx.beginPath(); 40 | _ctx.arc(x, y, r, 0, 2 * Math.PI); 41 | _ctx.fill(); 42 | } 43 | 44 | function line(x1, y1, x2, y2) { 45 | _ctx.beginPath(); 46 | _ctx.moveTo(x1, y1); 47 | _ctx.lineTo(x2, y2); 48 | _ctx.stroke(); 49 | } 50 | 51 | function path(spec) { 52 | _ctx.beginPath(); 53 | var parsed = spec.split(/\s+/g); 54 | function arg() { 55 | if (i == parsed.length) throw new Error("Expected number, found end of command."); 56 | var val = Number(parsed[++i]); 57 | if (isNaN(val)) throw new Error("Expected number, found '" + parsed[i] + "'"); 58 | return val; 59 | } 60 | try { 61 | for (var i = 0; i < parsed.length; ++i) { 62 | var cmd = parsed[i]; 63 | if (cmd == "c") { 64 | _ctx.closePath(); 65 | } else if (cmd == "g") { 66 | _ctx.moveTo(arg(), arg()); 67 | } else if (cmd == "l") { 68 | _ctx.lineTo(arg(), arg()); 69 | } else if (cmd == "q") { 70 | var x = arg(), y = arg(); 71 | _ctx.quadraticCurveTo(arg(), arg(), x, y); 72 | } else { 73 | throw new Error("Unrecognized path command: '" + cmd + "'"); 74 | } 75 | } 76 | _ctx.stroke(); 77 | } catch(e) { 78 | console.log("Bad path: " + e.message); 79 | } 80 | } 81 | 82 | function text(x, y, string) { 83 | _ctx.save(); 84 | _ctx.scale(1, -1); 85 | _ctx.font = "16px sans-serif"; 86 | _ctx.fillText(string, x, -y); 87 | _ctx.restore(); 88 | } 89 | 90 | function rotate(angle) { 91 | _ctx.save(); 92 | ++_pushDepth; 93 | _ctx.rotate(angle * Math.PI / 180); 94 | } 95 | 96 | function moveTo(x, y) { 97 | _ctx.save(); 98 | ++_pushDepth; 99 | _ctx.translate(x, y); 100 | } 101 | 102 | function scale(factor) { 103 | _ctx.save(); 104 | ++_pushDepth; 105 | _ctx.scale(factor, factor); 106 | } 107 | 108 | function goBack() { 109 | _ctx.restore(); 110 | --_pushDepth; 111 | } 112 | 113 | function fill(color) { 114 | _ctx.fill(); 115 | } 116 | -------------------------------------------------------------------------------- /examples/drawing_de.js: -------------------------------------------------------------------------------- 1 | // use_html: drawing.html 2 | // Dies ist die Definition einer Zeichnung: 3 | 4 | function drawing() { 5 | color("yellow"); 6 | circle(0, 0, 50); 7 | color("black"); 8 | circle(-20, 10, 7); 9 | circle(20, 10, 7); 10 | lineWidth(3); 11 | path("g -20 -10 q 20 -10 0 -50 c"); 12 | } 13 | 14 | // Folgende Funktionen stehen zur Verfügung: 15 | // 16 | // color(string) - setzt die Farbe 17 | // lineWidth(number) - setzt die Dicke der Linie 18 | // box(x, y, width, height) - zeichnet einen Kasten 19 | // circle(x, y, radius) - zeichnet einen Kreis 20 | // line(x1, y1, x2, y2) - zeichnet eine Linie 21 | // text(x, y, string) - zeichnet einen Text 22 | // clear() - leert den Bildschirm 23 | // path(string) - zeichnet eine komplexe Linie (Pfad) 24 | // Für einen Pfad kann man folgende Anweisungen geben: 25 | // g x y - zum Punkt x,y bewegen, ohne zu zeichnen 26 | // l x y - zeichet eine Linie vom aktuellen Punkt bis zum Punkt x,y 27 | // c - zeichnet eine Linie, die zurückführt zum Anfang des Pfads 28 | // q x y cx cy - zeichnet eine Kurve zu x,y, wobei cx,cy als 29 | // „Kontrollpunkt“ zur Definition der Rundung dient 30 | // 31 | // fill() - fülle den Pfad mit der aktuellen Farbe 32 | // 33 | // Alle Koordinaten (Punkte) werden so interpretiert, dass 0,0 34 | // im Zentrum des Bildschirms liegt. x ist die horizontale Achse, y die vertikale. 35 | // Positive x-Werte bewegen sich nach rechts, positive y-Werte bewegen sich nach 36 | // oben. 37 | // Folgende Operationen können dieses Koordinatensystem verändern: 38 | // 39 | // moveTo(x, y) - bewegt den Ursprung nach x,y 40 | // rotate(degrees) - rotiert (dreht) alle nachfolgenden Zeichenoperationen 41 | // um die angegebene Gradzahl 42 | // scale(factor) - skaliert die nachfolgenden Zeichenoperationen 43 | // (größer/kleiner) 44 | // goBack() - macht eine Transformation rückgängig 45 | -------------------------------------------------------------------------------- /examples/drawing_function.js: -------------------------------------------------------------------------------- 1 | // use_html: drawing.html 2 | function smiley(x, y) { 3 | moveTo(x, y); 4 | color("yellow"); 5 | circle(0, 0, 50); 6 | color("black"); 7 | circle(-20, 10, 7); 8 | circle(20, 10, 7); 9 | lineWidth(3); 10 | path("g -20 -10 q 20 -10 0 -50 c"); 11 | goBack(); 12 | } 13 | 14 | function drawing() { 15 | smiley(0, 0); 16 | smiley(-100, 20); 17 | smiley(100, 50); 18 | } 19 | 20 | // The following functions are available: 21 | // 22 | // color(string) - set the current color 23 | // lineWidth(number) - set the line width 24 | // box(x, y, width, height) - draw a box 25 | // circle(x, y, radius) - draw a circle 26 | // line(x1, y1, x2, y2) - draw a line 27 | // text(x, y, string) - draw text 28 | // clear() - clear the screen 29 | // path(string) - draw a complex line 30 | // In a line description, the following commands are valid: 31 | // g x y - go to point x,y without drawing 32 | // l x y - draw a line from the current point to point x,y 33 | // c - draw a line back to the start of the line 34 | // q x y cx cy - draw a curve to x,y, using cx,cy as 35 | // 'control point' to determine the curvature 36 | // 37 | // fill() - fill the current path with the current color 38 | // 39 | // Coordinates are interpreted as if 0,0 is the center of the 40 | // screen. x is the horizontal axis, and y the vertical. 41 | // Positive x goes to the right, positive y goes up. 42 | // These operations can transform the coordinate system: 43 | // 44 | // moveTo(x, y) - move the origin to x, y 45 | // rotate(degrees) - rotate subsequent drawing operations 46 | // by a number of degrees 47 | // scale(factor) - scale subsequent drawing operations 48 | // goBack() - undo one transformation 49 | -------------------------------------------------------------------------------- /examples/drawing_function_de.js: -------------------------------------------------------------------------------- 1 | // use_html: drawing.html 2 | function smiley(x, y) { 3 | moveTo(x, y); 4 | color("yellow"); 5 | circle(0, 0, 50); 6 | color("black"); 7 | circle(-20, 10, 7); 8 | circle(20, 10, 7); 9 | lineWidth(3); 10 | path("g -20 -10 q 20 -10 0 -50 c"); 11 | goBack(); 12 | } 13 | 14 | function drawing() { 15 | smiley(0, 0); 16 | smiley(-100, 20); 17 | smiley(100, 50); 18 | } 19 | 20 | // Folgende Funktionen stehen zur Verfügung: 21 | // 22 | // color(string) - setzt die Farbe 23 | // lineWidth(number) - setzt die Dicke der Linie 24 | // box(x, y, width, height) - zeichnet einen Kasten 25 | // circle(x, y, radius) - zeichnet einen Kreis 26 | // line(x1, y1, x2, y2) - zeichnet eine Linie 27 | // text(x, y, string) - zeichnet einen Text 28 | // clear() - leert den Bildschirm 29 | // path(string) - zeichnet eine komplexe Linie (Pfad) 30 | // Für einen Pfad kann man folgende Anweisungen geben: 31 | // g x y - zum Punkt x,y bewegen, ohne zu zeichnen 32 | // l x y - zeichet eine Linie vom aktuellen Punkt bis zum Punkt x,y 33 | // c - zeichnet eine Linie, die zurückführt zum Anfang des Pfads 34 | // q x y cx cy - zeichnet eine Kurve zu x,y, wobei cx,cy als 35 | // „Kontrollpunkt“ zur Definition der Rundung dient 36 | // 37 | // fill() - fülle den Pfad mit der aktuellen Farbe 38 | // 39 | // Alle Koordinaten (Punkte) werden so interpretiert, dass 0,0 40 | // im Zentrum des Bildschirms liegt. x ist die horizontale Achse, y die vertikale. 41 | // Positive x-Werte bewegen sich nach rechts, positive y-Werte bewegen sich nach 42 | // oben. 43 | // Folgende Operationen können dieses Koordinatensystem verändern: 44 | // 45 | // moveTo(x, y) - bewegt den Ursprung nach x,y 46 | // rotate(degrees) - rotiert (dreht) alle nachfolgenden Zeichenoperationen 47 | // um die angegebene Gradzahl 48 | // scale(factor) - skaliert die nachfolgenden Zeichenoperationen 49 | // (größer/kleiner) 50 | // goBack() - macht eine Transformation rückgängig 51 | -------------------------------------------------------------------------------- /examples/drawing_if.js: -------------------------------------------------------------------------------- 1 | // use_html: drawing.html 2 | function drawing() { 3 | var count = 0; 4 | while (count < 20) { 5 | if (count % 2 == 0) { 6 | color("black"); 7 | } else { 8 | color("gray"); 9 | } 10 | circle(count * 10, 0, 4); 11 | count = count + 1; 12 | } 13 | } 14 | 15 | // The following functions are available: 16 | // 17 | // color(string) - set the current color 18 | // lineWidth(number) - set the line width 19 | // box(x, y, width, height) - draw a box 20 | // circle(x, y, radius) - draw a circle 21 | // line(x1, y1, x2, y2) - draw a line 22 | // text(x, y, string) - draw text 23 | // clear() - clear the screen 24 | // path(string) - draw a complex line 25 | // In a line description, the following commands are valid: 26 | // g x y - go to point x,y without drawing 27 | // l x y - draw a line from the current point to point x,y 28 | // c - draw a line back to the start of the line 29 | // q x y cx cy - draw a curve to x,y, using cx,cy as 30 | // 'control point' to determine the curvature 31 | // 32 | // fill() - fill the current path with the current color 33 | // 34 | // Coordinates are interpreted as if 0,0 is the center of the 35 | // screen. x is the horizontal axis, and y the vertical. 36 | // Positive x goes to the right, positive y goes up. 37 | // These operations can transform the coordinate system: 38 | // 39 | // moveTo(x, y) - move the origin to x, y 40 | // rotate(degrees) - rotate subsequent drawing operations 41 | // by a number of degrees 42 | // scale(factor) - scale subsequent drawing operations 43 | // goBack() - undo one transformation 44 | -------------------------------------------------------------------------------- /examples/drawing_if_de.js: -------------------------------------------------------------------------------- 1 | // use_html: drawing.html 2 | function drawing() { 3 | var count = 0; 4 | while (count < 20) { 5 | if (count % 2 == 0) { 6 | color("black"); 7 | } else { 8 | color("gray"); 9 | } 10 | circle(count * 10, 0, 4); 11 | count = count + 1; 12 | } 13 | } 14 | 15 | // Folgende Funktionen stehen zur Verfügung: 16 | // 17 | // color(string) - setzt die Farbe 18 | // lineWidth(number) - setzt die Dicke der Linie 19 | // box(x, y, width, height) - zeichnet einen Kasten 20 | // circle(x, y, radius) - zeichnet einen Kreis 21 | // line(x1, y1, x2, y2) - zeichnet eine Linie 22 | // text(x, y, string) - zeichnet einen Text 23 | // clear() - leert den Bildschirm 24 | // path(string) - zeichnet eine komplexe Linie (Pfad) 25 | // Für einen Pfad kann man folgende Anweisungen geben: 26 | // g x y - zum Punkt x,y bewegen, ohne zu zeichnen 27 | // l x y - zeichet eine Linie vom aktuellen Punkt bis zum Punkt x,y 28 | // c - zeichnet eine Linie, die zurückführt zum Anfang des Pfads 29 | // q x y cx cy - zeichnet eine Kurve zu x,y, wobei cx,cy als 30 | // „Kontrollpunkt“ zur Definition der Rundung dient 31 | // 32 | // fill() - fülle den Pfad mit der aktuellen Farbe 33 | // 34 | // Alle Koordinaten (Punkte) werden so interpretiert, dass 0,0 35 | // im Zentrum des Bildschirms liegt. x ist die horizontale Achse, y die vertikale. 36 | // Positive x-Werte bewegen sich nach rechts, positive y-Werte bewegen sich nach 37 | // oben. 38 | // Folgende Operationen können dieses Koordinatensystem verändern: 39 | // 40 | // moveTo(x, y) - bewegt den Ursprung nach x,y 41 | // rotate(degrees) - rotiert (dreht) alle nachfolgenden Zeichenoperationen 42 | // um die angegebene Gradzahl 43 | // scale(factor) - skaliert die nachfolgenden Zeichenoperationen 44 | // (größer/kleiner) 45 | // goBack() - macht eine Transformation rückgängig 46 | -------------------------------------------------------------------------------- /examples/drawing_loop.js: -------------------------------------------------------------------------------- 1 | // use_html: drawing.html 2 | function drawing() { 3 | color("red"); 4 | var column = 0; 5 | while (column < 20) { 6 | circle(column * 10, 0, 4); 7 | column = column + 1; 8 | } 9 | } 10 | 11 | // The following functions are available: 12 | // 13 | // color(string) - set the current color 14 | // lineWidth(number) - set the line width 15 | // box(x, y, width, height) - draw a box 16 | // circle(x, y, radius) - draw a circle 17 | // line(x1, y1, x2, y2) - draw a line 18 | // text(x, y, string) - draw text 19 | // clear() - clear the screen 20 | // path(string) - draw a complex line 21 | // In a line description, the following commands are valid: 22 | // g x y - go to point x,y without drawing 23 | // l x y - draw a line from the current point to point x,y 24 | // c - draw a line back to the start of the line 25 | // q x y cx cy - draw a curve to x,y, using cx,cy as 26 | // 'control point' to determine the curvature 27 | // 28 | // fill() - fill the current path with the current color 29 | // 30 | // Coordinates are interpreted as if 0,0 is the center of the 31 | // screen. x is the horizontal axis, and y the vertical. 32 | // Positive x goes to the right, positive y goes up. 33 | // These operations can transform the coordinate system: 34 | // 35 | // moveTo(x, y) - move the origin to x, y 36 | // rotate(degrees) - rotate subsequent drawing operations 37 | // by a number of degrees 38 | // scale(factor) - scale subsequent drawing operations 39 | // goBack() - undo one transformation 40 | -------------------------------------------------------------------------------- /examples/drawing_loop_de.js: -------------------------------------------------------------------------------- 1 | // use_html: drawing.html 2 | function drawing() { 3 | color("red"); 4 | var column = 0; 5 | while (column < 20) { 6 | circle(column * 10, 0, 4); 7 | column = column + 1; 8 | } 9 | } 10 | 11 | // Folgende Funktionen stehen zur Verfügung: 12 | // 13 | // color(string) - setzt die Farbe 14 | // lineWidth(number) - setzt die Dicke der Linie 15 | // box(x, y, width, height) - zeichnet einen Kasten 16 | // circle(x, y, radius) - zeichnet einen Kreis 17 | // line(x1, y1, x2, y2) - zeichnet eine Linie 18 | // text(x, y, string) - zeichnet einen Text 19 | // clear() - leert den Bildschirm 20 | // path(string) - zeichnet eine komplexe Linie (Pfad) 21 | // Für einen Pfad kann man folgende Anweisungen geben: 22 | // g x y - zum Punkt x,y bewegen, ohne zu zeichnen 23 | // l x y - zeichet eine Linie vom aktuellen Punkt bis zum Punkt x,y 24 | // c - zeichnet eine Linie, die zurückführt zum Anfang des Pfads 25 | // q x y cx cy - zeichnet eine Kurve zu x,y, wobei cx,cy als 26 | // „Kontrollpunkt“ zur Definition der Rundung dient 27 | // 28 | // fill() - fülle den Pfad mit der aktuellen Farbe 29 | // 30 | // Alle Koordinaten (Punkte) werden so interpretiert, dass 0,0 31 | // im Zentrum des Bildschirms liegt. x ist die horizontale Achse, y die vertikale. 32 | // Positive x-Werte bewegen sich nach rechts, positive y-Werte bewegen sich nach 33 | // oben. 34 | // Folgende Operationen können dieses Koordinatensystem verändern: 35 | // 36 | // moveTo(x, y) - bewegt den Ursprung nach x,y 37 | // rotate(degrees) - rotiert (dreht) alle nachfolgenden Zeichenoperationen 38 | // um die angegebene Gradzahl 39 | // scale(factor) - skaliert die nachfolgenden Zeichenoperationen 40 | // (größer/kleiner) 41 | // goBack() - macht eine Transformation rückgängig 42 | -------------------------------------------------------------------------------- /examples/drawing_tree.js: -------------------------------------------------------------------------------- 1 | // use_html: drawing.html 2 | function branch(thickness) { 3 | // Give the branches individuality by randomizing their length 4 | // (between 2 and 5 times their thickness) 5 | var height = thickness * (2 + Math.random() * 3); 6 | // Draw this branch 7 | color("black"); 8 | box(-thickness / 2, height, thickness, height); 9 | 10 | // Go to the end of this branch 11 | moveTo(0, height); 12 | if (thickness < 2) { 13 | // Draw a leaf, and nothing more, if this branch is very thin 14 | color("purple"); 15 | circle(0, 0, 5); 16 | } else { 17 | // Draw two branches springing from this branch, rotated at 18 | // 30-degree angles 19 | rotate(-30); 20 | branch(thickness * 0.8); 21 | goBack(); 22 | rotate(30); 23 | branch(thickness * 0.8); 24 | goBack(); 25 | } 26 | // Clears the moveTo above 27 | goBack(); 28 | } 29 | 30 | function drawing() { 31 | // Move down to make room for tree crown 32 | moveTo(0, -200); 33 | // Draw the trunk, which in turn draws branches, and so on. 34 | branch(16); 35 | } 36 | 37 | // The following functions are available: 38 | // 39 | // color(string) - set the current color 40 | // lineWidth(number) - set the line width 41 | // box(x, y, width, height) - draw a box 42 | // circle(x, y, radius) - draw a circle 43 | // line(x1, y1, x2, y2) - draw a line 44 | // text(x, y, string) - draw text 45 | // clear() - clear the screen 46 | // path(string) - draw a complex line 47 | // In a line description, the following commands are valid: 48 | // g x y - go to point x,y without drawing 49 | // l x y - draw a line from the current point to point x,y 50 | // c - draw a line back to the start of the line 51 | // q x y cx cy - draw a curve to x,y, using cx,cy as 52 | // 'control point' to determine the curvature 53 | // 54 | // fill() - fill the current path with the current color 55 | // 56 | // Coordinates are interpreted as if 0,0 is the center of the 57 | // screen. x is the horizontal axis, and y the vertical. 58 | // Positive x goes to the right, positive y goes up. 59 | // These operations can transform the coordinate system: 60 | // 61 | // moveTo(x, y) - move the origin to x, y 62 | // rotate(degrees) - rotate subsequent drawing operations 63 | // by a number of degrees 64 | // scale(factor) - scale subsequent drawing operations 65 | // goBack() - undo one transformation 66 | -------------------------------------------------------------------------------- /examples/drawing_tree_de.js: -------------------------------------------------------------------------------- 1 | // use_html: drawing.html 2 | function branch(thickness) { 3 | // Give the branches individuality by randomizing their length 4 | // (between 2 and 5 times their thickness) 5 | var height = thickness * (2 + Math.random() * 3); 6 | // Draw this branch 7 | color("black"); 8 | box(-thickness / 2, height, thickness, height); 9 | 10 | // Go to the end of this branch 11 | moveTo(0, height); 12 | if (thickness < 2) { 13 | // Draw a leaf, and nothing more, if this branch is very thin 14 | color("purple"); 15 | circle(0, 0, 5); 16 | } else { 17 | // Draw two branches springing from this branch, rotated at 18 | // 30-degree angles 19 | rotate(-30); 20 | branch(thickness * 0.8); 21 | goBack(); 22 | rotate(30); 23 | branch(thickness * 0.8); 24 | goBack(); 25 | } 26 | // Clears the moveTo above 27 | goBack(); 28 | } 29 | 30 | function drawing() { 31 | // Move down to make room for tree crown 32 | moveTo(0, -200); 33 | // Draw the trunk, which in turn draws branches, and so on. 34 | branch(16); 35 | } 36 | 37 | // Folgende Funktionen stehen zur Verfügung: 38 | // 39 | // color(string) - setzt die Farbe 40 | // lineWidth(number) - setzt die Dicke der Linie 41 | // box(x, y, width, height) - zeichnet einen Kasten 42 | // circle(x, y, radius) - zeichnet einen Kreis 43 | // line(x1, y1, x2, y2) - zeichnet eine Linie 44 | // text(x, y, string) - zeichnet einen Text 45 | // clear() - leert den Bildschirm 46 | // path(string) - zeichnet eine komplexe Linie (Pfad) 47 | // Für einen Pfad kann man folgende Anweisungen geben: 48 | // g x y - zum Punkt x,y bewegen, ohne zu zeichnen 49 | // l x y - zeichet eine Linie vom aktuellen Punkt bis zum Punkt x,y 50 | // c - zeichnet eine Linie, die zurückführt zum Anfang des Pfads 51 | // q x y cx cy - zeichnet eine Kurve zu x,y, wobei cx,cy als 52 | // „Kontrollpunkt“ zur Definition der Rundung dient 53 | // 54 | // fill() - fülle den Pfad mit der aktuellen Farbe 55 | // 56 | // Alle Koordinaten (Punkte) werden so interpretiert, dass 0,0 57 | // im Zentrum des Bildschirms liegt. x ist die horizontale Achse, y die vertikale. 58 | // Positive x-Werte bewegen sich nach rechts, positive y-Werte bewegen sich nach 59 | // oben. 60 | // Folgende Operationen können dieses Koordinatensystem verändern: 61 | // 62 | // moveTo(x, y) - bewegt den Ursprung nach x,y 63 | // rotate(degrees) - rotiert (dreht) alle nachfolgenden Zeichenoperationen 64 | // um die angegebene Gradzahl 65 | // scale(factor) - skaliert die nachfolgenden Zeichenoperationen 66 | // (größer/kleiner) 67 | // goBack() - macht eine Transformation rückgängig 68 | -------------------------------------------------------------------------------- /examples/event_code.js: -------------------------------------------------------------------------------- 1 | var _handlers = {}, mouseX = 0, mouseY = 0; 2 | 3 | function setHandler(which, press, release) { 4 | _handlers[which] = {press: press, release: release}; 5 | } 6 | 7 | var _keyName = function() { 8 | var names = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", 9 | 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", 10 | 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", 11 | 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete", 12 | 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 13 | 221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home", 14 | 63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"}; 15 | (function() { 16 | // Number keys 17 | for (var i = 0; i < 10; i++) names[i + 48] = String(i); 18 | // Alphabetic keys 19 | for (var i = 65; i <= 90; i++) names[i] = String.fromCharCode(i); 20 | // Function keys 21 | for (var i = 1; i <= 12; i++) names[i + 111] = names[i + 63235] = "F" + i; 22 | })(); 23 | return function(e) { return names[e.keyCode] || "Unknown"; }; 24 | }(); 25 | 26 | function _buttonName(e) { 27 | var which = e.which; 28 | if (!which) { 29 | if (e.button & 1) which = 1; 30 | else if (e.button & 2) which = 3; 31 | else if (e.button & 4) which = 2; 32 | } 33 | if (which == 1 && e.ctrlKey && /Mac/.test(navigator.platform)) which = 3; 34 | return "Mouse-" + (which == 1 ? "Left" : which == 2 ? "Middle" : "Right"); 35 | } 36 | 37 | function _doHandle(name, down) { 38 | var handler = _handlers[name]; 39 | if (!handler) return; 40 | if (down && handler.state) return; 41 | handler.state = down; 42 | var func = handler[down ? "press" : "release"]; 43 | if (func) func(); 44 | } 45 | 46 | window.addEventListener("keydown", function(e) {_doHandle(_keyName(e), true);}, false); 47 | window.addEventListener("keyup", function(e) {_doHandle(_keyName(e), false);}, false); 48 | window.addEventListener("mousedown", function(e) {_doHandle(_buttonName(e), true);}, false); 49 | window.addEventListener("mouseup", function(e) {_doHandle(_buttonName(e), false);}, false); 50 | 51 | window.addEventListener("mousemove", function(e) { 52 | mouseX = e.pageX - _centerX; mouseY = _centerY - e.pageY; 53 | }, false); 54 | -------------------------------------------------------------------------------- /examples/interact.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Graphics sandbox 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/invaders.js: -------------------------------------------------------------------------------- 1 | // use_html: interact.html 2 | // ****************************************** 3 | // INVADERS.JS 4 | // A very simple Space Invaders knock-off 5 | // ****************************************** 6 | 7 | // The width and height of the game area 8 | var width = 600, height = 300; 9 | // An array containing the currently attacking invaders 10 | var invaders = []; 11 | // Array containing bullets that are currently flying 12 | var bullets = []; 13 | // Set to true when an invader reaches the bottom of the screen 14 | var gameOver = false; 15 | 16 | // The player's position is based on the mouse position. Because we 17 | // move the viewport, we have to 'move' mouse coordinates into our own 18 | // coordinate system before we can use them. 'mouseX' is provided by 19 | // the helper code for this example (described near the bottom of the 20 | // program). 21 | function playerX() { 22 | return mouseX + width / 2; 23 | } 24 | 25 | // Add a bullet object at the player's current position. 26 | function fireBullet() { 27 | bullets.push({x: playerX(), y: 10, alive: true}); 28 | } 29 | 30 | // Call fireBullet every time the left mouse button is pressed. 31 | // 'setHandler' is also described near the bottom of the program. 32 | setHandler("Mouse-Left", fireBullet); 33 | 34 | // Add a new space invader object at a random position along the top 35 | // of the screen. 36 | function newInvader() { 37 | invaders.push({x: Math.random() * width, y: height, alive: true}); 38 | } 39 | 40 | // Calculate the distance between two objects. Both objects must have 41 | // x and y properties. Uses a textbook Pythagoras formula. Needed to 42 | // be able to tell when an invader and a bullet collide. 43 | function distance(obj1, obj2) { 44 | var dx = obj1.x - obj2.x, dy = obj1.y - obj2.y; 45 | return Math.sqrt(dx * dx + dy * dy); 46 | } 47 | 48 | // This will 49 | // - Move each bullet up a little 50 | // - Draw each bullet 51 | // - Mark bullets that leave the game area as no longer alive 52 | // - Check whether a bullet hits an invader. 53 | // - If it does, mark both it and the invader as dead 54 | function processBullets() { 55 | for (var b = 0; b < bullets.length; b = b + 1) { 56 | var bullet = bullets[b]; 57 | bullet.y = bullet.y + 12; 58 | drawBullet(bullet); 59 | if (bullet.y > height) 60 | bullet.alive = false; 61 | for (var i = 0; i < invaders.length; i = i + 1) { 62 | var invader = invaders[i]; 63 | if (distance(bullet, invader) < 17) { 64 | invader.alive = false; 65 | bullet.alive = false; 66 | } 67 | } 68 | } 69 | } 70 | 71 | // Move each invader down a little. Draw them. When one hits the 72 | // bottom of the game area, set gameOver to true and mark the invader 73 | // as dead. 74 | function processInvaders() { 75 | for (var i = 0; i < invaders.length; i = i + 1) { 76 | var invader = invaders[i]; 77 | invader.y = invader.y - 2; 78 | drawInvader(invader); 79 | if (invader.y < 0) { 80 | gameOver = true; 81 | invader.alive = false; 82 | } 83 | } 84 | } 85 | 86 | // Used to remove dead bullets and invaders at the end of every turn. 87 | function removeDeadObjects(array) { 88 | var live = []; 89 | for (var i = 0; i < array.length; ++i) { 90 | if (array[i].alive) 91 | live.push(array[i]); 92 | } 93 | return live; 94 | } 95 | 96 | // Process a single step of the game (done twenty times per second). 97 | function frame() { 98 | // There is a 5% chance per turn, as long as the game is not over, 99 | // that a new invader is added. 100 | // The ! operator means 'not', the && operator means 'and'. 101 | // So this says 'if not gameOver and Math.random() is less than 0.05' 102 | if (!gameOver && Math.random() < 0.05) 103 | newInvader(); 104 | 105 | // Clear the view. 106 | clear(); 107 | // Make 0,0 the bottom left of the game area 108 | moveTo(-width / 2, -height / 2); 109 | // Draw a line at ground level. 110 | color("silver"); 111 | line(0, 0, width, 0); 112 | 113 | processBullets(); 114 | processInvaders(); 115 | // Discard dead objects. 116 | bullets = removeDeadObjects(bullets); 117 | invaders = removeDeadObjects(invaders); 118 | 119 | drawPlayer(playerX(), 0); 120 | if (gameOver) { 121 | color("red"); 122 | text(playerX() - 40, -25, "GAME OVER"); 123 | } 124 | } 125 | 126 | function drawing() { 127 | setInterval(frame, 50); 128 | } 129 | 130 | // Functions for drawing the various elements in the game. 131 | 132 | function drawInvader(invader) { 133 | moveTo(invader.x, invader.y); 134 | if (invader.alive) 135 | color("lightgreen"); 136 | else 137 | color("orange"); 138 | circle(0, 0, 14); 139 | color("green"); 140 | circle(-12, 8, 8); 141 | circle(12, 8, 8); 142 | color("black"); 143 | circle(-12, 8, 4); 144 | circle(12, 8, 4); 145 | goBack(); 146 | } 147 | 148 | function drawPlayer(x, y) { 149 | moveTo(x, y); 150 | color("steelblue"); 151 | box(-20, 5, 40, 10); 152 | color("black"); 153 | box(-6, 15, 4, 14); 154 | box(2, 15, 4, 14); 155 | goBack(); 156 | } 157 | 158 | function drawBullet(bullet) { 159 | moveTo(bullet.x, bullet.y); 160 | color("red"); 161 | lineWidth(3); 162 | line(-4, -4, -4, 4); 163 | line(4, -4, 4, 4); 164 | goBack(); 165 | } 166 | 167 | // Use the setHandler function to respond to key or mouse input. 168 | // setHandler("Left", goLeft) - to call the goLeft function whenever 169 | // the left arrow is pressed 170 | // setHandler("U", startAccelerate, stopAccelerate) - a second 171 | // function can be given, which will be called when the key is 172 | // released again. Letter keys are named by uppercase letters. 173 | // Use the names "Mouse-Left", "Mouse-Right", and "Mouse-Middle" for 174 | // the mouse buttons. The variables mouseX and mouseY provide the 175 | // current mouse coordinates. 176 | 177 | // These are the old drawing functions: 178 | // 179 | // color(string) - set the current color 180 | // lineWidth(number) - set the line width 181 | // box(x, y, width, height) - draw a box 182 | // circle(x, y, radius) - draw a circle 183 | // line(x1, y1, x2, y2) - draw a line 184 | // text(x, y, string) - draw text 185 | // clear() - clear the screen 186 | // path(string) - draw a complex line 187 | // In a line description, the following commands are valid: 188 | // g x y - go to point x,y without drawing 189 | // l x y - draw a line from the current point to point x,y 190 | // c - draw a line back to the start of the line 191 | // q x y cx cy - draw a curve to x,y, using cx,cy as 192 | // 'control point' to determine the curvature 193 | // 194 | // fill() - fill the current path with the current color 195 | // 196 | // Coordinates are interpreted as if 0,0 is the center of the 197 | // screen. x is the horizontal axis, and y the vertical. 198 | // Positive x goes to the right, positive y goes up. 199 | // These operations can transform the coordinate system: 200 | // 201 | // moveTo(x, y) - move the origin to x, y 202 | // rotate(degrees) - rotate subsequent drawing operations 203 | // by a number of degrees 204 | // scale(factor) - scale subsequent drawing operations 205 | // goBack() - undo one transformation 206 | -------------------------------------------------------------------------------- /examples/invaders_de.js: -------------------------------------------------------------------------------- 1 | // use_html: interact.html 2 | // ****************************************** 3 | // INVADERS.JS 4 | // Ein einfacher Space Invaders-Abklatsch 5 | // ****************************************** 6 | 7 | // Breite (width) und Höhe (height) der Spielfläche 8 | var width = 600, height = 300; 9 | // ein Array (Liste), dass die gerade attackierenden Invaders beinhaltet 10 | var invaders = []; 11 | // ein Array mit den Kugeln, die gerade umherfliegen 12 | var bullets = []; 13 | // soll auf "true" (wahr) gesetzt werden, wenn ein Invader den Boden erreicht 14 | var gameOver = false; 15 | 16 | // Die Position des Spieler orientiert sich an der Position des Mauszeigers. 17 | // Weil wir den angezeigten Ausschnitt (viewport) bewegen, müssen wir die 18 | // Maus-Koordinaten in unser eigenes Koordinatensystem überführen, bevor 19 | // wir sie benutzen können. Der 'mouseX'-Wert wird von dem Helfer-Code dieses 20 | // Beispiels zur Verfügung gestellt (Beschreibung am unteren Ende des Programms). 21 | function playerX() { 22 | return mouseX + width / 2; 23 | } 24 | 25 | // Fügt eine Kugel (bullet) ein an der aktuellen Position des Spielers. 26 | function fireBullet() { 27 | bullets.push({x: playerX(), y: 10, alive: true}); 28 | } 29 | 30 | // Die Funktion 'fireBullet' wird jedes Mal aufgerufen, wenn die linke Maustaste 31 | // gedrückt wird. 'setHandler' wird auch am unteren Ende des Programms erklärt. 32 | setHandler("Mouse-Left", fireBullet); 33 | 34 | // Fügt einen neuen Invader an einer zufälligen Position des oberen 35 | // Bildschirmrands ein. 36 | function newInvader() { 37 | invaders.push({x: Math.random() * width, y: height, alive: true}); 38 | } 39 | 40 | // Berechnet die Distanz zwischen zwei Objekten. Beide Objekte müssen die 41 | // Eigenschaften x und y haben. Es wird einfach der Satz des Pythagoras 42 | // verwendet. Die Funktion wird benötigt um festzustellen, wann ein Invader 43 | // von einer Kugel getroffen wird. 44 | function distance(obj1, obj2) { 45 | var dx = obj1.x - obj2.x, dy = obj1.y - obj2.y; 46 | return Math.sqrt(dx * dx + dy * dy); 47 | } 48 | 49 | // Die Funktion 50 | // - bewegt jede Kugel ein Stück nach oben 51 | // - zeichnet jede einzelne Kugel 52 | // - markiert Kugeln, die außerhalb der Spielfläche sind als inaktiv 53 | // - prüft, ob eine Kugel einen Invader trifft 54 | // - wenn ja, markiert Invader und Kugel als inaktiv (tot) 55 | function processBullets() { 56 | for (var b = 0; b < bullets.length; b = b + 1) { 57 | var bullet = bullets[b]; 58 | bullet.y = bullet.y + 12; 59 | drawBullet(bullet); 60 | if (bullet.y > height) 61 | bullet.alive = false; 62 | for (var i = 0; i < invaders.length; i = i + 1) { 63 | var invader = invaders[i]; 64 | if (distance(bullet, invader) < 17) { 65 | invader.alive = false; 66 | bullet.alive = false; 67 | } 68 | } 69 | } 70 | } 71 | 72 | // Bewegt die Invaders ein Stück nach unten und zeichnet sie. 73 | // Wenn einer den Boden erreicht wird 'gameOver' auf "true" (wahr) gesetzt 74 | // und der Invader als tot markiert. 75 | function processInvaders() { 76 | for (var i = 0; i < invaders.length; i = i + 1) { 77 | var invader = invaders[i]; 78 | invader.y = invader.y - 2; 79 | drawInvader(invader); 80 | if (invader.y < 0) { 81 | gameOver = true; 82 | invader.alive = false; 83 | } 84 | } 85 | } 86 | 87 | // Hier werden nach jeder Runde alle inaktiven bzw. toten Kugel und Invaders 88 | // gelöscht. 89 | function removeDeadObjects(array) { 90 | var live = []; 91 | for (var i = 0; i < array.length; ++i) { 92 | if (array[i].alive) 93 | live.push(array[i]); 94 | } 95 | return live; 96 | } 97 | 98 | // Ein einzelner Schritt des Spiels wird abgearbeitet. 99 | // Das passiert zwanzig Mal in der Sekunde. 100 | function frame() { 101 | // Pro Schritt gibt es eine 5%ige Chance, dass ein neuer Invader hinzukommt. 102 | // Der !-Operator bedeutet 'nicht', der &&-Operator bedeutet 'und'. 103 | // Also 'wenn nicht gameOver und Math.random() kleiner als 0.05'. 104 | if (!gameOver && Math.random() < 0.05) 105 | newInvader(); 106 | 107 | // Clear the view. 108 | clear(); 109 | // Make 0,0 the bottom left of the game area 110 | moveTo(-width / 2, -height / 2); 111 | // Draw a line at ground level. 112 | color("silver"); 113 | line(0, 0, width, 0); 114 | 115 | processBullets(); 116 | processInvaders(); 117 | // Discard dead objects. 118 | bullets = removeDeadObjects(bullets); 119 | invaders = removeDeadObjects(invaders); 120 | 121 | drawPlayer(playerX(), 0); 122 | if (gameOver) { 123 | color("red"); 124 | text(playerX() - 40, -25, "GAME OVER"); 125 | } 126 | } 127 | 128 | function drawing() { 129 | setInterval(frame, 50); 130 | } 131 | 132 | // Functions for drawing the various elements in the game. 133 | 134 | function drawInvader(invader) { 135 | moveTo(invader.x, invader.y); 136 | if (invader.alive) 137 | color("lightgreen"); 138 | else 139 | color("orange"); 140 | circle(0, 0, 14); 141 | color("green"); 142 | circle(-12, 8, 8); 143 | circle(12, 8, 8); 144 | color("black"); 145 | circle(-12, 8, 4); 146 | circle(12, 8, 4); 147 | goBack(); 148 | } 149 | 150 | function drawPlayer(x, y) { 151 | moveTo(x, y); 152 | color("steelblue"); 153 | box(-20, 5, 40, 10); 154 | color("black"); 155 | box(-6, 15, 4, 14); 156 | box(2, 15, 4, 14); 157 | goBack(); 158 | } 159 | 160 | function drawBullet(bullet) { 161 | moveTo(bullet.x, bullet.y); 162 | color("red"); 163 | lineWidth(3); 164 | line(-4, -4, -4, 4); 165 | line(4, -4, 4, 4); 166 | goBack(); 167 | } 168 | 169 | // Benutze die 'setHandler'-Funktion um auf Tasten- oder Mauseingaben zu 170 | // reagieren. 171 | // setHandler("Left", goLeft) - ruft die 'goLeft'-Funktion auf, wenn die linke 172 | // Pfeiltaste gedrückt wird. 173 | // setHandler("U", startAccelerate, stopAccelerate) - Eine zweite Funktion 174 | // kann übergeben werden, die aufgerufen wird, wenn die Taste losgelassen 175 | // wird. Buchstabentasten werden mit Großbuchstaben benannt. 176 | // Die Namen "Mouse-Left", "Mouse-Right" und "Mouse-Middle" werden für die 177 | // Maustasten vwerwendet. Die Variablen 'mouseX' und 'mouseY' enthalten die 178 | // aktuelle Mausposition. 179 | 180 | // Folgende Funktionen stehen zur Verfügung: 181 | // 182 | // color(string) - setzt die Farbe 183 | // lineWidth(number) - setzt die Dicke der Linie 184 | // box(x, y, width, height) - zeichnet einen Kasten 185 | // circle(x, y, radius) - zeichnet einen Kreis 186 | // line(x1, y1, x2, y2) - zeichnet eine Linie 187 | // text(x, y, string) - zeichnet einen Text 188 | // clear() - leert den Bildschirm 189 | // path(string) - zeichnet eine komplexe Linie (Pfad) 190 | // Für einen Pfad kann man folgende Anweisungen geben: 191 | // g x y - zum Punkt x,y bewegen, ohne zu zeichnen 192 | // l x y - zeichet eine Linie vom aktuellen Punkt bis zum Punkt x,y 193 | // c - zeichnet eine Linie, die zurückführt zum Anfang des Pfads 194 | // q x y cx cy - zeichnet eine Kurve zu x,y, wobei cx,cy als 195 | // „Kontrollpunkt“ zur Definition der Rundung dient 196 | // 197 | // fill() - fülle den Pfad mit der aktuellen Farbe 198 | // 199 | // Alle Koordinaten (Punkte) werden so interpretiert, dass 0,0 200 | // im Zentrum des Bildschirms liegt. x ist die horizontale Achse, y die vertikale. 201 | // Positive x-Werte bewegen sich nach rechts, positive y-Werte bewegen sich nach 202 | // oben. 203 | // Folgende Operationen können dieses Koordinatensystem verändern: 204 | // 205 | // moveTo(x, y) - bewegt den Ursprung nach x,y 206 | // rotate(degrees) - rotiert (dreht) alle nachfolgenden Zeichenoperationen 207 | // um die angegebene Gradzahl 208 | // scale(factor) - skaliert die nachfolgenden Zeichenoperationen 209 | // (größer/kleiner) 210 | // goBack() - macht eine Transformation rückgängig 211 | -------------------------------------------------------------------------------- /examples/life_expectancy.js: -------------------------------------------------------------------------------- 1 | // use_html: data.html 2 | var width = 600, height = 300; 3 | 4 | function showCountry(country) { 5 | var step = width / country.life_expectancy.length; 6 | for (var pos = 0; pos < country.life_expectancy.length; pos = pos + 1) { 7 | var le = country.life_expectancy[pos]; 8 | circle(step * pos, le * 3, 2); 9 | } 10 | } 11 | 12 | function drawing() { 13 | moveTo(-width / 2, -height / 2); 14 | color("red"); 15 | showCountry(countryData[66]); // Germany 16 | color("green"); 17 | showCountry(countryData[81]); // India 18 | color("blue"); 19 | showCountry(countryData[150]); // Russian Federation 20 | } 21 | 22 | // The following functions are available: 23 | // 24 | // color(string) - set the current color 25 | // lineWidth(number) - set the line width 26 | // box(x, y, width, height) - draw a box 27 | // circle(x, y, radius) - draw a circle 28 | // line(x1, y1, x2, y2) - draw a line 29 | // text(x, y, string) - draw text 30 | // clear() - clear the screen 31 | // path(string) - draw a complex line 32 | // In a line description, the following commands are valid: 33 | // g x y - go to point x,y without drawing 34 | // l x y - draw a line from the current point to point x,y 35 | // c - draw a line back to the start of the line 36 | // q x y cx cy - draw a curve to x,y, using cx,cy as 37 | // 'control point' to determine the curvature 38 | // 39 | // fill() - fill the current path with the current color 40 | // 41 | // Coordinates are interpreted as if 0,0 is the center of the 42 | // screen. x is the horizontal axis, and y the vertical. 43 | // Positive x goes to the right, positive y goes up. 44 | // These operations can transform the coordinate system: 45 | // 46 | // moveTo(x, y) - move the origin to x, y 47 | // rotate(degrees) - rotate subsequent drawing operations 48 | // by a number of degrees 49 | // scale(factor) - scale subsequent drawing operations 50 | // goBack() - undo one transformation 51 | -------------------------------------------------------------------------------- /examples/life_expectancy_de.js: -------------------------------------------------------------------------------- 1 | // use_html: data.html 2 | var width = 600, height = 300; 3 | 4 | function showCountry(country) { 5 | var step = width / country.life_expectancy.length; 6 | for (var pos = 0; pos < country.life_expectancy.length; pos = pos + 1) { 7 | var le = country.life_expectancy[pos]; 8 | circle(step * pos, le * 3, 2); 9 | } 10 | } 11 | 12 | function drawing() { 13 | moveTo(-width / 2, -height / 2); 14 | color("red"); 15 | showCountry(countryData[66]); // Germany 16 | color("green"); 17 | showCountry(countryData[81]); // India 18 | color("blue"); 19 | showCountry(countryData[150]); // Russian Federation 20 | } 21 | 22 | // Folgende Funktionen stehen zur Verfügung: 23 | // 24 | // color(string) - setzt die Farbe 25 | // lineWidth(number) - setzt die Dicke der Linie 26 | // box(x, y, width, height) - zeichnet einen Kasten 27 | // circle(x, y, radius) - zeichnet einen Kreis 28 | // line(x1, y1, x2, y2) - zeichnet eine Linie 29 | // text(x, y, string) - zeichnet einen Text 30 | // clear() - leert den Bildschirm 31 | // path(string) - zeichnet eine komplexe Linie (Pfad) 32 | // Für einen Pfad kann man folgende Anweisungen geben: 33 | // g x y - zum Punkt x,y bewegen, ohne zu zeichnen 34 | // l x y - zeichet eine Linie vom aktuellen Punkt bis zum Punkt x,y 35 | // c - zeichnet eine Linie, die zurückführt zum Anfang des Pfads 36 | // q x y cx cy - zeichnet eine Kurve zu x,y, wobei cx,cy als 37 | // „Kontrollpunkt“ zur Definition der Rundung dient 38 | // 39 | // fill() - fülle den Pfad mit der aktuellen Farbe 40 | // 41 | // Alle Koordinaten (Punkte) werden so interpretiert, dass 0,0 42 | // im Zentrum des Bildschirms liegt. x ist die horizontale Achse, y die vertikale. 43 | // Positive x-Werte bewegen sich nach rechts, positive y-Werte bewegen sich nach 44 | // oben. 45 | // Folgende Operationen können dieses Koordinatensystem verändern: 46 | // 47 | // moveTo(x, y) - bewegt den Ursprung nach x,y 48 | // rotate(degrees) - rotiert (dreht) alle nachfolgenden Zeichenoperationen 49 | // um die angegebene Gradzahl 50 | // scale(factor) - skaliert die nachfolgenden Zeichenoperationen 51 | // (größer/kleiner) 52 | // goBack() - macht eine Transformation rückgängig 53 | -------------------------------------------------------------------------------- /examples/rainbow.js: -------------------------------------------------------------------------------- 1 | // use_html: drawing.html 2 | function rainbow(x, y) { 3 | var colors = ["red", "orange", "yellow", "green", "cyan", "purple", "white"]; 4 | var count = 0; 5 | while (count < colors.length) { 6 | color(colors[count]); 7 | circle(x, y, 150 - 5 * count); 8 | count = count + 1; 9 | } 10 | } 11 | 12 | function drawing() { 13 | rainbow(-130, 40); 14 | rainbow(130, -30); 15 | } 16 | -------------------------------------------------------------------------------- /examples/transform.js: -------------------------------------------------------------------------------- 1 | // use_html: data.html 2 | var width = 600, height = 300; 3 | 4 | function visualizeHistory(array, vscale) { 5 | var hscale = width / array.length; 6 | for (var pos = 0; pos < array.length; pos = pos + 1) { 7 | circle(hscale * pos, array[pos] * vscale, 2); 8 | } 9 | } 10 | 11 | function showWorldPopulation() { 12 | var populationPerYear = [] 13 | var maxPopulation = 6000000000; // Not quite correct! 14 | 15 | // Your code here. 16 | 17 | var verticalScale = height / maxPopulation; 18 | visualizeHistory(populationPerYear, verticalScale); 19 | } 20 | 21 | function drawing() { 22 | moveTo(-width / 2, -height / 2); 23 | color("silver"); 24 | line(0, 0, width, 0); 25 | line(0, 0, 0, height); 26 | color("blue"); 27 | showWorldPopulation(); 28 | } 29 | -------------------------------------------------------------------------------- /examples/weather_report.js: -------------------------------------------------------------------------------- 1 | // use_html: data.html 2 | 3 | var weatherData = [ 4 | { 5 | date: "2012-08-21", 6 | temperature: 30, 7 | humidity: 10 8 | }, 9 | { 10 | date: "2012-08-22", 11 | temperature: 24, 12 | humidity: 45 13 | }, 14 | { 15 | date: "2012-08-23", 16 | temperature: 28, 17 | humidity: 30 18 | } 19 | ]; 20 | 21 | 22 | function average(property) { 23 | var sum = 0, 24 | count = 0; 25 | 26 | while (count < weatherData.length) { 27 | var temperature = weatherData[count][property]; 28 | sum = sum + temperature; 29 | count = count + 1; 30 | } 31 | return Math.floor(sum / count); 32 | } 33 | 34 | function barChart(x, y, barWidth, property) { 35 | var gutter = 2, 36 | xPosition = x, 37 | yPosition = y; 38 | 39 | var count = 0; 40 | while (count < weatherData.length) { 41 | var barHeight = -1 * weatherData[count][property]; 42 | box(xPosition, yPosition, barWidth, barHeight); 43 | xPosition = xPosition + barWidth + gutter; 44 | count = count + 1; 45 | } 46 | } 47 | 48 | function drawing() { 49 | 50 | color("red"); 51 | barChart(0, 140, 20, "temperature"); 52 | text(0, 120, "Average temperature: " + average("temperature") + "°"); 53 | 54 | 55 | color("blue"); 56 | barChart(0, 20, 20, "humidity"); 57 | text(0, 0, "Average humidity: " + average("humidity") + "%"); 58 | } 59 | 60 | 61 | 62 | // The following functions are available: 63 | // 64 | // color(string) - set the current color 65 | // lineWidth(number) - set the line width 66 | // box(x, y, width, height) - draw a box 67 | // circle(x, y, radius) - draw a circle 68 | // line(x1, y1, x2, y2) - draw a line 69 | // text(x, y, string) - draw text 70 | // clear() - clear the screen 71 | // path(string) - draw a complex line 72 | // In a line description, the following commands are valid: 73 | // g x y - go to point x,y without drawing 74 | // l x y - draw a line from the current point to point x,y 75 | // c - draw a line back to the start of the line 76 | // q x y cx cy - draw a curve to x,y, using cx,cy as 77 | // 'control point' to determine the curvature 78 | // 79 | // fill() - fill the current path with the current color 80 | // 81 | // Coordinates are interpreted as if 0,0 is the center of the 82 | // screen. x is the horizontal axis, and y the vertical. 83 | // Positive x goes to the right, positive y goes up. 84 | // These operations can transform the coordinate system: 85 | // 86 | // moveTo(x, y) - move the origin to x, y 87 | // rotate(degrees) - rotate subsequent drawing operations 88 | // by a number of degrees 89 | // scale(factor) - scale subsequent drawing operations 90 | // goBack() - undo one transformation 91 | -------------------------------------------------------------------------------- /examples/weather_report_average.js: -------------------------------------------------------------------------------- 1 | // use_html: data.html 2 | 3 | var weatherData = [ 4 | { 5 | date: "2012-08-22", 6 | temperature: 30, 7 | humidity: 40 8 | }, 9 | { 10 | date: "2012-08-23", 11 | temperature: 32, 12 | humidity: 80 13 | }, 14 | { 15 | date: "2012-08-24", 16 | temperature: 28, 17 | humidity: 20 18 | } 19 | ]; 20 | 21 | 22 | function averageTemperature(property) { 23 | var sum = 0, 24 | count = 0; 25 | 26 | while (count < weatherData.length) { 27 | count = count + 1; 28 | } 29 | 30 | return sum; 31 | } 32 | 33 | function barChart(x, y, barWidth, property) { 34 | var gutter = 2, 35 | xPosition = x, 36 | yPosition = y; 37 | 38 | var count = 0; 39 | while (count < weatherData.length) { 40 | var barHeight = -1 * weatherData[count][property]; 41 | box(xPosition, yPosition, barWidth, barHeight); 42 | xPosition = xPosition + barWidth + gutter; 43 | count = count + 1; 44 | } 45 | } 46 | 47 | function drawing() { 48 | 49 | text(0, 120, "Average temperature: " + averageTemperature() + "°"); 50 | 51 | } 52 | 53 | 54 | 55 | // The following functions are available: 56 | // 57 | // color(string) - set the current color 58 | // lineWidth(number) - set the line width 59 | // box(x, y, width, height) - draw a box 60 | // circle(x, y, radius) - draw a circle 61 | // line(x1, y1, x2, y2) - draw a line 62 | // text(x, y, string) - draw text 63 | // clear() - clear the screen 64 | // path(string) - draw a complex line 65 | // In a line description, the following commands are valid: 66 | // g x y - go to point x,y without drawing 67 | // l x y - draw a line from the current point to point x,y 68 | // c - draw a line back to the start of the line 69 | // q x y cx cy - draw a curve to x,y, using cx,cy as 70 | // 'control point' to determine the curvature 71 | // 72 | // fill() - fill the current path with the current color 73 | // 74 | // Coordinates are interpreted as if 0,0 is the center of the 75 | // screen. x is the horizontal axis, and y the vertical. 76 | // Positive x goes to the right, positive y goes up. 77 | // These operations can transform the coordinate system: 78 | // 79 | // moveTo(x, y) - move the origin to x, y 80 | // rotate(degrees) - rotate subsequent drawing operations 81 | // by a number of degrees 82 | // scale(factor) - scale subsequent drawing operations 83 | // goBack() - undo one transformation 84 | -------------------------------------------------------------------------------- /examples/weather_report_visualization.js: -------------------------------------------------------------------------------- 1 | // use_html: data.html 2 | 3 | var weatherData = [ 4 | { 5 | date: "2012-08-21", 6 | temperature: 30, 7 | humidity: 10 8 | }, 9 | { 10 | date: "2012-08-22", 11 | temperature: 24, 12 | humidity: 45 13 | }, 14 | { 15 | date: "2012-08-23", 16 | temperature: 28, 17 | humidity: 30 18 | } 19 | ]; 20 | 21 | function barChart(x, y, barWidth) { 22 | var gutter = 2, 23 | xPosition = x, 24 | yPosition = y; 25 | 26 | var barHeight = -1 * weatherData[0].temperature; 27 | box(xPosition, yPosition, barWidth, barHeight); 28 | 29 | barHeight = -1 * weatherData[1].temperature; 30 | xPosition = xPosition + gutter + barWidth; 31 | box(xPosition, yPosition, barWidth, barHeight); 32 | 33 | barHeight = -1 * weatherData[2].temperature; 34 | xPosition = xPosition + gutter + barWidth; 35 | box(xPosition, yPosition, barWidth, barHeight); 36 | } 37 | 38 | function drawing() { 39 | color("red"); 40 | barChart(0, 0, 20); 41 | } 42 | 43 | 44 | 45 | // The following functions are available: 46 | // 47 | // color(string) - set the current color 48 | // lineWidth(number) - set the line width 49 | // box(x, y, width, height) - draw a box 50 | // circle(x, y, radius) - draw a circle 51 | // line(x1, y1, x2, y2) - draw a line 52 | // text(x, y, string) - draw text 53 | // clear() - clear the screen 54 | // path(string) - draw a complex line 55 | // In a line description, the following commands are valid: 56 | // g x y - go to point x,y without drawing 57 | // l x y - draw a line from the current point to point x,y 58 | // c - draw a line back to the start of the line 59 | // q x y cx cy - draw a curve to x,y, using cx,cy as 60 | // 'control point' to determine the curvature 61 | // 62 | // fill() - fill the current path with the current color 63 | // 64 | // Coordinates are interpreted as if 0,0 is the center of the 65 | // screen. x is the horizontal axis, and y the vertical. 66 | // Positive x goes to the right, positive y goes up. 67 | // These operations can transform the coordinate system: 68 | // 69 | // moveTo(x, y) - move the origin to x, y 70 | // rotate(degrees) - rotate subsequent drawing operations 71 | // by a number of degrees 72 | // scale(factor) - scale subsequent drawing operations 73 | // goBack() - undo one transformation 74 | -------------------------------------------------------------------------------- /fonts.googleapis.com/css-family=Averia+Serif+Libre:300,400: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Averia Serif Libre'; 3 | font-style: normal; 4 | font-weight: 300; 5 | src: local('Averia Serif Libre Light'), local('AveriaSerifLibre-Light'), url(yvITAdr5D1nlsdFswJAb8Vos2Pdf-dQN4tJmHAEs2hQ.woff2) format('woff2'); 6 | } 7 | @font-face { 8 | font-family: 'Averia Serif Libre'; 9 | font-style: normal; 10 | font-weight: 400; 11 | src: local('Averia Serif Libre Regular'), local('AveriaSerifLibre-Regular'), url(fdtF30xa_Erw0zAzOoG4BVVaXhodyZpwkPyKEugoMLo.woff2) format('woff2'); 12 | } 13 | -------------------------------------------------------------------------------- /fonts.googleapis.com/fdtF30xa_Erw0zAzOoG4BVVaXhodyZpwkPyKEugoMLo.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenTechSchool/js-beginners-1/68d524f268e1ee756717777bf4cc0ff3327f4274/fonts.googleapis.com/fdtF30xa_Erw0zAzOoG4BVVaXhodyZpwkPyKEugoMLo.woff2 -------------------------------------------------------------------------------- /fonts.googleapis.com/yvITAdr5D1nlsdFswJAb8Vos2Pdf-dQN4tJmHAEs2hQ.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenTechSchool/js-beginners-1/68d524f268e1ee756717777bf4cc0ff3327f4274/fonts.googleapis.com/yvITAdr5D1nlsdFswJAb8Vos2Pdf-dQN4tJmHAEs2hQ.woff2 -------------------------------------------------------------------------------- /footprint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenTechSchool/js-beginners-1/68d524f268e1ee756717777bf4cc0ff3327f4274/footprint.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Curriculum — JavaScript for absolute beginners 5 | 6 | 7 | 8 | 9 | 10 |

Curriculum: JavaScript for absolute beginners

11 | 12 |

Auf Deutsch »

13 | 14 |

The goal of this workshop is to learn enough JavaScript to be 15 | dangerous, and to get a good feel for the natural habitat (web, 16 | browser, HTML) of JavaScript programs.

17 | 18 |

Tools

19 | 20 |

We will be using the Google Chrome browser as our development 21 | environment for the course, because of the excellent developer tools 22 | it provides. If you have a strong, passionate affinity for some other 23 | browser (please let it not be Internet Explorer), you are also free to 24 | try and use that—most modern browsers have decent developer tools—but 25 | the text on these pages will describe the Chrome functionality.

26 | 27 |

If you don't already have Chrome installed, get it here:

28 | 29 | 33 | 34 |

Beyond a browser, no desktop software will be necessary. We will be 35 | writing and trying out JavaScript programs directly inside of the 36 | browser.

37 | 38 |

Process

39 | 40 |

The first few hours will be spent working with trivial pieces of 41 | programs, in order to get a feel for the language. Despair not, 42 | for these are simply a gateway to bigger, greater things and there 43 | will also be colors and animations.

44 | 45 |

This document will provide you with step-by-step guidance for 46 | exploring the browser and its JavaScript environment, and for writing 47 | your first few programs.

48 | 49 |

Each step will be marked with a goal (why are we doing this), a 50 | precise, dry, guideline on what to do, and an explanation of how and 51 | why the thing you are doing works. For example:

52 | 53 |
54 |

Example step

55 |

Goal

56 |

See what a step looks like.

57 |

Instructions

58 |

Read this text carefully.

59 |

Explanation

60 |

The goal always comes first. Without goal, there is no action. 61 | The instructions are written in a way that is unambiguous and plain, 62 | but don't provide background. They are followed by an explanation 63 | that, hopefully, makes it clear how and why they work.

64 |
65 | 66 |

Resources

67 | 68 |

It is a good idea to keep 69 | this cheat sheet open in a tab in your browser, and use 71 | it to look up the precise notation for something whenever you forget. 72 | Don't worry about it looking like gibberish for now. It is only 73 | intended to look up things after they have been explained by 74 | the course material.

75 | 76 |

Our coaches are also always happy to answer questions. If at any 77 | point you feel confused or stuck, get our attention, and we will do 78 | our very best to un-confuse you.

79 | 80 |

Let's go

81 | 82 |

→ To the first page.

83 | -------------------------------------------------------------------------------- /index_de.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Kursmaterial — JavaScript für absolute Beginner 5 | 6 | 7 | 8 | 9 | 10 |

Kursmaterial: JavaScript für absolute Beginner

11 | 12 |

In English »

13 | 14 |

Unser Ziel für diesen Workshop ist es, genug JavaScript zu lernen 15 | um gefährlich zu sein und nebenbei ein Gefühl für JavaScripts natürlichen 16 | Lebensraum (Web, Browser, HTML) zu bekommen.

17 | 18 |

Was Du brauchst

19 | 20 |

Als Entwicklungsumgebung für den Kurs werden wir Google Chrome verwenden, 21 | weil es ein Browser ist, der ausgezeichnete Tools für Entwickler bereithält. 22 | Falls Du eine ausgeprägte persönliche Vorliebe für einen anderen Browser haben 23 | solltest (bitte lass es nicht Internet Explorer sein), kannst du auch gerne 24 | probieren diesen zu verwenden—die meisten modernen Browser haben ganz ordentliche 25 | Tools für Entwickler—aber dieses Tutorial wird die Funktionalitäten von Chrome 26 | beschreiben. 27 |

28 | 29 |

Wenn Du Chrome noch nicht installiert hast, kannst Du ihn hier herunterladen:

30 | 31 | 34 | 35 |

Abgesehen von einem Browser brauchst Du keine weitere Software. 36 | Wir werden unsere JavaScript-Programme direkt im Browser schreiben und 37 | ausprobieren.

38 | 39 |

Ablauf

40 | 41 |

Die ersten paar Stunden werden wir mit banalen Programm-Schnipseln 42 | verbringen, um ein Gefühl für die Sprache zu bekommen. Gib nicht auf, 43 | denn diese Vorübungen erlauben Dir Zugang zu einer Welt größerer, 44 | interessanterer Dinge und es wird auch Farben und Animationen geben.

45 | 46 |

Dieses Dokument ist eine Schritt-für-Schritt Anleitung, mit der Du 47 | den Browser und seine JavaScript-Umgebung erkunden kannst und lernst, 48 | Deine ersten eigenen Programme zu schreiben.

49 | 50 |

Jeder Schritt wird ein Ziel haben (es beschreibt das Warum), 51 | Anweisungen was genau zu tun ist, und eine Erklärung, die 52 | Dir sagt wie und warum das funktioniert was Du da tust. Zum Beispiel:

53 | 54 |
55 |

Beispiel für einen Schritt

56 |

Ziel

57 |

Sehen wie ein Schritt aussieht.

58 |

Anweisungen

59 |

Lies diesen Text aufmerksam.

60 |

Erklärung

61 |

Das Ziel kommt immer zuerst. Ohne Ziel, keine Aktion. 62 | Die Anweisungen sind schlicht und eindeutig gehalten und enthalten 63 | keine Hintergrund-Informationen. Danach kommt eine Erklärung, die 64 | (hoffentlich) klarmacht, wie und warum alles funktioniert.

65 |
66 | 67 |

Informationsquellen

68 | 69 |

Eine gute Idee ist es, diesen Spickzettel in einem Browser-Tab geöffnet zu halten, 71 | damit Du dort schnell nachschauen kannst, wie genau etwas zu schreiben 72 | oder zu lesen ist. Mach Dir keine Sorgen, wenn Dir dieser Zettel jetzt 73 | erstmal gar nichts sagt. Er ist dafür gedacht, Dinge nachzuschlagen 74 | nachdem sie Dir erklärt wurden.

75 | 76 |

Darüber hinaus sind unsere Coaches auch immer gerne bereit Fragen 77 | zu beantworten. Falls Du irgendwann zwischendurch das Gefühl hast, 78 | dass Du verwirrt bist oder nicht weiterkommst, mach Dich bemerkbar 79 | und wir werden unser Bestes tun Dich zu "entwirren".

80 | 81 |

Los geht's

82 | 83 |

→ Zur ersten Seite.

84 | -------------------------------------------------------------------------------- /lib/README: -------------------------------------------------------------------------------- 1 | Do a 2 | 3 | git clone http://marijnhaverbeke.nl/git/codemirror2 4 | 5 | in this directory to fetch the dependency. 6 | -------------------------------------------------------------------------------- /lib/codemirror2/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2012 by Marijn Haverbeke 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | 21 | Please note that some subdirectories of the CodeMirror distribution 22 | include their own LICENSE files, and are released under different 23 | licences. 24 | -------------------------------------------------------------------------------- /lib/codemirror2/lib/codemirror.css: -------------------------------------------------------------------------------- 1 | .CodeMirror { 2 | line-height: 1em; 3 | font-family: monospace; 4 | 5 | /* Necessary so the scrollbar can be absolutely positioned within the wrapper on Lion. */ 6 | position: relative; 7 | /* This prevents unwanted scrollbars from showing up on the body and wrapper in IE. */ 8 | overflow: hidden; 9 | } 10 | 11 | .CodeMirror-scroll { 12 | overflow-x: auto; 13 | overflow-y: hidden; 14 | height: 300px; 15 | /* This is needed to prevent an IE[67] bug where the scrolled content 16 | is visible outside of the scrolling box. */ 17 | position: relative; 18 | outline: none; 19 | } 20 | 21 | /* Vertical scrollbar */ 22 | .CodeMirror-scrollbar { 23 | float: right; 24 | overflow-x: hidden; 25 | overflow-y: scroll; 26 | 27 | /* This corrects for the 1px gap introduced to the left of the scrollbar 28 | by the rule for .CodeMirror-scrollbar-inner. */ 29 | margin-left: -1px; 30 | } 31 | .CodeMirror-scrollbar-inner { 32 | /* This needs to have a nonzero width in order for the scrollbar to appear 33 | in Firefox and IE9. */ 34 | width: 1px; 35 | } 36 | .CodeMirror-scrollbar.cm-sb-overlap { 37 | /* Ensure that the scrollbar appears in Lion, and that it overlaps the content 38 | rather than sitting to the right of it. */ 39 | position: absolute; 40 | z-index: 1; 41 | float: none; 42 | right: 0; 43 | min-width: 12px; 44 | } 45 | .CodeMirror-scrollbar.cm-sb-nonoverlap { 46 | min-width: 12px; 47 | } 48 | .CodeMirror-scrollbar.cm-sb-ie7 { 49 | min-width: 18px; 50 | } 51 | 52 | .CodeMirror-gutter { 53 | position: absolute; left: 0; top: 0; 54 | z-index: 10; 55 | background-color: #f7f7f7; 56 | border-right: 1px solid #eee; 57 | min-width: 2em; 58 | height: 100%; 59 | } 60 | .CodeMirror-gutter-text { 61 | color: #aaa; 62 | text-align: right; 63 | padding: .4em .2em .4em .4em; 64 | white-space: pre !important; 65 | cursor: default; 66 | } 67 | .CodeMirror-lines { 68 | padding: .4em; 69 | white-space: pre; 70 | cursor: text; 71 | } 72 | .CodeMirror-lines * { 73 | /* Necessary for throw-scrolling to decelerate properly on Safari. */ 74 | pointer-events: none; 75 | } 76 | 77 | .CodeMirror pre { 78 | -moz-border-radius: 0; 79 | -webkit-border-radius: 0; 80 | -o-border-radius: 0; 81 | border-radius: 0; 82 | border-width: 0; margin: 0; padding: 0; background: transparent; 83 | font-family: inherit; 84 | font-size: inherit; 85 | padding: 0; margin: 0; 86 | white-space: pre; 87 | word-wrap: normal; 88 | line-height: inherit; 89 | color: inherit; 90 | } 91 | 92 | .CodeMirror-wrap pre { 93 | word-wrap: break-word; 94 | white-space: pre-wrap; 95 | word-break: normal; 96 | } 97 | .CodeMirror-wrap .CodeMirror-scroll { 98 | overflow-x: hidden; 99 | } 100 | 101 | .CodeMirror textarea { 102 | outline: none !important; 103 | } 104 | 105 | .CodeMirror pre.CodeMirror-cursor { 106 | z-index: 10; 107 | position: absolute; 108 | visibility: hidden; 109 | border-left: 1px solid black; 110 | border-right: none; 111 | width: 0; 112 | } 113 | .cm-keymap-fat-cursor pre.CodeMirror-cursor { 114 | width: auto; 115 | border: 0; 116 | background: transparent; 117 | background: rgba(0, 200, 0, .4); 118 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800); 119 | } 120 | /* Kludge to turn off filter in ie9+, which also accepts rgba */ 121 | .cm-keymap-fat-cursor pre.CodeMirror-cursor:not(#nonsense_id) { 122 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); 123 | } 124 | .CodeMirror pre.CodeMirror-cursor.CodeMirror-overwrite {} 125 | .CodeMirror-focused pre.CodeMirror-cursor { 126 | visibility: visible; 127 | } 128 | 129 | div.CodeMirror-selected { background: #d9d9d9; } 130 | .CodeMirror-focused div.CodeMirror-selected { background: #d7d4f0; } 131 | 132 | .CodeMirror-searching { 133 | background: #ffa; 134 | background: rgba(255, 255, 0, .4); 135 | } 136 | 137 | /* Default theme */ 138 | 139 | .cm-s-default span.cm-keyword {color: #708;} 140 | .cm-s-default span.cm-atom {color: #219;} 141 | .cm-s-default span.cm-number {color: #164;} 142 | .cm-s-default span.cm-def {color: #00f;} 143 | .cm-s-default span.cm-variable {color: black;} 144 | .cm-s-default span.cm-variable-2 {color: #05a;} 145 | .cm-s-default span.cm-variable-3 {color: #085;} 146 | .cm-s-default span.cm-property {color: black;} 147 | .cm-s-default span.cm-operator {color: black;} 148 | .cm-s-default span.cm-comment {color: #a50;} 149 | .cm-s-default span.cm-string {color: #a11;} 150 | .cm-s-default span.cm-string-2 {color: #f50;} 151 | .cm-s-default span.cm-meta {color: #555;} 152 | .cm-s-default span.cm-error {color: #f00;} 153 | .cm-s-default span.cm-qualifier {color: #555;} 154 | .cm-s-default span.cm-builtin {color: #30a;} 155 | .cm-s-default span.cm-bracket {color: #cc7;} 156 | .cm-s-default span.cm-tag {color: #170;} 157 | .cm-s-default span.cm-attribute {color: #00c;} 158 | .cm-s-default span.cm-header {color: blue;} 159 | .cm-s-default span.cm-quote {color: #090;} 160 | .cm-s-default span.cm-hr {color: #999;} 161 | .cm-s-default span.cm-link {color: #00c;} 162 | 163 | span.cm-header, span.cm-strong {font-weight: bold;} 164 | span.cm-em {font-style: italic;} 165 | span.cm-emstrong {font-style: italic; font-weight: bold;} 166 | span.cm-link {text-decoration: underline;} 167 | 168 | div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} 169 | div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} 170 | -------------------------------------------------------------------------------- /lib/codemirror2/mode/css/css.js: -------------------------------------------------------------------------------- 1 | CodeMirror.defineMode("css", function(config) { 2 | var indentUnit = config.indentUnit, type; 3 | function ret(style, tp) {type = tp; return style;} 4 | 5 | function tokenBase(stream, state) { 6 | var ch = stream.next(); 7 | if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("meta", stream.current());} 8 | else if (ch == "/" && stream.eat("*")) { 9 | state.tokenize = tokenCComment; 10 | return tokenCComment(stream, state); 11 | } 12 | else if (ch == "<" && stream.eat("!")) { 13 | state.tokenize = tokenSGMLComment; 14 | return tokenSGMLComment(stream, state); 15 | } 16 | else if (ch == "=") ret(null, "compare"); 17 | else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare"); 18 | else if (ch == "\"" || ch == "'") { 19 | state.tokenize = tokenString(ch); 20 | return state.tokenize(stream, state); 21 | } 22 | else if (ch == "#") { 23 | stream.eatWhile(/[\w\\\-]/); 24 | return ret("atom", "hash"); 25 | } 26 | else if (ch == "!") { 27 | stream.match(/^\s*\w*/); 28 | return ret("keyword", "important"); 29 | } 30 | else if (/\d/.test(ch)) { 31 | stream.eatWhile(/[\w.%]/); 32 | return ret("number", "unit"); 33 | } 34 | else if (/[,.+>*\/]/.test(ch)) { 35 | return ret(null, "select-op"); 36 | } 37 | else if (/[;{}:\[\]]/.test(ch)) { 38 | return ret(null, ch); 39 | } 40 | else { 41 | stream.eatWhile(/[\w\\\-]/); 42 | return ret("variable", "variable"); 43 | } 44 | } 45 | 46 | function tokenCComment(stream, state) { 47 | var maybeEnd = false, ch; 48 | while ((ch = stream.next()) != null) { 49 | if (maybeEnd && ch == "/") { 50 | state.tokenize = tokenBase; 51 | break; 52 | } 53 | maybeEnd = (ch == "*"); 54 | } 55 | return ret("comment", "comment"); 56 | } 57 | 58 | function tokenSGMLComment(stream, state) { 59 | var dashes = 0, ch; 60 | while ((ch = stream.next()) != null) { 61 | if (dashes >= 2 && ch == ">") { 62 | state.tokenize = tokenBase; 63 | break; 64 | } 65 | dashes = (ch == "-") ? dashes + 1 : 0; 66 | } 67 | return ret("comment", "comment"); 68 | } 69 | 70 | function tokenString(quote) { 71 | return function(stream, state) { 72 | var escaped = false, ch; 73 | while ((ch = stream.next()) != null) { 74 | if (ch == quote && !escaped) 75 | break; 76 | escaped = !escaped && ch == "\\"; 77 | } 78 | if (!escaped) state.tokenize = tokenBase; 79 | return ret("string", "string"); 80 | }; 81 | } 82 | 83 | return { 84 | startState: function(base) { 85 | return {tokenize: tokenBase, 86 | baseIndent: base || 0, 87 | stack: []}; 88 | }, 89 | 90 | token: function(stream, state) { 91 | if (stream.eatSpace()) return null; 92 | var style = state.tokenize(stream, state); 93 | 94 | var context = state.stack[state.stack.length-1]; 95 | if (type == "hash" && context != "rule") style = "string-2"; 96 | else if (style == "variable") { 97 | if (context == "rule") style = "number"; 98 | else if (!context || context == "@media{") style = "tag"; 99 | } 100 | 101 | if (context == "rule" && /^[\{\};]$/.test(type)) 102 | state.stack.pop(); 103 | if (type == "{") { 104 | if (context == "@media") state.stack[state.stack.length-1] = "@media{"; 105 | else state.stack.push("{"); 106 | } 107 | else if (type == "}") state.stack.pop(); 108 | else if (type == "@media") state.stack.push("@media"); 109 | else if (context == "{" && type != "comment") state.stack.push("rule"); 110 | return style; 111 | }, 112 | 113 | indent: function(state, textAfter) { 114 | var n = state.stack.length; 115 | if (/^\}/.test(textAfter)) 116 | n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1; 117 | return state.baseIndent + n * indentUnit; 118 | }, 119 | 120 | electricChars: "}" 121 | }; 122 | }); 123 | 124 | CodeMirror.defineMIME("text/css", "css"); 125 | -------------------------------------------------------------------------------- /lib/codemirror2/mode/htmlmixed/htmlmixed.js: -------------------------------------------------------------------------------- 1 | CodeMirror.defineMode("htmlmixed", function(config, parserConfig) { 2 | var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true}); 3 | var jsMode = CodeMirror.getMode(config, "javascript"); 4 | var cssMode = CodeMirror.getMode(config, "css"); 5 | 6 | function html(stream, state) { 7 | var style = htmlMode.token(stream, state.htmlState); 8 | if (style == "tag" && stream.current() == ">" && state.htmlState.context) { 9 | if (/^script$/i.test(state.htmlState.context.tagName)) { 10 | state.token = javascript; 11 | state.localState = jsMode.startState(htmlMode.indent(state.htmlState, "")); 12 | state.mode = "javascript"; 13 | } 14 | else if (/^style$/i.test(state.htmlState.context.tagName)) { 15 | state.token = css; 16 | state.localState = cssMode.startState(htmlMode.indent(state.htmlState, "")); 17 | state.mode = "css"; 18 | } 19 | } 20 | return style; 21 | } 22 | function maybeBackup(stream, pat, style) { 23 | var cur = stream.current(); 24 | var close = cur.search(pat); 25 | if (close > -1) stream.backUp(cur.length - close); 26 | return style; 27 | } 28 | function javascript(stream, state) { 29 | if (stream.match(/^<\/\s*script\s*>/i, false)) { 30 | state.token = html; 31 | state.localState = null; 32 | state.mode = "html"; 33 | return html(stream, state); 34 | } 35 | return maybeBackup(stream, /<\/\s*script\s*>/, 36 | jsMode.token(stream, state.localState)); 37 | } 38 | function css(stream, state) { 39 | if (stream.match(/^<\/\s*style\s*>/i, false)) { 40 | state.token = html; 41 | state.localState = null; 42 | state.mode = "html"; 43 | return html(stream, state); 44 | } 45 | return maybeBackup(stream, /<\/\s*style\s*>/, 46 | cssMode.token(stream, state.localState)); 47 | } 48 | 49 | return { 50 | startState: function() { 51 | var state = htmlMode.startState(); 52 | return {token: html, localState: null, mode: "html", htmlState: state}; 53 | }, 54 | 55 | copyState: function(state) { 56 | if (state.localState) 57 | var local = CodeMirror.copyState(state.token == css ? cssMode : jsMode, state.localState); 58 | return {token: state.token, localState: local, mode: state.mode, 59 | htmlState: CodeMirror.copyState(htmlMode, state.htmlState)}; 60 | }, 61 | 62 | token: function(stream, state) { 63 | return state.token(stream, state); 64 | }, 65 | 66 | indent: function(state, textAfter) { 67 | if (state.token == html || /^\s*<\//.test(textAfter)) 68 | return htmlMode.indent(state.htmlState, textAfter); 69 | else if (state.token == javascript) 70 | return jsMode.indent(state.localState, textAfter); 71 | else 72 | return cssMode.indent(state.localState, textAfter); 73 | }, 74 | 75 | compareStates: function(a, b) { 76 | if (a.mode != b.mode) return false; 77 | if (a.localState) return CodeMirror.Pass; 78 | return htmlMode.compareStates(a.htmlState, b.htmlState); 79 | }, 80 | 81 | electricChars: "/{}:" 82 | } 83 | }, "xml", "javascript", "css"); 84 | 85 | CodeMirror.defineMIME("text/html", "htmlmixed"); 86 | -------------------------------------------------------------------------------- /lib/codemirror2/mode/javascript/javascript.js: -------------------------------------------------------------------------------- 1 | CodeMirror.defineMode("javascript", function(config, parserConfig) { 2 | var indentUnit = config.indentUnit; 3 | var jsonMode = parserConfig.json; 4 | 5 | // Tokenizer 6 | 7 | var keywords = function(){ 8 | function kw(type) {return {type: type, style: "keyword"};} 9 | var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); 10 | var operator = kw("operator"), atom = {type: "atom", style: "atom"}; 11 | return { 12 | "if": A, "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, 13 | "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, 14 | "var": kw("var"), "const": kw("var"), "let": kw("var"), 15 | "function": kw("function"), "catch": kw("catch"), 16 | "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), 17 | "in": operator, "typeof": operator, "instanceof": operator, 18 | "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom 19 | }; 20 | }(); 21 | 22 | var isOperatorChar = /[+\-*&%=<>!?|]/; 23 | 24 | function chain(stream, state, f) { 25 | state.tokenize = f; 26 | return f(stream, state); 27 | } 28 | 29 | function nextUntilUnescaped(stream, end) { 30 | var escaped = false, next; 31 | while ((next = stream.next()) != null) { 32 | if (next == end && !escaped) 33 | return false; 34 | escaped = !escaped && next == "\\"; 35 | } 36 | return escaped; 37 | } 38 | 39 | // Used as scratch variables to communicate multiple values without 40 | // consing up tons of objects. 41 | var type, content; 42 | function ret(tp, style, cont) { 43 | type = tp; content = cont; 44 | return style; 45 | } 46 | 47 | function jsTokenBase(stream, state) { 48 | var ch = stream.next(); 49 | if (ch == '"' || ch == "'") 50 | return chain(stream, state, jsTokenString(ch)); 51 | else if (/[\[\]{}\(\),;\:\.]/.test(ch)) 52 | return ret(ch); 53 | else if (ch == "0" && stream.eat(/x/i)) { 54 | stream.eatWhile(/[\da-f]/i); 55 | return ret("number", "number"); 56 | } 57 | else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) { 58 | stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); 59 | return ret("number", "number"); 60 | } 61 | else if (ch == "/") { 62 | if (stream.eat("*")) { 63 | return chain(stream, state, jsTokenComment); 64 | } 65 | else if (stream.eat("/")) { 66 | stream.skipToEnd(); 67 | return ret("comment", "comment"); 68 | } 69 | else if (state.reAllowed) { 70 | nextUntilUnescaped(stream, "/"); 71 | stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla 72 | return ret("regexp", "string-2"); 73 | } 74 | else { 75 | stream.eatWhile(isOperatorChar); 76 | return ret("operator", null, stream.current()); 77 | } 78 | } 79 | else if (ch == "#") { 80 | stream.skipToEnd(); 81 | return ret("error", "error"); 82 | } 83 | else if (isOperatorChar.test(ch)) { 84 | stream.eatWhile(isOperatorChar); 85 | return ret("operator", null, stream.current()); 86 | } 87 | else { 88 | stream.eatWhile(/[\w\$_]/); 89 | var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; 90 | return (known && state.kwAllowed) ? ret(known.type, known.style, word) : 91 | ret("variable", "variable", word); 92 | } 93 | } 94 | 95 | function jsTokenString(quote) { 96 | return function(stream, state) { 97 | if (!nextUntilUnescaped(stream, quote)) 98 | state.tokenize = jsTokenBase; 99 | return ret("string", "string"); 100 | }; 101 | } 102 | 103 | function jsTokenComment(stream, state) { 104 | var maybeEnd = false, ch; 105 | while (ch = stream.next()) { 106 | if (ch == "/" && maybeEnd) { 107 | state.tokenize = jsTokenBase; 108 | break; 109 | } 110 | maybeEnd = (ch == "*"); 111 | } 112 | return ret("comment", "comment"); 113 | } 114 | 115 | // Parser 116 | 117 | var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true}; 118 | 119 | function JSLexical(indented, column, type, align, prev, info) { 120 | this.indented = indented; 121 | this.column = column; 122 | this.type = type; 123 | this.prev = prev; 124 | this.info = info; 125 | if (align != null) this.align = align; 126 | } 127 | 128 | function inScope(state, varname) { 129 | for (var v = state.localVars; v; v = v.next) 130 | if (v.name == varname) return true; 131 | } 132 | 133 | function parseJS(state, style, type, content, stream) { 134 | var cc = state.cc; 135 | // Communicate our context to the combinators. 136 | // (Less wasteful than consing up a hundred closures on every call.) 137 | cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; 138 | 139 | if (!state.lexical.hasOwnProperty("align")) 140 | state.lexical.align = true; 141 | 142 | while(true) { 143 | var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement; 144 | if (combinator(type, content)) { 145 | while(cc.length && cc[cc.length - 1].lex) 146 | cc.pop()(); 147 | if (cx.marked) return cx.marked; 148 | if (type == "variable" && inScope(state, content)) return "variable-2"; 149 | return style; 150 | } 151 | } 152 | } 153 | 154 | // Combinator utils 155 | 156 | var cx = {state: null, column: null, marked: null, cc: null}; 157 | function pass() { 158 | for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); 159 | } 160 | function cont() { 161 | pass.apply(null, arguments); 162 | return true; 163 | } 164 | function register(varname) { 165 | var state = cx.state; 166 | if (state.context) { 167 | cx.marked = "def"; 168 | for (var v = state.localVars; v; v = v.next) 169 | if (v.name == varname) return; 170 | state.localVars = {name: varname, next: state.localVars}; 171 | } 172 | } 173 | 174 | // Combinators 175 | 176 | var defaultVars = {name: "this", next: {name: "arguments"}}; 177 | function pushcontext() { 178 | if (!cx.state.context) cx.state.localVars = defaultVars; 179 | cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; 180 | } 181 | function popcontext() { 182 | cx.state.localVars = cx.state.context.vars; 183 | cx.state.context = cx.state.context.prev; 184 | } 185 | function pushlex(type, info) { 186 | var result = function() { 187 | var state = cx.state; 188 | state.lexical = new JSLexical(state.indented, cx.stream.column(), type, null, state.lexical, info) 189 | }; 190 | result.lex = true; 191 | return result; 192 | } 193 | function poplex() { 194 | var state = cx.state; 195 | if (state.lexical.prev) { 196 | if (state.lexical.type == ")") 197 | state.indented = state.lexical.indented; 198 | state.lexical = state.lexical.prev; 199 | } 200 | } 201 | poplex.lex = true; 202 | 203 | function expect(wanted) { 204 | return function expecting(type) { 205 | if (type == wanted) return cont(); 206 | else if (wanted == ";") return pass(); 207 | else return cont(arguments.callee); 208 | }; 209 | } 210 | 211 | function statement(type) { 212 | if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex); 213 | if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex); 214 | if (type == "keyword b") return cont(pushlex("form"), statement, poplex); 215 | if (type == "{") return cont(pushlex("}"), block, poplex); 216 | if (type == ";") return cont(); 217 | if (type == "function") return cont(functiondef); 218 | if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), 219 | poplex, statement, poplex); 220 | if (type == "variable") return cont(pushlex("stat"), maybelabel); 221 | if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), 222 | block, poplex, poplex); 223 | if (type == "case") return cont(expression, expect(":")); 224 | if (type == "default") return cont(expect(":")); 225 | if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), 226 | statement, poplex, popcontext); 227 | return pass(pushlex("stat"), expression, expect(";"), poplex); 228 | } 229 | function expression(type) { 230 | if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator); 231 | if (type == "function") return cont(functiondef); 232 | if (type == "keyword c") return cont(maybeexpression); 233 | if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator); 234 | if (type == "operator") return cont(expression); 235 | if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator); 236 | if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator); 237 | return cont(); 238 | } 239 | function maybeexpression(type) { 240 | if (type.match(/[;\}\)\],]/)) return pass(); 241 | return pass(expression); 242 | } 243 | 244 | function maybeoperator(type, value) { 245 | if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator); 246 | if (type == "operator" || type == ":") return cont(expression); 247 | if (type == ";") return; 248 | if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator); 249 | if (type == ".") return cont(property, maybeoperator); 250 | if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator); 251 | } 252 | function maybelabel(type) { 253 | if (type == ":") return cont(poplex, statement); 254 | return pass(maybeoperator, expect(";"), poplex); 255 | } 256 | function property(type) { 257 | if (type == "variable") {cx.marked = "property"; return cont();} 258 | } 259 | function objprop(type) { 260 | if (type == "variable") cx.marked = "property"; 261 | if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression); 262 | } 263 | function commasep(what, end) { 264 | function proceed(type) { 265 | if (type == ",") return cont(what, proceed); 266 | if (type == end) return cont(); 267 | return cont(expect(end)); 268 | } 269 | return function commaSeparated(type) { 270 | if (type == end) return cont(); 271 | else return pass(what, proceed); 272 | }; 273 | } 274 | function block(type) { 275 | if (type == "}") return cont(); 276 | return pass(statement, block); 277 | } 278 | function vardef1(type, value) { 279 | if (type == "variable"){register(value); return cont(vardef2);} 280 | return cont(); 281 | } 282 | function vardef2(type, value) { 283 | if (value == "=") return cont(expression, vardef2); 284 | if (type == ",") return cont(vardef1); 285 | } 286 | function forspec1(type) { 287 | if (type == "var") return cont(vardef1, forspec2); 288 | if (type == ";") return pass(forspec2); 289 | if (type == "variable") return cont(formaybein); 290 | return pass(forspec2); 291 | } 292 | function formaybein(type, value) { 293 | if (value == "in") return cont(expression); 294 | return cont(maybeoperator, forspec2); 295 | } 296 | function forspec2(type, value) { 297 | if (type == ";") return cont(forspec3); 298 | if (value == "in") return cont(expression); 299 | return cont(expression, expect(";"), forspec3); 300 | } 301 | function forspec3(type) { 302 | if (type != ")") cont(expression); 303 | } 304 | function functiondef(type, value) { 305 | if (type == "variable") {register(value); return cont(functiondef);} 306 | if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext); 307 | } 308 | function funarg(type, value) { 309 | if (type == "variable") {register(value); return cont();} 310 | } 311 | 312 | // Interface 313 | 314 | return { 315 | startState: function(basecolumn) { 316 | return { 317 | tokenize: jsTokenBase, 318 | reAllowed: true, 319 | kwAllowed: true, 320 | cc: [], 321 | lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), 322 | localVars: parserConfig.localVars, 323 | context: parserConfig.localVars && {vars: parserConfig.localVars}, 324 | indented: 0 325 | }; 326 | }, 327 | 328 | token: function(stream, state) { 329 | if (stream.sol()) { 330 | if (!state.lexical.hasOwnProperty("align")) 331 | state.lexical.align = false; 332 | state.indented = stream.indentation(); 333 | } 334 | if (stream.eatSpace()) return null; 335 | var style = state.tokenize(stream, state); 336 | if (type == "comment") return style; 337 | state.reAllowed = !!(type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/)); 338 | state.kwAllowed = type != '.'; 339 | return parseJS(state, style, type, content, stream); 340 | }, 341 | 342 | indent: function(state, textAfter) { 343 | if (state.tokenize != jsTokenBase) return 0; 344 | var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical; 345 | if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev; 346 | var type = lexical.type, closing = firstChar == type; 347 | if (type == "vardef") return lexical.indented + 4; 348 | else if (type == "form" && firstChar == "{") return lexical.indented; 349 | else if (type == "stat" || type == "form") return lexical.indented + indentUnit; 350 | else if (lexical.info == "switch" && !closing) 351 | return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); 352 | else if (lexical.align) return lexical.column + (closing ? 0 : 1); 353 | else return lexical.indented + (closing ? 0 : indentUnit); 354 | }, 355 | 356 | electricChars: ":{}" 357 | }; 358 | }); 359 | 360 | CodeMirror.defineMIME("text/javascript", "javascript"); 361 | CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); 362 | -------------------------------------------------------------------------------- /lib/codemirror2/mode/xml/xml.js: -------------------------------------------------------------------------------- 1 | CodeMirror.defineMode("xml", function(config, parserConfig) { 2 | var indentUnit = config.indentUnit; 3 | var Kludges = parserConfig.htmlMode ? { 4 | autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true, 5 | 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true, 6 | 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true, 7 | 'track': true, 'wbr': true}, 8 | implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true, 9 | 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true, 10 | 'th': true, 'tr': true}, 11 | contextGrabbers: { 12 | 'dd': {'dd': true, 'dt': true}, 13 | 'dt': {'dd': true, 'dt': true}, 14 | 'li': {'li': true}, 15 | 'option': {'option': true, 'optgroup': true}, 16 | 'optgroup': {'optgroup': true}, 17 | 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true, 18 | 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true, 19 | 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true, 20 | 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true, 21 | 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true}, 22 | 'rp': {'rp': true, 'rt': true}, 23 | 'rt': {'rp': true, 'rt': true}, 24 | 'tbody': {'tbody': true, 'tfoot': true}, 25 | 'td': {'td': true, 'th': true}, 26 | 'tfoot': {'tbody': true}, 27 | 'th': {'td': true, 'th': true}, 28 | 'thead': {'tbody': true, 'tfoot': true}, 29 | 'tr': {'tr': true} 30 | }, 31 | doNotIndent: {"pre": true}, 32 | allowUnquoted: true, 33 | allowMissing: false 34 | } : { 35 | autoSelfClosers: {}, 36 | implicitlyClosed: {}, 37 | contextGrabbers: {}, 38 | doNotIndent: {}, 39 | allowUnquoted: false, 40 | allowMissing: false 41 | }; 42 | var alignCDATA = parserConfig.alignCDATA; 43 | 44 | // Return variables for tokenizers 45 | var tagName, type; 46 | 47 | function inText(stream, state) { 48 | function chain(parser) { 49 | state.tokenize = parser; 50 | return parser(stream, state); 51 | } 52 | 53 | var ch = stream.next(); 54 | if (ch == "<") { 55 | if (stream.eat("!")) { 56 | if (stream.eat("[")) { 57 | if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>")); 58 | else return null; 59 | } 60 | else if (stream.match("--")) return chain(inBlock("comment", "-->")); 61 | else if (stream.match("DOCTYPE", true, true)) { 62 | stream.eatWhile(/[\w\._\-]/); 63 | return chain(doctype(1)); 64 | } 65 | else return null; 66 | } 67 | else if (stream.eat("?")) { 68 | stream.eatWhile(/[\w\._\-]/); 69 | state.tokenize = inBlock("meta", "?>"); 70 | return "meta"; 71 | } 72 | else { 73 | type = stream.eat("/") ? "closeTag" : "openTag"; 74 | stream.eatSpace(); 75 | tagName = ""; 76 | var c; 77 | while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c; 78 | state.tokenize = inTag; 79 | return "tag"; 80 | } 81 | } 82 | else if (ch == "&") { 83 | var ok; 84 | if (stream.eat("#")) { 85 | if (stream.eat("x")) { 86 | ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";"); 87 | } else { 88 | ok = stream.eatWhile(/[\d]/) && stream.eat(";"); 89 | } 90 | } else { 91 | ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";"); 92 | } 93 | return ok ? "atom" : "error"; 94 | } 95 | else { 96 | stream.eatWhile(/[^&<]/); 97 | return null; 98 | } 99 | } 100 | 101 | function inTag(stream, state) { 102 | var ch = stream.next(); 103 | if (ch == ">" || (ch == "/" && stream.eat(">"))) { 104 | state.tokenize = inText; 105 | type = ch == ">" ? "endTag" : "selfcloseTag"; 106 | return "tag"; 107 | } 108 | else if (ch == "=") { 109 | type = "equals"; 110 | return null; 111 | } 112 | else if (/[\'\"]/.test(ch)) { 113 | state.tokenize = inAttribute(ch); 114 | return state.tokenize(stream, state); 115 | } 116 | else { 117 | stream.eatWhile(/[^\s\u00a0=<>\"\'\/?]/); 118 | return "word"; 119 | } 120 | } 121 | 122 | function inAttribute(quote) { 123 | return function(stream, state) { 124 | while (!stream.eol()) { 125 | if (stream.next() == quote) { 126 | state.tokenize = inTag; 127 | break; 128 | } 129 | } 130 | return "string"; 131 | }; 132 | } 133 | 134 | function inBlock(style, terminator) { 135 | return function(stream, state) { 136 | while (!stream.eol()) { 137 | if (stream.match(terminator)) { 138 | state.tokenize = inText; 139 | break; 140 | } 141 | stream.next(); 142 | } 143 | return style; 144 | }; 145 | } 146 | function doctype(depth) { 147 | return function(stream, state) { 148 | var ch; 149 | while ((ch = stream.next()) != null) { 150 | if (ch == "<") { 151 | state.tokenize = doctype(depth + 1); 152 | return state.tokenize(stream, state); 153 | } else if (ch == ">") { 154 | if (depth == 1) { 155 | state.tokenize = inText; 156 | break; 157 | } else { 158 | state.tokenize = doctype(depth - 1); 159 | return state.tokenize(stream, state); 160 | } 161 | } 162 | } 163 | return "meta"; 164 | }; 165 | } 166 | 167 | var curState, setStyle; 168 | function pass() { 169 | for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]); 170 | } 171 | function cont() { 172 | pass.apply(null, arguments); 173 | return true; 174 | } 175 | 176 | function pushContext(tagName, startOfLine) { 177 | var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent); 178 | curState.context = { 179 | prev: curState.context, 180 | tagName: tagName, 181 | indent: curState.indented, 182 | startOfLine: startOfLine, 183 | noIndent: noIndent 184 | }; 185 | } 186 | function popContext() { 187 | if (curState.context) curState.context = curState.context.prev; 188 | } 189 | 190 | function element(type) { 191 | if (type == "openTag") { 192 | curState.tagName = tagName; 193 | return cont(attributes, endtag(curState.startOfLine)); 194 | } else if (type == "closeTag") { 195 | var err = false; 196 | if (curState.context) { 197 | if (curState.context.tagName != tagName) { 198 | if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) { 199 | popContext(); 200 | } 201 | err = !curState.context || curState.context.tagName != tagName; 202 | } 203 | } else { 204 | err = true; 205 | } 206 | if (err) setStyle = "error"; 207 | return cont(endclosetag(err)); 208 | } 209 | return cont(); 210 | } 211 | function endtag(startOfLine) { 212 | return function(type) { 213 | if (type == "selfcloseTag" || 214 | (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) { 215 | maybePopContext(curState.tagName.toLowerCase()); 216 | return cont(); 217 | } 218 | if (type == "endTag") { 219 | maybePopContext(curState.tagName.toLowerCase()); 220 | pushContext(curState.tagName, startOfLine); 221 | return cont(); 222 | } 223 | return cont(); 224 | }; 225 | } 226 | function endclosetag(err) { 227 | return function(type) { 228 | if (err) setStyle = "error"; 229 | if (type == "endTag") { popContext(); return cont(); } 230 | setStyle = "error"; 231 | return cont(arguments.callee); 232 | } 233 | } 234 | function maybePopContext(nextTagName) { 235 | var parentTagName; 236 | while (true) { 237 | if (!curState.context) { 238 | return; 239 | } 240 | parentTagName = curState.context.tagName.toLowerCase(); 241 | if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) || 242 | !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { 243 | return; 244 | } 245 | popContext(); 246 | } 247 | } 248 | 249 | function attributes(type) { 250 | if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);} 251 | if (type == "endTag" || type == "selfcloseTag") return pass(); 252 | setStyle = "error"; 253 | return cont(attributes); 254 | } 255 | function attribute(type) { 256 | if (type == "equals") return cont(attvalue, attributes); 257 | if (!Kludges.allowMissing) setStyle = "error"; 258 | return (type == "endTag" || type == "selfcloseTag") ? pass() : cont(); 259 | } 260 | function attvalue(type) { 261 | if (type == "string") return cont(attvaluemaybe); 262 | if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();} 263 | setStyle = "error"; 264 | return (type == "endTag" || type == "selfCloseTag") ? pass() : cont(); 265 | } 266 | function attvaluemaybe(type) { 267 | if (type == "string") return cont(attvaluemaybe); 268 | else return pass(); 269 | } 270 | 271 | return { 272 | startState: function() { 273 | return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null}; 274 | }, 275 | 276 | token: function(stream, state) { 277 | if (stream.sol()) { 278 | state.startOfLine = true; 279 | state.indented = stream.indentation(); 280 | } 281 | if (stream.eatSpace()) return null; 282 | 283 | setStyle = type = tagName = null; 284 | var style = state.tokenize(stream, state); 285 | state.type = type; 286 | if ((style || type) && style != "comment") { 287 | curState = state; 288 | while (true) { 289 | var comb = state.cc.pop() || element; 290 | if (comb(type || style)) break; 291 | } 292 | } 293 | state.startOfLine = false; 294 | return setStyle || style; 295 | }, 296 | 297 | indent: function(state, textAfter, fullLine) { 298 | var context = state.context; 299 | if ((state.tokenize != inTag && state.tokenize != inText) || 300 | context && context.noIndent) 301 | return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; 302 | if (alignCDATA && / 2 | 3 | 4 | Curriculum — page 1 5 | 6 | 7 | 8 | 9 | 10 |

Curriculum: page 1, the basics

11 | 12 |

We'll learn to use the browser's JavaScript console, and do some 13 | fundamental programming.

14 | 15 | 16 |

Open the console

17 | 18 |

Goal

19 | 20 |

Access your browser's JavaScript console.

21 | 22 |

Instructions

23 | 24 |

In Chrome, press Ctrl+Shift+J on Windows or Linux, press 25 | Command+Opt+J on MacOS. (Hold down the first two keys, then press J. 26 | On German keyboards, Ctrl is labeled Strg.)

27 | 28 |

You can also go to the Chrome's main menu in the upper right corner of 29 | your window, and select More ToolsDeveloper Tools.

30 | 31 |

The console window should appear at the right side of your browser window.

32 | 33 |

Resize it by dragging its left border.

34 | 35 |

Click through the icons along the top, and enjoy the awesomely 36 | complicated-looking graphs and tech-garble. This 37 | is your command center now.

38 | 39 |

Explanation

40 | 41 |

The console is a powerful, convenient interface to the innards of a 42 | web page. It allows you to step through the atoms from which a page is 43 | built (the 'Elements' tab), to see which files it is composed of, to 44 | diagnose problems, and, most importantly for us, to play with the 45 | JavaScript environment in the current page.

46 | 47 |

Don't feel obliged to understand any of its functionality right 48 | now. Most of it, we will not need for this course, and the part that 49 | you need will be explained as we go on.

50 | 51 | 52 |

Enter your first code

53 | 54 |

Goal

55 | 56 |

Actually type in some JavaScript, and see it run.

57 | 58 |

Instructions

59 | 60 |

Go to the 'Console' tab in the browser console.

61 | 62 |

Type random junk next to the > sign and press enter.

63 | 64 |

Now type 1 + 1 and press enter.

65 | 66 |

Next, type alert("This computer does what [name] tells it to 67 | do"). Mind the double quotes and parentheses. Substitute your 68 | name for [name].

69 | 70 |

Explanation

71 | 72 |

This part is the essence of the JavaScript console: you get to type 73 | in a one-line program, and the browser will run it for you, and tell 74 | you what the result was. If you write something that is not a valid 75 | program, it will try to tell you what went wrong.

76 | 77 |

The first program, 1 + 1, won't look too foreign. You 78 | should read it as a series of commands to the computer: give me 79 | the number one, now give me another one, now add them both 80 | together. I.e. JavaScript programs do not refer to abstract 81 | concepts (addition of one and one), but to a series of very pedestrian 82 | steps that the computer is instructed to take.

83 | 84 |

The second program (alert(…)) is a function call. 85 | Functions are operations that can be invoked. The function available 86 | under the name alert is an operation for showing a little 87 | dialog window on the screen. The parentheses are the notation for 88 | invoking a function, and the values in between them are given to the 89 | function as further info. In this case, it told the alert 90 | function which text to display.

91 | 92 | 93 |

Understand expressions

94 | 95 |

Goal

96 | 97 |

Understand the most basic elements that programs are composed of.

98 | 99 |

Instructions

100 | 101 |

Combine the two programs from the previous step: alert(1 + 1).

102 | 103 |

Enter 1 + 1 * 10 and then (1 + 1) * 10. 104 | Note the different results.

105 | 106 |

Enter "hey" + "ho".

107 | 108 |

Explanation

109 | 110 |

The kind of program fragment we have been writing so far is called 111 | an expression. Expressions are like Lego blocks, in that you 112 | can combine them into bigger, more interesting expressions. For 113 | example alert(1 + 1) combines a call 114 | to alert with the computation of 1 + 1, and 115 | does what you'd expect: show the number two in a dialog.

116 | 117 |

When combining expressions by using things like + 118 | and * (operators), the meaning is not always 119 | entirely obvious. The * operator, used for 120 | multiplication, is applied before the + operator. 121 | Parentheses are used to explicitly indicate how the expressions are 122 | grouped.

123 | 124 |

Every expression has a value. The most basic expressions 125 | are numbers (1) and strings ("hey"). They 126 | simply describe a value directly. Strings are used to represent text, 127 | and numbers to represent numeric values. These are two 128 | different types of values. We'll see a few more types 129 | later.

130 | 131 |

When + is applied to number values, it means addition. 132 | When it is applied to string values, it glues the text in the strings 133 | together, producing a new string value.

134 | 135 | 136 |

Variables

137 | 138 |

Goal

139 | 140 |

Understand how to store values and refer to them by name. 141 | Understand what statements are.

142 | 143 |

Instructions

144 | 145 |

Enter the following lines at the console:

146 | 147 |
var myvalue = 32 * 32;
148 | alert(myvalue);
149 | myvalue = 10;
150 | alert(myvalue);
151 | 152 |

Explanation

153 | 154 |

The above program introduces three new concepts: the semicolons, 155 | the use of var, and the = operator.

156 | 157 |

The first is the easiest to explain. A program is a series 158 | of statements. An expression with a semicolon after it is a 159 | statement. There are other kinds of statements. The statements in a 160 | program are, as you'd expect, executed from top to bottom.

161 | 162 |

One special form of statement is a variable declaration. This 163 | introduces a name and associates a value with it. Afterwards, the name 164 | (myvalue, in this case) can be used as an expression that 165 | refers to the current value of the variable by that name.

166 | 167 |

A variable's value is not constant over the execution of a program 168 | (in this JavaScript variables differ from mathematical variables). 169 | The = operator can be used at any time to give it a new 170 | value, as in the third line of the example.

171 | 172 | 173 |

A web page

174 | 175 |

Goal

176 | 177 |

See how JavaScript programs operate in the context of web 178 | pages.

179 | 180 |

Instructions

181 | 182 |

Open the example 183 | page.

184 | 185 |

You will see the source for a very simple HTML page below, with the 186 | actual page shown above it. Read the source.

187 | 188 |

Try changing something, and clicking the 'Render' button above the 189 | source code. Open the JavaScript console in the new tab.

190 | 191 |

Explanation

192 | 193 |

What the sandbox page (which is itself a web page written in 194 | JavaScript) allows us to do is to write and try out web pages.

195 | 196 |

Pieces of JavaScript can be embedded in HTML documents with 197 | the <script> tag. In this case, there is a tiny 198 | program embedded that just defines a variable 199 | called myMessage and calls the console.log 200 | function on it.

201 | 202 |

When entering expressions directly into the console, the result 203 | will be displayed automatically. This does not happen for programs 204 | running as part of a web page. When you want to explicitly show 205 | something in the console, use the console.log 206 | function.

207 | 208 |

If you want to inspect the environment of a page shown in the 209 | sandbox, you have to take an extra step. If you open a console on that 210 | tab, and you type myMessage into it, it won't find that 211 | variable. This is because the console is connected to the sandbox page 212 | itself, not the page shown inside of it. At the top left of the console, 213 | there is a control that says <top>. Click on 214 | this and select the option with the name of the domain that is 215 | shown in the address bar of the browser to connect the console to the 216 | actual page we wrote.

217 | 218 |

The button in the example page has a snippet of JavaScript 219 | associated with it through an onclick attribute. 220 | Attributes are name="value" pairs that are specified in 221 | HTML tags. Because the button and the myMessage variable 222 | live on the same page, the onclick program 223 | (alert(myMessage);) can refer to it. 224 | The myvalue variable we defined earlier (on this tab) 225 | is not available on the other tab. Each page is its own 226 | little world, with its own set of variables.

227 | 228 |

And now

229 | 230 |

Things are about to get a lot more interactive.

231 | 232 |

→ Continue with the second page.

233 | -------------------------------------------------------------------------------- /page1_de.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Kursmaterial — Seite 1 5 | 6 | 7 | 8 | 9 | 10 |

Kursmaterial: Seite 1, Die Grundlagen

11 | 12 |

Wir lernen wie man die JavaScript-Konsole des Browsers verwendet 13 | und ein paar grundlegende Dinge programmiert.

14 | 15 | 16 |

Die Konsole öffnen

17 | 18 |

Ziel

19 | 20 |

Die JavaScript-Konsole Deines Browsers verwenden.

21 | 22 |

Anweisungen

23 | 24 |

Unter Windows und Linux: Drücke im geöffneten Chrome-Browser Strg+Shift+J. 25 | Unter MacOS: Command+Opt+J. (Halte die beiden ersten Tasten 26 | gedrückt und drücke dann J.)

27 | 28 |

Alternativ kannst Du auch das Menü in der 29 | rechten oberen Ecke des Browser-Fensters öffnen und 30 | Weitere ToolsEntwicklertools auswählen.

31 | 32 |

Die Konsole sollte nun im unteren Teil des Browser-Fensters erscheinen.

33 | 34 |

Verändere die Größe der Konsole indem Du den oberen Rand mit der Maus ziehst.

35 | 36 |

Klicke alle Icons der Reihe nach durch, um ganz wunderbar kompliziert 37 | aussehende Diagramme und technischen Schnick-Schnack zu bestaunen. 38 | Von nun an ist das Deine Steuerzentrale.

39 | 40 |

Erklärung

41 | 42 |

Die Konsole ist ein nützliches, praktisches Werkzeug, das Dir Zugang 43 | zum Innenleben von Webseiten gibt. Mit ihm kannst Du genau sehen, aus 44 | welchen Einzelteilen eine Seite zusammengesetzt ist (im 'Elements'-Tab) 45 | und aus welchen Dateien sie besteht. Du kannst Probleme diagnostizieren, 46 | und, was für uns am allerwichtigsten ist, Du kannst mit der 47 | JavaScript-Umgebung der jeweils aktuellen Seite spielen.

48 | 49 |

Erwarte nicht, dass Du jetzt schon verstehen musst, wozu die 50 | ganzen Funktionen der Konsole da sind. Das meiste davon werden 51 | wir in diesem Kurs nicht benötigen, und die Teile, die Du brauchst, 52 | wirst Du rechtzeitig erklärt bekommen.

53 | 54 |

Dein erstes Stück Code eingeben

55 | 56 |

Ziel

57 | 58 |

Etwas JavaScript eintippen und sehen was es tut.

59 | 60 |

Anweisungen

61 | 62 |

Gehe zum 'Console'-Tab, ganz rechts in der Browser-Konsole.

63 | 64 |

Tippe einfach wirres Zeug hinter dem >-Zeichen ein, 65 | und and drücke Enter.

66 | 67 |

Jetzt tippe 1 + 1 and drücke Enter.

68 | 69 |

Dann tippe alert("Dieser Computer tut was [Name] ihm sagt"). 70 | Achte auf die doppelten Anführungszeichen und Klammern. 71 | Ersetze [Name] mit Deinem Namen.

72 | 73 |

Erklärung

74 | 75 |

Das ist das Grundprinzip der JavaScript-Konsole: Du kannst ein 76 | einzeiliges Programm eintippen und der Browser fährt es für Dich 77 | ab und sagt Dir was das Ergebnis war. Wenn Du etwas schreibst, 78 | das nicht als gültiges Programm durchgeht, sagt er Dir was 79 | schiefgelaufen ist.

80 | 81 |

Das erste Programm (1 + 1) wird Dir nicht sehr fremd 82 | erscheinen. Es ist als eine Reihe von Anweisungen an den 83 | Computer zu lesen: nimm die Zahl eins, dann nimm nochmal die eins, 84 | und addiere die beiden zusammen. In JavaScript-Programmen 85 | kann man nicht direkt auf so abstrakte Konzepte wie "eins und eins 86 | addieren" Bezug nehmen, sondern man instruiert den Computer 87 | der Reihe nach, sozusagen zu Fuß.

88 | 89 |

Das zweite Programm (alert(…)) ist ein Funktionsaufruf. 90 | Funktionen sind Operationen, die ausgeführt werden können. 91 | Die Funktion, die unter dem Namen alert verfügbar ist, 92 | ist eine Operation, die ein kleines Dialog-Fenster auf dem Bildschirm 93 | anzeigt. Mit Hilfe der Klammern sagt man der Funktion, dass sie ausgeführt 94 | werden soll. Alles was zwischen den Klammern steht, sind zusätzliche 95 | Informationen, die man der Funktion mitgeben möchte. Im Beispiel haben 96 | wir der alert-Funktion gesagt, welchen Text sie anzeigen 97 | soll.

98 | 99 | 100 |

Ausdrücke verstehen

101 | 102 |

Ziel

103 | 104 |

Verstehen, was das Grundelement ist, aus dem Programme bestehen.

105 | 106 |

Anweisungen

107 | 108 |

Kombiniere die beiden Programme aus dem vorigen Schritt: alert(1 + 1).

109 | 110 |

Gib 1 + 1 * 10 in die Konsole ein und dann (1 + 1) * 10. 111 | Sieh Dir die unterschiedlichen Ergebnisse an.

112 | 113 |

Schreibe "hey" + "ho".

114 | 115 |

Erklärung

116 | 117 |

Die Art Programme, die wir bisher geschrieben haben, nennt man 118 | Ausdrücke (englisch: Expressions). 119 | Ausdrücke sind wie Legosteine: Du kannst mehrere 120 | davon nehmen und daraus größere, interessantere Ausdrücke bauen. 121 | Zum Beispiel: alert(1 + 1) kombiniert den Aufruf von 122 | alert mit dem Berechnen von 1 + 1, und tut 123 | genau was man erwarten würde: Es zeigt die Zahl zwei in einem 124 | Dialog-Fenster.

125 | 126 |

Wenn man so etwas wie + und * 127 | (Operatoren) zum Kombinieren von Ausdrücken verwendet, 128 | ist die Bedeutung manchmal nicht ganz offensichtlich. Der 129 | *-Operator, den man fürs Multiplizieren verwendet, 130 | wird vor dem +-Operator ausgewertet. Um explizit 131 | anzugeben wie Ausdrücke untereinander zusammengehören, verwendet 132 | man Klammern.

133 | 134 |

Jeder Ausdruck hat einen Wert. Die einfachsten Ausdrücke 135 | sind Zahlen (1) und Strings ("hey"), auch 136 | Zeichenketten genannt. Sie stehen unmittelbar für einen Wert: 137 | Strings repräsentieren Text und Zahlen repräsentieren Zahlenwerte. 138 | Damit hätten wir schon mal zwei verschiedene Typen von 139 | Werten. Später werden wir noch mehr Typen kennenlernen.

140 | 141 |

Wenn + auf Zahlenwerte angewendet wird, bedeutet 142 | es Addition. Wenn es auf Strings angewendet wird, klebt es deren 143 | Textinhalt aneinander und produziert damit einen neuen String.

144 | 145 | 146 |

Variablen

147 | 148 |

Ziel

149 | 150 |

Verstehen wie man Werte speichert und sie beim Namen nennt. 151 | Verstehen was Anweisungen sind.

152 | 153 |

Anweisungen

154 | 155 |

Gib die folgenden Zeilen in die Konsole ein:

156 | 157 |
var meinwert = 32 * 32;
158 | alert(meinwert);
159 | meinwert = 10;
160 | alert(meinwert);
161 | 162 |

Erklärung

163 | 164 |

Das obige Programm führt zwei neue Konzepte ein: Semikolons und 165 | die Verwendung von var.

166 | 167 |

Das erste Konzept ist einfach zu erklären. Ein Programm ist eine 168 | Reihe von Anweisungen (englisch: Statements). 169 | Packt man ein Semikolon hinter einen Ausdruck, hat man eine Anweisung. 170 | Es gibt auch andere Arten von Anweisungen. Die Anweisungen in einem 171 | Programm werden, wie man erwarten würde, von oben nach unten 172 | ausgeführt.

173 | 174 |

Eine spezielle Form einer Anweisung ist die Deklaration einer 175 | Variablen. Sie führt einen Namen ein und assoziiert diesen mit 176 | einem Wert. Danach kann dieser Name (in unserem Fall 177 | meinwert) als Ausdruck verwendet werden, der 178 | für den aktuellen Wert der Variablen mit diesem Namen steht.

179 | 180 |

Während ein Programm ausgeführt wird, muss der Wert einer 181 | Variablen nicht immer gleich bleiben. Man kann zu jeder Zeit den 182 | Operator = verwenden um einen neuen Wert zuzuweisen, 183 | wie in Zeile drei im Beispiel.

184 | 185 | 186 |

Eine Webseite

187 | 188 |

Ziel

189 | 190 |

Sehen wie JavaScript-Programme sich im Kontext von Webseiten 191 | verhalten.

192 | 193 |

Anweisungen

194 | 195 |

Öffne die Sandkasten-Seite.

196 | 197 |

Du wirst im unteren Teil den Quelltext einer sehr einfachen 198 | HTML-Seite sehen, und darüber die Seite selbst. Lies den Quelltext.

199 | 200 |

Probiere etwas zu verändern und den 'Render'-Button (über dem 201 | Quelltext) zu klicken. Öffne in dem neuen Tab auch die 202 | JavaScript-Konsole.

203 | 204 |

Erklärung

205 | 206 |

Die Sandkasten-Seite (die selbst eine in JavaScript geschriebene 207 | Webseite ist) ermöglicht es uns, Webseiten zu schreiben und 208 | auszuprobieren.

209 | 210 |

JavaScript-Code kann in HTML-Dokumente mit dem 211 | <script>-Tag eingebunden werden. Im Beispiel ist 212 | ein winziges Programm eingebunden, das eine Variable mit dem Namen 213 | myMessage definiert und auf ihr die Funktion 214 | console.log ausführt.

215 | 216 |

Beim direkten Eingeben von Ausdrücken in die Konsole wird das 217 | Ergebnis immer automatisch angezeigt. Für Programme, die Teil einer 218 | Webseite sind, ist das nicht so. Wenn Du etwas in der Konsole 219 | angezeigt haben möchtest, musst Du die Funktion 220 | console.log verwenden.

221 | 222 |

Wenn Du das Innenleben einer Seite anschauen möchtest, die im 223 | Sandkasten angezeigt wird, ist ein zusätzlicher Schritt nötig. 224 | Wenn Du die Konsole in diesem Tab öffnest und myMessage 225 | eintippst, wird es die Variable nicht finden. Der Grund ist, dass 226 | die Konsole mit der Sandkasten-Seite selbst verbunden ist, nicht 227 | mit der Seite, die darin angezeigt wird. Oben links in der Konsole 228 | gibt es eine Schaltfäche auf der <top> steht. 229 | Klicke sie an und wähle die Option mit dem Namen der Domain in der 230 | Adressleiste im Browser um die Konsole mit der Seite zu verbinden, 231 | die wir geschrieben haben.

232 | 233 |

Der Button auf der Beispielseite ist über sein 234 | onclick-Attribut mit einem Stück JavaScript-Code 235 | verknüpft. Attribute sind Paare der Form name="wert", 236 | die in HTML-Tags definiert werden. 237 | Weil der Button und die Variable myMessage auf 238 | derselben Seite leben, ist es für das onclick-Programm 239 | (alert(myMessage);) möglich, sich auf diese Variable 240 | zu beziehen. 241 | Die Variable meinwert, die wir vorher (im diesem Tab 242 | hier) definiert haben, ist im neuen Tab nicht verfügbar. 243 | Jede Seite ist eine eigene kleine Welt, mit seinen eigenen 244 | Variablen.

245 | 246 |

Und jetzt

247 | 248 |

Wir sind kurz davor alles viel interaktiver werden zu lassen.

249 | 250 |

→ Weiter geht's mit der nächsten Seite.

251 | -------------------------------------------------------------------------------- /page2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Curriculum — page 2 5 | 6 | 7 | 8 | 9 | 10 |

Curriculum: page 2, pictures

11 | 12 |

The previous page told you exactly, literally what to do, without 13 | leaving you any choices. We apologize for this shameless suppression 14 | of your artistic self. Now that you know the basics, the course 15 | material will be less linear, with more room for experimentation.

16 | 17 |

Open the picture playground

18 | 19 |

Goal

20 | 21 |

Get acquainted with our visual programming environment.

22 | 23 |

Instructions

24 | 25 |

Open the playground 26 | page in a new tab.

27 | 28 |

Rejoice.

29 | 30 |

Next, read the first part of the JavaScript program.

31 | 32 |

Randomly play around with the content of the drawing 33 | function. Change some numbers and colors, render again. Now read the 34 | text below the program and add some new shapes.

35 | 36 |

Explanation

37 | 38 |

What we are going to do is get a feel for programming concepts by 39 | applying them to something easily observable: graphics. The linked 40 | page defines a number of convenient drawing operations for us, and 41 | invites you to experiment with them.

42 | 43 |

At the bottom of the program there are a number of lines starting 44 | with two slashes (//). These are 45 | called comments. They clarify the program, but are not 46 | actually part of it. You can write anything you want in a comment, the 47 | computer won't even look at it.

48 | 49 |

Your programs, as entered into the sandbox page, don't run in a 50 | vacuum. We have, for the purpose of this course, defined a number of 51 | simple functions for performing graphics operations, as described at 52 | the bottom of the example, and your program may refer to those.

53 | 54 |

The function drawing() part defines a function 55 | named drawing. We'll see more about function definitions 56 | in a few steps, but this one is special, in that it is executed when 57 | the script is rendered. Thus, it is the place where the statements 58 | that produce your drawing go.

59 | 60 | 61 |

The loop

62 | 63 |

Goal

64 | 65 |

Learn what a loop is, and how to express them in JavaScript.

66 | 67 |

Problem statement: we want to draw twenty dots, without 68 | writing circle(x, y, something) twenty times.

69 | 70 |

Instructions

71 | 72 |

Open this link 73 | to get a drawing function containing this program:

74 | 75 |
color("red");
 76 | var column = 0;
 77 | while (column < 20) {
 78 |   circle(column * 10, 0, 4);
 79 |   column = column + 1;
 80 | }
81 | 82 |

Explanation

83 | 84 |

A program, when not otherwise instructed, will simply execute its 85 | statements from top to bottom. The great thing about making a computer 86 | work for us is that it can take repetetive tasks of our hand. Thus, we 87 | don't want to write circle(0, 0, 4); circle(10, 0, 4); etc 88 | to draw our dots.

89 | 90 |

The word while can be used to create a special kind of 91 | statement that is called a loop. It consists of 92 | a condition (column < 20) and a body 93 | (the part between the braces). A loop does not obey the usual top-down 94 | order of execution. It will continue executing the body as long as the 95 | condition holds true.

96 | 97 |

The braces around the two statements inside the loop are used to 98 | group them together—they make clear that these statements both belong 99 | to the loop body. You have probably noticed that some space is added 100 | in front of these, to make it clear that they are part of a block. 101 | This is done to help readability of the program, but isn't 102 | strictly required.

103 | 104 |

The example code uses a variable to track its progress. 105 | The column variable starts at zero, and is moved forward 106 | by one every time the loop body executes. A loop condition is a 107 | normal expression, and the < symbol is a normal 108 | operator that compares two expressions and returns a value that 109 | indicates whether the one to the left is smaller than the one to the 110 | right. Thus, we can expect the loop body to be executed exactly twenty 111 | times—first with column at zero, then at one, and so on 112 | until nineteen. When it reaches twenty, the condition no longer holds, 113 | and the program continues below the loop (which is the end of our 114 | example).

115 | 116 |

There are a few more things you might need to know about 117 | the < operator. The value it produces is not a number 118 | or a string, but a new type, called boolean. There are only 119 | two values of this type, called true 120 | and false. There are similar operators for checking 121 | whether a value is greater than (>) or equal to 122 | (==) to some other value.

123 | 124 |

Exercise: try to write a program that prints a 125 | 20-by-20 grid of dots, instead of just a line. You'll need 126 | two loops, and two counter variables (one for columns, one for rows). Hint: you may put a loop inside 127 | another loop.

128 | 129 |

When trying out programs in the sandbox, keep an eye on the 130 | console. When the computer can't make sense of your program, it will 131 | output (more or less informative) messages there. When nothing happens 132 | after pressing 'Render', chances are you mistyped something.

133 | 134 | 135 |

Conditional execution

136 | 137 |

Goal

138 | 139 |

Next, we want to draw every other dot in our lines of dots in a 140 | different color. The even ones should be black, the odd ones grey.

141 | 142 |

In order to do this, we will learn about conditional statements.

143 | 144 |

Instructions

145 | 146 |

Here is the program that, when put inside the drawing 147 | function, does what we want, and is 148 | available here:

149 | 150 |
var column = 0;
151 | while (column < 20) {
152 |   if (column % 2 == 0) {
153 |     color("black");
154 |   } else {
155 |     color("gray");
156 |   }
157 |   circle(column * 10, 0, 4);
158 |   column = column + 1;
159 | }
160 | 161 |

Explanation

162 | 163 |

The first new concept introduced here is the % 164 | operator. This is pronounced 'remainder'. It is not a very important 165 | operator, but it is useful here. What it does is divide the value on 166 | the left by the one on the right, and give us the remainder of that 167 | division. Thus, column % 2 == 0 is a way to check 168 | whether column is even—if it is, then the remainder of 169 | dividing it by two will be zero.

170 | 171 |

But the important new concept introduced here is 172 | the if/else statement. Like a loop, it 173 | accepts a condition. If the condition is true, it will 174 | execute the statement coming after it. Otherwise, it will execute the 175 | statement that follows the else word.

176 | 177 |

The else part can be left off to indicate that nothing 178 | at all should happen when the condition does not hold.

179 | 180 |

Exercise: extend the example program to draw every 181 | third dot 10 units higher than the others. Hint: define a 182 | variable height and set its value inside of a 183 | conditional.

184 | 185 | 186 |

Functions

187 | 188 |

Goal

189 | 190 |

Now consider that we want to draw a smiley in multiple, specific 191 | places. We could repeat the six statements needed to draw one such 192 | shape several times, but again, what we're trying to do here is to 193 | make the computer work for us.

194 | 195 |

We are about to learn how to define new functions to perform useful 196 | operations for us.

197 | 198 |

Instructions

199 | 200 |

This is the smiley function:

201 | 202 |
function smiley(x, y) {
203 |   moveTo(x, y);
204 |   color("yellow");
205 |   circle(0, 0, 50);
206 |   color("black");
207 |   circle(-20, 10, 7);
208 |   circle(20, 10, 7);
209 |   lineWidth(3);
210 |   path("g -20 -10 q 20 -10 0 -50 c");
211 |   goBack();
212 | }
213 | 214 |

You can put it in your code next to the drawing 215 | function, and change that function to call it, 216 | as shown 217 | here:

218 | 219 |
function drawing() {
220 |   smiley(0, 0);
221 |   smiley(-100, 20);
222 |   smiley(100, 50);
223 | }
224 | 225 |

Explanation

226 | 227 |

A function is, in effect, a shorthand for a piece of code. You 228 | define it with the function word as shown above. This 229 | produces a variable with the given name (smiley, in this 230 | case) that refers to the chunk of code. The words after the function's 231 | name—(x, y)—are the parameters to the function. 232 | These are given a value when the function is used. For 233 | example smiley(0, 0) will run the function's body with 234 | both x and y holding the value zero.

235 | 236 |

One thing to be aware of is that variables defined inside functions 237 | (including their parameters), are local to that function. So 238 | if you have another function that also has a parameter 239 | called x, such as circle, that 240 | function's x and the one in smiley are 241 | separate variables, and do not interfere with each other. Mentions 242 | of x in smiley refer to that 243 | function's x, and mentions in other functions refer to 244 | whichever variable happens to be called x in that 245 | function.

246 | 247 |

Exercise: define a 248 | function smileySquadron draws five smileys next to each 249 | other by using a while loop. Once it works, use it to 250 | draw a whole lot of smileys.

251 | 252 | 253 |

Free-form

254 | 255 |

Goal

256 | 257 |

Write some kind of entertaining graphical program yourself.

258 | 259 |

Instructions

260 | 261 |

Here are some tools to help you get started:

262 | 263 |

Math.random() can be used to produce a random 264 | (unpredictable) number between zero and one. Thus, Math.random() 265 | * 10 produces a number between zero and ten, and so on.

266 | 267 |

setInterval(func, n) is a way to run a function 268 | every n milliseconds. If you combine it with 269 | the clear function to clear the screen, you can produce 270 | an animation. You can find a 271 | demonstration here.

273 | 274 |

The moveTo, rotate, scale, 275 | and goBack functions defined in the playground, when 276 | combined with functions that call themselves, make it very easy to 277 | define hierarchical, fractal drawing. 278 | See this tree for 279 | an example.

280 | 281 |

Explanation

282 | 283 |

Doing is the best way to learn. Go nuts. Think of something 284 | elaborate. Ask the coaches for help when you are unsure how to go 285 | about something.

286 | 287 |

And on

288 | 289 |

→ To the third page.

290 | -------------------------------------------------------------------------------- /page2_de.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Kursmaterial — Seite 2 5 | 6 | 7 | 8 | 9 | 10 |

Kursmaterial: Seite 2, Bilder

11 | 12 |

Die vorige Seite hat Dir genau, Wort für Wort, gesagt was Du 13 | tun sollst, ohne Dir eine Wahl zu lassen. Wir entschuldigen uns 14 | für diese schamlose Unterdrückung deiner künstlerischen Identität. 15 | Jetzt, da Du die Grundlagen schon kennst, wird 16 | das Kursmaterial etwas weniger linear sein und Dir 17 | mehr Spielraum zum Experimentieren lassen.

18 | 19 |

Den Bilder-Spielplatz öffnen

20 | 21 |

Ziel

22 | 23 |

Mache Dich mit unserer visuellen Programmierumgebung vertraut.

24 | 25 |

Anweisungen

26 | 27 |

Öffne die Spielplatz-Seite 28 | in einem neuen Tab.

29 | 30 |

Frohlocke.

31 | 32 |

Lies den ersten Abschnitt des JavaScript-Programms im unteren 33 | Teil des Bildschirms.

34 | 35 |

Spiel ein bisschen mit dem Inhalt der drawing-Funktion 36 | herum. Verändere hier und da die Werte und Farben und klicke 37 | auf 'Render' um das Ergebnis zu sehen. Lies Dir danach den Text 38 | unter dem Programm durch und füge ein paar neue Formen hinzu.

39 | 40 |

Erklärung

41 | 42 |

Die Idee hier ist, ein Gefühl für Konzepte der Programmierung 43 | zu bekommen, indem wir sie auf etwas anwenden, das leicht 44 | zu beobachten ist: Grafiken. 45 | Die Spielumgebung hat eine Anzahl praktischer 46 | Zeichen-Operationen für uns vordefiniert und lädt uns ein, 47 | mit ihnen zu experimentieren.

48 | 49 |

Im unteren Teil des Programms gibt es mehrere Zeilen, 50 | die mit zwei Schrägstrichen (//) anfangen. Man nennt 51 | sie Kommentare. Sie helfen dabei, Programme verständlicher 52 | zu machen, sind aber nicht selbst Teil des Programms. 53 | In Kommentaren kannst Du schreiben was auch immer Du willst—der 54 | Computer schaut sich das sowieso nie an.

55 | 56 |

Die Programme, die Du in der Spielumgebung eingibst, laufen nicht 57 | im Vakuum. Für diesen Kurs haben wir eine Reihe von einfachen 58 | Funktionen vordefiniert, mit denen man grafische Operationen 59 | ausführen kann. Sie sind im Kommentar des Beispiels beschrieben 60 | und können von Deinem Programm verwendet werden.

61 | 62 |

Das Code-Stück function drawing() definiert 63 | eine Funktion mit dem Namen drawing. Ein paar 64 | Schritte weiter werden wir mehr über die Definition von Funktionen 65 | erfahren, aber diese eine Definition ist speziell: Sie wird 66 | immer ausgeführt, wenn Du den 'Render'-Button klickst. Dort 67 | gehören also die Anweisungen (englisch: Statements) hin, die 68 | Dein Bild produzieren.

69 | 70 | 71 |

Die Schleife

72 | 73 |

Ziel

74 | 75 |

Lernen was eine Schleife ist, und wie man sie in JavaScript ausdrückt.

76 | 77 |

Das Problem: Wir wollen zwanzig Punkte malen ohne 78 | circle(x, y, something) zwanzigmal hinzuschreiben.

79 | 80 |

Anweisungen

81 | 82 |

Öffne diesen Link, 83 | um zu einer drawing-Funktion mit folgendem Programm zu 84 | gelangen:

85 | 86 |
color("red");
 87 | var column = 0;
 88 | while (column < 20) {
 89 |   circle(column * 10, 0, 4);
 90 |   column = column + 1;
 91 | }
92 | 93 |

Erklärung

94 | 95 |

Solange man seinem Programm nichts anderes beibringt, wird es 96 | Anweisungen einfach von oben nach unten ausführen. 97 | Das Großartige daran, einen Computer für uns arbeiten zu lassen, 98 | ist, dass er uns eintönige Aufgaben abnehmen kann. 99 | Daher wollen wir gar nicht erst anfangen, circle(0, 0, 4); circle(10, 0, 4); 100 | usw. zu schreiben, um unsere Punkte zu malen.

101 | 102 |

Mit dem Wort while kann man eine besondere 103 | Art von Anweisungen einleiten, die man Schleifen nennt 104 | (englisch: loop). Eine Schleife besteht aus einer 105 | Bedingung (englisch: condition) und einem 106 | Schleifenkörper (englisch: body). Im Beispiel 107 | ist column < 20 die Bedingung und der Körper ist 108 | alles, was zwischen den geschweiften Klammern steht. 109 | Eine Schleife hält sich nicht an die gewöhnliche Top-Down-Reihenfolge. 110 | Stattdessen wiederholt sie den Körper so lange, wie die Bedingung 111 | gültig ist.

112 | 113 |

Die geschweiften Klammern halten die zwei Anweisungen im 114 | Inneren der Schleife zusammen—sie machen deutlich, dass beide 115 | zum Schleifenkörper gehören. Wahrscheinlich ist Dir aufgefallen, 116 | dass diese Zeilen etwas eingerückt sind. Das macht man, um 117 | Programme leichter lesbar zu machen (in diesem Fall, um es 118 | offensichtlicher zu machen wo der Block anfängt und aufhört). 119 | Unbedingt erforderlich ist es aber nicht.

120 | 121 |

Im Beispiel verwendet die Schleife eine Variable als inneren 122 | Fortschritts-Anzeiger. Die Variable column fängt 123 | mit dem Wert null an und wird jedesmal, wenn der Schleifenkörper 124 | ausgeführt wird, um eins erhöht. Eine Bedingung ist ein ganz 125 | normaler Ausdruck und das Symbol < ist ein 126 | gewöhnlicher Operator, der zwei Ausdrücke miteinander vergleicht 127 | und als Wert etwas zurückgibt, dass angibt ob der Wert auf der 128 | linken Seite kleiner ist als der auf der rechten Seite. 129 | Wir würden also erwarten, dass der Schleifenkörper genau 130 | zwanzigmal ausgeführt wird—beim ersten Mal mit column 131 | bei null, dann bei eins und so weiter, bis 19. 132 | Wenn column 20 erreicht, ist die Bedingung nicht 133 | mehr gültig und das Programm wird hinter der Schleife fortgesetzt 134 | (was in unserem Fall das Ende des Beispiels ist).

135 | 136 |

Es gibt noch ein paar wissenswerte Dinge zum 137 | <-Operator: Der Wert, den er produziert, 138 | ist keine Zahl und kein String, sondern ein neuer Typ, genannt 139 | Boolean. Dieser Typ hat nur zwei mögliche Werte: 140 | true und false. Andere Operatoren, 141 | die solche Werte produzieren, sind > (größer als) 142 | und == (gleich).

143 | 144 |

Übung: Versuche ein Programm zu schreiben, 145 | das, statt nur eine gepunktete Linie zu malen, ein Raster 146 | mit 20 mal 20 Punkten malt. Dafür brauchst Du zwei Schleifen 147 | und zwei Variablen zum Zählen, eine für die Spalten (columns) und eine für die Reihen (rows) des Rasters. Hinweis: Du kannst eine Schleife 148 | innerhalb einer anderen Schleife schreiben.

149 | 150 |

Während Du Programme in der Spielumgebung ausprobierst, halte 151 | ein Auge auf die Browser-Konsole. Wenn der Computer nicht 152 | versteht, was Dein Programm ihm sagen will, wird er Dir das 153 | dort (in mehr oder weniger verständlicher Form) mitteilen. 154 | Wenn nach einem Klick auf 'Render' nichts passiert, 155 | hast Du Dich wahrscheinlich irgendwo vertippt.

156 | 157 | 158 |

Bedingte Ausführung

159 | 160 |

Ziel

161 | 162 |

Als Nächstes wollen wir jeden zweiten Punkt unserer Punkt-Linien 163 | in einer anderen Farbe malen. Es soll immer ein Punkt schwarz sein 164 | und der nächste grau.

165 | 166 |

Dafür werden wir etwas über bedingte Anweisungen lernen.

167 | 168 |

Anweisungen

169 | 170 |

Ein Programm, das tut was wir wollen, wenn wir es in die 171 | drawing-Funktion packen, findest Du 172 | hier. 173 | So sieht es aus:

174 | 175 |
var column = 0;
176 | while (column < 20) {
177 |   if (column % 2 == 0) {
178 |     color("black");
179 |   } else {
180 |     color("gray");
181 |   }
182 |   circle(column * 10, 0, 4);
183 |   column = column + 1;
184 | }
185 | 186 |

Erklärung

187 | 188 |

Das erste neue Konzept hier ist der Operator %, 189 | gesprochen 'Modulo'. Man braucht ihn nicht so häufig, aber hier 190 | ist er nützlich. Er teil die Zahl auf der linken Seite durch die 191 | auf der rechten Seite und gibt den Rest der Division zurück. 192 | Mit column % 2 == 0 kann man also prüfen, ob 193 | column eine gerade Zahl ist, denn dann ist der 194 | Rest null, wenn man sie durch zwei teilt.

195 | 196 |

Das eigentlich wichtige neue Konzept hier ist die 197 | Anweisung if/else. Genau wie eine 198 | Schleife, benötigt auch sie eine Bedingung. 199 | Wenn die Bedingung wahr (true) ist, wird die 200 | darauf folgende Anweisung ausgeführt. Wenn nicht, führt es 201 | die Anweisung aus, die nach dem Wort else kommt.

202 | 203 |

Der else-Teil kann auch weggelassen werden, um 204 | anzuzeigen, dass gar nichts passieren soll, wenn die Bedingung 205 | nicht gilt.

206 | 207 |

Übung: Erweitere das Beispiel-Programm so, 208 | dass jeder dritte Punkt um 10 Einheiten nach oben verschoben 209 | erscheint. Hinweis: Definiere eine Variable height 210 | und setze ihren Wert innerhalb einer bedingten Anweisung.

211 | 212 | 213 |

Funktionen

214 | 215 |

Ziel

216 | 217 |

Was machen wir, wenn wir mehrere fröhliche Gesichter 218 | (englisch: Smileys) an verschiedenen Stellen auf dem Bildschirm 219 | platzieren wollen? Wir könnten natürlich die sechs Anweisungen 220 | wiederholen, die zum Malen einer solchen Form benötigt werden, 221 | aber wir wollen ja den Computer für uns arbeiten 222 | lassen.

223 | 224 |

Wir werden lernen, wie man neue Funktionen definiert, um 225 | nützliche Operationen für uns auszuführen.

226 | 227 |

Anweisungen

228 | 229 |

Hier ist die smiley-Funktion:

230 | 231 |
function smiley(x, y) {
232 |   moveTo(x, y);
233 |   color("yellow");
234 |   circle(0, 0, 50);
235 |   color("black");
236 |   circle(-20, 10, 7);
237 |   circle(20, 10, 7);
238 |   lineWidth(3);
239 |   path("g -20 -10 q 20 -10 0 -50 c");
240 |   goBack();
241 | }
242 | 243 |

Du kannst sie in Deinen Code vor (oder hinter) die 244 | drawing-Funktion packen und diese so umschreiben, 245 | dass sie die neue Funktion aufruft. 246 | So zum Beispiel:

247 | 248 |
function drawing() {
249 |   smiley(0, 0);
250 |   smiley(-100, 20);
251 |   smiley(100, 50);
252 | }
253 | 254 |

Erklärung

255 | 256 |

Eine Funktion ist im Prinzip eine abgekürzte Schreibweise 257 | für ein Stück Code. Man definiert sie mit dem Wort 258 | function, wie oben zu sehen ist. Das erzeugt 259 | eine Variable mit dem gewählten Namen (in diesem Fall 260 | smiley), der für das Stück Code steht. 261 | Die Wörter hinter dem Funktionsnamen—(x, y)—sind 262 | die Parameter der Funktion. 263 | Sie erhalten ihren Wert, wenn die Funktion aufgerufen wird. 264 | Zum Beispiel würde smiley(0, 0) den Körper der 265 | Funktion ausführen und dabei sowohl x als auch 266 | y den Wert null geben.

267 | 268 |

Eine Sache, die man beachten muss, ist, dass Variablen, die 269 | innerhalb von Funktionen definiert werden (einschließlich ihrer 270 | Parameter), lokal zu dieser Funktion sind. 271 | Also wenn Du eine zweite Funktion hast, die auch einen 272 | x-Parameter hat, wie zum zum Beispiel 273 | circle, dann sind die beiden x-Variablen 274 | unabhängig voneinander und beeinflussen sich nicht gegenseitig. 275 | Innerhalb von smiley steht x 276 | immer für das x, das in smiley definiert ist, 277 | und in einer anderen Funktion würde eben das x 278 | gemeint sein, das im Kontext dieser Funktion als Variable 279 | existiert.

280 | 281 |

Übung: Definiere eine Funktion 282 | smileySquadron die fünf Smileys nebeneinander malt. 283 | Verwende dafür eine while-Schleife. 284 | Und wenn das funktioniert, male so viele Smileys wie Du möchtest!

285 | 286 | 287 |

Kreativ-Zone

288 | 289 |

Ziel

290 | 291 |

Erfinde Dein eigenes, unterhaltsames, grafisches Programm.

292 | 293 |

Anweisungen

294 | 295 |

Hier sind ein paar Dinge, die nützlich sein könnten:

296 | 297 |

Math.random() produziert Zufallszahlen zwischen 0 und 1. 298 | Math.random() * 10 gibt also eine unvorhersehbare Zahl 299 | zwischen null und zehn zurück, usw.

300 | 301 |

Mit setInterval(func, n) kann man eine Funktion 302 | alle n Millisekunden abfahren. In Verbindung 303 | mit der Funktion clear kannst Du damit 304 | Animationen erstellen. Ein Beispiel dafür findest Du 305 | hier.

306 | 307 |

Die Funktionen moveTo, rotate, 308 | scale und goBack, die in der 309 | Spielumgebung definiert sind, können mit Funktionen kombiniert 310 | werden, die sich selbst aufrufen, um so sehr einfach hierarchische, 311 | fraktale Grafiken zu erstellen. 312 | Schau Dir als Beispiel 313 | diesen Baum 314 | an.

315 | 316 |

Erklärung

317 | 318 |

Am meisten lernt man, wenn man selbst etwas tut. 319 | Tob Dich aus. Denk Dir etwas Aufwändiges aus. 320 | Und wenn Du nicht genau weißt, wie Du Deine Pläne umsetzen kannst: 321 | Nun, dafür sind die Coaches da.

322 | 323 |

Und weiter geht's…

324 | 325 |

→ …mit der dritten Seite.

326 | -------------------------------------------------------------------------------- /page3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Curriculum — page 3 5 | 6 | 7 | 8 | 9 | 10 |

Curriculum: page 3, data

11 | 12 |

Inside the computer's world, there is only data. That which is not 13 | data, does not exist. Programs are data. Programs create new data. 14 | It's like some kind of strange, silicon-based cycle of life.

15 | 16 | 17 |

Collections

18 | 19 |

Goal

20 | 21 |

Learn how to group a set of values into a single collection, and 22 | use that collection.

23 | 24 |

Problem statement: draw a rainbow by drawing seven concentric 25 | circles with the following colors: red, orange, yellow, green, 26 | cyan, purple, white, each smaller than the last.

27 | 28 |

Instructions

29 | 30 |

This is the naive approach:

31 | 32 |
function rainbow(x, y) {
 33 |   color("red");
 34 |   circle(x, y, 150);
 35 |   color("orange");
 36 |   circle(x, y, 145);
 37 |   color("yellow");
 38 |   circle(x, y, 140);
 39 |   color("green");
 40 |   circle(x, y, 135);
 41 |   color("cyan");
 42 |   circle(x, y, 130);
 43 |   color("purple");
 44 |   circle(x, y, 125);
 45 |   color("white");
 46 |   circle(x, y, 120);
 47 | }
48 | 49 |

That is not wrong, but it is not right either. It repeats itself a 50 | lot. Here is a better version:

51 | 52 |
function rainbow(x, y) {
 53 |   var colors = ["red", "orange", "yellow", "green", "cyan", "purple", "white"];
 54 |   var count = 0;
 55 |   while (count < colors.length) {
 56 |     color(colors[count]);
 57 |     circle(x, y, 150 - 5 * count);
 58 |     count = count + 1;
 59 |   }
 60 | }
61 | 62 |

Explanation

63 | 64 |

The thing with the square brackets ([ 65 | and ]) is called an array. An array is a value that 66 | holds other values—in this case, it holds seven strings that name 67 | colors.

68 | 69 |

The values in an array are called its elements. The elements 70 | in an array are ordered, which means that each element has a position 71 | within the array. Array positions start at zero, so in the above 72 | example, "red" has position zero, 73 | and "white" (the seventh element) has position 6. The 74 | notation colors[1] is used to access the values in an 75 | array—in this case, it'd produce "orange".

76 | 77 |

Another new notation, though we've seen it before 78 | in Math.random is the dot in colors.length. 79 | It is used to fetch another kind of sub-value, called property, out of 80 | a value. In the case of Math.random, it is just used for 81 | grouping—a whole bunch of number-related functions are available as 82 | properties of Math (for example Math.round 83 | to round numbers). But in the case of colors.length, it 84 | retrieves a property value that is directly related 85 | to colors: the amount of elements in the array 86 | (seven).

87 | 88 |

So this typical while loop, using 89 | the count variable to track its progress, goes over the 90 | elements of the array one by one, uses them to set the current color, 91 | and then draws a circle of the right size.

92 | 93 |

Since this kind of loop is very common (create variable, test it 94 | in while condition, and update it), there is a more 95 | compact way to write it. This program is equivalent to the one 96 | above:

97 | 98 |
function rainbow(x, y) {
 99 |   var colors = ["red", "orange", "yellow", "green", "cyan", "purple", "white"];
100 |   for (var count = 0; count < colors.length; count = count + 1) {
101 |     color(colors[count]);
102 |     circle(x, y, 150 - 5 * count);
103 |   }
104 | }
105 | 106 |

In a for loop, initializing the loop state, checking 107 | it, and updating it, are all grouped together, to make it easier to 108 | see that they make up a single loop.

109 | 110 |

Exercise: Play with the look of the rainbows. E.g. make the 111 | stripes a bit bigger.

112 | 113 | 114 |

Named properties

115 | 116 |

Goal

117 | 118 |

Learn how to create objects, and access their properties.

119 | 120 |

Instructions

121 | 122 |

Open the console again, in case you had closed it.

123 | 124 |

Create a variable named myObject by entering this in the 125 | console: var myObject = {name: "Larry", score: 100};

126 | 127 |

You can now get the value of the name property of 128 | myObject by entering myObject.name into the 129 | console. You can do the same for the score property by 130 | entering myObject.score.

131 | 132 |

Next, enter myObject["name"] into the console, and then 133 | myObject["sco" + "re"].

134 | 135 |

Give the object another property by entering myObject.color = 136 | "purple". Then get the value of the newly created color 137 | property by entering myObject.color.

138 | 139 |

Change the score property by entering 140 | myObject.score = 105. Then check that you successfully changed the 141 | value by entering myObject.score.

142 | 143 |

Explanation

144 | 145 |

Objects are also collections of values. But they require every 146 | value to have a name. Arrays are useful when collecting any number of 147 | values in a homogenous group, whereas objects are more appropriate 148 | when each value has a specific, distinct role. I.e. a big bag of 149 | potatoes is an array, but the parts that make up a car (engine, wheels, 150 | each with their own role) form an object.

151 | 152 |

The {property1: value1, property2: value2} syntax is 153 | used to create a new object. There are two ways to access the 154 | properties of an object. The object.property way is used 155 | when you know the name of the property in advance. 156 | The object["property"] way allows the property name to be 157 | any expression, and thus is useful when the name needs to be computed 158 | somehow.

159 | 160 |

Together, objects and arrays provide a way to express a wide 161 | variety of information. For example, a list of players in a game would 162 | typically be an array of objects, where each object represents a 163 | player. If a list of achievements has to be associated with players, 164 | that would be another array inside of each object, and so on.

165 | 166 |

Exercise: Figure out a JavaScript representation 167 | for a chess game board. There are multiple good solutions.

168 | 169 | 170 |

We've got data

171 | 172 |

Goal

173 | 174 |

Perform a simple visualization of a dataset.

175 | 176 |

Instructions

177 | 178 |

In our new playground environment, we have a new variable 179 | available, weatherData. This contains an array of three objects 180 | with weather forecast information.

181 | 182 |

Each object (representing a day) has a date 183 | property containing a string, and temperature 184 | and humidity properties that contain numbers.

185 | 186 |

This program plots a bar chart showing the temperature at every single 187 | day in the data set.

188 | 189 |
var width = 600, height = 400;
190 | 
191 | var weatherData = [
192 | 	{
193 | 		date: "2012-08-21",
194 | 		temperature: 30,
195 | 		humidity: 10
196 | 	},
197 | 	{
198 | 		date: "2012-08-22",
199 | 		temperature: 24,
200 | 		humidity: 45
201 | 	},
202 | 	{
203 | 		date: "2012-08-23",
204 | 		temperature: 28,
205 | 		humidity: 30
206 | 	}
207 | ];
208 | 
209 | function barChart(x, y, barWidth) {
210 | 	var gutter = 2,
211 | 		xPosition = x,
212 | 		yPosition = y;
213 | 
214 | 	var barHeight = -1 * weatherData[0].temperature;
215 | 	box(xPosition, yPosition, barWidth, barHeight);
216 | 
217 | 	barHeight = -1 * weatherData[1].temperature;
218 | 	xPosition = xPosition + gutter + barWidth;
219 | 	box(xPosition, yPosition, barWidth, barHeight);
220 | 
221 | 	barHeight = -1 * weatherData[2].temperature;
222 | 	xPosition = xPosition + gutter + barWidth;
223 | 	box(xPosition, yPosition, barWidth, barHeight);
224 | }
225 | 
226 | function drawing() {
227 | 	color("red");
228 | 	barChart(0, 0, 20);
229 | }
230 | 231 |

You can see it in action here.

233 | 234 |

Explanation

235 | 236 |

In order to be a little disciplined about where we're going to 237 | draw, the program starts by defining the width and the height of the 238 | area it wants to draw in. 600 by 400 units.

239 | 240 |

The barChart function takes the position and the width 241 | of a bars it should plot as a parameter. It then draws a single bar 242 | using the box function. The height of the bar represents 243 | the temperature taken from the first day using 244 | weatherData[0].temperature

245 | 246 |

Afterwards, the function plots the temperature for second and 247 | the third day in the same way.

248 | 249 |

Exercise: Having reference every single day in 250 | the dataset in order to display its temperature is rather silly. 251 | Change the barChart function so that it uses a 252 | while loop to go through the dataset and draw the bar chart 253 | automatically.

254 | 255 |

In order to test if your function works as expected, add a few more 256 | days to the dataset. You can use data you acquire from 257 | the web.

258 | 259 |

And so we reach

260 | 261 |

→ The last page.

262 | -------------------------------------------------------------------------------- /page3_de.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Kursmaterial — Seite 3 5 | 6 | 7 | 8 | 9 | 10 |

Kursmaterial: Seite 3, Daten

11 | 12 |

In der Welt des Computers gibt es nur Daten. Was nicht Daten ist, 13 | ist nicht. Programme sind Daten. Programme erschaffen neue Daten. Es 14 | ist ein eigenartiger, auf Silicium basierender Kreislauf des Lebens.

15 | 16 | 17 |

Datenstrukturen

18 | 19 |

Ziel

20 | 21 |

Lerne mehrere Werte in einer Datenstruktur zu gruppieren und diese 22 | Gruppierung zu verwenden.

23 | 24 |

Aufgabe: Zeichne einen Regenbogen indem du sieben konzentrische 25 | Kreise mit den Farben red, orange, yellow, green, 26 | cyan, purple, white zeichnest, wobei jeder Kreis kleiner als der 27 | zuvor ist.

28 | 29 |

Anweisungen

30 | 31 |

Der naive Ansatz wäre:

32 | 33 |
function rainbow(x, y) {
 34 |   color("red");
 35 |   circle(x, y, 150);
 36 |   color("orange");
 37 |   circle(x, y, 145);
 38 |   color("yellow");
 39 |   circle(x, y, 140);
 40 |   color("green");
 41 |   circle(x, y, 135);
 42 |   color("cyan");
 43 |   circle(x, y, 130);
 44 |   color("purple");
 45 |   circle(x, y, 125);
 46 |   color("white");
 47 |   circle(x, y, 120);
 48 | }
49 | 50 |

Das ist nicht falsch, aber es ist auch nicht richtig. Es kommt ständig zu Wiederholungen. 51 | Hier ist eine 52 | bessere Variante:

53 | 54 |
function rainbow(x, y) {
 55 |   var colors = ["red", "orange", "yellow", "green", "cyan", "purple", "white"];
 56 |   var count = 0;
 57 |   while (count < colors.length) {
 58 |     color(colors[count]);
 59 |     circle(x, y, 150 - 5 * count);
 60 |     count = count + 1;
 61 |   }
 62 | }
63 | 64 |

Erklärung

65 | 66 |

Das Ding mit den eckigen Klammern ([ 67 | und ]) wird ein Array genannt. Ein Array ist ein 68 | Wert der andere Werte enthält - in diesem Fall enthält er sieben Strings 69 | die Farben benennen.

70 | 71 |

Die Werte in einem Array werden seine Elemente genannt. Die 72 | Elemente in einem Array sind geordnet, was bedeutet, dass jedes Element 73 | eine Position innerhalb des Arrays hat. Die Positionen in einem Array 74 | werden ab Null gezählt, so dass im Beispiel oben "red" die 75 | Position 0 hat, und "white" (das siebte Element) die 76 | Position 6. Die Schreibweise colors[1] wird benutzt um auf 77 | die Elemente in einem Array zuzugreifen — in diesem Fall wäre es 78 | "orange".

79 | 80 |

Eine weitere neue Schreibweise ist der Punkt in 81 | colors.length, auch wenn wir den bei 82 | Math.random schon gesehen haben. 83 | Er wird verwendet um auf andere Arten von Werten zuzugreifen, die 84 | Eigenschaften (properties) genannt werden. Bei 85 | Math.random wird es nur zur Gruppierung verwendet: 86 | Eine ganze Sammlung von mathematischen Funktionen sind als Eigenschaften 87 | von Math verfügbar (zum Beispiel Math.round 88 | zum Runden von Zahlen). Aber im Fall von colors.length 89 | wird auf eine Eigenschaft zugegriffen, die in direkter Verbindung zum 90 | Array colors steht: die Gesamtzahl der Elemente im Array 91 | (sieben).

92 | 93 |

Die while-Schleife läuft eines nach dem anderen über die 94 | Elemente des Arrays und verwendet dabei die Variable count 95 | um ihre Position zu speichern. Bei jedem Schritt werden die Elemente 96 | benutzt um die aktuelle Farbe zu setzen und anschließend wird ein Kreis 97 | der passenden Größe gezeichnet.

98 | 99 |

Weil diese Art von Schleife (Variable erzeugen, in der 100 | while-Bedingung prüfen, und aktualisieren) sehr häufig 101 | vorkommt, gibt es eine kompaktere Schreibweise dafür. Dieses Programm 102 | ist äquivalent zu dem Vorherigen:

103 | 104 |
function rainbow(x, y) {
105 |   var colors = ["red", "orange", "yellow", "green", "cyan", "purple", "white"];
106 |   for (var count = 0; count < colors.length; count = count + 1) {
107 |     color(colors[count]);
108 |     circle(x, y, 150 - 5 * count);
109 |   }
110 | }
111 | 112 |

In einer for-Schleife werden das Initialisieren der 113 | Variablen der Schleife, das Prüfen der Bedingung, und das Aktualisieren 114 | der Werte zusammen gruppiert, damit einfacher gesehen werden kann, dass 115 | sie gemeinsam die Schleife ausmachen.

116 | 117 |

Übung: Spiele ein bisschen mit dem Aussehen der Regenbögen. 118 | Sorge z.B. dafür, dass die Streifen etwas dicker werden.

119 | 120 | 121 |

Benannte Eigenschaften

122 | 123 |

Ziel

124 | 125 |

Lerne Objekte zu erzeugen und auf ihre Eigenschaften zuzugreifen.

126 | 127 |

Anweisungen

128 | 129 |

Öffne die Konsole wieder, falls du sie geschlossen hast.

130 | 131 |

Erzeuge eine Variable indem du folgendes in die Konsole eingibst: 132 | var myObject = {name: "Larry", score: 100};

133 | 134 |

Führe myObject.name und myObject.score aus.

135 | 136 |

Führe zudem myObject["name"] und myObject["sco" + 137 | "re"] aus.

138 | 139 |

Gib dem Objekt mit myObject.color = 140 | "purple" eine Eigenschaft hinzu. Dann führe 141 | myObject.color aus.

142 | 143 |

Verändere die score-Eigenschaft mit 144 | myObject.score = 105. Führe dann wieder myObject.score 145 | aus um sicher zu gehen, ob es geklappt hat.

146 | 147 |

Erklärung

148 | 149 |

Objekte sind ebenfalls Gruppierungen von Werten. Sie verlangen aber, 150 | dass jeder Wert einen Namen hat. Arrays sind nützlich um irgendeine 151 | Menge von Werten in einer homogenen Gruppe zu sammeln. Objekte dagegen 152 | sind besser geeignet wenn jeder Wert eine klar bestimmte Rolle in der 153 | Gruppierung spielt. Zum Beispiel ist eine Tüte Chips ein Array, aber die 154 | Teile eines Autos (Motor, Räder, etc.) bilden ein Objekt.

155 | 156 |

Die Schreibweise {property1: value1, property2: value2} 157 | wird verwendet um ein Objekt zu erzeugen. Es gibt zwei Arten um auf die 158 | Eigenschaften eines Objektes zuzugreifen. Die Art mit Punkt, 159 | object.property, wird verwendet, wenn der Name der 160 | Eigenschaft schon beim Schreiben des Programms bekannt ist. 161 | Die Art mit Klammern, object["property"], lässt zu, dass 162 | der Name der Eigenschaft als beliebiger Ausdruck angegeben wird und ist 163 | daher nützlich, wenn der Name erst noch erstellt werden muss.

164 | 165 |

Zusammen bieten Objekte und Arrays die Möglichkeit, eine große 166 | Bandbreite an Informationen darzustellen. Ein Beispiel: Eine Liste von 167 | Spielern in einem Spiel würde üblicherweise ein Array von Objekten sein, 168 | worin jedes Objekt einen Spieler repräsentiert. Falls eine Liste von 169 | Ergebnissen mit einzelnen Spielern verbunden wird, wäre diese wiederum 170 | ein Array in jedem der Spieler-Objekte. So kann man beliebig fortfahren. 171 |

172 | 173 |

Übung: Überlege dir eine JavaScript-Repräsentation 174 | eines Schachbretts. Es gibt mehrere gute Lösungen.

175 | 176 | 177 |

Wir haben Daten

178 | 179 |

Ziel

180 | 181 |

Mache eine einfache Visualisierung eines Datensatzes.

182 | 183 |

Anweisungen

184 | 185 |

In diesem Beispiel haben wir eine neue Variable, weatherData. 186 | Sie enthält ein Array mit 3 Objekten - welche Informationen zum kommenden Wetter beinhalten. 187 |

188 | 189 |

Jedes Object (stellvertretend für einen Tag) hat eine date Eigenschaft bestehend 190 | aus einem String, sowie Zahlen Werte für temperature und humidity. 191 |

192 | 193 |

Das Program zeichnet ein Balkendiagramm und stellt die Temperatur jeden Tages dar.

194 | 195 |
var width = 600, height = 400;
196 | 
197 | var weatherData = [
198 |   {
199 |     date: "2012-08-21",
200 |     temperature: 30,
201 |     humidity: 10
202 |   },
203 |   {
204 |     date: "2012-08-22",
205 |     temperature: 24,
206 |     humidity: 45
207 |   },
208 |   {
209 |     date: "2012-08-23",
210 |     temperature: 28,
211 |     humidity: 30
212 |   }
213 | ];
214 | 
215 | function barChart(x, y, barWidth) {
216 |   var gutter = 2,
217 |     xPosition = x,
218 |     yPosition = y;
219 | 
220 |   var barHeight = -1 * weatherData[0].temperature;
221 |   box(xPosition, yPosition, barWidth, barHeight);
222 | 
223 |   barHeight = -1 * weatherData[1].temperature;
224 |   xPosition = xPosition + gutter + barWidth;
225 |   box(xPosition, yPosition, barWidth, barHeight);
226 | 
227 |   barHeight = -1 * weatherData[2].temperature;
228 |   xPosition = xPosition + gutter + barWidth;
229 |   box(xPosition, yPosition, barWidth, barHeight);
230 | }
231 | 
232 | function drawing() {
233 |   color("red");
234 |   barChart(0, 0, 20);
235 | }
236 | 237 |

Du kannst es dir hier 238 | anschauen.

239 | 240 |

Erklärung

241 | 242 |

Um das Ganze ein wenig übersichtlich zu halten, wurden am Anfang erstmal die 243 | Breite und Höhe der Zeichenfläche festgelegt (600 und 400 Einheiten). 244 |

245 | 246 |

Die barChart Funktion nimmt die Position und die Breite der Balken als Parameter. 247 | Danach wird jeweils ein Balken mithilfe der box Funktion gezeichnet. 248 | Die Höhe des Balken entspricht dabei der Temperatur, daher am ersten Tag 249 | weatherData[0].temperature. 250 |

251 | 252 |

253 | Auf die gleiche Weise wird anschließend die Temperatur für den zweiten und dritten Tag dargestellt. 254 |

255 | 256 |

Übung: Jeden einzelnen Tag selber aufzurufen ist recht unflexibel. 257 | Ändere die barChart Funktion so, dass sie eine while Schleife verwendet 258 | um durch die Sammlung von Daten zu iterieren und diese automatisch zu zeichnen. 259 |

260 | 261 |

Um zu schauen ob deine Funktion so arbeitet wie du es erwartest, füge ein paar zusätzliche Tage 262 | zu dem Datensatz hinzu. Du kannst welche im Netz finden.

263 | 264 |

Und damit kommen wir…

265 | 266 |

→ …zur letzte Seite.

267 | -------------------------------------------------------------------------------- /page4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Curriculum — page 4 5 | 6 | 7 | 8 | 9 | 10 |

Outlook: a game

11 | 12 |

That's it for today! We hope you liked the workshop and you are hungry for 13 | more.

14 | 15 |

Putting together everything you learned so far and a bit more, you could 16 | do much bigger things. How about a game? At least you've earned yourself a play!

17 | 18 | 19 |

Play a game!

20 | 21 |

Goal

22 | 23 |

Just check it out and stop believing that programming an interactive game is 24 | a hard thing to do.

25 | 26 |

Instructions

27 | 28 |

Open the game.

29 | 30 |

Play the game. Think "Yeah, that would have been impressive—if 31 | this were 1970."

32 | 33 |

Read through the code and the comments.

34 | 35 |

Explanation

36 | 37 |

With some extremely trivial computations, you can produce an 38 | interactive game experience. Or some similarly engaging object, such 39 | as a simulation of something (physics, life). Isn't that cool?

40 | 41 | 42 |

Extend it

43 | 44 |

Goal

45 | 46 |

To deepen your understanding of the Invaders program, we try to 47 | customize it and add some features.

48 | 49 |

Instructions

50 | 51 |

Perform some or all of the modifications described below, and test 52 | (at every little step) whether things still work as expected.

53 | 54 |

At any time, you can reload the page (Ctrl-R / Cmd-R) to go back to 55 | the starting program. To undo just your last few changes, use the 56 | Ctrl-Z / Cmd-Z key in the editor. If at any point, you have a program 57 | that you feel you might want to return to, use the 'Save' control at 58 | the top of the page to store it. You can then recall it with the 59 | 'Load' control (note that this will overwrite your current 60 | program).

61 | 62 |

When stuck, don't sit around grinding your teeth. Ask the coaches 63 | for help early and often.

64 | 65 |

Explanation

66 | 67 |

If you have your own ideas for improvements to the game, or, for 68 | the more adventurous, for a completely different game you'd like to 69 | write—go right ahead. The ideas below are merely suggestions.

70 | 71 |

A) So, for one thing, this game is really easy. 72 | What every self-respecting arcade game does is increase difficulty 73 | over time. Add a 'level' counter that gets updated somehow in 74 | the frame function, and that influences the chance that a 75 | new invader will appear in a given turn. Display the current level 76 | somewhere on the screen using the text function.

77 | 78 |

B) Another neat feature would be to have multiple 79 | kinds of invaders. Make the newInvader function also add 80 | a type property to the invader it creates, which it 81 | randomly fills, for example like this:

82 | 83 |
function newInvader() {
 84 |   var type = "normal";
 85 |   if (Math.random() < 0.4)
 86 |     type = "super";
 87 |   else if (Math.random() < 0.2)
 88 |     type = "superduper";
 89 |   ....
 90 | }
91 | 92 |

Then update the drawInvader function to draw different 93 | types differently (for example, by simply giving them a different 94 | color), and update processBullets so that non-normal 95 | invaders have a certain chance (use Math.random again) to 96 | survive being hit by a bullet.

97 | 98 |

C) Finally, and slightly more challenging to do, 99 | you could make the invaders move back and forth horizontally during 100 | their descent.

101 | 102 |

The tricky part for this is to decide which way to move the 103 | invaders. If you want to make them zig-zag left and right 104 | synchronously, as in the original Space Invaders game, you'll have to 105 | use the same direction for all invaders. You could keep a counter 106 | variable for this that is incremented every turn, and that, when 107 | reaching some number of turns, causes the direction in which the 108 | invaders move (also a variable) to be flipped. You then also reset the 109 | counter back to zero when the flip happens, so that after another X 110 | turns it will flip the direction again.

111 | -------------------------------------------------------------------------------- /page4_de.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Kursmaterial — Seite 4 5 | 6 | 7 | 8 | 9 | 10 |

Ausblick: Ein Spiel

11 | 12 |

Das war‘s für heute! Wir hoffen der Workshop hat dir Spaß gemacht und du hast 13 | jetzt Lust auf mehr.

14 | 15 |

Wenn wir jetzt alles zusammennehmen, was wir bisher gemacht haben und noch 16 | ein bisschen was hinzufügen, kannst du Größeres schaffen. Wie wär‘s mit einem 17 | Spiel!? Zumindest hast du dir eine Runde Spielen verdient!

18 | 19 | 20 |

Spiel ein Spiel!

21 | 22 |

Ziel

23 | 24 |

Einfach ausprobieren und aufhören zu glauben, dass es irgendwie schwierig 25 | sein könnte, ein interaktives Spiel zu programmieren.

26 | 27 |

Anweisungen

28 | 29 |

Öffne das Spiel.

30 | 31 |

Spiel das Spiel. Denk dir „Ja, das wäre beeindruckend, wenn es 1970 32 | wäre“.

33 | 34 |

Lies den Code und die Kommentare.

35 | 36 |

Erklärung

37 | 38 |

Mit einigen sehr einfachen Berechnungen kannst du ein interaktives Spiel 39 | schreiben, oder auch andere spannende Dinge machen wie z.B. Simulationen von 40 | physikalischem Verhalten. Ziemlich cool, oder?

41 | 42 | 43 |

Erweitere es

44 | 45 |

Ziel

46 | 47 |

Um das Invaders-Programm besser zu verstehen, versuchen wir es jetzt zu 48 | verändern und einige Funktionen hinzuzufügen.

49 | 50 |

Anweisungen

51 | 52 |

Setze alle der folgenden Anpassungen um und teste (in kleinen Schritten), ob 53 | alles noch wie erwartet funktioniert.

54 | 55 |

Du kannst die Seite jederzeit neu laden (Strg-R / Cmd-R), um zur 56 | ursprünglichen Version des Programms zurückzukehren. Um die letzten paar 57 | Änderungen zu widerrufen, kannst du auch die Tastenkombination Ctrl-Z / Cmd-Z 58 | (undo) im Text-Editor benutzen. Wenn du einen Stand deines Programms hast, 59 | zu dem du später vielleicht zurückkehren möchtest, kannst du den „Save“-Button 60 | oben auf der Seite benutzen, um zu speichern. Mit dem „Load“-Button kannst du 61 | die Version dann wiederherstellen (Achtung, damit überschreibst du dann das 62 | aktuelle Programm).

63 | 64 |

Wenn du nicht weiterkommst, grübel nicht zu lange. Du kannst die Coaches 65 | jederzeit und immer wieder fragen und dir helfen lassen.

66 | 67 |

Erklärung

68 | 69 |

Wenn du eigene Ideen für Verbesserungen des Spiel hast oder, für die 70 | abenteuerlustigen unter euch, für ein ganz eigenes Spiel, immer drauf los! 71 | Das Folgende sind nur Vorschläge.

72 | 73 |

a) Also, das Spiel ist wirklich simpel. Wie bei jedem 74 | ernstzunehmenden Spiel-Automaten wird die Schwierigkeit mit der Zeit immer 75 | größer. Füge einen „Level“-Zähler hinzu, der in der frame-Funktion 76 | gesetzt wird und der die Wahrscheinlichkeit erhöht, dass ein Invader in einem 77 | bestimmten Spielzug erscheint. Zeige das aktuelle Level irgendwo auf dem 78 | Bildschirm an, indem du die text-Funktion benutzt.

79 | 80 |

b) Eine weitere tolle Funktion wäre es, verschiedene Arten 81 | von Invaders zu haben. Ändere die newInvader-Funktion so, dass 82 | sie einem neu erzeugten Invader eine Eigenschaft type gibt, die 83 | zufällig gesetzt wird, z.B. so:

84 | 85 |
function newInvader() {
 86 |   var type = "normal";
 87 |   if (Math.random() < 0.4)
 88 |     type = "super";
 89 |   else if (Math.random() < 0.2)
 90 |     type = "superduper";
 91 |   ....
 92 | }
93 | 94 |

Als nächstes ändere die Funktion drawInvader so, dass sie 95 | verschiedene Typen bzw. Arten auch unterschiedlich darstellt (z.B. indem sie 96 | einfach eine andere Farbe bekommen) und verändere processBullets 97 | so, dass nicht-normale Invaders mit einer bestimmten Wahrscheinlichkeit 98 | (wieder mit Math.random) einen Treffer einer Kugel überleben.

99 | 100 |

c) Abschließend noch eine etwas größere Herausforderung: 101 | Du könntest die Invaders horizontal vor- und zurückbewegen während sie 102 | herabsinken.

103 | 104 |

Der schwierige Teil hier ist zu entscheiden, in welche Richtung die Invaders 105 | bewegt werden sollen. Wenn sie sich synchron im Zickzack bewegen sollen, wie im 106 | echten Space Invaders-Spiel, musst du für alle Invaders die gleiche Richtung 107 | angeben. Dafür könntest du eine Zähler-Variable benutzen, die bei jedem Zug 108 | erhöht wird. Sobald eine bestimmte Anzahl an Zügen erreicht ist (auch in 109 | einer Variable gespeichert), muss dann die Richtung geändert werden, wobei 110 | auch die Zähler-Variable auf Null zurückgesetzt wird und dann nach weiteren X 111 | Zügen die Richtung wieder geändert wird.

112 | -------------------------------------------------------------------------------- /sandbox/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sandbox 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 61 | 62 | 63 |
64 |
65 |
66 | 67 | or press cmd/ctrl + enter 68 | 69 |
70 |
71 | 72 | 73 |
74 |
75 | 76 | -------------------------------------------------------------------------------- /sandbox/sandbox.js: -------------------------------------------------------------------------------- 1 | var mode = "javascript", wrap = null; 2 | var frame, editorDiv, frameDiv, editor; 3 | 4 | var editorSize = 50; 5 | if (window.localStorage && localStorage.hasOwnProperty("editorSize")) 6 | editorSize = Number(localStorage.editorSize); 7 | 8 | function getFile(file, c, showErr) { 9 | var xhr = new XMLHttpRequest(); 10 | xhr.open("GET", "../examples/" + file, true); 11 | xhr.onreadystatechange = function() { 12 | if (xhr.readyState == 4) { 13 | if (xhr.status == 200) c(xhr.responseText); 14 | else if (showErr) showError("Could not fetch file '" + file + "': " + xhr.statusText); 15 | } 16 | }; 17 | xhr.send(null); 18 | } 19 | 20 | function resize() { 21 | var total = document.body.clientHeight; 22 | var top = total * editorSize / 100, bottom = total - top; 23 | editorDiv.style.height = (top - 40) + "px"; 24 | editor.getScrollerElement().style.height = (editorDiv.clientHeight - 40) + "px"; 25 | frameDiv.style.height = bottom + "px"; 26 | if (frame) resizeFrame(); 27 | } 28 | 29 | function resizeFrame() { 30 | frame.style.width = frameDiv.clientWidth + "px"; 31 | frame.style.height = frameDiv.clientHeight + "px"; 32 | } 33 | 34 | window.onload = function() { 35 | editorDiv = document.getElementById("editor"); 36 | frameDiv = document.getElementById("output"); 37 | editor = CodeMirror(editorDiv, { 38 | lineNumbers: true, 39 | lineWrapping: true, 40 | mode: "null", 41 | matchBrackets: true, 42 | }); 43 | window.addEventListener("resize", resize, false); 44 | document.getElementById("controls").addEventListener("mousedown", maybeStartResize, false); 45 | resize(); 46 | 47 | loadFile(); 48 | }; 49 | 50 | function maybeStartResize(e) { 51 | if (e.target != document.getElementById("controls")) return; 52 | e.preventDefault(); 53 | var curY = e.clientY, startY = curY, startHeight = parseInt(editorDiv.style.height) + 40; 54 | if (frame) frame.style.display = "none"; 55 | function drag(e) { 56 | var dY = e.clientY - curY; 57 | if (Math.abs(dY) > 3) { 58 | curY = e.clientY; 59 | var curHeight = Math.max(45, startHeight + (startY - curY)); 60 | editorSize = Math.min(100, Math.floor(curHeight * 100 / document.body.clientHeight)); 61 | resize(); 62 | } 63 | } 64 | function done() { 65 | if (frame) frame.style.display = ""; 66 | window.removeEventListener("mousemove", drag, false); 67 | window.removeEventListener("mouseup", done, false); 68 | if (window.localStorage) localStorage.editorSize = editorSize; 69 | } 70 | window.addEventListener("mousemove", drag, false); 71 | window.addEventListener("mouseup", done, false); 72 | } 73 | 74 | function updateLoadList(filename) { 75 | if (!window.localStorage) { 76 | document.getElementById("save-load").style.display = "none"; 77 | return; 78 | } 79 | var saved = [], test = filename + "-"; 80 | for (var field in localStorage) { 81 | if (field.slice(0, test.length) == test) 82 | saved.push(field.slice(test.length)); 83 | } 84 | var load = document.getElementById("load"); 85 | var opts = ""; 86 | for (var i = 0; i < saved.length; ++i) 87 | opts += ""; 88 | load.innerHTML = opts; 89 | load.options[0].selected = true; 90 | load.disabled = saved.length == 0; 91 | } 92 | 93 | function load() { 94 | var load = document.getElementById("load"), val = load.value; 95 | if (val == "*") return; 96 | editor.setValue(localStorage[val]); 97 | } 98 | 99 | function save() { 100 | var name = document.getElementById("savename").value; 101 | var file = document.location.hash.slice(1); 102 | for (var i = 1; !name; ++i) { 103 | if (!localStorage.hasOwnProperty(file + "-" + i)) 104 | name = i; 105 | } 106 | localStorage[file + "-" + name] = editor.getValue(); 107 | updateLoadList(file); 108 | } 109 | 110 | function loadFile() { 111 | var file = document.location.hash.slice(1); 112 | document.title = "Sandbox: " + file; 113 | updateLoadList(file); 114 | var m = file.match(/^(.*)\.(\w+)$/); 115 | if (m && m[2] == "html") mode = "html"; 116 | else mode = "javascript"; 117 | 118 | document.getElementById("docname").innerText = file; 119 | 120 | getFile(file, function(txt) { 121 | editor.setOption("mode", mode == "javascript" ? mode : "text/html"); 122 | if (mode == "javascript") { 123 | var htmlfile = (m ? m[1] : file) + ".html"; 124 | var annot = txt.match(/^\/\/ use_html: (\S+)\n/); 125 | if (annot) { 126 | txt = txt.slice(annot[0].length); 127 | htmlfile = annot[1]; 128 | } 129 | editor.setValue(txt); 130 | getFile(htmlfile, function(txt) { 131 | wrap = txt; 132 | render(); 133 | }, true); 134 | } else { 135 | editor.setValue(txt); 136 | render(); 137 | } 138 | }, true); 139 | } 140 | 141 | window.addEventListener("hashchange", loadFile, false); 142 | window.addEventListener("keydown", function(event){ 143 | // ctrl and enter = render 144 | if((event.ctrlKey || event.metaKey) && event.which === 13) { 145 | event.preventDefault(); 146 | render(); 147 | } 148 | }); 149 | 150 | function showError(msg) { alert(msg); } 151 | 152 | function render() { 153 | if (frame) frame.parentNode.removeChild(frame); 154 | frame = document.createElement("iframe"); 155 | frame.src = "about:blank"; 156 | frameDiv.appendChild(frame); 157 | resizeFrame(); 158 | setTimeout(function() { 159 | var doc = frame.contentWindow.document; 160 | doc.open(); 161 | if (mode == "javascript") { 162 | doc.write(wrap + ""); 163 | } else { 164 | doc.write(editor.getValue()); 165 | } 166 | doc.close(); 167 | }, 50); 168 | } 169 | 170 | var dummy = document.createElement("div"); 171 | function htmlEsc(str) { 172 | dummy.textContent = str; 173 | return dummy.innerHTML; 174 | } 175 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0 21px; 3 | margin: 0 auto; 4 | font: 16px/2 sans-serif; 5 | color: #333; 6 | max-width: 700px; 7 | } 8 | 9 | h1, h2, h3 { 10 | color: black; 11 | padding-left: 13px; 12 | padding-right: 13px; 13 | border-bottom: 1px solid hsl(0,0%,88%); 14 | } 15 | 16 | h1 { 17 | font-size: 34pt; 18 | } 19 | h2 { 20 | font-size: 21pt; 21 | margin-top: 1.5em; 22 | } 23 | h2.step { 24 | background: url(footprint.png) no-repeat 97% 50%, hsl(205,100%,93%); 25 | } 26 | 27 | h3 { 28 | font-size: 18pt; 29 | } 30 | 31 | h3.goal { background: hsl(100,100%,93%); } 32 | h3.inst { background: hsl(35 ,95%,93%); } 33 | h3.ex { background: hsl(55 ,90%,93%); } 34 | 35 | h2.step, 36 | h3.goal, 37 | h3.inst, 38 | h3.ex { 39 | border-bottom: none; 40 | } 41 | 42 | p { 43 | margin-left: 13px; 44 | margin-right: 13px; 45 | } 46 | 47 | a { 48 | padding: 2px 5px; 49 | color: hsl(200,100%,34%); 50 | text-decoration: none; 51 | background: hsl(205,100%,95%); 52 | border-bottom: 1px solid hsl(205,100%,87%); 53 | box-shadow: 0 1px hsl(205,100%,98%); 54 | } 55 | a:hover { 56 | background: hsl(205,100%,90%); 57 | border-color: hsl(205,100%,83%); 58 | box-shadow: 0 1px hsl(205,100%,97%); 59 | } 60 | a:active { 61 | background: hsl(205,100%,85%); 62 | border-color: transparent; 63 | box-shadow: none; 64 | } 65 | 66 | div.box { 67 | margin-left: 70px; 68 | } 69 | 70 | pre { 71 | margin: 0 13px; 72 | padding: 13px 21px; 73 | font-size: 13px; 74 | line-height: 1.75; 75 | color: black; 76 | background: hsl(205,13%,98%); 77 | border: 1px solid hsl(205,13%,93%); 78 | border-radius: 3px; 79 | } 80 | 81 | code { 82 | background: hsl(205,13%,98%); 83 | border: 1px solid hsl(205,13%,93%); 84 | padding: 0.2em; 85 | font-size: 0.8em; 86 | border-radius: 3px; 87 | } --------------------------------------------------------------------------------