added procrank
[android-command-line.git] / index.html
1 <!DOCTYPE html> 
2 <!--
3   Copyright 2010 Google Inc.
4  
5   Licensed under the Apache License, Version 2.0 (the "License");
6   you may not use this file except in compliance with the License.
7   You may obtain a copy of the License at
8  
9      http://www.apache.org/licenses/LICENSE-2.0
10  
11   Unless required by applicable law or agreed to in writing, software
12   distributed under the License is distributed on an "AS IS" BASIS,
13   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   See the License for the specific language governing permissions and
15   limitations under the License.
16  
17   Original slides: Marcin Wichary (mwichary@google.com)
18   Modifications: Ernest Delgado (ernestd@google.com)
19                  Alex Russell (slightlyoff@chromium.org)
20                  Brad Neuberg
21 --> 
22 <html manifest="cache.manifest"> 
23   <head> 
24     <!--[if gte IE 9]>
25       <meta http-equiv="X-UA-Compatible" content="IE=edge" />
26     <![endif]--> 
27     
28     <!--[if lt IE 9]>
29       <meta http-equiv="X-UA-Compatible" content="IE=edge;chrome=1" />
30     <![endif]--> 
31  
32     <meta charset="utf-8" /> 
33     <title>Dobrica Pavlinušić: Android from source in command-line</title> 
34     <link href="http://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans+Mono" rel="stylesheet" type="text/css" /> 
35  
36     <style>      
37       body {
38         font: 20px "Lucida Grande", "Trebuchet MS", Verdana, sans-serif;
39         padding: 0;
40         margin: 0;
41         width: 100%;
42         height: 100%;
43         position: absolute;
44         left: 0px; top: 0px;
45       }
46       
47       .presentation {
48         position: absolute;
49         height: 100%;
50         width: 100%;
51         left: 0px;
52         top: 0px;
53         display: block;
54         overflow: hidden;
55         background: #778;
56       }
57       
58       .slides {
59         width: 100%;
60         height: 100%;
61         left: 0;
62         top: 0;
63         position: absolute;
64         display: block;
65         -webkit-transition: -webkit-transform 1s ease-in-out;
66         -moz-transition: -moz-transform 1s ease-in-out;
67         -o-transition: -o-transform 1s ease-in-out;
68         transition: transform 1s ease-in-out;
69         
70         /* so it's visible in the iframe. */
71         -webkit-transform: scale(0.8);
72         -moz-transform: scale(0.8);
73         -o-transform: scale(0.8);
74         transform: scale(0.8);
75         
76       }
77       
78       .slide {
79         display: none;
80         position: absolute;
81         overflow: hidden;
82         width: 900px;
83         height: 700px;
84         left: 50%;
85         top: 50%;
86         margin-top: -350px;
87         background-color: #eee;
88         background: -webkit-gradient(linear, left bottom, left top, from(#bbd), to(#fff));
89         background: -moz-linear-gradient(bottom, #bbd, #fff);
90         background: linear-gradient(bottom, #bbd, #fff);
91         -webkit-transition: all 0.25s ease-in-out;
92         -moz-transition: all 0.25s ease-in-out;
93         -o-transition: all 0.25s ease-in-out;
94         transition: all 0.25s ease-in-out;
95         -webkit-transform: scale(1);
96         -moz-transform: scale(1);
97         -o-transform: scale(1);
98         transform: scale(1);
99       }
100       
101       .slide:nth-child(even) {
102         -moz-border-radius: 20px 0;
103         -khtml-border-radius: 20px 0;
104         border-radius: 20px 0; /* includes Opera 10.5+ */
105         -webkit-border-top-left-radius: 20px;
106         -webkit-border-bottom-right-radius: 20px;
107       }
108       
109       .slide:nth-child(odd) {
110         -moz-border-radius: 0 20px;
111         -khtml-border-radius: 0 20px;
112         border-radius: 0 20px;
113         -webkit-border-top-right-radius: 20px;
114         -webkit-border-bottom-left-radius: 20px;
115       }
116  
117       .slide p, .slide textarea {
118         font-size: 120%;
119       }
120  
121       .slide .counter {
122         color: #999999;
123         position: absolute;
124         left: 20px;
125         bottom: 20px;
126         display: block;
127         font-size: 70%;
128       }
129  
130       .slide.title > .counter,
131       .slide.segue > .counter,
132       .slide.mainTitle > .counter {
133         display: none;
134       }
135  
136       .force-render {
137         display: block;
138         visibility: hidden;
139       }
140       
141       .slide.far-past {
142         display: block;
143         margin-left: -2400px;
144       }
145       
146       .slide.past {
147         visibility: visible;
148         display: block;
149         margin-left: -1400px;
150       }
151       
152       .slide.current {
153         visibility: visible;
154         display: block;
155         margin-left: -450px;
156       }
157       
158       .slide.future {
159         visibility: visible;
160         display: block;
161         margin-left: 500px;
162       }
163       
164       .slide.far-future {
165         display: block;
166         margin-left: 1500px;
167       }
168       
169       body.three-d div.slides {
170         -webkit-transform: translateX(50px) scale(0.8) rotateY(10deg);
171         -moz-transform: translateX(50px) scale(0.8) rotateY(10deg);
172         -o-transform: translateX(50px) scale(0.8) rotateY(10deg);
173         transform: translateX(50px) scale(0.8) rotateY(10deg);
174       }
175       
176       /* Content */
177       
178       @font-face { font-family: 'Junction'; src: url(src/Junction02.otf); }
179       @font-face { font-family: 'LeagueGothic'; src: url(src/LeagueGothic.otf); }
180       
181       header {
182         font-family: 'Droid Sans';
183         font-weight: normal;
184         letter-spacing: -.05em;
185         text-shadow: rgba(0, 0, 0, 0.2) 0 2px 5px;
186         left: 30px;
187         top: 25px;
188         margin: 0;
189         padding: 0;
190         font-size: 140%;
191       }
192       
193       h1 {
194         font-size: 140%;
195         display: inline;
196         font-weight: normal;
197         padding: 0;
198         margin: 0;
199       }
200       
201       h2 {
202         font-family: 'Droid Sans';
203         color: black;
204         font-size: 120%;
205         padding: 0;
206         margin: 20px 0;
207       }
208             
209       h2:first-child {
210         margin-top: 0;
211       }
212  
213       section, footer {
214         font-family: 'Droid Sans';
215         color: #3f3f3f;
216         text-shadow: rgba(0, 0, 0, 0.2) 0 2px 5px;
217         margin: 100px 30px 0;
218         display: block;
219         overflow: hidden;
220       }
221       
222       footer {
223         font-size: 100%;
224         margin: 20px 0 0 30px;
225       }
226  
227       a {
228         color: inherit;
229         display: inline-block;
230         text-decoration: none;
231         line-height: 110%;
232         border-bottom: 2px solid #3f3f3f;
233       }
234  
235       ul {
236         margin: 0;
237         padding: 0;
238       }
239  
240       button {
241         font-size: 100%;
242       }
243       
244       pre button {
245         margin: 2px;
246       }
247       
248       section.left {
249         float: left;
250         width: 390px;
251       }
252       
253       section.small {
254         font-size: 24px;
255       }
256       
257       section.small ul {
258         margin: 0 0 0 15px;
259         padding: 0;
260       }
261       
262       section.small li {
263         padding-bottom: 0;
264       }
265             
266       section.middle {
267         line-height: 2em;
268         text-align: center;
269         display: table-cell;
270         vertical-align: middle;
271         height: 700px;
272         width: 900px;
273       }
274       
275       pre {
276         text-align: left;
277         font-family: 'Droid Sans Mono', Courier;
278         font-size: 80%;
279         padding: 10px 20px;
280         background: rgba(255, 0, 0, 0.05);
281         -webkit-border-radius: 8px;
282         -khtml-border-radius: 8px;
283         -moz-border-radius: 8px;
284         border-radius: 8px;
285         border: 1px solid rgba(255, 0, 0, 0.2);
286       }
287       
288       pre select {
289         font-family: Monaco, Courier;
290         border: 1px solid #c61800;
291       }
292         
293       input {
294         font-size: 100%;
295         margin-right: 10px;
296         font-family: Helvetica;
297         padding: 3px;
298       }
299       input[type="range"] {
300         width: 100%;
301       }
302       
303       button {
304         margin: 20px 10px 0 0;
305         font-family: Verdana;
306       }
307       
308       button.large {
309         font-size: 32px;
310       }
311         
312       pre b {
313         font-weight: normal;
314         color: #c61800;
315         text-shadow: #c61800 0 0 1px;
316         /*letter-spacing: -1px;*/
317       }
318       pre em {
319         font-weight: normal;
320         font-style: normal;
321         color: #18a600;
322         text-shadow: #18a600 0 0 1px;
323       }
324       pre input[type="range"] {
325         height: 6px;
326         cursor: pointer;
327         width: auto;
328       }
329       
330       div.example {
331         display: block;
332         padding: 10px 20px;
333         color: black;
334         background: rgba(255, 255, 255, 0.4);
335         -webkit-border-radius: 8px;
336         -khtml-border-radius: 8px;
337         -moz-border-radius: 8px;
338         border-radius: 8px;
339         margin-bottom: 10px;
340         border: 1px solid rgba(0, 0, 0, 0.2);
341       }
342       
343       video {
344         -moz-border-radius: 8px;
345         -khtml-border-radius: 8px;
346         -webkit-border-radius: 8px;
347         border-radius: 8px;
348         border: 1px solid rgba(0, 0, 0, 0.2);
349       }
350       
351       .key {
352         font-family: 'Droid Sans';
353         color: black;
354         display: inline-block;
355         padding: 6px 10px 3px 10px;
356         font-size: 100%;
357         line-height: 30px;
358         text-shadow: none;
359         letter-spacing: 0;
360         bottom: 10px;
361         position: relative;
362         -moz-border-radius: 10px;
363         -khtml-border-radius: 10px;
364         -webkit-border-radius: 10px;
365         border-radius: 10px;
366         background: white;
367         box-shadow: rgba(0, 0, 0, 0.1) 0 2px 5px;
368         -webkit-box-shadow: rgba(0, 0, 0, 0.1) 0 2px 5px;
369         -moz-box-shadow: rgba(0, 0, 0, 0.1) 0 2px 5px;
370         -o-box-shadow: rgba(0, 0, 0, 0.1) 0 2px 5px;
371       }
372       
373       .key { font-family: Arial; }
374       
375       :not(header) > .key {
376         margin: 0 5px;
377         bottom: 4px;
378       }
379  
380       .two-column {
381         -webkit-column-count: 2;
382         -moz-column-count: 2;
383         column-count: 2;
384       }
385  
386       .stroke {
387         -webkit-text-stroke-color: red;
388         -webkit-text-stroke-width: 1px;
389       } /* currently webkit-only */
390       
391       .center {
392         text-align: center;
393       }
394       
395       #presentation-counter {
396         color: #ccc;
397         font-size: 70%;
398         letter-spacing: 1px;
399         position: absolute;
400         top: 40%;
401         left: 0;
402         width: 100%;
403         text-align: center;
404       }
405       
406       div:not(.current).reduced {
407         -webkit-transform: scale(0.8);
408         -moz-transform: scale(0.8);
409         -o-transform: scale(0.8);
410         transform: scale(0.8);
411       } 
412       
413       .no-transitions {
414         -webkit-transition: none;
415         -moz-transition: none;
416         -o-transition: none;
417         transition: none;
418       }
419  
420       .no-gradients {
421         background: none;
422         background-color: #fff;
423       }
424       
425       ul.bulleted {
426         padding-left: 30px;
427       }
428       
429     </style> 
430     
431   </head> 
432   <body> 
433     <div class="presentation"> 
434       <div id="presentation-counter"></div> 
435       <div class="slides"> 
436
437 <!--
438
439 Android
440 from
441 source
442 in
443 command-line
444
445 Android vs iPhone
446 TOC
447
448 Compile own ROM
449 CyanogenMod
450 Binary blobs from phone using adb pull
451 Android-x86
452 Downloads somewhat working (EeePC 701)
453 USB networking broken
454 http://github.com/dpavlin/android-adb-usb-tether
455
456 Debug from command-line
457 Do we need FLOSS app market?
458
459 -->
460
461         <div class="slide"> 
462           <section class="middle"> 
463             <h2>Android from source in command-line</h2>
464                         <img src="android-fastboot.png">
465                         <p>
466                                 Dobrica Pavlinušić
467                                 <br><a href="http://blog.rot13.org">http://blog.rot13.org/</a>
468                         </p>
469           </section> 
470         </div>
471
472         <div class="slide"> 
473           <section> 
474             <header> 
475               <h1>TOC</h1> 
476             </header> 
477               <h2>Compile Android from source code</h2> 
478               <h2>Command-line usage</h2> 
479               <h2>/system/bin</h2> 
480               <h2>Do we need FLOSS app market?</h2> 
481           </section> 
482         </div> 
483
484 <!--
485                 <div class="slide"> 
486                         <section class="middle"> 
487                                 <h2></h2> 
488                         </section> 
489                 </div>
490 -->
491                 <div class="slide"> 
492                         <section>
493                         <header>
494                         <h1>Compile Android from source</h1> 
495                         </header>
496
497                         <h2>Why is source important?</h2>
498                         <p>
499                         Lookup how is something implemented
500                         - <a href="http://github.com/dpavlin/android-adb-usb-tether">and find out why usb networking doesn't work for Google apps</a>
501                         </p>
502                         <p>Lastest Android released on abandoned hardware (Froyo on G1)</p>
503
504                         <h2>Ability to install your own ROM</h2>
505                         <p>
506                         severly udermined by attempts to provide full signature security from hardware to userspace
507                         </p>
508                         <p>
509                                 SPL
510                                 <span class="key">&gt;</span>
511                                 recovery
512                                 <span class="key">&gt;</span>
513                                 system
514                         </p>
515                         
516                         <h2>Porting to other devices</h2>
517                 </div>
518
519                 <div class="slide"> 
520                         <section>
521
522                         <header>
523                         <h1>Compile Android from source</h1> 
524                         </header>
525
526                         <h2>CyanogenMod</h2>
527
528             <ul class="bulleted"> 
529                                 <li>only for <b>rooted</b> phones (targets developers)
530                                 <li>binary blobs from phone using <tt>adb pull</tt></li>
531                                 <li><a href="http://wiki.cyanogenmod.com/index.php?title=Compile_CyanogenMod_for_Dream_%26_Sapphire">compile for your phone</a></li>
532 <pre>
533 dpavlin@android:/srv/cyanogen$ <b>. build/envsetup.sh</b>
534 dpavlin@android:/srv/cyanogen$ <b>lunch</b>
535 dpavlin@android:/srv/cyanogen$ <b>make -j8</b>
536 </pre>
537                                 <li>fastboot or sdcard <tt>update.zip</tt> flashing
538                                 <li><a href="http://github.com/CyanogenMod/android_vendor_cyanogen/blob/froyo/CHANGELOG.mkdn">additional features</a> on top of Google release
539             </ul>
540                         </section>
541         </div>
542
543                 <div class="slide"> 
544                         <section>
545
546                         <header>
547                         <h1>Compile Android from source</h1> 
548                         </header>
549
550                         <h2>Android-x86</h2>
551
552             <ul class="bulleted"> 
553                                 <li>Latest release <a href="http://android-x86.googlecode.com/files/android-x86-1.6-r2.iso">1.6r2</a> works on EeePC 701, VrtualBox and kvm</li>
554                                 <li><a href="http://www.android-x86.org/getsourcecode">compile source</a></li>
555                                 <li>Froyo (2.2) and Eclair (2.1) in various stages of <em>working</em>
556                                 <li>networking in kvm: boot in <b>debug</b> mode and in first prompt load network module:
557 <pre>
558 # <b>modprobe 8139cp</b>
559 </pre>
560                                 <li>add <tt>vga=788</tt> to kernel line in <tt>grub</tt> to make kvm happy
561             </ul>
562                         </section>
563         </div>
564
565
566
567                 <div class="slide"> 
568                         <section>
569                         <header>
570                         <h1>adb</h1> 
571                         </header>
572                         <h2>shell</h2>
573 <pre>
574 dpavlin@x200:/virtual/android$ <b>adb shell</b>
575 # <b>uname -a</b>
576 Linux localhost 2.6.35.4-cyanogenmod #57 PREEMPT Fri Sep 10 00:11:46 UTC 2010 armv6l GNU/Linux
577 </pre>
578
579                         <h2>logcat</h2>
580                         <p>Everything your Android is storing into log, <b>multiple buffers!</b></p>
581 <pre>
582 dpavlin@x200:/virtual/android$ <b>adb logcat -b events</b>
583 </pre>
584
585                         <h2>multiple devices</h2>
586 <pre>
587 dpavlin@x200:~$ <b>export ANDROID_SERIAL=127.0.0.1:5555</b>
588 </pre>
589
590                         </section>
591         </div>
592
593
594         <div class="slide"> 
595           <section class="middle"> 
596             <h1>Android userland</h1>
597                         <h2>/system/bin</h2>
598                         <a href="http://github.com/dpavlin/android-command-line">http://github.com/dpavlin/android-command-line</a>
599           </section> 
600         </div>
601
602
603                 <div class="slide"> 
604                         <section>
605                         <header>
606                         <h1>Dump debugging informations</h1> 
607                         </header>
608                         <h2>dumpstate</h2>
609                         <p>Big and verbose state of your device</p>
610 <pre>
611 dpavlin@x200:~$ <b>adb shell dumpstate > dumpstate.txt</b>
612 </pre>
613
614
615                         <h2>dumpsys</h2>
616                         <p>Who is listening to those intents?</p>
617 <pre>
618 dpavlin@x200:~$ <b>adb shell dumpsys > dumpsys.txt
619 </pre>
620
621                         </section>
622         </div>
623
624                 <div class="slide"> 
625                         <section>
626                         <header>
627                         <h1>service</h1> 
628                         </header>
629                         <h2>Make phone calls from command line</h2>
630 <pre>
631 # <b>service call phone 2 s16 "+31611530555"</b>
632 </pre>
633
634                         <p>
635                         Where did <b>2</b> came from?
636                         <a href="http://www.androidjavadoc.com/1.0_r1_src/constant-values.html#com.android">com.android.internal.telephony.ITelephony.Stub</a>
637                         </p>
638
639                         <h2>Rotate screen in emulator</h2>
640 <pre>
641 $ <b>service call window 18 i32 1</b> # landscape
642 $ <b>service call window 18 i32 0</b> # portrait
643 </pre>
644
645                         </section>
646         </div>
647
648                 <div class="slide"> 
649                         <section>
650                         <header>
651                         <h1>am</h1> 
652                         </header>
653                         <h2>Browser</h2>
654 <pre>
655 # <b>am start -a android.intent.action.MAIN -n com.android.browser/.BrowserActivity</b>
656 </pre>
657
658                         <h2>Settings</h2>
659 <pre>
660 # <b>am start -a android.intent.action.MAIN -n com.android.settings/.Settings</b>
661 </pre>
662                         </section>
663                         </section>
664         </div>
665
666                 <div class="slide"> 
667                         <section>
668                         <header>
669                         <h1>pm</h1> 
670                         </header>
671
672 <p>
673 Install application from phone to other device
674 </p>
675
676 <pre>
677 dpavlin@x200:~$ <b>adb shell pm list packages | grep replica</b>
678 package:com.replica.replicaisland
679 dpavlin@x200:~$ <b>adb shell pm path com.replica.replicaisland</b>
680 package:/mnt/asec/com.replica.replicaisland-1/pkg.apk
681 dpavlin@x200:~$ <b>adb pull /mnt/asec/com.replica.replicaisland-1/pkg.apk</b>
682 1373 KB/s (5144485 bytes in 3.658s)
683 dpavlin@x200:~$ <b>ANDROID_SERIAL=192.168.1.32:5555 adb install pkg.apk</b>
684 779 KB/s (5144485 bytes in 6.446s)
685         pkg: /data/local/tmp/pkg.apk
686 Success
687 </pre>
688                         </section>
689         </div>
690
691                 <div class="slide"> 
692                         <section>
693                         <header>
694                         <h1>procrank</h1> 
695                         </header>
696
697                         <p>show memory usage</p>
698 <pre>
699 # <b>procrank</b>
700   PID      Vss      Rss      Pss      Uss  cmdline
701   142   37328K   27332K   16926K   15472K  system_server
702   218   17568K   17564K    7469K    6228K  com.android.phone
703   220   16040K   16040K    5694K    4380K  org.zeam.core
704  1783   18276K   15880K    5308K    3836K  com.android.term
705   298   15172K   15164K    4905K    3636K  com.android.mms
706  1693   14860K   14860K    4200K    2724K  com.android.music
707   441   13260K   13260K    3752K    2616K  com.als.usagetimelines
708   209   13052K   13052K    3329K    2188K  com.access_company.graffiti
709  1700   13300K   13300K    3242K    1904K  android.process.media
710   107   11860K   11860K    2118K     900K  zygote
711   108     768K     768K     342K     300K  /system/bin/mediaserver
712  1826     488K     484K     296K     280K  procrank
713 </pre>
714
715                         </section>
716         </div>
717
718
719                 <div class="slide"> 
720                         <section>
721                         <header>
722                         <h1>Do we need FLOSS app market?</h1> 
723                         </header>
724 <p>
725 <a href="http://lwn.net/Articles/373128/">Jonathan Corbet of LWM fame</a> think we do and I agree.
726 </p>
727                         <h2>Working idea</h2>
728
729             <ul class="bulleted"> 
730                                 <li>FLOSS licence</li>
731                                 <li>source code repository (git)</li>
732                                 <li>all source searchable (gitweb?)</li>
733                                 <li>automatic builds (x86 NDK?)</li>
734                                 <li><b>download links from web!</b></li>
735                                 <li>backup apps to cloud (CouchDB?)</li>
736                         </ul>
737
738                         <p>Anybody interested in something like that?</p>
739
740                         </section>
741         </div>
742
743
744 <!-- extra slides -->
745
746         <div class="slide"> 
747           <section class="middle"> 
748             <h2>The Difference Between Android And iPhone</h2> 
749                         <p><a href="http://www.androidpolice.com/2010/09/16/comic-the-difference-between-android-and-iphone-this-pretty-much-sums-it-up/">This Pretty Much Sums It Up</a>
750           </section> 
751         </div>
752
753         <div class="slide"> 
754           <section class="middle"> 
755             <h2>Android</h2> 
756                         <img src="commic-Android.png">
757           </section> 
758         </div> 
759
760         <div class="slide"> 
761           <section class="middle"> 
762             <h2>iPhone</h2> 
763                         <img src="commic-iPhone.png">
764           </section> 
765         </div> 
766
767         <div class="slide"> 
768           <section class="middle"> 
769             <h1>Questions? Comments?</h1> 
770                         <h2>More information</h2>
771                         <p>this presentation: <a href="http://dpavlin.github.com/android-command-line/">http://dpavlin.github.com/android-command-line/</a></p>
772                         <p>repository: <a href="http://github.com/dpavlin/android-command-line/">http://github.com/dpavlin/android-command-line/</a></p>
773                         <p>my blog: <a href="http://blog.rot13.org">http://dpavlin.github.com/android-command-line/</a></p>
774                         </ul>
775           </section> 
776         </div> 
777
778         <div class="slide"> 
779           <section class="middle"> 
780           </section> 
781         </div> 
782
783         <div class="slide"> 
784           <section class="middle"> 
785             <h2>Slides template</h2> 
786             <p>Click here, Press <span class="key">&rarr;</span> key to advance.</p> 
787           </section> 
788         </div> 
789         
790
791         <div class="slide"> 
792           <section class="middle"> 
793             <h2> 
794               Attached Events
795             </h2> 
796             <ul> 
797               <li>[arrow keys] to go next and previous</p></li> 
798               <li>[mouse scroll wheel] to go next and previous</p></li> 
799               <li>[Ctrl or Command] + [+/-] to zoom in and out</p></li> 
800               <li>[touch gestures] for mobile devices</p></li> 
801             </ul> 
802           </section> 
803         </div> 
804  
805         <div class="slide"> 
806           <section class="middle"> 
807             <h2> 
808               Options
809             </h2> 
810             <ul> 
811               <li><input type="checkbox" id="toggle-size" /><label for="toggle-size"><span>Grow</span></label></li> 
812               <li><input type="checkbox" id="toggle-transitions" checked /><label for="toggle-transitions"><span>Transitions</span></label></li> 
813               <li><input type="checkbox" id="toggle-gradients" checked /><label for="toggle-gradients"><span>Gradients</span></label></li> 
814               <li><input type="checkbox" id="toggle-counter" checked /><label for="toggle-counter"><span>Slide numbers</span></label></li> 
815             </ul> 
816           </section> 
817         </div> 
818
819 <!--
820  
821         <div class="slide"> 
822           <section> 
823             <header> 
824               <h2>Placeholder content</h2> 
825             </header> 
826 <pre>// some sample code
827 &lt;canvas id="canvas" width="838" height="220"&gt;&lt;/canvas&gt;
828  
829 &lt;script&gt;
830   var canvasContext = document.getElementById("canvas").<b>getContext</b>("2d");
831   canvasContext.<b>fillRect</b>(250, 25, 150, 100);
832  
833   canvasContext.<b>beginPath</b>();
834   canvasContext.<b>arc</b>(450, 110, 100, Math.PI * 1/2, Math.PI * 3/2);
835   canvasContext.<b>lineWidth</b> = 15;
836   canvasContext.<b>lineCap</b> = 'round';
837   canvasContext.<b>strokeStyle</b> = 'rgba(255, 127, 0, 0.5)';
838   canvasContext.<b>stroke</b>();
839 &lt;/script&gt;
840 </pre> 
841             <ul class="bulleted"> 
842               <li>point 1</li> 
843               <li>point 2</li> 
844               <li>point 3</li> 
845             </ul> 
846           </section> 
847         </div> 
848
849 -->
850  
851       </div> <!-- slides --> 
852  
853     </div> <!-- presentation --> 
854  
855     <script> 
856       (function() {
857         var doc = document;
858         var disableBuilds = true;
859  
860         var ctr = 0;
861         var spaces = /\s+/, a1 = [''];
862  
863         var toArray = function(list) {
864           return Array.prototype.slice.call(list || [], 0);
865         };
866  
867         var byId = function(id) {
868           if (typeof id == 'string') { return doc.getElementById(id); }
869           return id;
870         };
871  
872         var query = function(query, root) {
873           if (!query) { return []; }
874           if (typeof query != 'string') { return toArray(query); }
875           if (typeof root == 'string') {
876             root = byId(root);
877             if(!root){ return []; }
878           }
879  
880           root = root || document;
881           var rootIsDoc = (root.nodeType == 9);
882           var doc = rootIsDoc ? root : (root.ownerDocument || document);
883  
884           // rewrite the query to be ID rooted
885           if (!rootIsDoc || ('>~+'.indexOf(query.charAt(0)) >= 0)) {
886             root.id = root.id || ('qUnique' + (ctr++));
887             query = '#' + root.id + ' ' + query;
888           }
889           // don't choke on something like ".yada.yada >"
890           if ('>~+'.indexOf(query.slice(-1)) >= 0) { query += ' *'; }
891  
892           return toArray(doc.querySelectorAll(query));
893         };
894  
895         var strToArray = function(s) {
896           if (typeof s == 'string' || s instanceof String) {
897             if (s.indexOf(' ') < 0) {
898               a1[0] = s;
899               return a1;
900             } else {
901               return s.split(spaces);
902             }
903           }
904           return s;
905         };
906  
907         var addClass = function(node, classStr) {
908           classStr = strToArray(classStr);
909           var cls = ' ' + node.className + ' ';
910           for (var i = 0, len = classStr.length, c; i < len; ++i) {
911             c = classStr[i];
912             if (c && cls.indexOf(' ' + c + ' ') < 0) {
913               cls += c + ' ';
914             }
915           }
916           node.className = cls.trim();
917         };
918  
919         var removeClass = function(node, classStr) {
920           var cls;
921           if (classStr !== undefined) {
922             classStr = strToArray(classStr);
923             cls = ' ' + node.className + ' ';
924             for (var i = 0, len = classStr.length; i < len; ++i) {
925               cls = cls.replace(' ' + classStr[i] + ' ', ' ');
926             }
927             cls = cls.trim();
928           } else {
929             cls = '';
930           }
931           if (node.className != cls) {
932             node.className = cls;
933           }
934         };
935  
936         var toggleClass = function(node, classStr) {
937           var cls = ' ' + node.className + ' ';
938           if (cls.indexOf(' ' + classStr.trim() + ' ') >= 0) {
939             removeClass(node, classStr);
940           } else {
941             addClass(node, classStr);
942           }
943         };
944  
945         var ua = navigator.userAgent;
946         var isFF = parseFloat(ua.split('Firefox/')[1]) || undefined;
947         var isWK = parseFloat(ua.split('WebKit/')[1]) || undefined;
948         var isOpera = parseFloat(ua.split('Opera/')[1]) || undefined;
949  
950         var canTransition = (function() {
951           var ver = parseFloat(ua.split('Version/')[1]) || undefined;
952           // test to determine if this browser can handle CSS transitions.
953           var cachedCanTransition = 
954             (isWK || (isFF && isFF > 3.6 ) || (isOpera && ver >= 10.5));
955           return function() { return cachedCanTransition; }
956         })();
957  
958         //
959         // Slide class
960         //
961         var Slide = function(node, idx) {
962           this._node = node;
963           if (idx >= 0) {
964             this._count = idx + 1;
965           }
966           if (this._node) {
967             addClass(this._node, 'slide distant-slide');
968           }
969           this._makeCounter();
970           this._makeBuildList();
971         };
972  
973         Slide.prototype = {
974           _node: null,
975           _count: 0,
976           _buildList: [],
977           _visited: false,
978           _currentState: '',
979           _states: [ 'distant-slide', 'far-past',
980                      'past', 'current', 'future',
981                      'far-future', 'distant-slide' ],
982           setState: function(state) {
983             if (typeof state != 'string') {
984               state = this._states[state];
985             }
986             if (state == 'current' && !this._visited) {
987               this._visited = true;
988               this._makeBuildList();
989             }
990             removeClass(this._node, this._states);
991             addClass(this._node, state);
992             this._currentState = state;
993  
994             // delay first auto run. Really wish this were in CSS.
995             /*
996             this._runAutos();
997             */
998             var _t = this;
999             setTimeout(function(){ _t._runAutos(); } , 400);
1000           },
1001           _makeCounter: function() {
1002             if(!this._count || !this._node) { return; }
1003             var c = doc.createElement('span');
1004             c.innerHTML = this._count;
1005             c.className = 'counter';
1006             this._node.appendChild(c);
1007           },
1008           _makeBuildList: function() {
1009             this._buildList = [];
1010             if (disableBuilds) { return; }
1011             if (this._node) {
1012               this._buildList = query('[data-build] > *', this._node);
1013             }
1014             this._buildList.forEach(function(el) {
1015               addClass(el, 'to-build');
1016             });
1017           },
1018           _runAutos: function() {
1019             if (this._currentState != 'current') {
1020               return;
1021             }
1022             // find the next auto, slice it out of the list, and run it
1023             var idx = -1;
1024             this._buildList.some(function(n, i) {
1025               if (n.hasAttribute('data-auto')) {
1026                 idx = i;
1027                 return true;
1028               }
1029               return false;
1030             });
1031             if (idx >= 0) {
1032               var elem = this._buildList.splice(idx, 1)[0];
1033               var transitionEnd = isWK ? 'webkitTransitionEnd' : (isFF ? 'mozTransitionEnd' : 'oTransitionEnd');
1034               var _t = this;
1035               if (canTransition()) {
1036                 var l = function(evt) {
1037                   elem.parentNode.removeEventListener(transitionEnd, l, false);
1038                   _t._runAutos();
1039                 };
1040                 elem.parentNode.addEventListener(transitionEnd, l, false);
1041                 removeClass(elem, 'to-build');
1042               } else {
1043                 setTimeout(function() {
1044                   removeClass(elem, 'to-build');
1045                   _t._runAutos();
1046                 }, 400);
1047               }
1048             }
1049           },
1050           buildNext: function() {
1051             if (!this._buildList.length) {
1052               return false;
1053             }
1054             removeClass(this._buildList.shift(), 'to-build');
1055             return true;
1056           },
1057         };
1058  
1059         //
1060         // SlideShow class
1061         //
1062         var SlideShow = function(slides) {
1063           this._slides = (slides || []).map(function(el, idx) {
1064             return new Slide(el, idx);
1065           });
1066  
1067           var h = window.location.hash;
1068           try {
1069             this.current = parseInt(h.split('#slide')[1], 10);
1070           }catch (e) { /* squeltch */ }
1071           this.current = isNaN(this.current) ? 1 : this.current;
1072           var _t = this;
1073           doc.addEventListener('keydown', 
1074               function(e) { _t.handleKeys(e); }, false);
1075           doc.addEventListener('mousewheel', 
1076               function(e) { _t.handleWheel(e); }, false);
1077           doc.addEventListener('DOMMouseScroll', 
1078               function(e) { _t.handleWheel(e); }, false);
1079           doc.addEventListener('touchstart', 
1080               function(e) { _t.handleTouchStart(e); }, false);
1081           doc.addEventListener('touchend', 
1082               function(e) { _t.handleTouchEnd(e); }, false);
1083           window.addEventListener('popstate', 
1084               function(e) { _t.go(e.state); }, false);
1085           this._update();          
1086         };
1087  
1088         SlideShow.prototype = {
1089           _slides: [],
1090           _update: function(dontPush) {
1091             document.querySelector('#presentation-counter').innerText = this.current;
1092             if (history.pushState) {
1093               if (!dontPush) {
1094                 history.pushState(this.current, 'Slide ' + this.current, '#slide' + this.current);
1095               }
1096             } else {
1097               window.location.hash = 'slide' + this.current;
1098             }
1099             for (var x = this.current-1; x < this.current + 7; x++) {
1100               if (this._slides[x-4]) {
1101                 this._slides[x-4].setState(Math.max(0, x-this.current));
1102               }
1103             }
1104           },
1105  
1106           current: 0,
1107           next: function() {
1108             if (!this._slides[this.current-1].buildNext()) {
1109               this.current = Math.min(this.current + 1, this._slides.length);
1110               this._update();
1111             }
1112           },
1113           prev: function() {
1114             this.current = Math.max(this.current-1, 1);
1115             this._update();
1116           },
1117           go: function(num) {
1118             if (history.pushState && this.current != num) {
1119               history.replaceState(this.current, 'Slide ' + this.current, '#slide' + this.current);
1120             }
1121             this.current = num;
1122             this._update(true);
1123           },
1124  
1125           _notesOn: false,
1126           showNotes: function() {
1127             var isOn = this._notesOn = !this._notesOn;
1128             query('.notes').forEach(function(el) {
1129               el.style.display = (notesOn) ? 'block' : 'none';
1130             });
1131           },
1132           switch3D: function() {
1133             toggleClass(document.body, 'three-d');
1134           },
1135           handleWheel: function(e) {
1136             var delta = 0;
1137             if (e.wheelDelta) {
1138               delta = e.wheelDelta/120;
1139               if (isOpera) {
1140                 delta = -delta;
1141               }
1142             } else if (e.detail) {
1143               delta = -e.detail/3;
1144             }
1145  
1146             if (delta > 0 ) {
1147               this.prev();
1148               return;
1149             }
1150             if (delta < 0 ) {
1151               this.next();
1152               return;
1153             }
1154           },
1155           handleKeys: function(e) {
1156             
1157             if (/^(input|textarea)$/i.test(e.target.nodeName)) return;
1158             
1159             switch (e.keyCode) {
1160               case 37: // left arrow
1161                 this.prev(); break;
1162               case 39: // right arrow
1163               case 32: // space
1164                 this.next(); break;
1165               case 50: // 2
1166                 this.showNotes(); break;
1167               case 51: // 3
1168                 this.switch3D(); break;
1169             }
1170           },
1171           _touchStartX: 0,
1172           handleTouchStart: function(e) {
1173             this._touchStartX = e.touches[0].pageX;
1174           },
1175           handleTouchEnd: function(e) {
1176             var delta = this._touchStartX - e.changedTouches[0].pageX;
1177             var SWIPE_SIZE = 150;
1178             if (delta > SWIPE_SIZE) {
1179               this.next();
1180             } else if (delta< -SWIPE_SIZE) {
1181               this.prev();
1182             }
1183           },
1184         };
1185  
1186         // Initialize
1187         var slideshow = new SlideShow(query('.slide'));
1188         
1189         
1190         
1191         
1192         
1193         document.querySelector('#toggle-counter').addEventListener('click', toggleCounter, false);
1194         document.querySelector('#toggle-size').addEventListener('click', toggleSize, false);
1195         document.querySelector('#toggle-transitions').addEventListener('click', toggleTransitions, false);
1196         document.querySelector('#toggle-gradients').addEventListener('click', toggleGradients, false);
1197  
1198  
1199         var counters = document.querySelectorAll('.counter');
1200         var slides = document.querySelectorAll('.slide');
1201  
1202         function toggleCounter() {
1203           toArray(counters).forEach(function(el) {
1204             el.style.display = (el.offsetHeight) ? 'none' : 'block';
1205           });
1206         }
1207         
1208         function toggleSize() {
1209           toArray(slides).forEach(function(el) {
1210             if (!/reduced/.test(el.className)) {
1211               addClass(el, 'reduced');
1212             }
1213             else {
1214               removeClass(el, 'reduced');
1215             }
1216           });
1217         }
1218  
1219         function toggleTransitions() {
1220           toArray(slides).forEach(function(el) {
1221             if (!/no-transitions/.test(el.className)) {
1222               addClass(el, 'no-transitions');
1223             }
1224             else {
1225               removeClass(el, 'no-transitions');
1226             }
1227           });
1228         }
1229         
1230         function toggleGradients() {
1231           toArray(slides).forEach(function(el) {
1232             if (!/no-gradients/.test(el.className)) {
1233               addClass(el, 'no-gradients');
1234             }
1235             else {
1236               removeClass(el, 'no-gradients');
1237             }
1238           });
1239         }
1240         
1241         
1242         
1243         
1244         
1245       })();
1246       
1247       
1248       
1249     </script> 
1250  
1251     <!--[if lt IE 9]>
1252     <script 
1253       src="http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js">
1254     </script>
1255                 <script>CFInstall.check({ mode: "overlay" });</script>
1256     <![endif]--> 
1257     
1258   </body> 
1259 </html>