├── footprint.png ├── lib ├── README └── codemirror2 │ ├── LICENSE │ ├── mode │ ├── htmlmixed │ │ └── htmlmixed.js │ ├── css │ │ └── css.js │ ├── xml │ │ └── xml.js │ └── javascript │ │ └── javascript.js │ └── lib │ └── codemirror.css ├── README.md ├── fonts.googleapis.com ├── fdtF30xa_Erw0zAzOoG4BVVaXhodyZpwkPyKEugoMLo.woff2 ├── yvITAdr5D1nlsdFswJAb8Vos2Pdf-dQN4tJmHAEs2hQ.woff2 └── css-family=Averia+Serif+Libre:300,400 ├── examples ├── drawing.html ├── data.html ├── interact.html ├── rainbow.js ├── basic.html ├── basic_de.html ├── transform.js ├── drawing_loop.js ├── drawing_if.js ├── drawing.js ├── drawing_function.js ├── drawing_loop_de.js ├── drawing_if_de.js ├── drawing_de.js ├── life_expectancy.js ├── drawing_function_de.js ├── drawing_animate.js ├── life_expectancy_de.js ├── weather_report_visualization.js ├── weather_report_average.js ├── drawing_tree.js ├── event_code.js ├── drawing_animate_de.js ├── drawing_tree_de.js ├── weather_report.js ├── drawing_code.js ├── invaders.js └── invaders_de.js ├── style.css ├── sandbox ├── index.html └── sandbox.js ├── index.html ├── index_de.html ├── page4.html ├── page4_de.html ├── page1.html ├── page3.html ├── page3_de.html ├── page1_de.html ├── page2.html └── page2_de.html /footprint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenTechSchool/js-beginners-1/HEAD/footprint.png -------------------------------------------------------------------------------- /lib/README: -------------------------------------------------------------------------------- 1 | Do a 2 | 3 | git clone http://marijnhaverbeke.nl/git/codemirror2 4 | 5 | in this directory to fetch the dependency. 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /fonts.googleapis.com/fdtF30xa_Erw0zAzOoG4BVVaXhodyZpwkPyKEugoMLo.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenTechSchool/js-beginners-1/HEAD/fonts.googleapis.com/fdtF30xa_Erw0zAzOoG4BVVaXhodyZpwkPyKEugoMLo.woff2 -------------------------------------------------------------------------------- /fonts.googleapis.com/yvITAdr5D1nlsdFswJAb8Vos2Pdf-dQN4tJmHAEs2hQ.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenTechSchool/js-beginners-1/HEAD/fonts.googleapis.com/yvITAdr5D1nlsdFswJAb8Vos2Pdf-dQN4tJmHAEs2hQ.woff2 -------------------------------------------------------------------------------- /examples/drawing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/basic_de.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |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/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 | -------------------------------------------------------------------------------- /lib/codemirror2/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2012 by Marijn HaverbekeThe 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 |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 |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 |See what a step looks like.
57 |Read this text carefully.
59 |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 |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 |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 |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 |Abgesehen von einem Browser brauchst Du keine weitere Software. 36 | Wir werden unsere JavaScript-Programme direkt im Browser schreiben und 37 | ausprobieren.
38 | 39 |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 |Sehen wie ein Schritt aussieht.
58 |Lies diesen Text aufmerksam.
60 |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 |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 |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 |Just check it out and stop believing that programming an interactive game is 24 | a hard thing to do.
25 | 26 |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 |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 |To deepen your understanding of the Invaders program, we try to 47 | customize it and add some features.
48 | 49 |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 |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.
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:
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.
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 |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 |Einfach ausprobieren und aufhören zu glauben, dass es irgendwie schwierig 25 | sein könnte, ein interaktives Spiel zu programmieren.
26 | 27 |Ö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 |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 |Um das Invaders-Programm besser zu verstehen, versuchen wir es jetzt zu 48 | verändern und einige Funktionen hinzuzufügen.
49 | 50 |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 |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.
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:
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.
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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /page1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |We'll learn to use the browser's JavaScript console, and do some 13 | fundamental programming.
14 | 15 | 16 |Access your browser's JavaScript console.
21 | 22 |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 Tools ▸ Developer Tools.
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 |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 |Actually type in some JavaScript, and see it run.
57 | 58 |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.
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].
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.
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.
Understand the most basic elements that programs are composed of.
98 | 99 |Combine the two programs from the previous step: alert(1 + 1).
Enter 1 + 1 * 10 and then (1 + 1) * 10.
104 | Note the different results.
Enter "hey" + "ho".
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.
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.
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.
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.
Understand how to store values and refer to them by name. 141 | Understand what statements are.
142 | 143 |Enter the following lines at the console:
146 | 147 |var myvalue = 32 * 32; 148 | alert(myvalue); 149 | myvalue = 10; 150 | alert(myvalue);151 | 152 |
The above program introduces three new concepts: the semicolons,
155 | the use of var, and the = operator.
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.
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.
See how JavaScript programs operate in the context of web 178 | pages.
179 | 180 |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 |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.
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.
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.
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.
Things are about to get a lot more interactive.
231 | 232 |→ Continue with the second page.
233 | -------------------------------------------------------------------------------- /page3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |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 |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 |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 | 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".
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).
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.
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:
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.
Exercise: Play with the look of the rainbows. E.g. make the 111 | stripes a bit bigger.
112 | 113 | 114 |Learn how to create objects, and access their properties.
119 | 120 |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};
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.
Next, enter myObject["name"] into the console, and then
133 | myObject["sco" + "re"].
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.
Change the score property by entering
140 | myObject.score = 105. Then check that you successfully changed the
141 | value by entering myObject.score.
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.
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 |Perform a simple visualization of a dataset.
175 | 176 |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.
Each object (representing a day) has a date
183 | property containing a string, and temperature
184 | and humidity properties that contain numbers.
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 |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
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.
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 |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 |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 |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 | 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".
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).
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.
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:
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.
Ü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 |Lerne Objekte zu erzeugen und auf ihre Eigenschaften zuzugreifen.
126 | 127 |Ö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};
Führe myObject.name und myObject.score aus.
Führe zudem myObject["name"] und myObject["sco" +
137 | "re"] aus.
Gib dem Objekt mit myObject.color =
140 | "purple" eine Eigenschaft hinzu. Dann führe
141 | myObject.color aus.
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.
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.
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 |Mache eine einfache Visualisierung eines Datensatzes.
182 | 183 |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 |
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 |
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 |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 |
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 |
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 |Wir lernen wie man die JavaScript-Konsole des Browsers verwendet 13 | und ein paar grundlegende Dinge programmiert.
14 | 15 | 16 |Die JavaScript-Konsole Deines Browsers verwenden.
21 | 22 |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 Tools ▸ Entwicklertools auswählen.
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 |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 |Etwas JavaScript eintippen und sehen was es tut.
59 | 60 |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.
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.
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ß.
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.
Verstehen, was das Grundelement ist, aus dem Programme bestehen.
105 | 106 |Kombiniere die beiden Programme aus dem vorigen Schritt: alert(1 + 1).
Gib 1 + 1 * 10 in die Konsole ein und dann (1 + 1) * 10.
111 | Sieh Dir die unterschiedlichen Ergebnisse an.
Schreibe "hey" + "ho".
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.
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.
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.
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.
Verstehen wie man Werte speichert und sie beim Namen nennt. 151 | Verstehen was Anweisungen sind.
152 | 153 |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 |
Das obige Programm führt zwei neue Konzepte ein: Semikolons und
165 | die Verwendung von var.
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.
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.
Sehen wie JavaScript-Programme sich im Kontext von Webseiten 191 | verhalten.
192 | 193 |Ö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 |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.
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.
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.
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.
Wir sind kurz davor alles viel interaktiver werden zu lassen.
249 | 250 |→ Weiter geht's mit der nächsten Seite.
251 | -------------------------------------------------------------------------------- /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 |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 |Get acquainted with our visual programming environment.
22 | 23 |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.
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.
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.
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.
Open this link
73 | to get a drawing function containing this program:
color("red");
76 | var column = 0;
77 | while (column < 20) {
78 | circle(column * 10, 0, 4);
79 | column = column + 1;
80 | }
81 |
82 | 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.
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.
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).
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.
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 |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 |Here is the program that, when put inside the drawing
147 | function, does what we want, and is
148 | available here:
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 | 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.
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.
The else part can be left off to indicate that nothing
178 | at all should happen when the condition does not hold.
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.
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 |This is the smiley function:
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:
function drawing() {
220 | smiley(0, 0);
221 | smiley(-100, 20);
222 | smiley(100, 50);
223 | }
224 |
225 | 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.
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.
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.
Write some kind of entertaining graphical program yourself.
258 | 259 |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.
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.
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.
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 |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 |Mache Dich mit unserer visuellen Programmierumgebung vertraut.
24 | 25 |Ö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.
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.
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.
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.
Öffne diesen Link,
83 | um zu einer drawing-Funktion mit folgendem Programm zu
84 | gelangen:
color("red");
87 | var column = 0;
88 | while (column < 20) {
89 | circle(column * 10, 0, 4);
90 | column = column + 1;
91 | }
92 |
93 | 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.
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.
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).
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).
Ü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 |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 |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:
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 | 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.
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.
Der else-Teil kann auch weggelassen werden, um
204 | anzuzeigen, dass gar nichts passieren soll, wenn die Bedingung
205 | nicht gilt.
Ü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.
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 |Hier ist die smiley-Funktion:
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:
function drawing() {
249 | smiley(0, 0);
250 | smiley(-100, 20);
251 | smiley(100, 50);
252 | }
253 |
254 | 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.
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.
Ü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!
Erfinde Dein eigenes, unterhaltsames, grafisches Programm.
292 | 293 |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.
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.
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.
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 |