-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
748 lines (633 loc) · 23.9 KB
/
index.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
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Serious JavaScript Presentation</title>
<meta name="description" content="A presentation on why JavaScript is great, and how you can write great JavaScript">
<meta name="author" content="Ian Truslove">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="reveal.js/css/reveal.min.css">
<link rel="stylesheet" href="reveal.js/css/theme/sky.css" id="theme">
<!--<link rel="stylesheet" href="reveal.js/css/theme/night.css" id="theme">-->
<!--<link rel="stylesheet" href="reveal.js/css/theme/default.css" id="theme">-->
<!-- For syntax highlighting -->
<link rel="stylesheet" href="reveal.js/lib/css/zenburn.css">
<link rel="stylesheet" href="css/overrides.css">
<!-- If the query includes 'print-pdf', use the PDF print sheet -->
<script>
document.write( '<link rel="stylesheet" href="reveal.js/css/print/' + ( window.location.search.match( /print-pdf/gi ) ? 'pdf' : 'paper' ) + '.css" type="text/css" media="print">' );
</script>
<!--[if lt IE 9]>
<script src="reveal.js/lib/js/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div class="reveal">
<!-- Any section element inside of this container is displayed as a slide -->
<div class="slides">
<section>
<h1>Serious Javascript</h1>
<h3>why JavaScript is great, & how you
can write great JavaScript </h3>
<p>
<small>Ian Truslove / <a href="mailto:ian.truslove@nsidc.org">ian.truslove@nsidc.org</a> / <a href="http://twitter.com/iantruslove">@iantruslove</a></small>
</p>
<p>
<small>UCAR Software Engineering Assembly, 1 April 2013</small>
</p>
</section>
<section>
<h2>Intro</h2>
<ul>
<li class="fragment">Audience</li>
<li class="fragment">Goals</li>
</ul>
</section>
<section>
<h2>Outline</h2>
<ol>
<li>Language Overview</li>
<li>Client-side JS</li>
<li>Server-side JS</li>
<li>Software Engineering</li>
</ol>
</section>
<section>
<h2>1. Overview of JavaScript</h2>
<div class="fragment">
<img src="images/pearl-oyster.jpg" width="460" height="276" alt="pearl oyster"/>
<small>Image credit: http://static.guim.co.uk/sys-images/Lifeandhealth/Pix/pictures/2008/11/05/oyster1.jpg</small>
</div>
</section>
<section>
<h3>A Quick Tour of the Dark Lands...</h3>
</section>
<section>
<h4>Wat?</h4>
<object width="560" height="315">
<param name="movie" value="http://www.youtube.com/v/kXEgk1Hdze0&start=80"></param>
<param name="allowFullScreen" value="true"></param>
<param name="allowscriptaccess" value="always"></param>
<embed src="http://www.youtube.com/v/kXEgk1Hdze0&start=80" type="application/x-shockwave-flash" width="560" height="315" allowscriptaccess="always" allowfullscreen="true"></embed>
</object>
<small>Link: <a href="http://www.youtube.com/v/kXEgk1Hdze0&start=80">http://www.youtube.com/v/kXEgk1Hdze0</a></small>
</section>
<section>
<h3>The Beautiful Parts</h3>
<ul>
<li class="fragment">First class functions</li>
<li class="fragment">Lexical scope and function closures</li>
<li class="fragment">Lambdas</li>
<li class="fragment">Functional arrays and objects</li>
<li class="fragment">(proper tail calls?)</li>
</ul>
</section>
<section>
<h3>The Strong Parts</h3>
<ul>
<li class="fragment">Tools for implementing language features</li>
<ul>
<li class="fragment"><i>Stronger for composition than inheritance</i></li>
</ul>
<li class="fragment">Widely-deployed platform</li>
<ul>
<li class="fragment"><i>(basically any web browser)</i></li>
</ul>
</ul>
</section>
<section>
<h3>The Unexpected Parts</h3>
<ul>
<li class="fragment">Scheme-like language with Java-like syntax</li>
<li class="fragment">Prototypal inheritance</li>
<ul>
<li class="fragment">Using specialized instances as the
basis for generalization</li>
</ul>
</ul>
</section>
<section>
<h3>Essential Reading</h3>
<img src="images/crockford-book.jpg" />
<p>Douglas Crockford - <i>JavaScript: The Good Parts</i></p>
<p>Thin book, lots of ideas. Disagree with it once you have
studied it.</p>
<small>Image credit: http://www.webdesignersreviewofbooks.com/images/69.jpg</small>
</section>
<section>
<h3>Example</h3>
<pre><code contenteditable>
// Write some 2d array operations
// to process things like this:
var testData = [
[0.1, 0.2, 0.2, 0.2, 0.1],
[0.1, 0.2, 0.3, 0.2, 0.1],
[0.1, 0.3, 0.4, 0.3, 0.1],
[0.1, 0.2, 0.3, 0.2, 0.1],
[0.1, 0.2, 0.2, 0.2, 0.1] ];
</code></pre>
</section>
<section>
<h4>Program by intent:</h4>
<pre><code contenteditable>
var testData = [
[0.1, 0.2, 0.2, 0.2, 0.1],
[0.1, 0.2, 0.3, 0.2, 0.1],
[0.1, 0.3, 0.4, 0.3, 0.1],
[0.1, 0.2, 0.3, 0.2, 0.1],
[0.1, 0.2, 0.2, 0.2, 0.1] ];
// What's the max value in the array?
ops2d.max(testData);
> 0.4
</code></pre>
</section>
<section>
<h4>Encapsulation with object literals</h4>
<pre><code contenteditable>
var ops2d = {
max: function (data) {
var max = ... // calculate max
return max;
}
}
</code></pre>
</section>
<section>
<h4>Array methods</h4>
<pre><code contenteditable>
var ops2d = {
max: function (data) {
// using ES5 Array.map
var maxOfEachRow = data.map(maxInRow);
return maxInRow(maxOfEachRow);
}
}
</code></pre>
</section>
<section>
<h4>Extract and encapsulate</h4>
<pre><code contenteditable>
var ops1d = {
max: function (row) { // i.e. maxInRow
// Using ES5 Array.reduce
return row.reduce(
function (acc, current) {
return Math.max(acc, current);
});
}
};
var ops2d = {
max: function (data) {
// Local var was flattened
return ops1d.max(data.map(ops1d.max));
}
};
</code></pre>
</section>
<section>
<h4>Done</h4>
<pre><code contenteditable>
// Try it...
var testData = [
[0.1, 0.2, 0.2, 0.2, 0.1],
[0.1, 0.2, 0.3, 0.2, 0.1],
[0.1, 0.3, 0.4, 0.3, 0.1],
[0.1, 0.2, 0.3, 0.2, 0.1],
[0.1, 0.2, 0.2, 0.2, 0.1] ];
ops1d.max(testData[0]);
> 0.2
ops2d.max(testData);
> 0.4
</code></pre>
</section>
<section>
<h4>Another example</h4>
<pre><code contenteditable>
// How about scaling the whole data array?
ops2d.scale(testData, 2);
> [ [0.2, 0.4, 0.4, 0.4, 0.2], /* etc ... */ ]
</code></pre>
</section>
<section>
<h4>First level of implementation</h4>
<pre><code contenteditable>
var ops2d = {
scale: function (data, scale) {
return data.map(
function (row) {
return row.map(
function (datum) {
return datum * scale;
});
});
}
};
</code></pre>
</section>
<section>
<h4>Extract and clean up</h4>
<pre><code contenteditable>
var ops1d = {
scale: function (row, scale) {
return row.map(
function (datum) { return datum*scale; }
);
}
};
var ops2d = {
scale: function (data, scale) {
return data.map(
function (row) { return ops1d.scale(row, scale); }
);
}
};
ops2d.scale(testData, 2);
> [ [0.2, 0.4, 0.4, 0.4, 0.2], /* ... */ ]
</code></pre>
</section>
<section>
<h4>Generalize</h4>
<pre><code contenteditable>
// Note assignment to the object by key:
ops2d.map = function (data, fn) {
return data.map(
function (row) { return row.map(fn); }
);
};
ops2d.map(testData, function (datum) { return datum*2 });
> [ [0.2, 0.4, 0.4, 0.4, 0.2], /* ... */ ]
</code></pre>
</section>
<section>
<h4>Generalize further</h4>
<pre><code contenteditable>
ops2d.map = function (data, fn) {
return data.map(
function (row) { return row.map(fn); }
);
};
var scaler = function(scale, datum) {
return scale*datum;
};
// Wouldn't it be nice if...
ops2d.map(testData, scaler.curry(2));
</code></pre>
</section>
<section>
<h4>Adding a curry function to Functions</h4>
<pre><code contenteditable>
// `prototype` is the mechanism for inheritance
Function.prototype.curry = function (firstArg) {
var fn = this;
return (function(x) {
return fn(firstArg, x);
});
};
(scaler.curry(2))(3);
> 6
</code></pre>
</section>
<section>
<h4>Composability!</h4>
<pre><code contenteditable>
// A new transformation:
var threshold = function(min, datum) {
return Math.max(min, datum);
};
ops2d.map(testData, threshold.curry(0.2));
> [ [0.2, 0.2, 0.2, 0.2, 0.2],
[0.2, 0.2, 0.3, 0.2, 0.2],
[0.2, 0.3, 0.4, 0.3, 0.2], /* etc ... */
</code></pre>
</section>
<section>
<h2>2. Standardization</h2>
<img src="images/committee.jpg" height="456px" width="495px" alt="Committee meeting" />
<small>
Image credit: http://untreaty.un.org/cod/avl/images/ha/udhr/photo%20gallery/03-large.jpg
</small>
<small>
References for this section: http://en.wikipedia.org/wiki/ECMAScript
</small>
</section>
<section>
<h3>
ECMAScript 3
</h3>
<p class="fragment">Dec 1999</p>
<p class="fragment">The JavaScript everyone knows</p>
</section>
<section>
<h3>
ECMAScript 4
</h3>
<p class="fragment">n/a - abandoned</p>
<p class="fragment">Contained classes, a module system,
optional type annotations and static typing (probably using a structural type system),
generators and iterators, destructuring assignment, and algebraic data types</p>
</section>
<section>
<h3>
ECMAScript 5
</h3>
<p class="fragment">Dec 2009</p>
<p class="fragment">Incremental improvements over ES3</p>
<p class="fragment">Strict mode, object getters and setters, <code>seal</code> and <code>freeze</code> methods,
new array methods incuding <code>indexOf</code>, <code>map</code>, <code>reduce</code>, <code>filter</code>
</p>
</section>
<section>
<h3>
Harmony (ECMAScript 6?)
</h3>
<p class="fragment">tbd</p>
<p class="fragment">Scaled-down version of ES4</p>
</section>
<section>
<h3>
Harmony (possible features)
</h3>
<ul>
<li><code>let</code>, <code>const</code>, and <code>function</code> definitions in block scope</li>
<li>destructuring:
<pre><code contenteditable>let {x, y} = point;
</code></pre></li>
<li>modules</li>
<li>classes</li>
<li>proxies (multiple inheritance)</li>
<li>binary data types</li>
<li>maps, sets, weak maps</li>
<li>default parameter values in functions</li>
<li><code>rest</code>, <code>spread</code> - ellipsis args in function param lists</li>
</ul>
</p>
</section>
<section>
<h3>
Harmony (possible features)
</h3>
<ul>
<li>iterators, generators, array comprehensions</li>
<li>arrow function syntax (c.f. CoffeeScript):<br/>
<pre><code contenteditable>let identity = (x) => x
</code></pre></li>
<li>Clean lambda syntax:</br>
<pre><code contenteditable>[1, 2, 3].map(x => x*x);
</code></pre></li>
<li>Deferreds and promises</li>
<li>Proper tail calls</li>
</ul>
</p>
</section>
<section>
<h2>3. Front End Development</h2>
<img src="images/geocities.png" />
<small>Image credit: http://img.gawkerassets.com/post/4/2013/02/geocities2.png</small>
</section>
<section>
<h3>Challenges for Front End Development</h3>
<ul>
<li class="fragment">Browser inconsistency</li>
<ul class="fragment">
<li>High variability of platform capabilities</li>
<li>High variability between feature
implementation on browsers (IE is particularly bad)</li>
</ul>
<li class="fragment">Code management</li>
<ul>
<li class="fragment">Egregiously poor engineering, e.g.
copy-paste code, google coding...</li>
<li class="fragment">Callback spaghetti</li>
<li class="fragment">Poor organization</li>
</ul>
<li class="fragment">Performance</li>
<ul class="fragment">
<li>Poor implementations</li>
<li>80/20</li>
</ul>
</section>
<section>
<h3>JS Browser Support</h3>
<img src="images/voodoo.jpg" />
<small>Image credit: http://www.37days.com/images/various/voodoo_1000x625.jpg</small>
</section>
<section>
<h3>JS Browser Support</h3>
<p>
<ul>
<li>ES5: <span class="fragment">~ IE9+, FFX4+, Chrome7+, Safari 5.1+</span></li>
<li>ES6: <span class="fragment"><40% in FFX 17</span></li>
</ul>
</p>
<p>
<small>Source: http://kangax.github.com/es5-compat-table/, http://kangax.github.com/es5-compat-table/es6/</small>
</p>
</section>
<section>
<h3>Browser Support</h3>
<ul>
<li class="fragment">No simple answer</li>
<li class="fragment">Compatibility tables</li>
<ul class="fragment">
<li>Kangax's <a href="http://kangax.github.com/es5-compat-table/">ES5</a> and <a href="http://kangax.github.com/es5-compat-table/es6/">ES6</a> tables</li>
<li><a href="http://www.quirksmode.org/compatibility.html">QuirksMode.org</a></li>
</ul>
<li class="fragment">Cross-platform libraries</li>
<ul class="fragment">
<li>jQuery, Prototype, etc.</li>
</ul>
<li class="fragment">Shims, polyfills, fallbacks</li>
<ul class="fragment">
<li>List of <a href="https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills">HTML5 Cross Browser Polyfills</a></li>
<li><a href="http://modernizr.com/">Modernizr</a></li>
</ul>
</ul>
</section>
<section>
<h3>Code Management</h3>
<img src="images/stefanov-book.jpg" />
<p>Stoyan Stefanov - <i>JavaScript Patterns</i></p>
<p>Covers the basics, through to patterns that are
ubiquitous in JS library code.</p>
<small>Image credit: http://www.i-newswire.com/Uploads/64855_2_2.jpg</small>
</section>
<section>
<h3>Performance</h3>
<img src="images/souders-book.jpg" />
<p>Steve Souders - <i>High Performance Web Sites</i></p>
<p>Covers web app performance holistically. Essential for any front
end developer.</p>
<small>Image credit:
http://blog.monitor.us/wp-content/uploads/2012/08/high-performance-web-sites.jpg</small>
</section>
<section>
<h3>Performance</h3>
<img src="images/zakas-book.jpg" />
<p>Nick Zakas - <i>High Performance JavaScript</i></p>
<p>Lots of JavaScript performance knowledge, tips, and tricks.</p>
<small>Image credit: http://d.gr-assets.com/books/1328834985l/7008656.jpg</small>
</section>
<section>
<h2>4. Server-Side JavaScript</h2>
</section>
<section>
<h3>Implementations & Characteristics</h3>
<p class="fragment"><a href="http://nodejs.org/">Node.js</a> - native C++ implementation, based on Google V8 engine. Includes <code>npm</code> package manager.</p>
<p class="fragment"><a href="https://developer.mozilla.org/en-US/docs/Rhino">Rhino</a>
- Java implementation of a JS engine, from Mozilla. Used
interactively, or embedded to add JS scripting into Java
apps.</p>
<p class="fragment"><a href="http://www.envjs.com/">Envjs</a>
- JS implementation of a browser's JS functionality.
Uses Rhino, support exists for other back ends. Primarily
used for headless testing.</p>
<p class="fragment"><a href="http://phantomjs.org/">PhantomJS</a>
- native headless webkit browser with JS API and REPL. Used for testing, scriptable browser.</p>
<p class="fragment"><a href="https://trac.webkit.org/wiki/JSC">JSC</a>
- JS parts of WebKit. REPL or command line runtime</p>
</section>
<section>
<h3>Node.js Overview</h3>
<ul>
<li class="fragment">Event-based, non-blocking
programming model</li>
<li class="fragment">Fast, efficient, especially for
<strong>distributed systems</strong></li>
<li class="fragment">Offers possibility of code reuse
across server and client</li>
<li class="fragment">Excellent package management system (<code>npm</code>)
and ecosystem</li>
</ul>
</section>
<section>
<h3>Node's Canonical Example: a Web Server</h3>
<div class="fragment">
<pre><code>
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8080, '127.0.0.1');
console.log('Server running at http://127.0.0.1:8080/');
</code></pre>
<small>source: http://nodejs.org</small>
</div>
</section>
<section>
<h3>Node Package Manager</h3>
<ul>
<li class="fragment">> 26,000 packages</li>
<ul class="fragment">
<li>Web frameworks and tools</li>
<li>Database connectivity</li>
<li>Functional libraries</li>
</ul>
<li class="fragment">Highly active community</li>
<li class="fragment">Good command-line tool</li>
</ul>
</section>
<section>
<h2>5. Engineering Practices</h2>
</section>
<section>
<h3>Modules</h3>
<ul>
<li class="fragment">Code patterns</li>
<li class="fragment">Script loaders</li>
<li class="fragment"><a href="http://www.commonjs.org/">CommonJS</a>,
<a href="https://github.com/amdjs/amdjs-api/wiki/AMD">AMD</a>,
<a href="https://github.com/umdjs/umd">UMD</a></li>
<li class="fragment">ES6</li>
</ul>
</section>
<section>
<h3>Tools</h3>
<ul>
<li class="fragment">Build: <a href="http://gruntjs.com/">Grunt</a></li>
<li class="fragment">Compile: <a href="http://jshint.com/">JSHint</a></li>
<li class="fragment">Project/Scaffold: <a href="http://yeoman.io/">Yeoman</a></li>
<li class="fragment">Test:
<a href="http://pivotal.github.com/jasmine/">Jasmine</a>,
<a href="http://sinonjs.org/">Sinon</a></li>
<li class="fragment">"Better JavaScript":
<a href="http://coffeescript.org/">CoffeeScript</a></li>
</ul>
</section>
<!-- TODO: links -->
<section>
<h3>(a few) Libraries</h3>
<ul>
<li class="fragment">Front-end "MVC" libraries:</li>
<ul>
<li class="fragment"><a href="http://angularjs.org/">Angular</a>,
<a href="http://knockoutjs.com/">Knockout</a>,
<a href="http://emberjs.com/">Ember</a>,
<a href="http://backbonejs.org/">Backbone</a>
</li>
</ul>
<li class="fragment">Helper libraries</li>
<ul>
<li class="fragment">
<a href="http://underscorejs.org/">Underscore</a>,
<a href="http://lodash.com/">Lo-Dash</a></li>
<li class="fragment">
<a href="http://jquery.com/">jQuery</a>,
<a href="http://zeptojs.com/">Zepto</a></li>
<li class="fragment">
<a href="http://modernizr.com/">Modernizr</a>,
<a href="http://requirejs.org/">Require</a></li>
</ul>
</ul>
</section>
<section>
<h2>Questions</h2>
<p> </p>
<blockquote>any application that can be written in JavaScript, will
eventually be written in JavaScript</blockquote>
<p> </p>
<small>"Atwood's Law",
http://www.codinghorror.com/blog/2007/07/the-principle-of-least-power.html</small>
<p> </p>
<small>This presentation:
http://iantruslove.github.com/serious-javascript-presentation</small>
<p> </p>
</section>
</div>
</div>
<script src="reveal.js/lib/js/head.min.js"></script>
<script src="reveal.js/js/reveal.min.js"></script>
<script>
// Full list of configuration options available here:
// https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: true,
theme: Reveal.getQueryHash().theme, // available themes are in /css/theme
transition: Reveal.getQueryHash().transition || 'none', // default/cube/page/concave/zoom/linear/fade/none
// Optional libraries used to extend on reveal.js
dependencies: [
{ src: 'reveal.js/lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: 'reveal.js/plugin/markdown/showdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'reveal.js/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'reveal.js/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
{ src: 'reveal.js/plugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } },
{ src: 'reveal.js/plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } }
// { src: 'reveal.js/plugin/remotes/remotes.js', async: true, condition: function() { return !!document.body.classList; } }
]
});
</script>
<script>
var _gaq=[['_setAccount','UA-37965473-2'],['_trackPageview']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>
<!-- controldeck.js -->
<script src="/socket.io/socket.io.js"></script>
<script src="/controldeck-slides.js"></script>
</body>
</html>