-
Notifications
You must be signed in to change notification settings - Fork 186
/
reference.html
474 lines (310 loc) · 16.5 KB
/
reference.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
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<base target="_top">
<title>Tangle: API Reference</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">
</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>Contents</h2>
<ul>
<li><a href="#html">HTML attributes</a></li>
<li><a href="#api">JavaScript API</a></li>
<li><a href="#classes">Tangle.classes</a></li>
<li><a href="#formats">Tangle.formats</a></li>
<li><a href="#kit">TangleKit</a></li>
</ul>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- HTML attributes -->
<p style="text-align:center; margin-top:40px;">* * *</p>
<h2 id="html">HTML attributes</h2>
<ul>
<li><a href="#class">class</a></li>
<li><a href="#data-var">data-var</a></li>
<li><a href="#data-format">data-format</a></li>
<li><a href="#data-other">other data attributes</a></li>
</ul>
<h4 id="class">class</h4>
<pre>
I want <span <b>class="TKAdjustableNumber"</b> data-var="cookies"></span> cookies.
</pre>
<p>The <code>class</code> attribute normally specifies a CSS class which gives an element a style. With Tangle, it can also specify a JavaScript class which gives an element a behavior. It might turn an element into a control that adjusts a variable, or a view that displays a variable. It is common to define a class in both CSS and Tangle, for appearance and behavior respectively.</p>
<p>A number of basic classes are included with <a href="#kit">TangleKit</a>. For details on how to create and plug in your own classes, see <a href="#classes">Tangle.classes</a>.</p>
<p>An element can have any number of classes, like so:</p>
<pre>
<span class="<b>MyClass MyOtherClass</b>" data-var="cookies">
</pre>
<p>Any of the classes can be defined in CSS, JavaScript, both, or neither. You might use one class for the visual presentation of a variable, and another to provide interactive manipulation.</p>
<h4 id="data-var">data-var</h4>
<pre>
I ate <span <b>data-var="cookies"</b>></span> cookies.
</pre>
<p>The <code>data-var</code> attribute specifies a variable. You typically use it to display the variable's value in some way, or to specify which variable a class should adjust.</p>
<p>The <code>data-var</code> attribute can go on any element. If the element has a class, the variable name will be passed to the class's <code>initialize</code> method, and the variable's value will be passed to the class's <code>update</code> method whenever it changes.</p>
<p>If none of the element's classes has an <code>update</code> method, Tangle will insert the variable's value into the element (before any existing content), and update it whenever it changes. The value will be formatted with the <code>data-format</code> attribute, if present. Tangle won't insert anything if any class has an <code>update</code> method, because it assumes that class is handling the display of the variable.</p>
<p>An element can have multiple variables, like so:</p>
<pre>
<span class="MyClass" data-var="<b>cookies tacos</b>">
</pre>
<p>All variable names will be passed to MyClass's <code>initialize</code> method, and all values will be passed to MyClass's <code>update</code> method. This is useful for two-dimensional controls that adjust two variables at once, or views that depend on multiple variables. See <a href="#classes">Tangle.classes</a> for details.</p>
<h4 id="data-format">data-format</h4>
<pre>
That cookie costs $<span data-var="cost" <b>data-format="%.2f"</b>></span>.
</pre>
<p>The variable is presented with the given format. You can specify a <a href="http://bit.ly/lwIyZR">printf</a>-style format, or define your own format functions. To use printf-style formats, you must include a sprintf library, such as the one that is provided with TangleKit. For details on defining custom formats, see <a href="#formats">Tangle.formats</a>.</p>
<p>If you specify multiple variables in the <code>data-var</code> attribute, all values will be passed to the format:</p>
<pre>
The cookies cost $<span data-var="<b>cost quantity</b>" data-format="<b>%.2f per %d</b>"></span>.
</pre>
<p>If you are using a custom format, you can pass parameters to it, separated by spaces. See <a href="#formats">Tangle.formats</a> for details.</p>
<pre>
<span data-var="cookies" data-format="<b>myFormat parameter1 parameter2</b>">
</pre>
<h4 id="data-other">other data attributes</h4>
<p>Classes may make use of other attributes with the <code>data-</code> prefix. For example, specifying the minimum and maximum values for a <code>TKAdjustableNumber</code>:
<pre>
<span class="TKAdjustableNumber" data-var="cookies" <b>data-min="0" data-max="20"</b>>
</pre>
<p>These additional attributes are passed to the class's <code>initialize</code> method, via the <a href="#options"><code>options</code></a> parameter.</p>
<p>For details on what attributes a class accepts, see the documentation for the individual class.</p>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- JavaScript API -->
<p style="text-align:center; margin-top:40px;">* * *</p>
<h2 id="api">JavaScript API</h2>
<ul>
<li><a href="#new">new Tangle (rootElement, model)</a></li>
<li><a href="#setModel">tangle.setModel(model)</a></li>
<li><a href="#getValue">tangle.getValue(variable)</a></li>
<li><a href="#setValue">tangle.setValue(variable, value)</a></li>
<li><a href="#setValues">tangle.setValues({ variable:value, variable:value })</a></li>
</ul>
<h4 id="new">new Tangle</h4>
<pre>
var tangle = <b>new Tangle</b> (rootElement, model);
</pre>
<pre>
var tangle = <b>new Tangle</b> (document.getElementById("calorieCalculator"), {
initialize: function () { this.cookies = 4; },
update: function () { this.calories = this.cookies * 50; }
});
</pre>
<p>Creates a new tangle. Tangle looks under rootElement for elements with classes or variables. Classes are initialized, and the model is set as described below.</p>
<p>You may create as many tangles as you like, with different rootElements or models. Each one keeps track of its own variables and classes. Typically you will create a tangle for each "interactive widget" in your document.</p>
<h4 id="setModel">setModel</h4>
<pre>
tangle.<b>setModel</b>(newModel);
</pre>
<pre>
tangle.<b>setModel</b>({
initialize: function () { this.cookies = 4; },
update: function () { this.calories = this.cookies * 50; }
});
</pre>
<p>This method changes and resets the current model.</p>
<p>The model should be an object with <code>initialize</code> and <code>update</code> methods. When the model is set, the <code><b>initialize</b></code> method is called to set the initial values of variables, and the <code><b>update</b></code> method is called to calculate variables derived from those. When a variable is changed subsequently via <code>tangle.setValue</code>, the <code><b>update</b></code> method will be called again to recalculate derived variables.</p>
<p>You may also define any methods that you want to use internally:</p>
<pre>
{ initialize: function () { this.cookies = 4; },
update: function () { this.calories = this.cookies * this.getCalPerCookie(); },
getCalPerCookie: function () { ... }
}
</pre>
<h4 id="getValue">getValue</h4>
<pre>
var value = tangle.<b>getValue</b>(variable);
</pre>
<pre>
var numberOfCookies = tangle.<b>getValue</b>("cookies");
</pre>
<p>Returns the current value of a variable.</p>
<h4 id="setValue">setValue</h4>
<pre>
tangle.<b>setValue</b>(variable, newValue);
</pre>
<pre>
tangle.<b>setValue</b>("cookies", 17);
</pre>
<p>Sets a new value for a variable. If the new value is different than the old one, the model is updated.</p>
<p>A variable is typically a number, but can be of any type. If you are using a reference type such as an Array, be aware that you cannot update the model by mutating the array. Instead, pass a new or copied array to <code>tangle.setValue</code>.</p>
<h4 id="setValues">setValues</h4>
<pre>
tangle.<b>setValues</b>({ variableName:value, variableName:value });
</pre>
<pre>
tangle.<b>setValues</b>({ cookies:17, cupcakes:12 });
</pre>
<p>Sets values for multiple variables at once.</p>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- Tangle.classes -->
<p style="text-align:center; margin-top:40px;">* * *</p>
<h2 id="classes">Tangle.classes</h2>
<pre>
Tangle.classes.MyClass = {
initialize: function (element, options, tangle, variable) { ... }, // optional
update: function (element, value) { ... } // optional
};
</pre>
<p>A Tangle class lets you associate some JavaScript code with an HTML element. It's typically used to define a control that adjusts a variable, or a view that displays a variable, although more creative uses are possible.</p>
<p>If your HTML contains:</p>
<pre>
<span <b>class="MyClass"</b> data-var="cookies">
</pre>
<p>then when the tangle is created, MyClass will be instantiated for that element, and if there is an <code><b>initialize</b></code> method, it will be called, and passed the name of the variable. If there is an <code><b>update</b></code> method, it will be called when the specified variable is initialized or changed, and passed the value of the variable.</p>
<h4>initialize</h4>
<p>The <code><b>initialize</b></code> method is a good place to add event listeners to the element, to set up an interactive control. The following example implements a control that increments the variable when it is clicked.</p>
<pre>
Tangle.classes.ClickableNumber = {
<b>initialize</b>: function (element, options, tangle, variable) {
element.onclick = function () {
var value = tangle.getValue(variable);
tangle.setValue(variable, value + 1);
};
}
};
</pre>
<p>The <code>options</code> parameter is described below.</p>
<h4>update</h4>
<p>The <code><b>update</b></code> method is for updating the element's appearance or contents when the variable changes. The following example resizes the element's width when the variable changes, perhaps for a bar in a bar chart.</p>
<pre>
Tangle.classes.StretchyBar = {
<b>update</b>: function (element, value) {
element.style.width = "" + value + "px";
}
};
</pre>
<h4>other methods</h4>
<p>You may also define any methods that you want to use internally.</p>
<pre>
Tangle.classes.StretchyBar = {
update: function (element, value) {
var width = value * this.getStretchiness();
element.style.width = "" + width + "px";
},
getStretchiness: function () {
...
}
};
</pre>
<h4>CSS</h4>
<p>Because these are CSS classes as well as Tangle classes, you can often specify the element's style in a CSS file, and only deal with behavior in JavaScript.</p>
<pre>
.ClickableNumber {
color: #46f;
border-bottom: 1px dashed #46f;
cursor: pointer;
}
</pre>
<h4>framework classes</h4>
<p>If <code>Tangle.classes.MyClass</code> is a function instead of an object, Tangle will call it as a constructor, instead of directly invoking an <code>initialize</code> method. So, if you're using a framework such as MooTools that has its own notion of what a "class" is, you can use its classes directly, and take advantage of inheritance and other features.</p>
<pre>
Tangle.classes.MyClass = new Class({ // assuming we're using MooTools
Extends: MyBaseClass,
initialize: function (element, options, tangle, variable) {
this.parent(element, options, tangle, variable);
...
}
});
</pre>
<h4>multiple variables</h4>
<p>An HTML element can specify any number of variables, and they will all be passed to <code><b>initialize</b></code> and <code><b>update</b></code>. For example, if your class expects two variables:</p>
<pre>
<span class="MyClass" <b>data-var="cookies cupcakes"</b>>
</pre>
<p>you would define it like so:</p>
<pre>
Tangle.classes.MyClass = {
initialize: function (element, options, tangle, <b>variable1, variable2</b>) { ... },
update: function (element, <b>value1, value2</b>) { ... }
};
</pre>
<p>This is useful for two-dimensional controls that adjust two variables at once, or views that display multiple variables.</p>
<h4 id="options">options</h4>
<p>The <code>initialize</code> method is passed an <code><b>options</b></code> parameter:</p>
<pre>
Tangle.classes.MyClass = {
initialize: function (element, <b>options</b>, tangle, variable) { ... }
};
</pre>
<p>The <code>options</code> parameter is an object containing the <code>data-</code> attributes of the elements. (The "<code>data-</code>" prefix is removed.) If your HTML is:</p>
<pre>
<span class="MyClass" <b>data-min="1" data-max="10"</b>>
</pre>
<p>then <code>options</code> will be an object like so:</p>
<pre>
{ min:"1", max:"10" }
</pre>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- Tangle.formats -->
<p style="text-align:center; margin-top:40px;">* * *</p>
<h2 id="formats">Tangle.formats</h2>
<pre>
Tangle.formats.myFormat = function (value) { return "..."; }
</pre>
<p>A Tangle format defines how to present a value. If your HTML is:</p>
<pre>
<span data-var="fractionOfCookiesRemaining" <b>data-format="percent"</b>>
</pre>
<p>then when the variable is updated, the following function will be called to turn the value into a string.</p>
<pre>
Tangle.formats.percent = function (value) { // formats 0.42 as "42%"
return "" + Math.round(value * 100) + "%";
};
</pre>
<p>You can often use <a href="http://bit.ly/lwIyZR">printf</a>-style formats instead, but <code>Tangle.formats</code> is available for your custom formatting needs. To use printf-style formats, you must include a sprintf library, such as the one that is provided with TangleKit.</p>
<h4>multiple variables</h4>
<p>If the <code>data-var</code> attribute specifies multiple variables, all values will be passed to the function.</p>
<pre>
<span data-var="<b>cookies cupcakes</b>" data-format="myFormat">
</pre>
<pre>
Tangle.formats.myFormat = function (value1, value2) { return "..."; }
</pre>
<h4>parameters</h4>
<p>You can specify parameters in the <code>data-format</code> attribute, separated by spaces. These strings will be passed to the function, after the variable values.</p>
<pre>
<span data-var="cookies" data-format="<b>myFormat huge</b>">
</pre>
<pre>
Tangle.formats.myFormat = function (value, size) { return "..."; }
</pre>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- TangleKit -->
<p style="text-align:center; margin-top:40px;">* * *</p>
<h2 id="kit">TangleKit</h2>
<p>TangleKit is an optional collection of Tangle classes and formats, for adjusting variables and visualizing values. You can grab whichever components you want, use them, extend them, modify them, or just learn from them and make your own.</p>
<p>TangleKit is currently pretty rudimentary, and not yet documented here. You can look through <a href="TangleKit/TangleKit.js">TangleKit.js</a> for what's currently available. Perhaps you'd even like to contribute to it.</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>