<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://web.dev/</id>
  <title>Jeremy Chone on web.dev</title>
  <updated>2026-04-15T23:21:06Z</updated>
  <author>
    <name>Jeremy Chone</name>
  </author>
  <link href="https://web.dev/authors/jeremychone/feed.xml" rel="self"/>
  <link href="https://web.dev/"/>
  <icon>https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bnjbSoWQdzP3AEYOyZnW.png?auto=format</icon>
  <logo>https://web.dev/images/shared/rss-banner.png</logo>
  <subtitle>Developer</subtitle>
  
  
  <entry>
    <title>Asynch JS - The power of $.Deferred</title>
    <link href="https://web.dev/async-deferred/"/>
    <updated>2012-08-29T00:00:00Z</updated>
    <id>https://web.dev/async-deferred/</id>
    <content type="html" mode="escaped">&lt;p&gt;One of the most important aspects about building smooth and responsive HTML5 applications is the synchronization
between all the different parts of the application such as data fetching, processing, animations, and user
interface elements.&lt;/p&gt;
&lt;p&gt;The main difference with a desktop or a native environment is that browsers do not give access to the threading model
and provide a single thread for everything accessing the user interface (i.e. the DOM). This means that all the
application logic accessing and modifying the user interface elements is always in the same thread, hence the
importance of keeping all the application work units as small and efficient as possible and taking advantage of any
asynchronous capabilities the browser offers as much as possible.&lt;/p&gt;
&lt;h2 id=&quot;browser-asynchronous-apis&quot;&gt;Browser Asynchronous APIs &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/async-deferred/#browser-asynchronous-apis&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Luckily, Browsers provide a number of asynchronous APIs such as the commonly used XHR (XMLHttpRequest or &#39;AJAX&#39;) APIs, as well
as IndexedDB, SQLite, HTML5 Web workers, and the HTML5 GeoLocation APIs to name a few. Even some DOM related actions are
exposed asynchronously, such CSS3 animation via the transitionEnd events.&lt;/p&gt;
&lt;p&gt;The way browsers expose asynchronous programming to the application logic is via events or callbacks.&lt;br /&gt;
In event-based asynchronous APIs, developers register an event handler for a given object
(e.g. HTML Element or other DOM objects) and then call the action. The browser will perform
the action usually in a different thread, and trigger the event in the main thread when appropriate.&lt;/p&gt;
&lt;p&gt;For example, code using the XHR API, an event based asynchronous API, would look like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Create the XHR object to do GET to /data resource  &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; xhr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;XMLHttpRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;xhr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;GET&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// register the event handler&lt;/span&gt;&lt;br /&gt;xhr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;load&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xhr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;We got data: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; xhr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// perform the work&lt;/span&gt;&lt;br /&gt;xhr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The CSS3 transitionEnd event is another example of a event based asynchronous API.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// get the html element with id &#39;flyingCar&#39;  &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; flyingCarElem &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;flyingCar&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// register an event handler &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// (&#39;transitionEnd&#39; for FireFox, &#39;webkitTransitionEnd&#39; for webkit) &lt;/span&gt;&lt;br /&gt;flyingCarElem&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;transitionEnd&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// will be called when the transition has finished.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;The car arrived&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// add the CSS3 class that will trigger the animation&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Note: some browers delegate some transitions to the GPU , but &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//       developer does not and should not have to care about it.&lt;/span&gt;&lt;br /&gt;flyingCarElemen&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;classList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;makeItFly&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Other browser APIs, such as SQLite and HTML5 Geolocation, are callback based, meaning
that the developer passes a function as argument that will get called back by the
underlying implementation with the corresponding resolution.&lt;/p&gt;
&lt;p&gt;For example, for HTML5 Geolocation, the code looks like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// call and pass the function to callback when done.&lt;/span&gt;&lt;br /&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;geolocation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCurrentPosition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Lat: &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; position&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;latitude &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39; &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;  &lt;br /&gt;                &lt;span class=&quot;token string&quot;&gt;&#39;Lon: &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; position&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;longitude&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;In this case, we just call a method and pass a function that will get called back with the
requested result. This allows the browser to implement
this functionality synchronously or asynchronously and give a single API to the developer regardless
of the implementation details.&lt;/p&gt;
&lt;h2 id=&quot;making-applications-asynchronous-ready&quot;&gt;Making Applications Asynchronous-Ready &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/async-deferred/#making-applications-asynchronous-ready&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Beyond the browser’s built-in asynchronous APIs, well architected applications should
expose their low level APIs in an asynchronous fashion as well, especially when they do any
sort of I/O or computational heavy processing. For example, APIs to get data should
be asynchronous, and should NOT look like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// WRONG: this will make the UI freeze when getting the data  &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;We got data: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This API design requires the &lt;strong&gt;getData()&lt;/strong&gt; to be blocking, which will freeze the user
interface until the data is fetched. If the data is local in the JavaScript context
then this might not be an issue, however if the data needs to be fetched from the
network or even locally in a SQLite or index store this could have dramatic impact on
the user experience.&lt;/p&gt;
&lt;p&gt;The right design is to proactively make all application API that could take some time
to process, asynchronous from the beginning as retrofitting synchronous application code
to be asynchronous can be a daunting task.&lt;/p&gt;
&lt;p&gt;For example the simplistic getData() API would become something like:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;getData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;We got data: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The nice thing about this approach is that this forces the application UI code to be
asynchronous-centric from the beginning and allows the underlying APIs to decide if
they need to be asynchronous or not in a later stage.&lt;/p&gt;
&lt;p&gt;Note that not all the application API need or should be asynchronous. The rule of
thumb is that any API that does any type of I/O or heavy processing (anything that
can take longer than 15ms) should be exposed asynchronously from the start even if
the first implementation is synchronous.&lt;/p&gt;
&lt;h2 id=&quot;handling-failures&quot;&gt;Handling Failures &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/async-deferred/#handling-failures&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One catch of asynchronous programing is that the traditional try/catch way to handle
failures does not really work anymore, as errors usually happen in another thread.
Consequently, the callee needs to have a structured way to notify the caller when
something goes wrong during the processing.&lt;/p&gt;
&lt;p&gt;In an event-based asynchronous API this is often accomplished by the application code
querying the event or object when receiving the event. For callback based
asynchronous APIs, the best practice is to have a second argument that takes a
function that would be called in case of a failure with the appropriate error
information as argument.&lt;/p&gt;
&lt;p&gt;Our getData call would look like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// getData(successFunc,failFunc);  &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;getData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;We got data: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;ex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;oops, some problem occured: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; ex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;putting-it-together-with-dollardeferred&quot;&gt;Putting it together with $.Deferred &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/async-deferred/#putting-it-together-with-dollardeferred&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One limitation of the above callback approach is that it can become really cumbersome
to write even moderately advanced synchronization logic.&lt;/p&gt;
&lt;p&gt;For example, if you need to wait for two asynchronous API to be done before doing a
third one, code complexity can rise quickly.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// first do the get data.   &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;getData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// then get the location&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;getLocation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;we got data: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; and location: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; location&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;ex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;getLocation failed: &quot;&lt;/span&gt;  &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; ex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;ex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;getData failed: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; ex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Things can even get more complex when the application needs to make the same call
from multiple parts of the application, as every call will have to perform these multi
step calls, or the application will have to implement its own caching mechanism.&lt;/p&gt;
&lt;p&gt;Luckily, there is a relatively old pattern, called Promises (kind of similar to
&lt;a href=&quot;http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Future.html&quot; rel=&quot;noopener&quot;&gt;Future&lt;/a&gt; in Java) and a robust and modern implementation
in jQuery core called &lt;a href=&quot;http://api.jquery.com/category/deferred-object/&quot; rel=&quot;noopener&quot;&gt;$.Deferred&lt;/a&gt; that provides a simple and powerful solution to asynchronous programing.&lt;/p&gt;
&lt;p&gt;To make it simple, the Promises pattern defines that the asynchronous API returns a
Promise object which is kind of a “Promise that the result will be resolved with the
corresponding data.” To get the resolution, the caller gets the Promise object and
calls a &lt;strong&gt;done(successFunc(data))&lt;/strong&gt; which will tell the Promise object to call this
&lt;strong&gt;successFunc&lt;/strong&gt; when the “data” is resolved.&lt;/p&gt;
&lt;p&gt;So, the getData call example above becomes like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// get the promise object for this API  &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; dataPromise &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// register a function to get called when the data is resolved&lt;/span&gt;&lt;br /&gt;dataPromise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;We got data: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// register the failure function&lt;/span&gt;&lt;br /&gt;dataPromise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;ex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;oops, some problem occured: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; ex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Note: we can have as many dataPromise.done(...) as we want. &lt;/span&gt;&lt;br /&gt;dataPromise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;We asked it twice, we get it twice: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Here, we get the &lt;strong&gt;dataPromise&lt;/strong&gt; object first and then call the &lt;strong&gt;.done&lt;/strong&gt; method to register
a function we want to get called back when the data gets resolved. We can also call
the &lt;strong&gt;.fail&lt;/strong&gt; method to handle the eventual failure.  Note that we can have as many &lt;strong&gt;.done&lt;/strong&gt;
or &lt;strong&gt;.fail&lt;/strong&gt; calls as we need since the underlying Promise implementation (jQuery code) will
handle the registration and callbacks.&lt;/p&gt;
&lt;p&gt;With this pattern, it is relatively easy to implement more advanced synchronization
code, and jQuery already provides the most common one such a &lt;a href=&quot;http://api.jquery.com/jQuery.when/&quot; rel=&quot;noopener&quot;&gt;$.when&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For example, the nested &lt;strong&gt;getData&lt;/strong&gt;/&lt;strong&gt;getLocation&lt;/strong&gt; callback above would become something like:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// assuming both getData and getLocation return their respective Promise&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; combinedPromise &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getLocation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// function will be called when both getData and getLocation resolve&lt;/span&gt;&lt;br /&gt;combinePromise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;location&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;We got data: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; dataResult &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; and location: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; location&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;And the beauty of it all is that jQuery.Deferred makes it very easy for developers to
implement the asynchronous function. For example, the getData could look something like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// 1) create the jQuery Deferred object that will be used&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; deferred &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Deferred&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// ---- AJAX Call ---- //&lt;/span&gt;&lt;br /&gt;XMLHttpRequest xhr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;XMLHttpRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;xhr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;GET&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// register the event handler&lt;/span&gt;&lt;br /&gt;xhr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;load&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xhr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// 3.1) RESOLVE the DEFERRED (this will trigger all the done()...)&lt;/span&gt;&lt;br /&gt;    deferred&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xhr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// 3.2) REJECT the DEFERRED (this will trigger all the fail()...)&lt;/span&gt;&lt;br /&gt;    deferred&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;HTTP error: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; xhr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// perform the work&lt;/span&gt;&lt;br /&gt;xhr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Note: could and should have used jQuery.ajax. &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Note: jQuery.ajax return Promise, but it is always a good idea to wrap it&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//       with application semantic in another Deferred/Promise  &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// ---- /AJAX Call ---- //&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// 2) return the promise of this deferred&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; deferred&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;So, when the getData() is called, it first creates a new jQuery.Deferred object (1)
and then returns its Promise (2) so that the caller can register its done and fail
functions. Then, when the XHR call returns, it either resolves the deferred (3.1) or
reject it (3.2). Doing the deferred.resolve will trigger all the done(…) functions
and other promise functions (e.g., then and pipe) and calling deferred.reject will
call all the fail() functions.&lt;/p&gt;
&lt;h2 id=&quot;use-cases&quot;&gt;Use Cases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/async-deferred/#use-cases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here are some good use cases where Deferred can be very useful:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Data Access:&lt;/strong&gt; Exposing data access APIs as $.Deferred is often the right design.
This is obvious for remote data, as synchronous remote calls would completely ruin the
user experience, but is also true for local data as often the lower level APIs (e.g.,
SQLite and IndexedDB) are asynchronous themselves. The Deferred API&#39;&#39;s $.when and .pipe
are extremely powerful to synchronize and chain asynchronous sub-queries.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UI Animations:&lt;/strong&gt; Orchestrating one or more animations with transitionEnd events
can be quite tedious, especially when the animations are a mixed of CSS3 animation
and JavaScript (as it is often the case). Wrapping the animation functions as Deferred
can significantly reduce the code complexity and improve flexibility. Even a simple
generic wrapper function like cssAnimation(className) that will return the Promise
object that gets resolved on transitionEnd could be of a great help.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UI Component Display:&lt;/strong&gt; This is a little bit more advanced, but advanced HTML
Component frameworks should use the Deferred as well. Without going too much into
the details (this will be the subject of another post), when an application needs to
display different parts of the user interface, having the lifecycle of those
components encapsulated in Deferred allows greater control of the timing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Any browser asynchronous API:&lt;/strong&gt; For normalization purpose, it is often a good
idea to wrap the browser API calls as Deferred. This takes literally 4 to 5 lines
of code each, but will greatly simplify any application code. As show in the above
getData/getLocation pseudo code, this allows the applications code to have one
asynchronous model across all types of API (browsers, application specifics, and
compound).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Caching:&lt;/strong&gt; This is kind of a side benefit, but can be very useful in some
occasion. Because the Promise APIs (e.g., .done(…) and .fail(…)) can be called
before or after the asynchronous call is performed, the Deferred object can be
used as a caching handle for an asynchronous call. For example, a CacheManager
could just keep track of Deferred for given requests, and return the Promise of
the matching Deferred if it has not be invalidated. The beauty is that the caller
does not have to know if the call has already been resolved or is in the process
of being resolved, its callback function will get called exactly the same way.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/async-deferred/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While the $.Deferred concept is simple, it can take time to get a good handle on it.
However, given the nature of the browser environment, mastering asynchronous
programing in JavaScript is a must for any serious HTML5 application developer and
the Promise pattern (and the jQuery implementation) are tremendous tools
to make asynchronous programming reliable and powerful.&lt;/p&gt;
</content>
    <author>
      <name>Jeremy Chone</name>
    </author>
  </entry>
  
  <entry>
    <title>Case Study - HTML5 MathBoard</title>
    <link href="https://web.dev/mathboard/"/>
    <updated>2011-10-28T00:00:00Z</updated>
    <id>https://web.dev/mathboard/</id>
    <content type="html" mode="escaped">&lt;h2 id=&quot;introduction&quot;&gt;Introduction &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#introduction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
&lt;img alt=&quot;MathBoard application&quot; decoding=&quot;async&quot; height=&quot;175&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 126px) 126px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TmDqcNJ9pDwoXKNl55jV.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TmDqcNJ9pDwoXKNl55jV.png?auto=format&amp;w=126 126w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TmDqcNJ9pDwoXKNl55jV.png?auto=format&amp;w=144 144w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TmDqcNJ9pDwoXKNl55jV.png?auto=format&amp;w=164 164w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TmDqcNJ9pDwoXKNl55jV.png?auto=format&amp;w=187 187w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TmDqcNJ9pDwoXKNl55jV.png?auto=format&amp;w=213 213w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TmDqcNJ9pDwoXKNl55jV.png?auto=format&amp;w=243 243w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TmDqcNJ9pDwoXKNl55jV.png?auto=format&amp;w=252 252w&quot; width=&quot;126&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;http://itunes.apple.com/us/app/mathboard/id373909837?mt=8&quot; rel=&quot;noopener&quot;&gt;MathBoard on iPad&lt;/a&gt;,
a &lt;a href=&quot;http://www.palasoftware.com/MathBoard.html&quot; rel=&quot;noopener&quot;&gt;PalaSoftware&lt;/a&gt; application,
is a highly polished application with many subtle but
natural animations and a unique realistic look and feel. The goal was to do the
highest fidelity port of the iPad application to HTML5.&lt;/p&gt;
&lt;p&gt;N2N-Apps is a Software Development company focusing on building next generation
of Web and Mobile application with HTML5 technology. The company was funded in
2010 by Jeremy Chone whom, after 11 years of engineering and management
experience from Netscape, Oracle, and Adobe, decided to share its expertise with
businesses to build high-quality Web and Mobile applications. N2N-Apps focuses
on quality and speed of delivery.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://chrome.google.com/webstore/detail/elcilkmmbpmchojdmdohhoalmfmkcklk&quot; rel=&quot;noopener&quot;&gt;Download MathBoard for the Chrome Web Store&lt;/a&gt;
&lt;a href=&quot;https://chrome.google.com/webstore/detail/ocjpbdojdmdmnoijibadlmpiamcmmmcj&quot; rel=&quot;noopener&quot;&gt;Download MathBoard for the Chrome Web Store&lt;/a&gt; (free version)&lt;/p&gt;
&lt;h2 id=&quot;requirements&quot;&gt;Requirements &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#requirements&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The key requirements for this HTML5 porting project were the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;High fidelity port of the original iPad application look and feel and user interface.&lt;/li&gt;
&lt;li&gt;Adapt to the target form factor (i.e. PC/Mac with keyboard/mouse vs touch screen).&lt;/li&gt;
&lt;li&gt;Implement 100% of the applicable features.&lt;/li&gt;
&lt;li&gt;Target principally HTML5 browsers.&lt;/li&gt;
&lt;li&gt;Make the application &amp;quot;server-less&amp;quot; so that the application runs entirely on the client and could be hosted on a static server or Google Chrome packaged application.&lt;/li&gt;
&lt;li&gt;Make a 1.0 version with all the features but the problem solver in less than a month.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;architecture&quot;&gt;Architecture &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#architecture&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
&lt;img alt=&quot;Architecture&quot; decoding=&quot;async&quot; height=&quot;206&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 161px) 161px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ioBgfDSe8lwlCBr71gqw.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ioBgfDSe8lwlCBr71gqw.png?auto=format&amp;w=161 161w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ioBgfDSe8lwlCBr71gqw.png?auto=format&amp;w=184 184w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ioBgfDSe8lwlCBr71gqw.png?auto=format&amp;w=209 209w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ioBgfDSe8lwlCBr71gqw.png?auto=format&amp;w=239 239w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ioBgfDSe8lwlCBr71gqw.png?auto=format&amp;w=272 272w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ioBgfDSe8lwlCBr71gqw.png?auto=format&amp;w=310 310w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/ioBgfDSe8lwlCBr71gqw.png?auto=format&amp;w=322 322w&quot; width=&quot;161&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Given the requirements, we decided to go with the following architecture:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;HTML5: Since we do not have any HTML4 support requirements, we decided to go with HTML5 as the base.&lt;/li&gt;
&lt;li&gt;jQuery: While HTML5 has many of the advanced selectors that make jQuery so
great, we decided to stick with jQuery anyway as it gave us a very robust and
mature way to manipulate the DOM and related events. jQuery also has the
benefit of being more DOM centric, which tends to make the
design and implementation of an application closer to HTML.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jeremychone/snowUI&quot; rel=&quot;noopener&quot;&gt;SnowUI&lt;/a&gt;: jQuery provides
a great API and best practice to work with the DOM,
however, for the HTML5 MathBoard application we needed an MVC or MVP style
framework to orchestrate all of the different views. SnowUI
is a simple yet powerful MVC framework on top of jQuery. It provides a DOM
centric MVC mechanism and a flexible way to build custom components while
leaving the opportunity for the application developer to use any widget/controls
library or custom code he or she deems optimal.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;ipad-to-pc-considerations&quot;&gt;iPad to PC considerations &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#ipad-to-pc-considerations&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When porting the application to HTML5 for PC usage, we had to make several
modifications to the design and user-interaction of the application.&lt;/p&gt;
&lt;h3 id=&quot;screen-orientation&quot;&gt;Screen orientation &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#screen-orientation&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The iPad MathBoard is exclusively vertically oriented, which was not optimal
for PC displays as they are generally used in a horizontal fashion. Consequently,
we reorganized the UI design and moved the settings panel to the right side, on a
sliding view (animated by CSS3 transitions).&lt;/p&gt;
&lt;figure&gt;
    &lt;img alt=&quot;Screen Orientation&quot; decoding=&quot;async&quot; height=&quot;276&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 500px) 500px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PQW1aE8WZqc3gibulDCM.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PQW1aE8WZqc3gibulDCM.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PQW1aE8WZqc3gibulDCM.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PQW1aE8WZqc3gibulDCM.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PQW1aE8WZqc3gibulDCM.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PQW1aE8WZqc3gibulDCM.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PQW1aE8WZqc3gibulDCM.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PQW1aE8WZqc3gibulDCM.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PQW1aE8WZqc3gibulDCM.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PQW1aE8WZqc3gibulDCM.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PQW1aE8WZqc3gibulDCM.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PQW1aE8WZqc3gibulDCM.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PQW1aE8WZqc3gibulDCM.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PQW1aE8WZqc3gibulDCM.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/PQW1aE8WZqc3gibulDCM.png?auto=format&amp;w=1000 1000w&quot; width=&quot;500&quot; /&gt;
    &lt;figcaption&gt;iPad vs. HTML5 screen orientation&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;input-keyboardmouse-vs-touch&quot;&gt;Input: keyboard/mouse vs. touch &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#input-keyboardmouse-vs-touch&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Another key difference between the iPad and Web version is the
input interface. On the iPad you have only the touch interface, on the PC
you need take into consideration both mouse and keyboard.&lt;/p&gt;
&lt;p&gt;The MathBoard input controls on the iPad are highly polished. We wanted the
same high fidelity representation in the Web interface. The solution
was adding support for keyboard shortcuts and replicating UI controls
using CSS positioning. The port to HTML5 was pixel perfect:&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;UI Controls&quot; decoding=&quot;async&quot; height=&quot;275&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 500px) 500px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/egAf6O9gsAUf3HVvq1KB.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/egAf6O9gsAUf3HVvq1KB.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/egAf6O9gsAUf3HVvq1KB.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/egAf6O9gsAUf3HVvq1KB.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/egAf6O9gsAUf3HVvq1KB.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/egAf6O9gsAUf3HVvq1KB.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/egAf6O9gsAUf3HVvq1KB.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/egAf6O9gsAUf3HVvq1KB.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/egAf6O9gsAUf3HVvq1KB.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/egAf6O9gsAUf3HVvq1KB.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/egAf6O9gsAUf3HVvq1KB.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/egAf6O9gsAUf3HVvq1KB.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/egAf6O9gsAUf3HVvq1KB.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/egAf6O9gsAUf3HVvq1KB.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/egAf6O9gsAUf3HVvq1KB.png?auto=format&amp;w=1000 1000w&quot; width=&quot;500&quot; /&gt;
  &lt;figcaption&gt;iPad vs. HTML5 Version Settings&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;As in the iPad interface, we allow the user to click on the left and right
arrow to change the value of a control. The vertical line can also be dragged to
quickly change values. A repeat behavior was implemented for &lt;code&gt;click&lt;/code&gt;
and &lt;code&gt;keydown&lt;/code&gt; so that users can accelerate the value change when the
mouse or the keyboard is pressed.&lt;/p&gt;
&lt;p&gt;TAB support was added to move from one input field to another and the
← and → arrows cycles through values.&lt;/p&gt;
&lt;p&gt;One feature in the iPad version that didn&#39;t make much sense for the PC
interface was the drawing board. While it could have been fancy to implement it,
drawing numbers with a mouse is not very practical. Instead, we decided to spend more
time polishing the keyboard interface than implementing the drawing board.&lt;/p&gt;
&lt;h2 id=&quot;html5-features&quot;&gt;HTML5 features &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#html5-features&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the Web version of MathBoard, we use many HTML5 features:&lt;/p&gt;
&lt;h3 id=&quot;local-storage&quot;&gt;Local storage &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#local-storage&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MathBoard allow users to save their quiz to later replay them. HTML5 MathBoard
implements this feature using HTML5 &lt;code&gt;localStorage&lt;/code&gt; using the
SnowUI DAO interface.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;localStorage&lt;/code&gt; was a natural choice since the data was simple
enough and did not require advanced indexing. We store all quizzes
in one JSON format that we &lt;code&gt;JSON.stringify&lt;/code&gt; as text.&lt;/p&gt;
&lt;p&gt;The snowUI DAO is a simple CRUD interface wrapper which allows the UI to
fetch data without having to worry about how it&#39;s actually stored. The DAO
implementation takes care of the storage particulars.&lt;/p&gt;
&lt;p&gt;In MathBoard, the storage requirements were very simple. We needed to
store only the user settings and the quiz data. Both where stored as JSON
strings in &lt;code&gt;localStorage&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So, for example, the DAO for the setting value looked like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;snow&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;registerDao&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;settingValue&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; _settingValues &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SettingValueDao&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// ------ DAO CRUD Interface ------ //&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// get&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token class-name&quot;&gt;SettingValueDao&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;objectType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getSettingValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// find, remove&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// save&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token class-name&quot;&gt;SettingValueDao&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;save&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;objectType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; storeValue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getSettingValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;settingValue&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;storeValue&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      storeValue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token function&quot;&gt;getSettingValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; storeValue&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    $&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;storeValue&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;saveSettingValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// ------ /DAO CRUD Interface ------ //&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getSettingValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_settingValues &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; settingValuesString &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;settingValues&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;settingValuesString&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        _settingValues &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;settingValuesString&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        _settingValues &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; _settingValues&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;saveSettingValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; settingValues &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getSettingValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;settingValues &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;settingValues&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;settingValues&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;settingValues&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SettingValueDao&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Once this DAO is registered for the &lt;code&gt;settingValue&lt;/code&gt;, the UI can
make the following call without needing to worry about the store logic:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; addition &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; snow&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;settingValue&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;operator_addition&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;addition&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// to check the addition checkbox&lt;/span&gt;&lt;br /&gt;snow&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;settingValue&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; addition&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;css3-fonts&quot;&gt;CSS3 fonts &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#css3-fonts&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MathBoard uses custom fonts. Thanks to CSS3 font support, it was trivial
to include the &#39;Chalkduster&#39; true type font into our application:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@font-face&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Chalkduster&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Chalkduster.ttf&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;And, since this font was the default for almost all the text in the
application, we made it the default for body.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #333333&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Chalkduster&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #ffffff&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;css3-gradient,-shadow,-rounded-corners&quot;&gt;CSS3 gradient, shadow, rounded corners &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#css3-gradient,-shadow,-rounded-corners&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;All gradient, shadow, transparency, and rounded corners are done with CSS3.
This was a real game saver compared to the traditional .png way of doing user interfaces.&lt;/p&gt;
&lt;p&gt;We also used advanced CSS3 properties to customize the look and feel of the
scrollbar to make it more subtle (see
&lt;a href=&quot;http://webkit.org/blog/363/styling-scrollbars/&quot; rel=&quot;noopener&quot;&gt;http://webkit.org/blog/363/styling-scrollbars/&lt;/a&gt;
for styling scroll bars on WebKit browsers).&lt;/p&gt;
&lt;h3 id=&quot;css3-transitions&quot;&gt;CSS3 transitions &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#css3-transitions&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For HTML5 MathBoard, we replicated all of the iPad&#39;s animations
and even added a new one for the sliding right panel. Thanks to CSS3 transitions,
adding animations was trivial and allowed for the best performance.&lt;/p&gt;
&lt;p&gt;We had three main animations in the applications.&lt;/p&gt;
&lt;h4 id=&quot;1-the-sliding-right-pane&quot;&gt;1.) The sliding right pane &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#1-the-sliding-right-pane&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The first animation is on the right pane (&lt;code&gt;#rightPane&lt;/code&gt;), which slides
closed when the user starts a new quiz and slides open when the user ends a quiz.
To create this effect, we used the following CSS transition and triggered it
via JavaScript. The default style of the rightPane is open:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;#rightPane&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* look and feel, and layout property */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 370px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 598px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 28px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 720px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* open */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;-webkit-transition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; all .6s ease-in-out&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;When the user starts a quiz, our JavaScript logic moves the panel:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $rightPane &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#rightPane&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; left &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; $rightPane&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;left &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  $rightPane&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;left&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; left &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;px&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;A few notes on this implementation:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Given that the application sizes are fixed, we could have used a CSS
class &#39;.close&#39; and hardcode the close position the same way we hardcode the open one.&lt;/li&gt;
&lt;li&gt;We could also have used CSS &#39;translate&#39;, which would have been more
performant than animating the pane&#39;s &#39;left&#39; property. This is especially true
for mobile devices (such as iOS) where 3D transforms are hardware accelerated.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;setTimeout&lt;/code&gt; is not strictly necessary in this case since the original
position was set prior to the modification. However, it allows the browser
to make the animation smoother by displaying the quiz just before sliding the rightPane in.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;2-settings-dialog-box-animation&quot;&gt;2.) Settings dialog box animation &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#2-settings-dialog-box-animation&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;When the user clicks on a setting in the right, the settings dialog appears
from the bottom of the screen and scrolls down to the appropriate section.&lt;/p&gt;
&lt;p&gt;To accomplish this, we had a similar transition to the right pane. The only thing that
took some time was to resolve the jerkiness on first appearance of the dialog.
To instruct the browser to cache the dialog UI, we ended up displaying it
once and scrolling to it. At first, we tried with &lt;code&gt;display: none&lt;/code&gt;.
This approach was wrong because the browser assumed the dialog does not need to be shown.
The solution was to display the settings with a &lt;code&gt;z-index: -1&lt;/code&gt; at initialization,
making it invisible to the user but visible to the browser.&lt;/p&gt;
&lt;h4 id=&quot;3-quiz-success-or-incorrect-message-animation&quot;&gt;3.) Quiz success or incorrect message animation &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#3-quiz-success-or-incorrect-message-animation&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The third animation is actually two in one. When the &#39;success&#39; or &#39;incorrect&#39;
message appears, first scale to a point, wait for a little, and finally
scale even bigger and disappear. For this, we have two CSS3 animation styles,
and orchestrate it via JavaScript on a &lt;code&gt;webkitTransitionEnd&lt;/code&gt; event.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.quiz-result &gt; div.anim1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.8&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;-webkit-transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;6&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;6&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.quiz-result &gt; div.anim2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;-webkit-transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;9&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;9&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  $msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;anim1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;$msg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;webkitTransitionEnd&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;$msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;anim1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        $msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;anim1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        $msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;anim2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      $msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token function&quot;&gt;displayNextItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      freezeInput &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;audio-tag&quot;&gt;Audio tag &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#audio-tag&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When users answer a quiz, the application makes a success or fail sound.
The simple choice was to use the audio tag and call &lt;code&gt;play()&lt;/code&gt; on them.
These audio bits are added to the main page of the application:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;audio&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;audioCorrect&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;correct.mp3&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;preload&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;auto&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;autobuffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;audio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;audio&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;audioWrong&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;wrong.mp3&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;preload&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;auto&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;autobuffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;audio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/mathboard/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;HTML5 is truly enabling a new breed of Web, desktop, and mobile applications.
CSS3 was instrumental in customizing the look and feel of the application to
closely match the high sophistication of MathBoard for iPad, HTML5 storage was
a perfect fit for our data persistence, and the simplicity of HTML5 audio allowed
us to closely replicate the iPad app.&lt;/p&gt;
</content>
    <author>
      <name>Jeremy Chone</name>
    </author>
  </entry>
</feed>
