forked from instructure/instructure.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
982 lines (772 loc) · 80.5 KB
/
atom.xml
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
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Instructure Tech Blog]]></title>
<link href="http://instructure.github.io/atom.xml" rel="self"/>
<link href="http://instructure.github.io/"/>
<updated>2014-04-22T15:48:21-06:00</updated>
<id>http://instructure.github.io/</id>
<author>
<name><![CDATA[Instructure]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[ImageSweep : drawable management for Android]]></title>
<link href="http://instructure.github.io/blog/2014/04/21/android-image-sweep/"/>
<updated>2014-04-21T07:29:00-06:00</updated>
<id>http://instructure.github.io/blog/2014/04/21/android-image-sweep</id>
<content type="html"><![CDATA[<p>Software engineering is full of trade-offs: speed/memory usage, features/bugs, etc.
The list goes on and on. The Android team here at Instructure found an interesting trade-off: developer-time versus application size.
As we get new icons/images from our UI/UX team, we have two choices: bundle all of them into the application or add them as they’re needed in our project.
The trade-off becomes relatively straight-forward: either we spend time constantly adding images to our project or the user has to deal with their size when they install our application.</p>
<p>At a high-level, the solution is simple: find all the unused drawables in the project and remove them when you build for release.
Historically that’s been a tedious and error-prone process, but not anymore.
I’m proud to announce a new open-source script from Instructure: <a href="https://github.com/instructure/android-ImageSweep">ImageSweep</a>.
It will run through every file in your project and check for references to drawable resources using regular expressions to check for instances of <em>R.drawable.</em> and <em>@drawable/</em>.
The script will then iterate through the resource folder and delete ALL unused drawable resources.</p>
<p>It’s extremely easy to use. Simply run:</p>
<pre><code> python ImageSweep.py project_src_directory
</code></pre>
<p>where <code>project_src_directory</code> is the relative or absolute file-path where your source code lives.
Make sure the chosen directory contains <em>all</em> of your source code and AndroidManifest.xml, but none of the libraries you’ve included. The script auto-determines where the project’s resource folder is and libraries can potentially break this detection.</p>
<p>We recently added this script to our release process for <a href="https://play.google.com/store/apps/details?id=com.instructure.candroid">Canvas for Android</a>.
In that project, we were able to delete 2,593 files for a total of 72.37 Mbs freed on disk.
This correlated to a <em>46%</em> size decrease on the apk itself and <em>26%</em> size decrease on the installed application.</p>
<p>To get started, visit the <a href="https://github.com/instructure/android-ImageSweep">project homepage</a>. Take note of the warnings in the README prior to using the script.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Continuous Integration]]></title>
<link href="http://instructure.github.io/blog/2014/02/24/ci/"/>
<updated>2014-02-24T11:04:00-07:00</updated>
<id>http://instructure.github.io/blog/2014/02/24/ci</id>
<content type="html"><![CDATA[<p>Parallelization, Selenium, AWS, and a CI server are common implementations for agile
shops, and we are no exception. Since I’ve been here, maintenance hasn’t
been a nightmare, nor has it been a dream. We’ve learned a few things
to streamline our maintenance process and would love to share the things
that made our lives easier.</p>
<p>When looking at what was eating up our time, we found the differences
between our CI environment and average developer’s environment was at
the forefront. Most of us at Instructure use Macs, a few of us Windows,
and there are a handful Linux users. Among us, browser choice varies,
but the most popular is Chrome. Engineers develop locally using their
own OS, browser type/version and the Ruby Selenium driver to power
tests. Listed below are a few of the differences we found:</p>
<ol>
<li> AWS images were Ubuntu</li>
<li> Variance in browser versions</li>
<li> Selenium grid uses Java stand alone server VS local specs running using native Ruby driver</li>
<li> Variance in native event capabilities VS Jenkins running exclusively using native events</li>
<li> Parallelization in CI vs single threaded specs in developer’s environment</li>
</ol>
<!-- more -->
<p>We began to strive for consistency between the average dev environment and
the CI environments, where we could, without sacraficing production like implementation.
This helped with mitigating many intermittency issues. During this
process, it simplified the CI upgrade process while edging maintenance
towards dreamland and further from Elm St.</p>
<p>So, what did we do to make this happen? First, all logic for Selenium
driver code was changed from Selenium grid\Java stand-alone server to
the native Ruby Selenium driver. This change immediately resulted in
noticeable stability improvements, and easier resolution for
intermittency creep from tests.</p>
<p>In the past, we had challenges reproducing errors, locally, that our CI
server would throw because of the variance in environments. We spent a
lot of time debugging these errors, and had to create CI environments
that devs could SSH into, to debug the spec failures. This was highly
inefficient, and not consistent with the nature or true purpose of CI.
Making the two environments consistent gave us more time to work on
other things, instead of time-consuming and meaningless failures that were challenging and
intensive to debug. Now we are easily able to (for the most part)
reproduce all errors produced by our CI server.</p>
<p>Along the way, we also found Selenium grid was not the ideal solution for us.
The main reason being the variance in spec outcomes
between dev environments and CI, resulting in too much overhead for
maintenance and upgrades, while also sapping dev time on CI spec
debugging. Many shops use a hardware infrastructure that is distributed
across multiple boxes and the tests are farmed out to them; this is
ideal for Selenium grid. We, however, prefer one big box with
parallelization done internally, reducing the need for a Java stand-alone
server and Selenium grid. Capabilities for the drivers are consumed from
config files written at runtime for different browsers and we have no
need to push each test to a Selenium hub to be farmed out to a worker.
We found this complicated setup offered little reward and brought on
noticeable burden in maintenance and stability while introducing a
variance in spec outcomes.</p>
<p>Making these changes made our lives noticeably easier. When managing
or implementing a CI environment, we believe it’s prudent to not only consider your core
tech architecture, but the relationship with your developer’s workflow.
Although complex implementations of Selenium grid and multiple browsers can be beneficial,
it may add more complications than are worth it.
We recommend a lean implementation of Selenium, using the driver of the native application
language for tighter integration and better maintenance with more consistency between test runs.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Ember Run Loop and TDD]]></title>
<link href="http://instructure.github.io/blog/2014/01/24/ember-run-loop-and-tdd/"/>
<updated>2014-01-24T08:58:00-07:00</updated>
<id>http://instructure.github.io/blog/2014/01/24/ember-run-loop-and-tdd</id>
<content type="html"><![CDATA[<p>Each month, <a href="http://www.meetup.com/EmberJS-SLC/">nerds unite</a> at the Instructure building to share their knowledge on <a href="http://www.emberjs.com">Ember</a>. This month we had two presentations by a couple of Instructure engineers. Here are the videos and accompanying slides/code.</p>
<h2>Ember Run Loop</h2>
<p>Jason Madsen (<a href="https://twitter.com/jason_madsen">@jason_madsen</a>) discussed the what, why, and how of the Ember Run Loop. Learn how Ember manages the run loop for you, and cases where you will want to manage the run loop. Here’s a hint: speed and testing.</p>
<iframe width="560" height="315" src="http://instructure.github.io//www.youtube.com/embed/RLgPBM72LQw" frameborder="0" allowfullscreen></iframe>
<p><a href="http://knomedia.github.io/presentation_2014_01_23_ember_run_loop">Slides</a></p>
<h2>Testing Your Ember Application using TDD</h2>
<p>Eric Berry (<a href="https://twitter.com/cavneb">@cavneb</a>) presented on how to “Test Drive” your Ember applications. Eric starts from scratch and walks through different types of tests that can be written. By the end, you will have a much better understanding of how to test your Ember application.</p>
<iframe width="560" height="315" src="http://instructure.github.io//www.youtube.com/embed/GRT5YcXmm7E" frameborder="0" allowfullscreen></iframe>
<p><a href="http://cavneb.github.io/presentations-2014.01.23-Ember-Testing">Slides</a> |
<a href="https://github.com/cavneb/presentations-2014.01.23-Ember-Testing/tree/master/ember-app">Code</a></p>
<h2>Nerd with us!</h2>
<p>Feel free to join our monthly meetups (even remotely). The meetings are posted at <a href="http://www.meetup.com/EmberJS-SLC/">http://www.meetup.com/EmberJS-SLC/</a>.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Faster I18n Backend for Ruby Written in C]]></title>
<link href="http://instructure.github.io/blog/2014/01/07/faster-ruby-i18n-backend-written-in-c/"/>
<updated>2014-01-07T07:32:00-07:00</updated>
<id>http://instructure.github.io/blog/2014/01/07/faster-ruby-i18n-backend-written-in-c</id>
<content type="html"><![CDATA[<p>Every so often, we like to do a hack(fest|stravaganza|nado) here at
Instructure. It’s an opportunity for engineers to spend several days
building something cool to improve <a href="https://github.com/instructure/canvas-lms">Canvas</a>.</p>
<p>For our inaugural hackthing back in May, I worked on the problem of having
lots of objects in memory in Ruby 1.9. Ruby uses a mark-and-sweep garbage
collector, so the more Ruby objects you have in memory, the longer each GC
run will take. This can be a significant contributor to slow page loads in
a large Rails app like Canvas.</p>
<!--more-->
<p>At the time, Canvas was localized in 7 languages (we’re now up to 15). We
use the excellent <a href="https://github.com/svenfuchs/i18n">I18n gem</a> with a
<a href="https://github.com/instructure/canvas-lms/blob/stable/config/initializers/i18n.rb">few</a>
<a href="https://github.com/instructure/canvas-lms/blob/stable/lib/tasks/i18n.rake">handy</a>
<a href="https://github.com/instructure/canvas-lms/tree/stable/lib/i18n_extraction">extensions</a>
of our own. While I18n’s default in-memory backend is plenty fast, it
comes at the cost of having all of those strings in memory. Every new
language you add or feature you implement makes the GC problem even worse.</p>
<p>Because localization strings should be static for the lifetime of a Rails
process, there is no reason the garbage collector needs to know about them
at all. But we still want to keep them in memory for optimal speed.</p>
<p>Enter <a href="https://github.com/instructure/i18nema">I18nema</a>, a fast I18n
backend that unstops the garbage collector and gets everything running
quickly and smoothly :).</p>
<h2>What Is an I18nema?</h2>
<p>At its core, I18nema is a Ruby C extension that moves I18n’s translations
out of Ruby-land and into C structs. It also includes a handful of other
optimizations to I18n, leading to some nice all around speedups.</p>
<h2>How Is It Administered?</h2>
<p>In your Gemfile, do</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">gem</span> <span class="no">RUBY_VERSION</span> <span class="o">>=</span> <span class="s1">'2.0'</span> <span class="p">?</span> <span class="s1">'i18nema'</span> <span class="p">:</span> <span class="s1">'i18nema19'</span>
</span></code></pre></td></tr></table></div></figure>
<p>and then put something like this in an initializer:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">I18n</span><span class="o">.</span><span class="n">backend</span> <span class="o">=</span> <span class="ss">I18nema</span><span class="p">:</span><span class="ss">:Backend</span><span class="o">.</span><span class="n">new</span>
</span></code></pre></td></tr></table></div></figure>
<p>You can still pull in additional I18n features (e.g. <code>I18n::Backend::Fallbacks</code>).
Refer to <a href="https://github.com/instructure/i18nema/blob/master/README.md">the README</a>
for more information.</p>
<h2>How Will It Improve My Quality of Life?</h2>
<h3>More Get-Up-and-Go</h3>
<p>I18nema loads translations into memory much more quickly—<strong>over 4x!</strong>—
making for much faster Rails startup time. While this is just a one time
hit, it’s very noticeable when you’re waiting on it (e.g. console, specs).
In Canvas, I18nema brings it down to a little over a second (from almost
6).</p>
<h3>Minimal Blockage</h3>
<p>Because there are fewer Ruby objects, the periodic GC runs are
proportionally faster with I18nema. That means faster page loads for your
users.</p>
<p>How much faster is a question of how many translations you have versus how
many other Ruby objects. Applications that are localized in more languages
should see a bigger boost (since the translations make up a bigger share
of the original ObjectSpace).</p>
<p>For example, Canvas is translated into fifteen languages, and I18nema
reduces both (startup) ObjectSpace and GC runtime by <strong>about 15%</strong>. As more
languages are added, that number should only increase.</p>
<p>I18nema also moves I18n’s normalized_key_cache into C structs. This key
cache grows over time (it eventually holds a key/value for every
translation key used in the app), so that’s another area where I18nema is
nicer on ObjectSpace than vanilla I18n.</p>
<h3>More Pep in Your Step</h3>
<p>I18nema speeds up <code>translate</code> calls, getting the right text to your users
more quickly.</p>
<p>Simple lookups (i.e. no options or interpolation) take a bit <strong>over 15%</strong> less
time.</p>
<p>Lookups with options see slightly bigger gains (<strong>over 20%</strong> less time), in
part due to some speedups on the Ruby side of things (I18n uses
<code>Hash#except</code>, which is quite slow when you have a long list of
arguments).</p>
<h2>Is I18nema Right for Me?</h2>
<p>I18nema is not for everyone.</p>
<p>If you’re still on Ruby 1.8, you should not use I18nema. Although I18nema
has been tested on Ruby 1.9, 2.0, and 2.1, it has only been benchmarked
on 1.9. You may find it less effective on 2.1, due to its <a href="http://tmm1.net/ruby21-rgengc/">dramatic GC improvements</a>.</p>
<p>When using I18nema, you should make sure that your translation files are
UTF-8. I18nema cannot be used with <code>.rb</code> translation files (only <code>.yml</code>)</p>
<p>Refer to <a href="https://github.com/instructure/i18nema/blob/master/README.md">the fine print</a>
for more information and benchmarks.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Generating Accessible Colors in JavaScript]]></title>
<link href="http://instructure.github.io/blog/2013/12/30/generating-accessible-colors-in-javascript/"/>
<updated>2013-12-30T14:42:00-07:00</updated>
<id>http://instructure.github.io/blog/2013/12/30/generating-accessible-colors-in-javascript</id>
<content type="html"><![CDATA[<p>We recently released a major upgrade to Canvas’s calendar. Although the primary objective was adding an agenda view and other accessibility tools, we also took the opportunity to update its visual design, including the color coding that links events and calendars. We’ve released this new color code generator as a Bower package at <a href="https://github.com/instructure/color-slicer">github/instructure/color-slicer</a>. Here’s why we switched.</p>
<!--more-->
<h2>Objectives</h2>
<p>Our old color coding system was pretty simple: we had a list of ten hues, and we assigned them to calendars in order. The drawbacks were that colors would repeat after ten calendars and that the colors used weren’t very appealing.</p>
<p> <img src="http://i.imgur.com/6lBEr3V.png" alt="" /></p>
<p>Another system we considered was <a href="https://github.com/instructure/canvas-lms/blob/stable/app/coffeescripts/util/contextColors.coffee">our hash-based color generator</a>, which creates a color based on an object name or ID. This would avoid repetition, but unlucky users could end up with three slightly different shades of green for their three courses.</p>
<p>For the new system, then, we had three goals:</p>
<ul>
<li>Produce colors that look nice and are accessibly readable for text.</li>
<li>Allow an unlimited number of colors without repetition.</li>
<li>Keep colors visually distinct, especially for short lists.</li>
</ul>
<h2>Text colors</h2>
<p>The simplest way to generate bright colors would be use HSV and to vary the hue while using 100% saturation and value. For text on a white background, though, this makes yellows almost invisible:</p>
<p><a href="http://jsfiddle.net/3KX8d/1/"><img src="http://i.imgur.com/kk4ntIE.png" /></a></p>
<p>Instead, we use the <a href="http://en.wikipedia.org/wiki/Lab_color_space">Lab color space</a>, which adjusts for human sensitivity to green, providing a better measurement of lightness and more evenly distributed hues. This not only looks better, but also helps users with limited vision by meeting <a href="http://webaim.org/resources/contrastchecker/">WCAG AA contrast guidelines</a>.</p>
<p><a href="http://jsfiddle.net/G9Qmm/1/"><img src="http://i.imgur.com/V5jstLt.png?1" /></a></p>
<h2>Spacing</h2>
<p>An easy way to space the colors would be to divide the hue circle by the number of calendars. We didn’t want all of the colors to change whenever a user added a course, though; we wanted to use the same colors for the first three calendars whether there were three or thirty total. To accomplish this, we <a href="http://jsfiddle.net/UqSS3/6/">progressively divide each gap in half</a>: first we use 0°, then 180°, then 90°, then 270°, then 45°, and so on. This way, your first few calendars are always very visually distinct.</p>
<p>Formally, this is essentially an <a href="http://en.wikipedia.org/wiki/Online_algorithm">online</a> <a href="http://en.wikipedia.org/wiki/Thomson_problem">Thomson problem</a>. We’re lucky to only have to solve the one-dimensional version, but the same basic idea could certainly be used to vary hue and value simultaneously if you wanted to generate many distinct colors and didn’t care about legibility. The <a href="http://sitemason.vanderbilt.edu/page/hmbADS">spiral point heuristic</a> would probably work well—we’d love to see someone send us a pull request.</p>
<h2>Results</h2>
<p>We’re always refining our user experience, but we’re happy with the look of our new colors.</p>
<p> <img src="http://i.imgur.com/GLSrwyh.png?1" alt="" /></p>
<p>We’ve released <a href="https://github.com/instructure/color-slicer">color-slicer</a> in UMD format under an MIT license, so it should be easy to add to your projects. I hope you’ll find it useful. My favorite part of working at Instructure—better than weekly lunch—is spending most of my time crafting code that we give back to the community. Let us know what you think.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Facebook React vs. Ember]]></title>
<link href="http://instructure.github.io/blog/2013/12/17/facebook-react-vs-ember/"/>
<updated>2013-12-17T08:54:00-07:00</updated>
<id>http://instructure.github.io/blog/2013/12/17/facebook-react-vs-ember</id>
<content type="html"><![CDATA[<div class="comment">Edited Jan 13, 2014 with minor changes which allow for testing timeouts in Ember.</div>
<p>We engineers at Instructure love <a href="http://www.emberjs.com">Ember</a>. We also love to learn about other frameworks and know which tools are the best for the job at hand. One of the newer frameworks to come out is React.</p>
<p><a href="http://facebook.github.io/react/">React</a> is Facebook’s new JavaScript library for building user interfaces. I’m excited to see another player in the game of front-end JS frameworks. When we have so much mind share going to a similar problem, we all win.</p>
<p>On the home page <a href="http://instructure.github.io/images/posts/react-website.png">(screenshot)</a>, there are a few examples of how React can be used. I thought it might be fun to show how each of these can be done using Ember.</p>
<!-- more -->
<h2>A Simple Component</h2>
<p>React components take data and return content which is to be displayed. Here’s their example code:</p>
<figure class='code'><figcaption><span>React</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="cm">/** @jsx React.DOM */</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">HelloMessage</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
</span><span class='line'> <span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="o"><</span><span class="nx">div</span><span class="o">></span><span class="p">{</span><span class="s1">'Hello '</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span><span class="o"><</span><span class="err">/div>;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span><span class='line'>
</span><span class='line'><span class="nx">React</span><span class="p">.</span><span class="nx">renderComponent</span><span class="p">(</span><span class="o"><</span><span class="nx">HelloMessage</span> <span class="nx">name</span><span class="o">=</span><span class="s2">"John"</span> <span class="o">/></span><span class="p">,</span> <span class="nx">mountNode</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>
<p>Let’s build this in Ember. For something as simple as this example, a <a href="http://emberjs.com/guides/templates/writing-helpers/">Handlebars Helper</a> will do the trick.</p>
<figure class='code'><figcaption><span>Ember</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="nx">Ember</span><span class="p">.</span><span class="nx">Handlebars</span><span class="p">.</span><span class="nx">helper</span><span class="p">(</span><span class="s1">'hello-message'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">escaped</span> <span class="o">=</span> <span class="nx">Handlebars</span><span class="p">.</span><span class="nx">Utils</span><span class="p">.</span><span class="nx">escapeExpression</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
</span><span class='line'> <span class="k">return</span> <span class="k">new</span> <span class="nx">Handlebars</span><span class="p">.</span><span class="nx">SafeString</span><span class="p">(</span><span class="s1">'<div>Hello '</span> <span class="o">+</span> <span class="nx">escaped</span> <span class="o">+</span> <span class="s1">'</div>'</span><span class="p">);</span>
</span><span class='line'><span class="p">});</span>
</span><span class='line'>
</span><span class='line'><span class="p">{{{</span><span class="nx">hello</span><span class="o">-</span><span class="nx">message</span> <span class="s2">"John"</span><span class="p">}}}</span>
</span></code></pre></td></tr></table></div></figure>
<h3>Example:</h3>
<p><a class="jsbin-embed" href="http://jsbin.com/ecAJuxE/4/edit?html,js,output">Facebook React vs Ember</a><script src="http://static.jsbin.com/js/embed.js"></script></p>
<h2>A Stateful Component</h2>
<p>The stateful component example on the React page is cool. It tracks the elapsed time on a page (since refresh). Here’s their code:</p>
<figure class='code'><figcaption><span>React</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="kd">var</span> <span class="nx">Timer</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
</span><span class='line'> <span class="nx">getInitialState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="p">{</span><span class="nx">secondsElapsed</span><span class="o">:</span> <span class="mi">0</span><span class="p">};</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'> <span class="nx">tick</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">secondsElapsed</span><span class="o">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">secondsElapsed</span> <span class="o">+</span> <span class="mi">1</span><span class="p">});</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'> <span class="nx">componentDidMount</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">interval</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">tick</span><span class="p">,</span> <span class="mi">1000</span><span class="p">);</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'> <span class="nx">componentWillUnmount</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">clearInterval</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">interval</span><span class="p">);</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'> <span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="nx">React</span><span class="p">.</span><span class="nx">DOM</span><span class="p">.</span><span class="nx">div</span><span class="p">({},</span>
</span><span class='line'> <span class="s1">'Seconds Elapsed: '</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">secondsElapsed</span>
</span><span class='line'> <span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>
<p>Since we are maintaining state within the component itself, let’s build it using an Ember Component.</p>
<figure class='code'><figcaption><span>Ember</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="nx">App</span><span class="p">.</span><span class="nx">TimeOnPageComponent</span> <span class="o">=</span> <span class="nx">Em</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'> <span class="nx">secondsViewed</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">// Increment the secondsViewed attribute</span>
</span><span class='line'> <span class="nx">tick</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">incrementProperty</span><span class="p">(</span><span class="s1">'secondsViewed'</span><span class="p">);</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'>
</span><span class='line'> <span class="nx">onInterval</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'> <span class="nx">Ember</span><span class="p">.</span><span class="nx">run</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">tick</span><span class="p">);</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">// Initiates timer when element is rendered</span>
</span><span class='line'> <span class="nx">startTimer</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">_interval</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">onInterval</span><span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">),</span> <span class="mi">1000</span><span class="p">);</span>
</span><span class='line'> <span class="p">}.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'didInsertElement'</span><span class="p">),</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">// Ensure that the timer stops when closed</span>
</span><span class='line'> <span class="nx">clearInterval</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">clearInterval</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">_interval</span><span class="p">);</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">_interval</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
</span><span class='line'> <span class="p">}.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'willDestroyElement'</span><span class="p">)</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>
<h3>Example:</h3>
<p><a class="jsbin-embed" href="http://jsbin.com/OPeVeted/6/embed?js,output">Facebook React vs Ember</a><script src="http://static.jsbin.com/js/embed.js"></script></p>
<h2>An Application</h2>
<p>The application example is a simple todo list which has a TodoList class (for rendering content) and a TodoApp class (maintains the state and renders the layout). Here’s the code:</p>
<figure class='code'><figcaption><span>React</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="cm">/** @jsx React.DOM */</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">TodoList</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
</span><span class='line'> <span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">createItem</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">itemText</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="o"><</span><span class="nx">li</span><span class="o">></span><span class="p">{</span><span class="nx">itemText</span><span class="p">}</span><span class="o"><</span><span class="err">/li>;</span>
</span><span class='line'> <span class="p">};</span>
</span><span class='line'> <span class="k">return</span> <span class="o"><</span><span class="nx">ul</span><span class="o">></span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">items</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">createItem</span><span class="p">)}</span><span class="o"><</span><span class="err">/ul>;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">TodoApp</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
</span><span class='line'> <span class="nx">getInitialState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="p">{</span><span class="nx">items</span><span class="o">:</span> <span class="p">[],</span> <span class="nx">text</span><span class="o">:</span> <span class="s1">''</span><span class="p">};</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'> <span class="nx">onChange</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">text</span><span class="o">:</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">value</span><span class="p">});</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'> <span class="nx">handleSubmit</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">e</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">nextItems</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">items</span><span class="p">.</span><span class="nx">concat</span><span class="p">([</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">text</span><span class="p">]);</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">nextText</span> <span class="o">=</span> <span class="s1">''</span><span class="p">;</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">items</span><span class="o">:</span> <span class="nx">nextItems</span><span class="p">,</span> <span class="nx">text</span><span class="o">:</span> <span class="nx">nextText</span><span class="p">});</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'> <span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="p">(</span>
</span><span class='line'> <span class="o"><</span><span class="nx">div</span><span class="o">></span>
</span><span class='line'> <span class="o"><</span><span class="nx">h3</span><span class="o">></span><span class="nx">TODO</span><span class="o"><</span><span class="err">/h3></span>
</span><span class='line'> <span class="o"><</span><span class="nx">TodoList</span> <span class="nx">items</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">items</span><span class="p">}</span> <span class="o">/></span>
</span><span class='line'> <span class="o"><</span><span class="nx">form</span> <span class="nx">onSubmit</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">handleSubmit</span><span class="p">}</span><span class="o">></span>
</span><span class='line'> <span class="o"><</span><span class="nx">input</span> <span class="nx">onChange</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">onChange</span><span class="p">}</span> <span class="nx">value</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">text</span><span class="p">}</span> <span class="o">/></span>
</span><span class='line'> <span class="o"><</span><span class="nx">button</span><span class="o">></span><span class="p">{</span><span class="s1">'Add #'</span> <span class="o">+</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">items</span><span class="p">.</span><span class="nx">length</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)}</span><span class="o"><</span><span class="err">/button></span>
</span><span class='line'> <span class="o"><</span><span class="err">/form></span>
</span><span class='line'> <span class="o"><</span><span class="err">/div></span>
</span><span class='line'> <span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span><span class='line'><span class="nx">React</span><span class="p">.</span><span class="nx">renderComponent</span><span class="p">(</span><span class="o"><</span><span class="nx">TodoApp</span> <span class="o">/></span><span class="p">,</span> <span class="nx">mountNode</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>
<p>When writing this in Ember, we would use both a controller and a handlebars template. The controller will maintain the state and respond to user interaction and the template will display the form and list.</p>
<figure class='code'><figcaption><span>Ember (controller)</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="nx">App</span><span class="p">.</span><span class="nx">ApplicationController</span> <span class="o">=</span> <span class="nx">Em</span><span class="p">.</span><span class="nx">ArrayController</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'> <span class="nx">content</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="p">[];</span>
</span><span class='line'> <span class="p">}.</span><span class="nx">property</span><span class="p">(),</span>
</span><span class='line'>
</span><span class='line'> <span class="nx">btnLabel</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="s2">"Add #"</span> <span class="o">+</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">'content.length'</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
</span><span class='line'> <span class="p">}.</span><span class="nx">property</span><span class="p">(</span><span class="s1">'content.length'</span><span class="p">),</span>
</span><span class='line'>
</span><span class='line'> <span class="nx">actions</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">handleSubmit</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">'content'</span><span class="p">).</span><span class="nx">pushObject</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">'text'</span><span class="p">));</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">'text'</span><span class="p">,</span> <span class="s1">''</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>
<figure class='code'><figcaption><span>Ember (template)</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt"><div></span>
</span><span class='line'> <span class="nt"><h3></span>TODO<span class="nt"></h3></span>
</span><span class='line'> <span class="nt"><ul></span>
</span><span class='line'> {{#each content}}
</span><span class='line'> <span class="nt"><li></span>{{this}}<span class="nt"></li></span>
</span><span class='line'> {{/each}}
</span><span class='line'> <span class="nt"></ul></span>
</span><span class='line'>
</span><span class='line'> <span class="nt"><form</span> <span class="err">{{</span><span class="na">action</span> <span class="err">"</span><span class="na">handleSubmit</span><span class="err">"</span> <span class="na">on=</span><span class="s">"submit"</span><span class="err">}}</span><span class="nt">></span>
</span><span class='line'> {{input value=text}}
</span><span class='line'> <span class="nt"><button</span> <span class="na">type=</span><span class="s">"submit"</span><span class="nt">></span>{{btnLabel}}<span class="nt"></button></span>
</span><span class='line'> <span class="nt"></form></span>
</span><span class='line'><span class="nt"></div></span>
</span></code></pre></td></tr></table></div></figure>
<h3>Example:</h3>
<p><a class="jsbin-embed" href="http://jsbin.com/OkOLEze/4/embed?html,js,output">Facebook React vs Ember</a><script src="http://static.jsbin.com/js/embed.js"></script></p>
<h2>A Component Using External Plugins</h2>
<p>This example on the React website under <em>A Component Using External Plugins</em> is a great example of encapsulating functionality.</p>
<figure class='code'><figcaption><span>React</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="cm">/** @jsx React.DOM */</span>
</span><span class='line'>
</span><span class='line'><span class="kd">var</span> <span class="nx">converter</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Showdown</span><span class="p">.</span><span class="nx">converter</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'><span class="kd">var</span> <span class="nx">MarkdownEditor</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
</span><span class='line'> <span class="nx">getInitialState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="p">{</span><span class="nx">value</span><span class="o">:</span> <span class="s1">'Type some *markdown* here!'</span><span class="p">};</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'> <span class="nx">handleChange</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="nx">value</span><span class="o">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">refs</span><span class="p">.</span><span class="nx">textarea</span><span class="p">.</span><span class="nx">getDOMNode</span><span class="p">().</span><span class="nx">value</span><span class="p">});</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'> <span class="nx">render</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="p">(</span>
</span><span class='line'> <span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"MarkdownEditor"</span><span class="o">></span>
</span><span class='line'> <span class="o"><</span><span class="nx">h3</span><span class="o">></span><span class="nx">Input</span><span class="o"><</span><span class="err">/h3></span>
</span><span class='line'> <span class="o"><</span><span class="nx">textarea</span>
</span><span class='line'> <span class="nx">onChange</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">handleChange</span><span class="p">}</span>
</span><span class='line'> <span class="nx">ref</span><span class="o">=</span><span class="s2">"textarea"</span>
</span><span class='line'> <span class="nx">defaultValue</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">value</span><span class="p">}</span> <span class="o">/></span>
</span><span class='line'> <span class="o"><</span><span class="nx">h3</span><span class="o">></span><span class="nx">Output</span><span class="o"><</span><span class="err">/h3></span>
</span><span class='line'> <span class="o"><</span><span class="nx">div</span>
</span><span class='line'> <span class="nx">className</span><span class="o">=</span><span class="s2">"content"</span>
</span><span class='line'> <span class="nx">dangerouslySetInnerHTML</span><span class="o">=</span><span class="p">{{</span>
</span><span class='line'> <span class="nx">__html</span><span class="o">:</span> <span class="nx">converter</span><span class="p">.</span><span class="nx">makeHtml</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">value</span><span class="p">)</span>
</span><span class='line'> <span class="p">}}</span>
</span><span class='line'> <span class="o">/></span>
</span><span class='line'> <span class="o"><</span><span class="err">/div></span>
</span><span class='line'> <span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span><span class='line'>
</span><span class='line'><span class="nx">React</span><span class="p">.</span><span class="nx">renderComponent</span><span class="p">(</span><span class="o"><</span><span class="nx">MarkdownEditor</span> <span class="o">/></span><span class="p">,</span> <span class="nx">mountNode</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>
<p>The caveat to this example is that it assumes that the <a href="https://github.com/coreyti/showdown">showdown</a> library is already loaded. In our Ember example, note that the library is loaded in the <em>head</em>.</p>
<figure class='code'><figcaption><span>Ember (controller)</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="nx">App</span><span class="p">.</span><span class="nx">ApplicationRoute</span> <span class="o">=</span> <span class="nx">Em</span><span class="p">.</span><span class="nx">Route</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'> <span class="nx">model</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="p">{</span> <span class="nx">value</span><span class="o">:</span> <span class="s1">'Type some *markdown* here!'</span> <span class="p">};</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span><span class='line'>
</span><span class='line'><span class="nx">Em</span><span class="p">.</span><span class="nx">Handlebars</span><span class="p">.</span><span class="nx">registerBoundHelper</span><span class="p">(</span><span class="s1">'markdown'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">str</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">converter</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Showdown</span><span class="p">.</span><span class="nx">converter</span><span class="p">();</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">html</span> <span class="o">=</span> <span class="nx">converter</span><span class="p">.</span><span class="nx">makeHtml</span><span class="p">(</span><span class="nx">str</span> <span class="o">||</span> <span class="s1">''</span><span class="p">);</span>
</span><span class='line'> <span class="k">return</span> <span class="k">new</span> <span class="nx">Handlebars</span><span class="p">.</span><span class="nx">SafeString</span><span class="p">(</span><span class="nx">html</span><span class="p">);</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>
<figure class='code'><figcaption><span>Ember (template)</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt"><div</span> <span class="na">class=</span><span class="s">"container"</span><span class="nt">></span>
</span><span class='line'> <span class="nt"><h3></span>Input<span class="nt"></h3></span>
</span><span class='line'> {{textarea value=value class="form-control"}}
</span><span class='line'> <span class="nt"><h3></span>Output<span class="nt"></h3></span>
</span><span class='line'> {{markdown value}}
</span><span class='line'><span class="nt"></div></span>
</span></code></pre></td></tr></table></div></figure>
<p>I added Twitter Bootstrap to this example for cleanliness.</p>
<p><a class="jsbin-embed" href="http://jsbin.com/eyOlOFI/7/embed?js,output">Facebook React vs Ember</a><script src="http://static.jsbin.com/js/embed.js"></script></p>
<p>I haven’t spent enough time with React to be able to convert the <a href="http://www.emberjs.com">Ember examples</a> to it, but I would love to see someone do that for a better comparison.</p>
<div class="about-box">
<a href="http://coderberry.me"><img src="https://en.gravatar.com/userimage/2313670/31b6875622886c41f150245d58acbd0e.jpg?size=100" class="avatar" align="left" /></a>
<p>
<a href="http://coderberry.me" class="author-name">Eric Berry</a> is a software engineer at <a href="http://www.instructure.com">Instructure</a> and loves giving back to the community via blog posts and meetups. He was a co-founder of <a href="http://h71028.www7.hp.com/enterprise/cache/504712-0-0-225-121.html">ShareAPhoto, Ltd</a>, a European online photo sharing company which was acquired by Hewlett-Packard in 2006. He was the author of <a href="http://www.amazon.com/Rails-Pocket-Reference-OReilly/dp/0596520700">Rails Pocket Reference</a> (published 2008 – O’Reilly). He spear-headed <a href="http://teachmetocode.com/screencasts/page/9/">TeachMeToCode.com</a>, a popular on-demand screencasting website dedicated to helping others learn how to program.
</p>
</div>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Android Async HTTP Clients: Volley vs Retrofit]]></title>
<link href="http://instructure.github.io/blog/2013/12/09/volley-vs-retrofit/"/>
<updated>2013-12-09T13:47:00-07:00</updated>
<id>http://instructure.github.io/blog/2013/12/09/volley-vs-retrofit</id>
<content type="html"><![CDATA[<p>We recently released a new version of our mobile app for Android. Although it was a huge improvement from previous installments in terms of features, design, and usability, there was one nagging issue in the back of our minds: speed. There are times when the app isn’t as snappy as we’d like it to be. After some profiling, benchmarks, and common sense, we determined that retrieving data from the API (the networking) was the bottleneck.</p>
<h2>The Old Way: AsyncTasks</h2>
<p>As of the latest version, we use the built-in AsyncTasks to retrieve data from Canvas’ servers. A quick Google search will explain the numerous issues with our approach: no orientation-change support, no ability to cancel network calls, as well as no easy way to make API calls in parallel. With the exception of Froyo and Gingerbread, AsyncTasks (by default) run in a serialized fashion. In a practical sense, this means that only one AsyncTask is running at any given time. Views that require multiple API calls (the DashBoard currently has 7) run extremely slow; sometimes taking multiple seconds to load.</p>
<!-- more -->
<h2>Introducing Volley and Retrofit</h2>
<p>Luckily, there are a few third party libraries that provide support for concurrent background threads, network caching, as well as other features that clean up networking code substantially. The first library that we looked into was <a href="https://android.googlesource.com/platform/frameworks/volley/">Volley</a>, an open-source library written by Google. It’s currently used in AOSP Android as well as most of Google’s first-party applications. The other library we looked into was <a href="http://square.github.io/retrofit/">RetroFit</a>, another open-source library written by Square.</p>
<h2>How We Decided</h2>
<p>The decision to switch the architecture of our networking code was not an easy one to make. The interface with the Canvas API is a substantial part of our application. At the time of writing this blog post, the Canvas for Android project has about 43,000 lines of actual code. Around 3,500 lines of that code are dedicated to interfacing with the Canvas API (setting up API endpoints, etc). JSON parsing comprises of another 7,300 lines of code. That means that more than 25% of our code is dedicated to retrieving/saving data from the Canvas API. That’s just making the API calls and parsing the results. That doesn’t include any AsyncTask code or caching, which we feel should be categorized as networking code as well.</p>
<p>As you can see, if we were going to switch out our networking code, it would have to be for <em>compelling</em> reasons as it’d be a huge refactor. In order to decide if it was worth it, we did a lot of reading about both Volley and Retrofit. We looked at forums, blogposts, example code; we read as much as we could. We learned a lot, but we will try to summarize it the best we can.</p>
<p>From outwards appearances, they are quite similar in usage. They both allow you to provide a “callback”, which is an interface with two methods that you must override: success and failure. One of the methods will be called on the main thread at the completion of the asynchronous network call. The big difference is in how you specify the API endpoint and what you actually get back.</p>
<p>With Volley, you specify the <strong>entire</strong> endpoint dynamically (parameters and all) at the time of making the API call. By default, Volley returns a JSONObject or a JSONArray depending on the type of request.</p>
<p>Retrofit, on the other hand, has you set the base endpoint url for all API calls, then it has you build static interfaces that specify endpoints using Java <em>annotations</em>. You can cleanly and dynamically substitute path-segments, POST/GET variables, etc. into the endpoint at the time of making the API call. In order to make an API call with RetroFit, you call a method on the interface, pass in any substitutions, and it will return to you a java model object. By default, Retrofit does the JSON parsing automatically using GSON (which is really, really fast) although you can plug in your own JSON parser if you want. Even though the setup is slightly different, the actual API calls are done in a similar way.</p>
<p>In order to get some performance benchmarks, We wrote a sample application where we could control/simulate real-world API calls that Canvas for Android actually makes. It would also give me a little bit of experience actually using the libraries. To start off with, we wrote a very basic app that allowed me to toggle between an easy API with little JSON parsing and a complex API with a long response. The total number of API calls to make could be changed in the app as well. We also included the exact suite of API calls that the Canvas for Android Dashboard makes for a more real-world test. This benchmark showed me three things: 1) they were both significantly easier to use than AsyncTasks, 2) they both cleaned up the codebase, and 3) they were both a lot faster than what we were currently doing. Obviously the benchmarks fluctuated based upon network conditions; however, they consistently outperformed the way we are currently doing our networking.</p>
<p> <img src="http://i.imgur.com/tIdZkl3.png" alt="" /></p>
<p>In all three tests with varying repeats (1 – 25 times), Volley was anywhere from 50% to 75% faster. Retrofit clocked in at an impressive 50% to 90% faster than the AsyncTasks, hitting the same endpoint the same number of times. On the <em>Dashboard test suite</em>, this translated into loading/parsing the data several seconds faster. That is a massive real-world difference. In order to make the tests fair, the times for AsyncTasks/Volley included the JSON parsing as Retrofit does it for you automatically.</p>
<p>At this point, we wanted to switch our networking library for performance reasons, but our decision had to take other criteria into consideration. If we were going to spend time refactoring a quarter of our code base, we would have to be a little bit picky. Some of the things we took into account were speed, ease of integration, code cleanup, scalability, and time required to write new API calls.</p>
<h2>RetroFit Wins</h2>
<p>In the end, we decided to go with Retrofit for our application. Not only is it ridiculously fast, but it meshes quite well with our existing architecture. We were able to make a parent <em>Callback Interface</em> that automatically handles the error function, caching, and pagination with little to no effort for our APIs. In order to merge in Retrofit, we have to rename our variables to make our models GSON compliant, write a few simple interfaces, delete functions from the old API, and modify our fragments to not use AsyncTasks. Now that we have a few fragments completely converted, it’s pretty painless. There were some growing pains and issues that we had to overcome, but overall it went smoothly. In the beginning, we ran into a few technical issues/bugs, but Square has a fantastic <a href="https://plus.google.com/communities/109244258569782858265">Google+ community</a> that was able to help us through it. We have successfully converted our entire app to Retrofit. A build that’s running solely retrofit can be expected in the Play Store in the coming weeks.</p>
<p>Feel free to ask questions in the comments if you have any.</p>
<h2>Resources:</h2>
<h3>Retrofit:</h3>
<ul>
<li><a href="https://github.com/square/retrofit">Source and Samples</a> (Source and samples)</li>
<li><a href="http://square.github.io/retrofit/">Square Homepage</a></li>
<li><a href="https://plus.google.com/u/0/communities/109244258569782858265">Square Google+ Community</a></li>
</ul>
<h3>Volley:</h3>
<ul>
<li><a href="https://android.googlesource.com/platform/frameworks/volley/">Source</a></li>
<li><a href="https://developers.google.com/live/shows/474338138">Demonstration</a></li>
<li><a href="https://github.com/ogrebgr/android_volley_examples">Github of Examples</a></li>
<li><a href="http://www.technotalkative.com/android-volley-library-example">Usage Example</a></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Crafting accessible content]]></title>
<link href="http://instructure.github.io/blog/2013/12/02/crafting-accessible-content/"/>
<updated>2013-12-02T09:52:00-07:00</updated>
<id>http://instructure.github.io/blog/2013/12/02/crafting-accessible-content</id>
<content type="html"><![CDATA[<p>At Instructure, we’re moving more and more of our app to the client with technologies like <a href="http://emberjs.com">Ember.js</a>. While it and other JavaScript frameworks have made this transition easier, they’ve also introduced new challenges around keeping our content accessible.</p>
<p>The old advice we’ve all heard about using semantic markup, headers, and <code>alt</code> attributes on <code><img /></code> tags is still true, but it doesn’t address how we can best develop accessible content in a rich client application. Despite rumors to the contrary, rich content <em>can</em> be accessible if we pay attention to a few basics.</p>
<!--more-->
<h2>Getting started with accessibility</h2>
<blockquote><p>The Web is fundamentally designed to work for all people, whatever their hardware, software, language, culture, location, or physical or mental ability. When the Web meets this goal, it is accessible to people with a diverse range of hearing, movement, sight, and cognitive ability.</p><footer><strong>W3</strong> <cite><a href='http://www.w3.org/standards/webdesign/accessibility'>www.w3.org/standards/webdesign/…</a></cite></footer></blockquote>
<p>Let’s start with a few definitions:</p>
<ul>
<li><strong>Accessibility</strong>: Web content is accessible when it usable by persons with disabilities. While this includes users of screen readers, it also includes persons with cognitive and other disabilities.</li>
<li><strong>WAI-ARIA</strong>: A suite of technologies designed to make rich Internet applications accessible to users with disabilities.</li>
</ul>
<p>Authoring accessible rich content most often means (1) using WAI-ARIA attributes such as <code>role</code> and <code>aria-expanded</code> to mark-up content in a machine-parseable way; (2) ensuring that all content is keyboard navigable; and (3) managing page focus.</p>
<p>So what does all of this mean when you’re developing widgets? Let’s take a look at an example of a button set component.</p>
<h2>Building a button set</h2>
<p>We’re going to build an accessible <a href="http://getbootstrap.com/components/#btn-groups">button set</a> using Twitter’s Bootstrap styles and jQuery.</p>
<p>Our button set is going to work like a filter, so users can only select one button at a time. This means it’s like a radio button. Watch how we can use aria roles and attributes to convey that behavior to non-sighted users:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt"><div</span> <span class="na">class=</span><span class="s">"btn-group"</span> <span class="na">role=</span><span class="s">"radiogroup"</span><span class="nt">></span>
</span><span class='line'> <span class="nt"><button</span> <span class="na">type=</span><span class="s">"button"</span>
</span><span class='line'> <span class="na">class=</span><span class="s">"btn btn-default active"</span>
</span><span class='line'> <span class="na">role=</span><span class="s">"radio"</span>
</span><span class='line'> <span class="na">aria-checked=</span><span class="s">"true"</span><span class="nt">></span>Open<span class="nt"></button></span>
</span><span class='line'> <span class="nt"><button</span> <span class="na">type=</span><span class="s">"button"</span>
</span><span class='line'> <span class="na">class=</span><span class="s">"btn btn-default"</span>
</span><span class='line'> <span class="na">role=</span><span class="s">"radio"</span>
</span><span class='line'> <span class="na">aria-checked=</span><span class="s">"false"</span><span class="nt">></span>Closed<span class="nt"></button></span>
</span><span class='line'><span class="nt"></div></span>
</span></code></pre></td></tr></table></div></figure>
<p>First, notice that we didn’t change Twitter’s recommended button set markup — we only augmented it with the <code>role</code> attributes and an <code>aria-checked</code> attribute. The <code>role</code> attribute describes the component’s behavior to screen readers, and <code>aria-checked</code> attribute notifies users of the current option in the same way that the <code>active</code> class does for sighted users.</p>
<p>Here’s the JavaScript to make this happen:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">$</span><span class="p">.</span><span class="nx">fn</span><span class="p">.</span><span class="nx">buttonset</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">on</span><span class="p">(</span><span class="s1">'click'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">$target</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'> <span class="nx">$target</span><span class="p">.</span><span class="nx">siblings</span><span class="p">()</span>
</span><span class='line'> <span class="p">.</span><span class="nx">removeClass</span><span class="p">(</span><span class="s1">'active'</span><span class="p">)</span>
</span><span class='line'> <span class="p">.</span><span class="nx">attr</span><span class="p">(</span><span class="s1">'aria-checked'</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'> <span class="nx">$target</span>
</span><span class='line'> <span class="p">.</span><span class="nx">addClass</span><span class="p">(</span><span class="s1">'active'</span><span class="p">)</span>
</span><span class='line'> <span class="p">.</span><span class="nx">attr</span><span class="p">(</span><span class="s1">'aria-checked'</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span><span class='line'> <span class="p">});</span>
</span><span class='line'><span class="p">};</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// usage</span>
</span><span class='line'><span class="nx">$</span><span class="p">(</span><span class="s1">'.btn-group .btn'</span><span class="p">).</span><span class="nx">buttonset</span><span class="p">();</span>
</span></code></pre></td></tr></table></div></figure>
<p>While we’re defining this as a jQuery plugin, we could have just as easily made an Ember component, an Angular directive, or a Backbone view.</p>
<p>We’ve found that this level is often the best place for dealing with accessibility. By handling accessibility details in our reusable widgets and libraries we can code it once and benefit across our stack. New engineers can immediately start writing accessible code, and all engineers benefit from quick, accessible implementations of common patterns.</p>
<p>In this case, our code is almost all standard jQuery. This solution doesn’t require us to manage focus or worry about keyboard navigation because buttons are already in the tab order, but often widget markup will need a <code>tabindex=-1</code> attribute and calls like <code>$('.item').focus()</code> to ensure that screen reader users aren’t lost on the page.</p>
<p>Here’s our component in action (it’s easier to test with a screen reader if you pop out this example into its own page first):</p>
<p><a class="jsbin-embed" href="http://jsbin.com/OBoqALa/1/embed?output">JS Bin</a><script src="http://static.jsbin.com/js/embed.js"></script></p>
<h2>Testing accessibility</h2>
<p>If you’re on a Mac, you already have the software you need to get started testing for accessibility. OSX ships with a screen reader, VoiceOver, that can be enabled in your System Preferences and activated by pressing Cmd-F5.</p>
<p>If you’re on Windows, take a look at the free <a href="http://www.nvaccess.org/">NVDA</a> or, if you’re doing professional development, the more widely used <a href="http://www.freedomscientific.com/products/fs/jaws-product-page.asp">JAWS</a>.</p>
<p>To ensure that everything we write is accessible, we test all new commits in VoiceOver and JAWS as well as in our supported browsers before merging to master. And while giving accessibility top priority alongside visual fidelity and layout initially slowed us down, we’ve long since adjusted and now have better code and a better product.</p>
<h2>Wrapping up</h2>
<p>Developing with accessibility in mind has been a great experience at Instructure. By starting with an eye to accessibility we’ve been able to leverage WAI-ARIA tools to create rich, accessible content in an unobtrusive way.</p>
<h3>Additional resources</h3>
<p>To learn more about accessibility, take a look at the W3’s <a href="http://www.w3.org/TR/wai-aria-practices">Authoring Practices</a> document. It covers additional topics like keyboard shortcuts, managing focus, and properly labeling content. The Illinois Center of Information Technology and Web Accessibility also have a great <a href="http://test.cita.uiuc.edu/aria/">collection of accessibility examples</a>.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Hello World!]]></title>
<link href="http://instructure.github.io/blog/2013/12/02/hello-world/"/>
<updated>2013-12-02T08:39:00-07:00</updated>
<id>http://instructure.github.io/blog/2013/12/02/hello-world</id>
<content type="html"><![CDATA[<p>Welcome to our new blog! Instructure is a technology company. And we have some pretty killer technologists who have opinions. This blog is an outlet for them to talk about stuff.</p>
<p>Feel free to join in the discussion. If you disagree, don’t be a wimp—speak up.</p>
<p>Look forward to talking more!</p>
<p>Joel
CTO</p>
]]></content>
</entry>
</feed>