-
Notifications
You must be signed in to change notification settings - Fork 186
/
guide.html
369 lines (254 loc) · 14.4 KB
/
guide.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<base target="_top">
<title>Tangle: Getting Started</title>
<link href='http://fonts.googleapis.com/css?family=Lato' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="Fonts/Insolent/stylesheet.css" type="text/css">
<link rel="stylesheet" href="Fonts/BorisBlackBloxx/stylesheet.css" type="text/css">
<link rel="stylesheet" href="style.css" type="text/css">
<!-- Tangle -->
<script type="text/javascript" src="Tangle.js"></script>
<!-- TangleKit -->
<link rel="stylesheet" href="TangleKit/TangleKit.css" type="text/css">
<script type="text/javascript" src="TangleKit/mootools.js"></script>
<script type="text/javascript" src="TangleKit/sprintf.js"></script>
<script type="text/javascript" src="TangleKit/BVTouchable.js"></script>
<script type="text/javascript" src="TangleKit/TangleKit.js"></script>
<!-- examples -->
<script type="text/javascript" src="Examples/CookieExample.js"></script>
</head>
<body>
<div id="everything">
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- header -->
<div id="header">
<h1><a href="./">tangle</a></h1>
<h3>explorable explanations made easy</h3>
<div class="menu">
<a href="guide.html">Getting Started</a>
<a href="reference.html">API Reference</a>
<a href="download.html">Download</a>
<a href="https://groups.google.com/group/tangle-talk/topics">Discuss</a>
</div>
</div> <!-- header -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- body -->
<div id="body" class="small">
<h2>Getting Started</h2>
<p>Tangle lets you write documents that change.</p>
<p>Let's say you're writing an article about dieting, and want to discuss the calorie content of various foods. You might write the following.</p>
<div class="example">
<div class="exampleTop"></div>
<div class="exampleCenter">
<p>When you eat 3 cookies, you consume <b>150 calories</b>. That's 7% of your recommended daily calories.</p>
</div>
<div class="exampleBottom"></div>
</div>
<p>That's a true statement, but it only applies directly to those few readers who eat 3 cookies a day. Most of your readers eat more or less. What if the reader could adjust the statement to see information about their own situation? What if readers could explore alternative scenarios as well?</p>
<div id="cookieExample" class="example">
<div class="exampleTop"></div>
<div class="exampleCenter">
<p>When you eat <span data-var="cookies" class="TKAdjustableNumber" data-min="2" data-max="100"> cookies</span>, you consume <b data-var="calories"> calories</b>. That's <span data-var="dailyPercent" data-format="%.0f">%</span> of your recommended daily calories.</p>
</div>
<div class="exampleBottom"></div>
</div>
<p>Let's see how to write this example.</p>
<h2>Variables</h2>
<p>We start by identifying the <strong>variables</strong> — those parts of the statement that need to change. In this case, there are three varying numbers in the statement, so we need three variables.</p>
<div class="example">
<div class="exampleTop"></div>
<div class="exampleCenter">
<p>When you eat <strong>3 cookies</strong>, you consume <strong>150 calories</strong>. That's <strong>7%</strong> of your recommended daily calories.</p>
</div>
<div class="exampleBottom"></div>
</div>
<p>We'll call these variables <strong>cookies</strong>, <strong>calories</strong>, and <strong>dailyPercent</strong> respectively.</p>
<h2>HTML</h2>
<p>Now, let's look at the HTML for the statement.</p>
<pre>
<p>When you eat 3 cookies, you consume <b>150 calories</b>.
That's 7% of your recommended daily calories.</p>
</pre>
<h6>data-var</h6>
<p>Let's start with the "150 calories" part. Notice that it's inside <code><b></code> tags, to make it bold. We'll make two simple changes:</p>
<pre>
<p>When you eat 3 cookies, you consume <b <strong>data-var="calories"</strong>> calories</b>.
That's 7% of your recommended daily calories.</p>
</pre>
<p>First, we added the <code><b>data-var="calories"</b></code> attribute to the <b> tag. This tells Tangle to insert the value of the "calories" variable inside the tag. So, if the calories variable were 500, it would appear as "500 calories".</p>
<p>Second, we removed the "150" from inside the tag, because Tangle is going to insert the correct number itself.</p>
<h6>span</h6>
<p>Now, let's look at the "7%" part. It's not inside a tag, so we need to put it inside one. The <code><span></code> tag is typically used for this purpose. Unlike <code><b></code>, it has no intrinsic meaning of its own — it's simply a generic container that we can attach style and variable information to.</p>
<pre>
<p>When you eat 3 cookies, you consume <b data-var="calories"> calories</b>.
That's <strong><span data-var="dailyPercent"></strong>%<strong></span></strong> of your recommended daily calories.</p>
</pre>
<p>Tangle will insert the value of the "dailyPercent" variable at the start of the span.</p>
<h6>class</h6>
<p>Now, we'll look at the "3 cookies" part. This part isn't just dynamic — it's interactive. We want the reader to be able to adjust the variable by dragging on the number. For this, we use a class. A Tangle class can describe how the reader interacts with an HTML element, or how a variable should be displayed.</p>
<p>We'll use the class "<code>TKAdjustableNumber</code>", which comes with TangleKit. (The "TK" prefix refers to "TangleKit".) TangleKit is a collection of basic classes for you to use. Once you start tangling more heavily, you might want to start making your own classes.</p>
<pre>
<p>When you eat <strong><span class="TKAdjustableNumber" data-var="cookies"></strong> cookies<strong></span></strong>,
you consume <b data-var="calories"> calories</b>. That's
<span data-var="dailyPercent">%</span> of your recommended daily calories.</p>
</pre>
<h6>id</h6>
<p>Finally, we need to make sure that we're able to find this statement from JavaScript. The easiest way to do so is to add an <code>id</code> attribute to the tag that contains it. In this case, our statement is inside a <p> paragraph tag, and we can name it like so:</p>
<pre>
<p <strong>id="calorieCalculator"</strong>>
When you eat <span class="TKAdjustableNumber" data-var="cookies"> cookies</span>,
you consume <b data-var="calories"> calories</b>. That's
<span data-var="dailyPercent">%</span> of your recommended daily calories.</p>
</pre>
<p>That's all we need to do with the HTML. Next, we'll tell Tangle how to calculate those variables.</p>
<h2>JavaScript</h2>
<p>In JavaScript, we need to "create a tangle" for all of the HTML elements and variables involved in this particular statement. We do so with <code><b>new Tangle</b></code>, like so:</p>
<pre>
var tangle = new Tangle(rootElement, model);
</pre>
<p>But first, we need the <code>rootElement</code> and the <code>model</code>.</p>
<h6>rootElement</h6>
<p>The <code>rootElement</code> refers to the element that contains our statement. In this case, we put an <code>id</code> attribute on the surrounding paragraph, so we can find it easily:</p>
<pre>
var rootElement = document.getElementById("calorieCalculator");
</pre>
<h6>model</h6>
<p>The <code>model</code> tells Tangle how to initialize and update the variables. It has this form:</p>
<pre>
var model = {
initialize: function () { ... },
update: function () { ... }
};
</pre>
<p>The <code>initialize</code> method runs when the tangle is first created. This is where you set the initial values of independent variables. We want the statement initially to read, "When you eat 3 cookies...", so we need the <code>cookies</code> variable to start at 3.</p>
<pre>
var model = {
initialize: function () {
<strong>this.cookies = 3;</strong>
},
update: function () { ... }
};
</pre>
<p>The <code>update</code> method runs whenever a variable changes. This is where you describe how to calculate "derived variables" — variables that depend on others. The <code>calories</code> variable can be calculated from <code>cookies</code>:
<pre>
var model = {
initialize: function () {
this.cookies = 3;
},
update: function () {
<strong>this.calories = this.cookies * 50;</strong>
}
};
</pre>
<p>and the <code>dailyPercent</code> variable can be calculated from <code>calories</code>.</p>
<pre>
var model = {
initialize: function () {
this.cookies = 3;
},
update: function () {
this.calories = this.cookies * 50;
<strong>this.dailyPercent = 100 * this.calories / 2100;</strong>
}
};
</pre>
<p>This works fine, but it's a little hard to read. Someone perusing this code might not immediately understand what the "50" and "2100" are all about. Let's give them more descriptive names.</p>
<pre>
var model = {
initialize: function () {
this.cookies = 3;
<strong>this.caloriesPerCookie = 50;</strong>
<strong>this.dailyCalories = 2100;</strong>
},
update: function () {
this.calories = this.cookies * <strong>this.caloriesPerCookie</strong>;
this.dailyPercent = 100 * this.calories / <strong>this.dailyCalories</strong>;
}
};
</pre>
<p>The code is now much easier to follow. And later, if we want <code>caloriesPerCookie</code> or <code>dailyCalories</code> to be adjustable, we can do so directly in the HTML, without touching the JavaScript.</p>
<h6>new Tangle</h6>
<p>We can now create the tangle. Instead of writing out the <code>rootElement</code> and <code>model</code> separately, we typically just define them inline, like so:</p>
<pre>
var tangle = new Tangle (document.getElementById("calorieCalculator"), {
initialize: function () {
this.cookies = 3;
this.caloriesPerCookie = 50;
this.dailyCalories = 2100;
},
update: function () {
this.calories = this.cookies * this.caloriesPerCookie;
this.dailyPercent = 100 * this.calories / this.dailyCalories;
}
});
</pre>
<p>That's all there is to the JavaScript.</p>
<h2>Formats and Classes</h2>
<p>We're almost done. But when we try it out, we get this:</p>
<div id="cookieExample2" class="example">
<div class="exampleTop"></div>
<div class="exampleCenter">
<p>When you eat <span data-var="cookies" class="TKAdjustableNumber" data-min="2" data-max="100"> cookies</span>, you consume <b data-var="calories"> calories</b>. That's <span data-var="dailyPercent">%</span> of your recommended daily calories.</p>
</div>
<div class="exampleBottom"></div>
</div>
<p>Our <code>dailyPercent</code> is perhaps a little more precise than necessary. To tell Tangle how to properly display that variable, we can specify a format.</p>
<h6>Formats</h6>
<p>In the HTML, we add a <code><b>data-format</b></code> attribute:</p>
<pre>
That's <span data-var="dailyPercent" <strong>data-format="%.0f"</strong>>%</span>
of your recommended daily calories.
</pre>
<p><code>%.0f</code> is known as a <a href="http://bit.ly/lwIyZR">printf</a>-style format, which is a standard language for describing how numbers should be printed. Here, we specified that we wanted to round off the number, with no digits after the decimal point.</p>
<p>It's possible to create your own format functions and use those as well, but in this case, the printf format works fine.</p>
<div id="cookieExample3" class="example">
<div class="exampleTop"></div>
<div class="exampleCenter">
<p>When you eat <span data-var="cookies" class="TKAdjustableNumber" data-min="2" data-max="100"> cookies</span>, you consume <b data-var="calories"> calories</b>. That's <span data-var="dailyPercent" data-format="%.0f">%</span> of your recommended daily calories.</p>
</div>
<div class="exampleBottom"></div>
</div>
<h6>Classes</h6>
<p>Currently, we can adjust the <code>cookies</code> variable by dragging it, thanks to the <code>TKAdjustableNumber</code> class that we specified:</p>
<pre>
<span data-var="cookies" class="<b>TKAdjustableNumber</b>">
</pre>
<p>Perhaps you don't like dragging, and would rather let your readers type in a number instead. We can simply switch the class to <code>TKNumberField</code>:</p>
<pre>
<span data-var="cookies" class="<strong>TKNumberField</strong>">
</pre>
<p>And our statement becomes:</p>
<div id="cookieExample4" class="example">
<div class="exampleTop"></div>
<div class="exampleCenter">
<p>When you eat <span data-var="cookies" class="TKNumberField" data-size="3"> cookies</span>, you consume <b data-var="calories"> calories</b>. That's <span data-var="dailyPercent" data-format="%.0f">%</span> of your recommended daily calories.</p>
</div>
<div class="exampleBottom"></div>
</div>
<p>TangleKit contains a growing selection of classes, and you can define your own classes easily.</p>
<h2>Possibilities</h2>
<p>We just worked through a very simple example, to give you a taste of what you can tangle. But there's much more you can do.</p>
<ul class="dotted">
<li>Create rich data visualizations, such as charts and graphs, using Tangle classes.</li>
<li>Create dynamic data displays, such as stock tickers and weather reports, using Tangle to maintain a clean separation between back-end data and front-end views.</li>
<li>Pass around strings, arrays, and other objects in variables, for more data-heavy applications.</li>
<li>Create controls and views that use multiple variables at once.</li>
</ul>
<p>You might want to look over the <a href="reference.html">API reference</a>, or just <a href="download.html">download Tangle</a> and dive right in.</p>
</div> <!-- body -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- footer -->
<div id="footer">
<div id="footerShadow"></div>
<div class="author"><a href="http://worrydream.com/">Bret Victor</a></div>
<div class="menu">
<a href="guide.html">Getting Started</a>
<a href="reference.html">API Reference</a>
<a href="download.html">Download</a>
<a href="https://groups.google.com/group/tangle-talk/topics">Discuss</a>
</div>
</div> <!-- footer -->
</div> <!-- everything -->
</body></html>