<?xml version="1.0" encoding="UTF-8"?> <feed xmlns="http://www.w3.org/2005/Atom"><title>Dev.Opera</title><link href="https://dev.opera.com/"/><link type="application/atom+xml" rel="self" href="https://dev.opera.com/feed/"/><updated>2017-02-07T17:38:22+00:00</updated><id>https://dev.opera.com/</id><author><name>Dev.Opera editors</name><email></email></author><entry><id>https://dev.opera.com/articles/pwa-resources/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/pwa-resources/"/><title>Progressive Web Apps: The definitive collection of resources</title><published>2016-11-11T00:00:00+00:00</published><updated>2016-11-11T00:00:00+00:00</updated><author><name>Bruce Lawson, Shwetank Dixit</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>Want to get started with progressive web apps, but not sure where to start? This page will list the best resources we know of to help you understand Progressive Web Apps (PWAs), get started and learn things in depth.</p>

<p>Make sure to bookmark this page, as this is a living document that we’ll be adding to from time to time.</p>

<h2 id="progressive-web-apps-the-what-how-and-why">Progressive Web Apps: The what, how and why</h2>

<p>These articles introduce the concept of Progressive Web apps and serve as a jumping point to learn more about them.</p>

<ul>
  <li><a href="https://dev.opera.com/blog/pwa-taipei/">Progressive Web Apps: the future of Apps</a>: A 20 minute video of a presentation by Opera’s Bruce Lawson, introducing the overall “why” and “what” of PWAs.</li>
  <li><a href="https://www.youtube.com/watch?v=MyQ8mtR9WxI">Progressive Web Apps (Chrome Dev Summit 2015)</a>: Alex Russell (Google) and Andreas Bovens (Opera) introduce the concepts, code and cross-browser nature of PWAs.</li>
  <li><a href="https://infrequently.org/2015/06/progressive-apps-escaping-tabs-without-losing-our-soul/">Progressive Web Apps: Escaping Tabs without losing our soul</a>: Alex Russell’s original blog post outlining the concept of PWAs. A must-read.</li>
  <li><a href="https://developers.google.com/web/progressive-web-apps/">Progressive Web Apps on Google Web Fundamentals</a>: This is a comprehensive set of tutorials various aspects of developing PWAs from the Google Team.</li>
  <li><a href="https://addyosmani.com/blog/getting-started-with-progressive-web-apps/">Getting Started with Progressive Web apps</a>: Addy Osmani’s guide to getting started with PWAs</li>
  <li><a href="https://www.smashingmagazine.com/2016/08/a-beginners-guide-to-progressive-web-apps/">A Beginner’s Guide to Progressive Web Apps</a>: A good intro article by Smashing Magazine</li>
</ul>

<h2 id="ui-concepts">UI Concepts</h2>

<p>One of the best things about PWAs are that they can be added to the home screen of your Android device, just like native apps can. This section contains relevant articles covering the ‘Add to Home Screen’ capability, as well as a few articles on how to make your web app UI running smoothly.</p>

<ul>
  <li><a href="https://medium.com/net-magazine/html-manifest-402e6a8cc0e9">Adding to Home Screen</a>: Bruce Lawson on adding your site to the mobile home screen.</li>
  <li><a href="https://developers.google.com/web/updates/2014/11/Support-for-installable-web-apps-with-webapp-manifest-in-chrome-38-for-Android">The Google Team’s Overview of Adding to Home Screen</a>: A nice overview of the options available for various use cases when implementing ‘Add to Home Screen’ functionality.</li>
  <li><a href="https://aerotwist.com/blog/flip-your-animations/">FLIP your animations</a>: It’s important that your PWA runs smoothly. Paul Lewis explains how to implement smooth animations in your app.</li>
  <li><a href="http://engineering.flipboard.com/2015/02/mobile-web/">Jankfree</a>: A collection of resources all about improving web UI performance and reducing ‘Jank’.</li>
  <li><a href="http://engineering.flipboard.com/2015/02/mobile-web/">60fps on the Mobile Web</a>: The Flipboard team discusses how to get 60fps performance for your web frontend on mobile devices.</li>
  <li><a href="https://w3c.github.io/manifest/">The Web App Manifest Specification</a>.</li>
</ul>

<h2 id="offline">Offline</h2>

<p>Progressive Web Apps are capable of running offline just like native apps. This is primarily through a feature called ‘Service Worker’. Service Workers are great, and besides being used to make web apps run offline, are also required for other functionality like Push Notifications and Background Sync.</p>

<ul>
  <li><a href="https://vimeo.com/175121061">What we need from the Web, and what it needs from us</a>: A 43 minute video by Shwetank Dixit, introducing PWAs from the perspective of web users in India. Service Workers begins at minute 18.</li>
  <li><a href="https://www.youtube.com/watch?v=cmGr0RszHc8">Instant Loading: Building offline-first Progressive Web Apps</a>: A 45 minute video by Jake Archibald, one of the designers of Service Workers.</li>
  <li><a href="https://developers.google.com/web/fundamentals/primers/service-worker/">Service Workers: An Introduction</a>: A great intro by the Google Team on what you need to know to get started with Service Workers.</li>
  <li><a href="https://jakearchibald.com/2014/offline-cookbook/">The Offline Cookbook</a>: Jake Archibald covers a variety of use cases for offline functionality along with helpful illustrations and code examples for the service wokers code. Very well worth a look!</li>
  <li><a href="http://12devsofxmas.co.uk/2016/01/day-9-service-worker-santas-little-performance-helper/">Service Worker: Santa’s Little Performance Helper</a>: Phil Nash covers Service Worker through a practical example. Its also contains a great example of caching web fonts for offline use using Service Workers.</li>
  <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers">Using Service Workers</a>: The Mozilla team’s introduction to Service Workers on MDN. It contains some useful infographics on various parts of the Service Worker lifecycle, and more.</li>
  <li><a href="https://www.smashingmagazine.com/2016/02/making-a-service-worker/">Making a Service Worker</a>: A fantastic article by Lyza Danger Gardner going in-depth with Service Workers.</li>
  <li><a href="https://serviceworke.rs">serviceworke.rs</a>: Mozilla’s site detailing various caching strategies and use cases along with code examples.</li>
  <li><a href="https://medium.com/dev-channel/offline-storage-for-progressive-web-apps-70d52695513c#.9n1e1i81i">Offline Storage for Progressive Web Apps</a>: Addy Osmani lists out a number of libraries and tools available for making web apps run offline.</li>
  <li><a href="https://remysharp.com/2016/03/22/the-copy--paste-guide-to-your-first-service-worker">The Copy and Paste Guide to your first Service Worker</a>: Remy Sharp writes about how to get started quickly.</li>
  <li><a href="http://alistapart.com/article/offline-first">Designing Offline-first Web Apps</a>: Besides giving helpful tips on good offline experiences, this article helps you think differently about offline as a user state in the first place.</li>
  <li><a href="https://w3c.github.io/ServiceWorker/">The Service Workers Specification</a></li>
</ul>

<h2 id="push-notifications">Push Notifications</h2>

<p>Push notifications are helpful in notifying the user of important, relevant or timely events, even if your site isn’t open in the browser, or even when the browser is closed. With the Push API spec and Service Workers, you can finally implement this in your progressive web app too. Be careful not to spam your users!</p>

<ul>
  <li><a href="https://opbeat.com/community/posts/towards-better-apps-the-what-why-of-progressive-web-apps-by-andreas-bovens/">Towards better apps: the what &amp; why of progressive web apps</a>: A 43 minute video in which Andreas Bovens introduces PWAs, Service Workers and — around the 23 minute mark — Push Notifications.</li>
  <li><a href="https://developers.google.com/web/fundamentals/engage-and-retain/push-notifications/">Web Push Notifications: Timely, Relevant and Precise</a>: Google’s introduction to Web Push notifications.</li>
  <li><a href="https://developer.mozilla.org/en/docs/Web/API/Push_API">Push API documentation on MDN</a></li>
  <li><a href="https://hacks.mozilla.org/2015/10/keep-pushing-it-with-the-w3c-push-api/">Keep Pushing it, with the Web Push API</a>: Chris Mills explains the Web Push API.</li>
  <li><a href="https://www.w3.org/TR/push-api/">The Push API specification</a></li>
</ul>

<h2 id="tools-and-libraries">Tools and Libraries</h2>

<p>This section lists out a number of tools which might end up saving you a lot of time and effort when coding up for your PWAs.</p>

<ul>
  <li><a href="https://github.com/GoogleChrome/sw-toolbox">sw-toolbox</a>: A helpful library with account for a lot of different caching use-cases.</li>
  <li><a href="https://github.com/GoogleChrome/sw-precache">sw-precache</a>: A tool to pre-emptively cache all static resources for offline use.</li>
  <li><a href="https://github.com/GoogleChrome/lighthouse">Lighthouse</a>: Auditing and performance metrics for Progressive Web Apps.</li>
  <li><a href="https://brucelawson.github.io/manifest/">Manifest Generator</a>: A tool which automatically generates a web manifest file for you.</li>
  <li><a href="https://www.npmjs.com/package/manifest-json">manifest-json</a>: Another tool (this is using the command line) to generate a web manifest file for you.</li>
  <li><a href="https://github.com/hemanth/generator-pwa">generator-pwa</a>: A yeoman generator for a basic PWA app.</li>
  <li><a href="https://github.com/TalAter/UpUp">UpUp</a>: Read the <a href="https://dev.opera.com/articles/offline-with-upup-service-workers/">article by the library’s author</a> on how to use it.</li>
  <li><a href="https://github.com/google/web-starter-kit">Web Starter Kit</a>: A boilerplate for web development including sw-toolbox and sw-precache libraries.</li>
  <li><a href="https://github.com/sdgluck/fetch-sync">Fetch-sync</a>: Fetch Sync allows you to proxy fetch requests through the Background Sync API so that they are honoured if made when the UA is offline.</li>
  <li><a href="https://github.com/sdgluck/msgr">Msgr</a>: Nifty service worker/client message utility.</li>
</ul>

<h2 id="showcases-case-studies-and-more">Showcases, case studies and more</h2>

<p>Take a look at what others are doing with Progressive Web Apps. Get inspiration and see how it has benefitted others in key business metrics.</p>

<ul>
  <li><a href="https://pwa.rocks">PWA.Rocks</a>: The showcase for the best Progressive Web Apps in the world. It’s maintained by the Opera Developer Relations team, and we accept Pull Requests if you have a great-looking responsive PWA. Remember, sites aren’t “mobile-only” so the best PWAs look great on desktop and devices.</li>
  <li><a href="https://developers.google.com/web/showcase/">Google PWA Showcase</a>: Google’s showcase of companies which have befitted from PWAs.</li>
  <li><a href="https://cloudfour.com/thinks/the-business-case-for-progressive-web-apps/">The Business Case for Progressive Web Apps</a>: Jason Grigsby writes a compelling case for the business benefits of PWAs.</li>
  <li><a href="https://dev.opera.com/articles/pwa-nigeria-kenya-interview/">PWAs: An African Perspective</a>: We interview two great developers from Nigeria and Kenya about PWAs. Read their thoughts on how PWAs can help solve problems in that region.</li>
</ul>
]]></content></entry><entry><id>https://dev.opera.com/articles/pwa-desktop/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/pwa-desktop/"/><title>Progressive web apps running as native OS X apps</title><published>2016-07-26T00:00:00+00:00</published><updated>2016-07-26T00:00:00+00:00</updated><author><name>Vlad Filippov</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<h2 id="progressive-web-apps-are-getting-ready-for-desktop">Progressive Web Apps are getting ready for desktop</h2>

<p>If you follow the Progressive Web App scene you’ve probably already seen multiple examples of the <a href="https://airhorner.com/">Air Horner app</a> in mobile browsers such as Opera Mobile and Chrome for Android. However it is not easy to get your favorite PWA (such as Air Horner) to be a primary citizen on your favorite <em>desktop</em> operating system.</p>

<p>Browser makers are working on getting better support for PWAs in desktop, but it’s not quite ready yet. This is why I started the <a href="https://github.com/vladikoff/PWAify">PWAify</a> project. This project is powered by Node.js and Electron, which already have a huge community and provide ease of use for new and experienced developers. The PWAify project is still in the early experimental stages — use it at your own risk.</p>

<p>The goal of the PWAify project is to provide a solution for PWAs on desktop while we wait for browsers to develop support. In addition this project allows developers to experiment, give better feedback to browser makers, and improve the <a href="https://www.w3.org/TR/appmanifest/">Web App Manifest specification</a>.</p>

<figure block="figure">
	<img elem="media" src="/articles/pwa-desktop/android-vs-osx.jpg" alt="Installed Air Horner app on Android and OS X" />
	<figcaption elem="caption">What the installed Air Horner app looks like on Android and OS X</figcaption>
</figure>

<h2 id="bringing-your-pwa-to-desktop">Bringing your PWA to desktop</h2>

<p>To create a sample app with PWAify follow the <a href="https://github.com/vladikoff/PWAify#readme">latest documentation on GitHub</a>.</p>

<p>Currently the simplest use case is to just provide an HTTPS URL to the remote app. For example:</p>

<pre><code>pwaify https://voice-memos.appspot.com/
</code></pre>

<p>There are some advanced options for the tool as well. You can specify the platform of your choice and an icon file once you are ready to distribute your app:</p>

<pre><code>pwaify https://voice-memos.appspot.com/ \
	--platforms=darwin \
	--icon chrome-touch-icon-384x384.icns
</code></pre>

<p>When you run the <code>pwaify</code> command it fetches and processes the <code>manifest.json</code> for the given PWA. Some early work is in place to simplify the process of generating desktop icons by looking at icons provided in the manifest. The current downside of the <code>pwaify</code> approach is the size of the executable for each application, but there is already huge list of <a href="http://electron.atom.io/apps/">Electron apps</a> out there that require the download. In my mind I try not to worry about the download size. Instead I try to focus on the future of progressive apps instead.</p>

<p>Here’s an example of <a href="https://voice-memos.appspot.com/">a simple progressive web app</a> working on Windows, Ubuntu and OS X:</p>

<figure block="figure">
	<img elem="media" src="/articles/pwa-desktop/multi-platform.jpg" alt="Voice Memos PWA running on Windows, Linux, and OS X" />
	<figcaption elem="caption">Voice Memos PWA running on Windows, Linux, and OS X</figcaption>
</figure>

<p>For the purposes of the screenshot I rebuilt the Voice Memos app on all platforms. It is also possible to setup a build server for your application once you want to add multi-platform support. You can use the PWAify tool today by pointing it at your own app or one of the apps in the <a href="https://pwa.rocks/">pwa.rocks list</a>.</p>

<p>Besides the Voice Memos application, my second favorite example is the 2048 tile game, by using PWAify with <a href="https://2048-opera-pwa.surge.sh/">2048-opera-pwa.surge.sh</a> I can easily jump back to the saved game state after I restart the application.</p>

<p>The PWAify project is open source, so you can fork it and extend functionality. For example you can add auto-update and custom UI for your application. In the spirit of keeping as much as possible of the application on the web I suggest only introducing minimal changes to the application wrapper. Treat the PWAify’d version of the app just like any other desktop browser would treat it.</p>

<h2 id="the-future">The Future</h2>

<p>Recently <a href="https://medium.com/web-on-the-edge/progressive-web-apps-on-windows-8d8eb68d524e">Microsoft announced</a> that the Windows Store will start supporting the W3C Web App Manifest. This will help you distribute the applications for Windows Store users, but you don’t have wait for Microsoft. There is nothing stopping you today to build one version of your web application and get it in the hands of your users on desktop. You can even go beyond Windows users and distribute on other operating systems.</p>

<p>Some future ideas for the PWAify project itself include:</p>

<ul>
  <li>implementing more of the Web App Manifest spec.</li>
  <li>reloading <code>manifest.json</code> from the server, which would allow dynamically changing certain properties of the application by updating the <code>manifest.json</code> remotely.</li>
  <li>experimenting with new manifest features, such as window size and minimal UI.</li>
  <li>working with the Electron app community to make it easier to generate application icons for cross-platform use.</li>
</ul>

<p>Tools like Electron and PWAify put yourself in control of application distribution while allowing you to use the latest web technologies. Write one awesome progressive web application for multiple distribution targets!</p>

<p>Feel free to <a href="https://github.com/vladikoff/PWAify/issues/new">file an issue against the PWAify project</a> if you have other ideas that will benefit the future of progressive web apps.</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/pwa-nigeria-kenya-interview/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/pwa-nigeria-kenya-interview/"/><title>Progressive Web Apps in Nigeria and Kenya: a Double Interview</title><published>2016-06-16T00:00:00+00:00</published><updated>2016-06-16T00:00:00+00:00</updated><author><name>Andreas Bovens, Bruce Lawson</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<p>While keeping an eye on Twitter mentions of progressive web apps, I came across a number of conversations between web developers in Nigeria and Kenya. Intrigued, I got in touch with them to hear their thoughts on progressive web apps, resulting in this double interview.</p>

<p><strong>Hi! Please tell us a little about yourselves.</strong></p>

<figure block="figure">
	<img elem="media" src="/articles/pwa-nigeria-kenya-interview/constance-okoghenun.jpg" width="200" alt="Constance Okoghenun" />
</figure>

<p><em>Constance Okoghenun, <a href="https://twitter.com/okoghenun">@okoghenun</a>:</em> I’m from Lagos, Nigeria. I work as a UI Specialist for <a href="https://konga.com/">Konga</a>, Nigeria’s largest online marketplace helping tens of thousands of merchants selling over 200,000 products on our platform. At Konga I help to build products that provide great shopping experiences for our customers. I also help organise and speak from time to time at <a href="http://usable.ng/">Usable</a> (formerly UXLagos), where designers, developers and enthusiasts here in Lagos and, recently, Abuja Nigeria, have monthly conversations about how to improve the experiences we deliver to our customers.</p>

<p>I love the web and have been working on the web for about 5 years now. It has been a delight to see it mature and become better as a platform, enabling me and other developers and designers to offer increasingly better experiences to our users.</p>

<figure block="figure">
	<img elem="media" src="/articles/pwa-nigeria-kenya-interview/eugene-mutai.jpg" width="200" alt="Eugene Mutai" />
</figure>

<p><em>Eugene Mutai, <a href="https://twitter.com/kn9ts">@kn9ts</a>:</em> I’m from Nairobi, Kenya. I’m currently working for/with <a href="https://andela.com/">Andela</a>. Andela is new startup, with a revolutionary model founded on the principle that brilliance is evenly distributed around the world, but opportunity is not. Andela is transforming the brightest minds in Africa into world-class developers, who then are fused into startups or Fortune 500 companies all over the world. I am currently working as a full-time full-stack developer for <a href="http://www.rbi.com/">RBI</a>, a Canadian multinational company (and one of the largest fast food brands in the world) whose brands include Burger King and Tim Hortons.</p>

<p>I have been a web enthusiast and developer for at least four years now. I am also a <a href="https://developers.google.com/experts/people/eugene-mutai">Google Developer Expert on Web Technologies</a>, attributed by one of my community contributions such as being the lead manager of the <a href="http://www.meetup.com/nairobi-js/">Nairobi JavaScript Community</a> growing it to over 450 members, and I regularly speak at a variety of programming and tech meetups.</p>

<p><strong>We met online because you were talking about Progressive Web Apps (PWAs) on Twitter. What is it about them that excites you?</strong></p>

<p><em>Eugene:</em> I haven’t talked about progressive web apps on Twitter only; I have evangelized about them wherever I got the chance to. My last talk on progressive web apps was at <a href="http://nairobitechweek.com/">Nairobi Tech Week</a>, the largest tech event in Sub-Saharan Africa this year. I’ve also written a blog post about it — <a href="https://medium.com/@kn9ts/progressive-webs-apps-africa-may-be-the-biggest-gainer-b45e05b14893">Progressive Webs Apps: Africa may be the biggest gainer</a> — which is a robust answer to the above question.</p>

<p>In summary, I am excited that finally web technology is earning its place on mobile. PWAs are changing the way web apps have been viewed: a secondary, less-intuitive and less-performant alternative to using a mobile app’s service. While settling in on mobile, leveraging its greatest advantage over native mobile apps — very low friction in usage — it may solve problems that make the daily usage of native mobile applications in Africa a challenge, e.g. the size of apps and requirement of new downloads every time they are updated, <a href="http://slides.com/eugenemutai/progressive-web-apps#/34">among many others</a>.</p>

<p>On a side note, as a passionate web developer, it’s been tons of losing development battles with Android developers, and I’m finally unquantifiably happy we are becoming a force to be reckoned with.</p>

<p><em>Constance:</em> There are lots of exciting things about progressive web apps and the new range of possibilities they bring to the web. If I were to pick just one feature of progressive web apps that I’m super-excited about, it’s the ability to detect and handle offline / unreliable network conditions with service workers.</p>

<p>This is vitally important, as web apps finally now have a space on user home screens — so being slow to load or breaking because of network unreliability is not acceptable. And, in my part of the world, where getting good connectivity speeds on mobile is pretty difficult, service workers present an opportunity for developers to build apps that aren’t just fast, but which are also resilient.</p>

<p>An example of this is Konga’s PWA: when we detect that the user is offline and has items in their shopping cart, we provide them the option of going through an offline checkout experience, thereby preventing internet connectivity from becoming a bottleneck when they shop with us.</p>

<p><strong>Constance, what are the characteristics of the Nigerian market that make PWAs an appealing development route?</strong></p>

<p><em>Constance:</em> Data is pretty expensive in Nigeria. Over the last 12 months, <a href="https://techpoint.ng/2016/05/17/data-plan-wars-nigeria/">data prices have become lower</a>, but not low enough to make the majority of the Nigerian internet market data insensitive. On average, it costs about NGN 1000 (about $5) to get 1GB of data. In a country where minimum wage is about NGN 18,000 (about $90) that is already 5.6% of the monthly salaries. So, as you can imagine, Nigerians are extremely data sensitive.</p>

<p>A huge number of smartphone users do not download their apps and never update their apps. Instead, people side-load apps and other content from third parties who have these apps downloaded to a PC and for a small fee will install apps from their computers to users’ phones. Among younger, more tech-savvy Nigerians, the app <a href="https://play.google.com/store/apps/details?id=cn.xender">Xender</a> is really popular as it allows them skip app downloads and just send it from one device to another.</p>

<p>As you can imagine, these workarounds for downloading apps from the app store create all sorts of problems for developers — from app distribution, to getting the most recent, bug-free versions of apps in the hands of users.</p>

<p>With PWAs giving web apps a place in the user’s home screen, without the download overhead of native apps, this becomes more exciting; developers in Nigeria can now always give a great and up-to-date experience to their users. Also, they have the ability to re-engage with their users via push notifications, and improve conversions.</p>

<p><strong>Eugene, is it similar in Kenya?</strong></p>

<p><em>Eugene:</em> The average pay is Kenya is approximately $300-400 a month. On a good month, with tough choices made in budgeting, one gets to barely spare $30 after covering monthly expenses. It costs $1 for 135MB of data and $5 for 1GB of data. On average a user has 15+ apps installed (extrapolated from global mobile app install stats). At least half of these apps demand to be updated after a day or two (best case scenario is weekly).</p>

<p>If each app is on average 15MB, this means 150MB of data used up on downloads from re-installations without considering each user’s unique personal data usage. If at least $5 of data is being used for updates only, I’d say this is very challenging to a user if they are is to keep up with these updates. Some updates also are just bug fixes — I kid you not, no one would update the app for that (including me) unless the bug is not negligible.</p>

<p><strong>Constance, what were the challenges of making the Konga PWA?</strong></p>

<p><em>Constance:</em> The biggest for us at Konga was time: we had only about six weeks to build a stable version of our app and we did it in time. Thinking offline-first was something we had to get used to doing. Apart from those, building our PWA wasn’t very difficult.</p>

<p><strong>And how was user feedback for your PWA, Constance?</strong></p>

<p><em>Constance:</em> Though we haven’t officially launched the app yet, feedback has been overwhelmingly positive. It requires 84% less data to complete the first transaction vs the previous mobile web experience, and 63% less data for initial load, and we are not even done building and optimizing the app. It certainly will be a delight for our users when it gets into their hands.</p>

<p>To quote our CEO Shola Adekoya:</p>

<blockquote>
  <p>We estimate that with our new light, super-fast, UX-rich browsing capability, customers’ data consumption will fall dramatically.</p>
</blockquote>

<p><strong>Back to Eugene now. How was user feedback to your evangelism, Eugene?</strong></p>

<p><em>Eugene:</em> I’m been satisfactorily happy with the feedback I have got from my blog post and all my talks on PWAs. In the last talk I gave, at one point a member of the audience who was an Android developer (among many others in the room) who became anxious and disturbed that PWAs would render native Android developers jobless. The best answer I could give was we’re only moving in the mobile department since we’re now in a sharing economy, and not kicking them out, and the hype was to only create awareness to all web tech developers and not to cause panic among Android developers.</p>

<p><strong>Do you think those Android developers’ concerns are justified? Do you see PWAs becoming dominant in the kind of markets that you work in?</strong></p>

<p><em>Eugene:</em> No, I don’t think they’re justified. First of all, awareness about PWAs is something that needs to be urgently addressed. Every time I give a talk on PWAs the facial response of the audience is like “Why didn’t I know about this? This is revolutionary!” and the question that always follows is “Where can I find more information and learn about PWAs?”</p>

<p>Furthermore, I don’t envision PWAs being dominant in the mobile apps space, but I see their presence vastly increasing once knowledge about them is in the hands of every web developer. PWAs solve a number of challenges for entrepreneurs: it’s a cross-platform solution, there’s very low friction compared to native apps, there’s no APK size limitation, and so on.</p>

<p><em>Constance:</em> I also don’t think that fear of PWAs is justified. I think both PWAs and native SDKs are just tools in a good developer’s tool box. There are use cases where a PWA would be perfect, and there are others for which a native app is best. Each developer just needs to evaluate when to use what. Moreover, there is nothing stopping native mobile developers from working on the web; Konga’s PWA was built by both our current mobile team (Android and iOS developers) and our front-end team.</p>

<p><strong>What else would you like to see browsers do to make PWAs more widely available and accepted?</strong></p>

<p><em>Constance:</em> Lots of developers use frameworks; it would be great to see vendors reach out to the maintainers of those frameworks and work with them improving their tooling and processes, so that it’s super easy to build PWAs with their frameworks and tools. More importantly, I’d like to see a more consistent implementation of the web specs that PWAs are based on.</p>

<p><em>Eugene:</em> Opera and Google Chrome have done a wonderful job so far. When talking about PWAs being installable, the “Add to home screen” option isn’t that convincing. I’d like to see something like “Install Web App” or “Add to Your Apps”.</p>

<p>Browsers should offer APIs so that PWAs can compete on an equal footing as native mobile apps. I am aware these missing APIs such as Bluetooth, NFC, USB access and so forth are currently being worked on. So this is just a matter of time.</p>

<p><strong>Thank you both!</strong></p>
]]></content></entry><entry><id>https://dev.opera.com/articles/web-bluetooth-intro/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/web-bluetooth-intro/"/><title>An introduction to the Web Bluetooth API</title><published>2016-03-02T00:00:00+00:00</published><updated>2016-03-02T00:00:00+00:00</updated><author><name>Shwetank Dixit</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<h2 id="introduction">Introduction</h2>

<figure block="figure" mod="right">
	<video elem="media" controls="" cover="/articles/web-bluetooth-intro/video.jpg" width="360" height="640" style="margin: 0 0 15px 15px;">
		<source src="/articles/web-bluetooth-intro/video.mp4" type="video/mp4" />
		<source src="/articles/web-bluetooth-intro/video.webm" type="video/webm" />
	</video>
</figure>

<p>There is an explosion of electronic devices nowadays, and with many of them, it’s possible to interact with them via <a href="https://en.wikipedia.org/wiki/Bluetooth_low_energy">Bluetooth Low Energy</a>, or BLE. However, installing a separate app for interacting with every single bluetooth gadget is impractical. What if we could communicate with them through a web browser? The Web Bluetooth API aims to do exactly that with a promise-based API, which allows you to interact with many BLE enabled devices. This is also great for companies intending to launch new gadgets, as instead of spending time and money on developing a separate app for multiple platforms, they can offer interaction with their gadget in a cross-platform manner, as it could be controlled directly from a web page.</p>

<h2 id="the-web-bluetooth-api">The Web Bluetooth API</h2>

<p>So far, the ability to communicate with BLE devices has been possible only for native apps. The Web Bluetooth API aims to change that and brings this to web browsers as well. The <a href="https://webbluetoothcg.github.io/web-bluetooth/">specification for the Web Bluetooth API</a> is not final yet, and you’re free to <a href="https://github.com/WebBluetoothCG/web-bluetooth/issues">share your feedback</a> on what you would want in it as well.</p>

<p>Right now, the Web Bluetooth API is in <a href="https://play.google.com/store/apps/details?id=com.opera.browser.beta">Opera for Android beta</a>. You can activate it by going to <code>opera://flags</code> and enabling Web Bluetooth in the options provided on that page.</p>

<h2 id="some-prerequisites">Some prerequisites</h2>

<ul>
  <li><strong>HTTPS only</strong>: The API only works on pages served over HTTPS. Most privacy-sensitive web APIs are now switching over to the HTTPS-only model, and this one is no exception.</li>
  <li><strong>Requires user action</strong>: We want to make sure that the API doesn’t work in the background without the user knowing about it, which is why there is a prompt shown to user to choose which device to pair with. Additionally, we also don’t want sites to show up this prompt straightaway without any user interaction. That is why methods in this API only work when called in response to a user action (like responding to a <code>click</code> event).</li>
</ul>

<h2 id="getting-basic-device-information">Getting Basic Device Information</h2>

<p>Let’s take a look at some code to figure out how to use this API to get some basic information regarding a BLE device.</p>

<p>Here is a very simple example, showing a button:</p>

<pre><code>&lt;button id="the-button"&gt;Try it&lt;/button&gt;
</code></pre>

<p>…and the following JavaScript:</p>

<pre><code>const button = document.querySelector('#the-button');
button.addEventListener('click', function() {
	navigator.bluetooth.requestDevice({
		filters: [{
			services: ['battery_service']
		}]
	}).then(device =&gt; {
		console.log('Got device:', device.name);
		console.log('id:', device.id);
	});
});
</code></pre>

<p>As mentioned earlier, the method <code>navigator.bluetooth.requestDevice()</code> can only be called in response to a user action like a button click. This method calls up a dialog box showing the list of available BLE devices matching the query filter. In our case, the filter we have set pertains to BLE devices which expose a so-called “GATT service” called <code>battery_service</code>. We’ll find out more about GATT services in the next section.</p>

<p>Keep in mind that it is necessary to include at least one filter when requesting device access using the Web Bluetooth API.</p>

<p>Once the user selects the device and connects to it, it can then print out the device name and its ID.</p>

<h2 id="what-are-gatt-services">What are GATT services?</h2>

<p>GATT stands for <a href="https://developer.bluetooth.org/TechnologyOverview/Pages/GATT.aspx">Generic Attribute Profile</a> and provides a standard way for Bluetooth devices to advertise their services to the outside world. Your cell phone might provide a GATT service to show the current battery level. Your fitness band might provide a service that too, along with another one showing the current heart rate count. There are a <a href="https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx">number of services which are exposed through GATT</a>, and we can listen to those services depending on which of those services are exposed by the device.</p>

<p>Some devices may not list their services in the standardized list of GATT services, in which case you could use their full Bluetooth UUID or a short 16- or 32-bit ID instead. Of course, this depends on whether the device has any documentation mentioning these UUIDs and what they are for.</p>

<pre><code>navigator.bluetooth.requestDevice({
	filters: [{
		services: ['0009180d-0000-1000-8000-00705f9b34fb']
	}]
});
</code></pre>

<h2 id="reading-and-writing-gatt-services">Reading and writing GATT services</h2>

<p>Once we have connected to a device, the next step is of course, to read some useful data from it. To do that, we need to connect to the device’s GATT server by using the method <code>gatt.connect()</code>. Let’s take our previous code sample and extend it. This is based on the <a href="https://googlechrome.github.io/samples/web-bluetooth/battery-level.html">Battery Level Sample Code</a> demo, which you can also check out (Note however that it uses the <code>connectGATT()</code> method which is deprecated from Chromium 50 onwards).</p>

<pre><code>navigator.bluetooth.requestDevice({
	filters: [{
		services: ['battery_service']
	}]
}).then(device =&gt; {
	console.log('Got device:', device.name);
	console.log('id:', device.id);
	return device.gatt.connect(); // Chromium 49 and below use `connectGATT()` but from Chromium 50 it will use gatt.connect();
})
.then(server =&gt; {
	console.log('Getting Battery Service…');
	return server.getPrimaryService('battery_service');
})
.then(service =&gt; {
	console.log('Getting Battery Characteristic…');
	return service.getCharacteristic('battery_level');
})
.then(characteristic =&gt; {
	console.log('Reading battery level…');
	return characteristic.readValue();
})
.then(value =&gt; {
	value = value.buffer ? value : new DataView(value);
	console.log('Battery percentage:', value.getUint8(0));
})
.catch(exception =&gt; {
	console.log(exception);
});
</code></pre>

<p>Here we are reading the <a href="https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.battery_level.xml">standardized battery level GATT characteristic</a>. Keep in mind that the value in the end is given as a <a href="https://docs.webplatform.org/wiki/javascript/DataView"><code>DataView</code></a> object which then needs to be parsed correctly to get the final value.</p>

<p>Writing values would typically require entering the appropriate values to be parsed as a <code>BufferSource</code>, which are either an <code>ArrayBuffer</code> or a view onto an <code>ArrayBuffer</code> like a <code>DataView</code> object (You can see a <a href="https://heycam.github.io/webidl/#idl-buffer-source-types">list of buffer source types</a>). For example, for resetting the <code>enerygyExpended</code> field in a heart rate monitor, we can use the <a href="https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue"><code>writeValue()</code></a> method like so:</p>

<pre><code>navigator.bluetooth.requestDevice({
	filters: [{
		services: ['heart_rate']
	}]
}).then(device =&gt; {
	console.log('Got device:', device.name);
	console.log('id:', device.id);
	return device.gatt.connect();
})
.then(server =&gt; server.getPrimaryService('heart_rate'))
.then(service =&gt; service.getCharacteristic('heart_rate_control_point'))
.then(characteristic =&gt; {
	const resetEnergyExpended = new Uint8Array([1]);
	// A value of `1` is a signal to reset it.
	return characteristic.writeValue(resetEnergyExpended);
})
.then(value =&gt; {
	console.log('Reset value of energy expended field');
})
.catch(exception =&gt; {
	console.log(exception);
});
</code></pre>

<p>If you don’t have a device which exposes GATT services but still want to play with the API, try out the <a href="https://github.com/WebBluetoothCG/ble-test-peripheral-android">BLE Peripheral Simulator App</a>.</p>

<h2 id="advanced-uses">Advanced uses</h2>

<p>Different devices will expose different services and have documentation describing how to access those services. For example, the BB-8 Toy by Sphero has some of their documentation on how to do that <a href="https://github.com/orbotix/DeveloperResources/blob/master/docs/Sphero_API_1.50.pdf">over here</a>.</p>

<p>Using this, it’s possible to create a <a href="https://operasoftware.github.io/bb8/">web app</a> that can control the BB-8 toy! Check out the <a href="https://github.com/operasoftware/bb8">code for it</a>.</p>

<p>Others have made web apps to <a href="https://github.com/poshaughnessy/web-bluetooth-parrot-drone">control drones</a>, <a href="https://github.com/WebBluetoothCG/demos/blob/gh-pages/heart-rate-sensor">heart-rate sensors</a>, <a href="https://github.com/WebBluetoothCG/demos">and more</a>. If you make a demo, be sure to add it to the list!</p>

<h2 id="whats-to-come">What’s to come</h2>

<p>The implementation of the Web Bluetooth API in Chromium in definitely not complete yet. Check out the <a href="https://github.com/WebBluetoothCG/web-bluetooth/issues">list of issues regarding implementation</a> in the spec. One of the most promising things to look forward to is the capability for websites to scan for <a href="https://github.com/WebBluetoothCG/web-bluetooth/issues/191">nearby BLE advertisements themselves</a>.</p>

<p>It would also be cool for websites to access the current RSSI (Received Signal Strength Indicator) and txPower levels, as well as any associated URLs shared through the <a href="https://en.wikipedia.org/wiki/Eddystone_%28Google%29">Eddystone protocol</a> without the need to pair with each individual device. All these exciting things are yet to come.</p>

<p>You can check out the <a href="https://github.com/WebBluetoothCG/web-bluetooth/blob/gh-pages/implementation-status.md">implementation status on various platforms</a> as well as a hardware compatibility list. If using Android, we recommend using the latest version for best and most consistent results.</p>

<h2 id="further-reading">Further Reading</h2>

<ul>
  <li><a href="https://webbluetoothcg.github.io/web-bluetooth">The Web Bluetooth Specification</a></li>
  <li><a href="https://github.com/WebBluetoothCG/demos">A collection of Web Bluetooth API Demos</a></li>
  <li><a href="https://github.com/operasoftware/bb8">Opera’s BB-8 Demo</a></li>
  <li><a href="https://github.com/WebBluetoothCG/ble-test-peripheral-android">BLE Peripheral Simulator App</a></li>
</ul>
]]></content></entry><entry><id>https://dev.opera.com/articles/working-with-theme-overlay/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/working-with-theme-overlay/"/><title>The New Start Page: Working With the Theme Overlay</title><published>2016-02-15T00:00:00+00:00</published><updated>2016-02-15T00:00:00+00:00</updated><author><name>Shwetank Dixit</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<p>From Opera 36 onwards, the start page will have a brand new look. It introduces various design improvements, right from the placement of key icons, to the sizes of the speed dial tiles. As part of this, it also introduces a translucent gray overlay on themes.</p>

<p>Previously the title text for speed dial tiles was always having a white background and black text. The new design got rid of it, and overall speed dial tiles look much better. However, a side-effect of it was that reading the text totally depended on the background picture in the theme.</p>

<p>A solution to this is to introduce a subtle gray translucent overlay on themes and have the title text color for speed dial tiles white by default. We wanted to create a design that could work for any image you would try (or already have installed), meaning that even busy images would work just well and you will have a good experience using the new start page. While this solves the legibility issue by making the text very easy to read, some theme designers might want to not have this overlay, depending on their preference.</p>

<p>So we have introduced an option for theme authors to specify whether an overlay should be applied to their theme or not. If they choose not to apply an overlay on their theme images, then they can do so, and even specify the color for the speed dial text and other icons on the start page. This gives greater control in the hands of the theme creator.</p>

<h2 id="what-does-this-mean-for-theme-designers">What does this mean for theme designers?</h2>

<p>As a theme designer, you have two choices. If you want the background image to work with the overlay, then there is nothing extra you need to do. The overlay is applied by default, and all the text and icons will be white in color to contrast with the overlay (which gives it a nice contrast, making sure its readable) so no extra work needed there.</p>

<p>However, if you would like the overlay not to be applied to your background image, you now have the option to do so. However, keep in mind that in this case, you have the responsibility to make sure that all text and icons are properly visible to users.</p>

<h2 id="disabling-the-theme-overlay">Disabling the theme overlay</h2>

<figure block="figure">
    <img elem="media" src="/articles/working-with-theme-overlay/theme-comparison.gif" alt="Theme comparison" />
    <figcaption elem="caption">Theme with overlay enabled and disabled</figcaption>
</figure>

<p>We have introduced a new option in the Persona.ini file. You can now use <code>Use Overlay</code> to tell Opera whether to have it enabled or not. If you don’t want the overlay, simply write</p>

<pre><code>[Start Page]
Background					= background.jpg
Position					= center
Use Overlay					= false;
</code></pre>

<p>This will disable the overlay.</p>

<h2 id="making-text-and-icons-readable">Making text and icons readable</h2>

<p>Once you disable the overlay, it is up to you to make sure all the text and icons are having proper contrast and are readable by the user. For this, the existing option of <code>Title Text Color</code> will matter a lot.</p>

<p>Let’s take the example of the following of a theme with a disabled overlay.</p>

<figure block="figure">
    <img elem="media" src="/articles/working-with-theme-overlay/birdtheme-disabled.jpg" alt="Bird theme with disabled overlay" />
</figure>

<p>Now the image here is very light and provides very little contrast to the text, which is white in color. Let’s make it dark to provide it proper contrast. Let’s write the following:</p>

<pre><code>[Start Page]
Background				= background.jpg
Position				= center
Use Overlay				= false;
Title Text Color		= #000000
</code></pre>

<p>This gives us the following result:</p>

<figure block="figure">
    <img elem="media" src="/articles/working-with-theme-overlay/birdtheme-black.jpg" alt="Bird theme with black text and icon colors" />
</figure>

<p>This is much better. However, you could go ahead and provide more style which matches the color scheme (rather than the standard black) while still providing good contrast. Let’s change the text color like so:</p>

<pre><code>Title Text Color     = #ff0000
</code></pre>

<p>This results in the image having good contrast and matching the color scheme.</p>

<figure block="figure">
    <img elem="media" src="/articles/working-with-theme-overlay/birdtheme-main.jpg" alt="Bird theme with text and icon colors matching the color scheme" />
</figure>

<p>Keep in mind that, despite the name, using <code>Title Text Color</code> will affect the color of not just the text, but also the icons on the start page.</p>

<p>In the above image, you can notice how the icons have the color applied to it too.</p>

<h2 id="conclusion">Conclusion</h2>

<p>The new start page for Opera features an all new re-design. This features a new overlay for images which makes it work with a lot of images, even <em>busy</em> images, while still providing readability for users. Theme designers get greater control over how they want their background images to be displayed.</p>

<p>If they want to disable the overlay, they can use <code>Use Overlay = false</code> in the <code>Persona.ini</code> file. If overlay is disabled, then theme designers should keep in mind readability for text and icons on the start page by specifying an appropriate color for them using <code>Title Text Color</code> in the <code>Persona.ini</code> file.</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/offline-with-upup-service-workers/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/offline-with-upup-service-workers/"/><title>Building Offline Sites with ServiceWorkers and UpUp</title><published>2016-01-19T00:00:00+00:00</published><updated>2016-01-19T00:00:00+00:00</updated><author><name>Tal Ater</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<figure block="figure" mod="right" style="margin-left:20px">
	<img elem="media" src="/articles/offline-with-upup-service-workers/upup-phone-anim.gif" alt="Offline content demo" />
</figure>

<p>We are living in an increasingly mobile world. We rely on our phones to keep us connected wherever we go, and to provide us with the information we need to get through our day.</p>

<p>But connectivity hasn’t quite caught up with our dependence on it yet.</p>

<p>Every day we find ourselves without a working internet connection. Even in countries with near-perfect coverage, we lose connectivity when stepping into the elevator, or taking the subway. We have areas in our house that never seem to have a solid connection… and don’t even get me started about travel. The minute we leave our comfortable homes and offices, whether we’re boarding a plane, or just driving from town to town, we are at the mercy of the cell towers.</p>

<p>Now think of your users, and their dependence on the information you provide them. Are you running a travel site offering online hotel bookings? What would your users do if they just landed in Tokyo, without a local data plan, but they needed to access your site in order to find their hotel’s address? Does your store have a website? What would your users do if they were riding the elevator down to the parking lot while trying to find out your store’s opening hours?</p>

<p>Luckily we are living in very exciting times for web development. New technologies are coming out every day, unleashing new possibilities, and changing our perception of what is and isn’t possible in the browser. Two of the most important technologies to come out in recent years — service workers and the CacheStorage API — allow us an amazing level of control over the user’s browsing experience — even when their internet connection fails.</p>

<h2 id="taking-control-of-the-offline-experience">Taking control of the offline experience</h2>

<p>One library to provide an easy solution for the connectivity problem is called <a href="https://www.talater.com/upup/">UpUp</a>. <em>(Editor’s note: Tal is the developer of the UpUp library.)</em></p>

<p>UpUp allows you to define exactly what you want to show your users when they are offline, while handling all of the logic of intercepting requests, detecting when they fail, returning the right content from cache, managing that cache, and generally dealing with all the headaches of cross-browser compatibility.</p>

<p>The content you show your users can be as simple as one page (e.g. your business’ info, address, etc.), all the way to fully customized offline experiences with data customized for each user (e.g. a travel site’s user could browse his bookings, and get details on each booking, even while offline).</p>

<p>The best part of all, UpUp lets you do all of this in just a few lines of code:</p>

<pre><code>&lt;script src="/upup.min.js"&gt;&lt;/script&gt;
&lt;script&gt;
	UpUp.start({
		'content-url': 'offline.html'
	});
&lt;/script&gt;
</code></pre>

<p>In this article we’ll first look at how you can use UpUp to add offline capabilities to your site in under 10 minutes. We will then dive deeper behind the scenes, and see how UpUp achieves all of this.</p>

<h2 id="minute-tutorial">10 minute tutorial</h2>

<p>Let’s begin with a simple site, and add offline features to it:</p>

<pre><code>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
	&lt;meta charset="utf-8"&gt;
	&lt;title&gt;Lonely Globe Advisor&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
	&lt;h1&gt;Top Hotels in Rome&lt;/h1&gt;
	&lt;ol&gt;
		&lt;li&gt;Villa Domus — Via Piacenza 9, Rome, Italy&lt;/li&gt;
		&lt;li&gt;Hotel Trivelli — Piazza Barberini 11, Rome, Italy&lt;/li&gt;
	&lt;/ol&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>

<p>Our sample site, Lonely Globe Advisor, offers visitors a list of the top fictional hotels in Rome.</p>

<p>But what happens if our user just landed in Rome and doesn’t have a local data plan? She’ll be out of luck.</p>

<p>We can improve on this experience by loading UpUp, and telling it what content we want it to show the user if she is offline.</p>

<pre><code>&lt;h1&gt;Top Hotels in Rome&lt;/h1&gt;
&lt;ol&gt;
	&lt;li&gt;Villa Domus — Via Piacenza 9, Rome, Italy&lt;/li&gt;
	&lt;li&gt;Hotel Trivelli — Piazza Barberini 11, Rome, Italy&lt;/li&gt;
&lt;/ol&gt;
&lt;script src="/upup.min.js"&gt;&lt;/script&gt;
&lt;script&gt;
	UpUp.start({
		'content-url': '/offline.html'
	});
&lt;/script&gt;
</code></pre>

<p>With just this tiny bit of code, we’ve added an offline experience for our site, and allowed our users to see the best hotels in Rome… even when they can’t access the web.</p>

<p>Any user that visited our site in the past, and is now trying to access it again without an internet connection, will now see the content of <code>offline.html</code>. Make sure you create this file and place it in the location you defined under <code>content-url</code>.</p>

<p>The sample above just shows a simple html page. You can improve on your offline content by including stylesheets, images, or even videos in your <code>offline.html</code>. You just need to make sure to tell UpUp what files you’re using, and it will cache them so they are available for your users when they are offline.</p>

<pre><code>&lt;h1&gt;Top Hotels in Rome&lt;/h1&gt;
&lt;ol&gt;
	&lt;li&gt;Villa Domus — Via Piacenza 9, Rome, Italy&lt;/li&gt;
	&lt;li&gt;Hotel Trivelli — Piazza Barberini 11, Rome, Italy&lt;/li&gt;
&lt;/ol&gt;
&lt;script src="/upup.min.js"&gt;&lt;/script&gt;
&lt;script&gt;
	UpUp.start({
		'content-url': 'offline.html',
		'assets': [
			'css/bootstrap.min.css',
			'img/trivelli.jpg',
			'mov/intro.mp4'
		]
	});
&lt;/script&gt;
</code></pre>

<p>With just one command and a couple of settings, we can create rich offline experiences for our users. These can be as simple as the example above, or as robust as a full single page application using frameworks like AngularJS, with content customized for each user, videos and files the user can access while offline.</p>

<p>There’s a more <a href="https://www.talater.com/upup/getting-started-with-offline-first.html">detailed tutorial</a> available on the official site, as well as complete documentation of <a href="https://github.com/TalAter/UpUp/blob/master/docs/README.md">UpUp’s API</a>.</p>

<h2 id="how-does-it-work">How does it work?</h2>

<p>How does UpUp serve this content to our users if they aren’t connected to the internet?</p>

<h4 id="tldr">tl;dr</h4>

<p>UpUp uses a new type of script called a ServiceWorker. This script runs even when the user is offline, and wraps every request made to the server with a promise. If the server can’t be reached, that promise is broken. The script catches broken promises, checks in its cache to see what offline content you’ve chosen to show and returns that instead of an error.</p>

<h4 id="serviceworkers">ServiceWorkers</h4>

<p>In order to understand how this works, let’s first understand how ServiceWorkers work.</p>

<p>A ServiceWorker is a special type of script that any site can register in the user’s browser. Once registered, this script sits in a very interesting position between the browser windows and that site’s server.</p>

<figure block="figure">
	<img elem="media" src="/articles/offline-with-upup-service-workers/serviceworker-online.gif" alt="Request and response to server through a ServiceWorker" />
</figure>

<p>As you can see, while the ServiceWorker runs within the user’s browser, it isn’t attached to any one window. Instead it runs in the background, and can communicate with the windows in its scope (the site that registered it).</p>

<p>From this unique location in the browser, ServiceWorkers have the power to examine each request as it is sent from the user’s browser, decide what to do with it, and then send it to the server. The ServiceWorker can then examine the response as it is returned from the server, decide what to do with it, and then pass either the original or a modified response back to the user’s window.</p>

<p>In a way, you can think of a ServiceWorker as a local proxy server inside the user’s browser. A proxy written in JavaScript that has the power to change requests and their responses.</p>

<p>Now if you think about this flow, you can probably begin to see the many different possibilities this grants us as developers.</p>

<p>For example, you could have a templating engine written entirely inside a ServiceWorker. This ServiceWorker would intercept requests to the server for HTML, asking the server for JSON instead. It would then parse that JSON against a template it has stored within it, and finally return simple HTML as the response. This could save us from rendering the HTML on the server, save bandwidth in the responses, and save us from having to include the templating logic in every page of our site. In other words, the server returns simple JSON, and the web page receives simple HTML.</p>

<p>Another idea could be a ServiceWorker that redirects requests to video files to either SD or HD videos based on the user’s connection speed or settings — this could be done without requiring each page to hold the logic for making that decision, or involving the server in the decision, allowing us to use a server optimized for delivering static files.</p>

<h4 id="serviceworkers-and-upup">ServiceWorkers and UpUp</h4>

<p>UpUp uses the power of ServiceWorkers to provide a solution to the lost connectivity problem described above, and serve content to the user even when their connection is down.</p>

<p>Let’s follow what happens behind the scenes of UpUp.</p>

<p>We’ll begin by registering a ServiceWorker. Once registered, all requests from the browser to our server go through the ServiceWorker, where they are wrapped in a JavaScript promise, and pass on untouched to our server. If that promise is broken (ie. we did not receive a response from the server), the ServiceWorker catches that error before it is shown to the user. It will then check for the cached content we’ve decided to show the user, and return that as the response, instead of an error .</p>

<figure block="figure">
	<img elem="media" src="/articles/offline-with-upup-service-workers/serviceworker-offline.gif" alt="Request and response to server through a ServiceWorker falling back to cache" />
</figure>

<p>To the browser’s window, responses returned from the server or from the cache by the ServiceWorker look exactly the same.</p>

<h5 id="where-does-the-offline-content-come-from">Where does the offline content come from?</h5>

<p>The final piece of the puzzle is the new caching technology used by UpUp — CacheStorage. Note: don’t confuse this with the browser’s own cache, or with that <a href="http://alistapart.com/article/application-cache-is-a-douchebag">douchebag</a>, the Application Cache. This is something new and much more powerful.</p>

<p>When we first registered our ServiceWorker, we told it what content to store in cache for later (we defined this in the <code>content-url</code> and <code>assets</code> settings). The UpUp ServiceWorker script went ahead and fetched that content, and stored it using the CacheStorage interface.</p>

<p>This content will now be available for the ServiceWorker the next time the user is offline.</p>

<h2 id="important-serviceworkers-considerations">Important ServiceWorkers Considerations</h2>

<p>When using ServiceWorkers, there are a few things you need to always keep in mind.</p>

<h4 id="https-only">HTTPS Only</h4>

<p>To preserve the user’s security and privacy, ServiceWorkers can only detect requests over a secure connection.</p>

<p>During development you can use UpUp through localhost or file (e.g. both <code>http://localhost/</code> and <code>file:///Users/tal_ater/index.html</code> are OK), but to deploy it to production you’ll need to have HTTPS set up on your server.</p>

<h4 id="browser-support">Browser Support</h4>

<p>UpUp plays nicely with all browsers, progressively enhancing browsers that support ServiceWorkers, while leaving users with older browsers unaffected.</p>

<p>UpUp currently supports Opera (since version 27), Chrome (since version 40) and Firefox (since version 41). If your users are using a different browser, they simply won’t notice anything different.</p>

<h4 id="where-should-i-place-my-files">Where Should I Place My Files?</h4>

<p>For security reasons, the browser only lets UpUp’s ServiceWorker see network requests within its scope.</p>

<p>The scope that the ServiceWorker can affect is determined by where you’ve placed <code>upup.min.js</code> and <code>upup.sw.min.js</code>. For example, if you place it on <code>https://yoursite.com/js/upup.sw.min.js</code>, UpUp will only be able to show your offline content when users try to look at the /js/ directory.</p>

<p>This is why it’s important to place both files on the same server as your content, and not in a subdirectory. This should ideally be in the root of your site (e.g. <code>https://yoursite.com/upup.min.js</code>).</p>

<h2 id="whats-next">What’s Next?</h2>

<p>It’s hard not to be excited about all the new possibilities ServiceWorker opens up to us as developers.</p>

<p>Go ahead, and try UpUp on your own site, you can see it in action and find more details and tutorials on doing <a href="https://www.talater.com/upup/">Offline First with UpUp</a>.</p>

<p>If you’d like to dive deeper and play some more with ServiceWorkers, there’s a <a href="http://www.html5rocks.com/en/tutorials/service-worker/introduction/">great introduction</a> by Matt Gaunt. If you’d like a few other ideas of how to improve caching with ServiceWorkers, check out Jake Archibald’s <a href="https://jakearchibald.com/2014/offline-cookbook/">Offline Cookbook</a>.</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/release-the-beacons/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/release-the-beacons/"/><title>Release the Beacons!</title><published>2015-10-08T00:00:00+00:00</published><updated>2015-10-08T00:00:00+00:00</updated><author><name>Bruce Lawson</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<p>Norway is the nation that gave the world the <a href="http://inventors.about.com/library/inventors/blpaperclip.htm">paperclip</a> and the <a href="http://inventors.about.com/od/famousinventions/fl/Who-Invented-the-Cheese-Slicer.htm">cheese slicer</a>, so it’s easy to see that R&amp;D is a national tradition here (it stands for “research and development”, not “reindeer and dogsleds”, although those are nice too).</p>

<p>Today, Opera R&amp;D released a <a href="https://www.opera.com/download/get/?partner=www&amp;product=android&amp;level=Developer">labs build of Opera for Android</a> (APK, 30 MB) with URL beacon detection.</p>

<h2 id="what-are-url-beacons">What are URL beacons?</h2>

<p>A “beacon” is defined as “a fire or light set up in a high or prominent position as a warning, signal, or celebration”, and this is very much the same in the context of the Physical Web (aka “The Internet of Things”). A beacon is a low-powered chip with its own power source that does one thing: it broadcasts information, using a Bluetooth low energy (BLE) message format like Eddystone, AltBeacon or iBeacon.</p>

<p>These formats compete with each other. The latter two broadcast a Unique Identification Number (UID), so users need an app specific for those beacons, or require Apple’s Passbook to do anything with those UIDs.</p>

<p><a href="https://github.com/google/eddystone">Eddystone</a>, named after a famous <a href="https://en.wikipedia.org/wiki/Eddystone_Lighthouse">British lighthouse</a>, simply broadcasts a URL. This simplicity makes these URL beacons especially interesting in the context of the mobile web. (Eddystone actually supports <a href="https://github.com/google/eddystone">broadcasting UIDs</a> as well. This Opera Labs build currently only supports Eddystone-URL.)</p>

<p>When a user with Bluetooth software comes near a beacon, their device can pick up the URL. And what better way to handle a URL than with a browser?</p>

<h2 id="labs-build">Labs build</h2>

<p>Today’s Labs build is Opera 32 for Android, with additional beacon goodness. Installing it won’t overwrite any existing installations of Opera for Android or Opera Beta. (If you have a previous <em>Labs</em> build of Opera, uninstall that one first.)</p>

<p>To use beacons, accept the dialog shown on first run. Beacons are shown in the “Nearby” panel, which you find on the right of the “Discover” panel. Two swiped to the right and you’re there!.</p>

<p>Here’s a photo taken at our local bus stop. The bus stop is broadcasting a unique URL (other bus stops can broadcast different URLs).</p>

<figure block="figure">
	<img elem="media" src="/articles/release-the-beacons/bus-stop.jpg" alt="" />
</figure>

<p>For those who don’t read Norwegian (why not?) it’s telling us that the number 30 to Bygdoy is coming now, the number 30 to the Opera office in Nydalen is coming in 5 minutes, which is lucky, or we’d be late for work again. (Not our fault! We were in the pub last night — checking out their beacons, naturally.)</p>

<figure block="figure">
	<img elem="media" src="/articles/release-the-beacons/others.jpg" alt="" />
</figure>

<p>Additionally, as there are few beacons “in the wild” at the moment, this Opera Labs build’s “Nearby” panel shows Wikipedia entries based on geolocation, so that there’s always something shown. This allows for a mix of geotagged “general interest” Wikipedia stuff, and very location-specific info coming from beacons.</p>

<p>Beacons will trigger an Android system notification, so you can easily find out if there’s a new beacon around. Wikipedia results on the other hand do not display a notification.</p>

<h2 id="security-and-privacy">Security and privacy</h2>

<p>Beacon signals are one-way only. They are emitted by the beacon, and picked up by your phone, and nothing is ever sent back to the beacon. This is great for privacy, because it means that the owner of the beacon cannot track anyone who steps within range.</p>

<p>There is, however, a privacy trap here that we could fall into if we’re not careful. Consider the naive beacon-scanning application: it sits in the background of your phone and scans for beacons. Every time it sees a new beacon, it resolves a shortened URL to a real URL. Then it fetches the web page at that location, in order to extract some metadata to show you. The problem here is that the owner of the beacon probably controls the web page. When they see that you request the web page, they know that you’re probably near the beacon. If they own a lot of beacons — maybe it’s an international chain store or a fast-food establishment — they can track your IP address wherever you go.</p>

<p>To better protect you, the beacon scanner in the Opera browser comes with an anonymizing service, which shields you from making direct contact with these web pages. Rather than fetching metadata from the web page directly, the Opera browser sends a request to our server. The server will resolve URLs, fetch and parse pages, and prepare icons, then return just the bits you’re interested in. This results in less data traffic used, fewer CPU cycles spent and most importantly, better privacy (provided, of course, that you trust Opera).</p>

<h2 id="populating-the-nearby-list">Populating the Nearby list</h2>

<p>So maybe you’ve ordered yourself a handful of beacons, and you want to prepare your web pages for beaconization (new technologies require new words). But, how exactly does the “Nearby” screen in the Opera browser transform full web pages into simple list elements? If you want to make your page look good in the “Nearby” screen, you’ve got three choices at the moment — just use one. We recommend plain HTML.</p>

<h3 id="html">HTML</h3>

<p>This is maybe the most straightforward solution. Use the <code>&lt;title&gt;</code> element, the <code>&lt;meta name="description"&gt;</code> element to hold the description (any line breaks will be replicated in the “Nearby” panel) and point <code>&lt;link rel="icon"&gt;</code> tag point to a high-resolution icon. A 144 × 144 PNG will look great.</p>

<h3 id="open-graph">Open Graph</h3>

<p>As an alternative to the approach above, you can use the following Open Graph tags, respectively: <code>&lt;meta name="og:title"&gt;</code>, <code>&lt;meta name="og:description"&gt;</code> and <code>&lt;meta name="og:image"&gt;</code>.</p>

<h3 id="schemaorg">Schema.org</h3>

<p>Finally, you can choose to annotate your HTML with <a href="http://schema.org/">Schema.org</a> microdata. Specifically, we look for the tags <code>&lt;meta itemprop="name"&gt;</code>, <code>&lt;meta itemprop="description"&gt;</code> and <code>&lt;meta itemprop="image"&gt;</code>.</p>

<h3 id="example">Example</h3>

<p>As an example, the “bus stop” URL has the following markup:</p>

<pre><code>&lt;head&gt;
	&lt;meta charset="UTF-8"&gt;
	&lt;meta name="description" content="
		30 til Bygdøy via Bygdøynes om 2 min
		56 til Solemskogen om 4 min
		30 til Bygdøy via Bygdøynes om 12 min
		30 til Nydalen klokka 14:54
		56 til Solemskogen klokka 14:58"&gt;
	&lt;meta http-equiv="refresh" content="30"&gt;
	&lt;link rel="icon" href="ruter.png"&gt;
	&lt;title&gt;Gullhaugveien&lt;/title&gt;
&lt;/head&gt;
</code></pre>

<p>The page title of the “Nearby” entry comes from the HTML <code>&lt;title&gt;</code>, the icon from the <code>&lt;link rel="icon"&gt;</code> and the main content from the <code>&lt;meta name="description"&gt;</code> element; line breaks in the content of the tag are reproduced in the Nearby panel. The <code>&lt;body&gt;</code> of the page is irrelevant, so one URL can be used to populate the “Nearby” panel and as a conventional web page.</p>

<h2 id="hardware-support-and-battery-usage">Hardware support and battery usage</h2>

<p>Depending on the Bluetooth hardware in the device, this Labs build can drain the battery. Newer hardware offloads scanning to the Bluetooth chip, and you will not notice any extra battery usage. But older hardware (like the Nexus 5) wakes up the device at specific intervals and will thus drain the battery faster. You can check this from “Nearby” → Settings cogwheel → Debug information. There we show the level of hardware support and estimated battery usage (low, medium, high).</p>

<h2 id="setting-up-your-own-beacons">Setting up your own beacons.</h2>

<p>It’s easy to buy Eddystone beacons, and to set them up from a computer, using a Bluetooth 4.0 Low Energy dongle. Opera’s Tommy Thorsen wrote a python script to <a href="https://github.com/google/eddystone/tree/master/eddystone-url/implementations/linux-url-advertiser">advertise a URL using Eddystone-URL</a>.</p>

<h2 id="why-are-beacons-a-good-fit-for-opera">Why are beacons a good fit for Opera?</h2>

<p>We at Opera R&amp;D really like beacons, especially URL-beacons. As a web browser, URLs are exactly what we’re good at, and new ways to discover more URLs is great news for us. But, what will we do with these URLs? And what can beacons really be used for?</p>

<p>You can divide technologies into two groups: technologies that have a specific use case vs. technologies that can do all sorts of stuff, but we’re not sure what the interesting use cases are. Some of the most revolutionary technologies fall within the latter group. Take the World Wide Web as an example; the technology is really just bits of text that can contain links to other bits of text. But, as people have started using and extending the technology, we’ve taken it to a level which surely no one could have imagined a few years ago. Or, SMS, which is just an afterthought in the GSM specification but, despite (or because of?) its limitations, became hugely popular.</p>

<p>New use cases will come about when the <a href="https://webbluetoothcg.github.io/web-bluetooth/">Web Bluetooth API</a> is finished: you can then discover and use Bluetooth smart devices directly from the browser. For instance, here’s a cool Firefox OS demo <a href="https://hacks.mozilla.org/2015/08/flying-a-drone-in-your-browser-with-webbluetooth/">Flying a drone in your browser with Web Bluetooth</a>.</p>

<p>Can beacons be the next groundbreaking thing? That’s hard to say, but the technology has that potential: like the web and SMS, it provides a simple but versatile service, on top of which developers can improvise and innovate. Linking beacons to the web, via the browser, is a solid step forward, and will hopefully accelerate that innovation.</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/installable-web-apps/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/installable-web-apps/"/><title>Installable Web Apps and Add to Home screen</title><published>2015-09-23T00:00:00+00:00</published><updated>2015-09-23T00:00:00+00:00</updated><author><name>Andreas Bovens, Bruce Lawson</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<figure block="figure">
	<img elem="media" src="/articles/installable-web-apps/voice-memos.jpg" alt="Installation of Voice Memos app" />
</figure>

<p>Today, we’ve launched Opera 32 for Android. Along with a host of bug fixes, stability improvements and an updated Chromium engine for maximum compatibility and security, you’ll find some features that are deliberately designed to bridge the gap between native apps and the “mobile web” (or, at least, the web viewed on mobile devices).</p>

<p>(Updated 30 September 2015: today’s update to Opera 32 for Android changes the name selection criteria.)</p>

<p>One of the bigger gaps has been the difference between bookmarking a site and installing an application. We know that, even on desktop, <a href="https://www.opera.com/blogs/desktop/2013/07/ctrl-z-of-ctrl-d/">most people don’t use bookmarks</a>. We also know that people love “installing” apps that live on a device’s homescreen, with a crystal-clear icon imploring them to tickle them into life with a tap of the finger.</p>

<p>When a user loads a site in Opera 32 for Android, taps the plus sign, and chooses “Add to home screen”, a shortcut to this site is placed on the home screen of her/his device, allowing for direct access and increased visibility.</p>

<p>Through the magic of web standards, site owners can make this even better: by serving the site over HTTPS and providing some metadata in a <a href="https://w3c.github.io/manifest/">manifest file</a> a web app can get an optimized icon, and be run in “standalone” or even “fullscreen” mode, with a custom orientation. These web apps also run in a separate process, just like a native app. We call this “Installable Web Apps”.</p>

<p>You can try this out on <a href="https://dev.opera.com/">Dev.Opera</a> or <a href="https://airhorner.com/">Airhorner</a>. Cool, huh?</p>

<h2 id="why">Why?</h2>

<p>We’re very excited about Installable Web Apps, as they bridge the gap between native and web apps in a most elegant way: they allow you to build applications using the full web stack that run in the browser as well as outside of it, without sacrificing crucial functionality like hyperlinking, and without the need for app stores or gatekeepers.</p>

<p>If you want to read more about why this is an exciting evolution, Alex Russell of the Google Chrome team has an excellent write-up called <a href="https://infrequently.org/2015/06/progressive-apps-escaping-tabs-without-losing-our-soul/">Progressive Apps: Escaping Tabs Without Losing Our Soul</a> that explains many of the advantages from both a developer and a consumer perspective.</p>

<p>Here are two more that appeal to us:</p>

<h3 id="no-update-distribution-lag">No update distribution lag</h3>

<p>With a centralised app store distribution model, the user receives a notification that a new version of your app is available; they download it and install it. However, in many parts of the world, data is expensive or WiFi is a luxury, so people don’t update over their mobile connections. This means that outdated versions of your app continue to be used long after you’ve released an update. If the outdated version has a security flaw, this is a problem.</p>

<p>With Installable Web Apps, the app is actually on your web server, so the instant you update it, everybody gets it, at the time they need it — there’s no update distribution lag, and the user isn’t wasting their precious data to download a complete new version of your app.</p>

<h3 id="less-storage-space-required">Less storage space required</h3>

<p>The <a href="https://think.storage.googleapis.com/docs/mobile-app-marketing-insights.pdf">average app user has 36 apps on their smartphone (PDF)</a>. 25% are used daily (social/comms/gaming); 25% are never used.</p>

<p>Those occasionally used apps are taking up a lot of storage on a device that may be inexpensive and therefore have little space. According to <a href="vhttp://www.techrepublic.com/article/ram-a-lama-dont-be-a-ding-ding-about-android-storage/">Techrepublic</a>,</p>

<blockquote>
  <p>Internal storage is particularly important, because this is where your apps are stored. If you buy a budget or entry-level phone, you’ll probably find around 512 MB of internal storage. With this low amount of storage, you’ll only be able to install a few apps.</p>
</blockquote>

<p>In addition, we know from the <a href="https://www.youtube.com/watch?v=7V-fIGMDsmE&amp;feature=youtu.be&amp;t=1h21m30s">2015 Google I/O keynote</a> that…</p>

<blockquote>
  <p>Over a quarter of new Android devices have only 512 MB of RAM</p>
</blockquote>

<p>In short, installing and running various apps on low-end devices is not always so straightforward.</p>

<p>It’s here that installable Web Apps come in: they typically only store an icon, a text-based JSON manifest and some cached data on the device, which is likely to use less storage.</p>

<h2 id="installation-mechanisms">Installation mechanisms</h2>

<p>In this release, site visitors can add a website to their home screen by tapping the <strong>+</strong> icon on the left of the address bar.</p>

<p>In a future release, we’ll make it more discoverable: under certain circumstances Opera will prompt the user to add the site they’re visiting to the Home screen.</p>

<h2 id="defining-start-up-characteristics">Defining start-up characteristics</h2>

<p>To make your site fully “installable”, you need to declare some characteristics in a special manifest file.</p>

<p>The manifest file is a simple JSON text file; link to it from the <code>&lt;head&gt;</code> with a line like this:</p>

<pre><code>&lt;link rel="manifest" href="/manifest.json"&gt;
</code></pre>

<h3 id="defining-icons">Defining icons</h3>

<p>Your app will be added to Home screen with its own icon, rather than that of the browser. For this, the manifest has an <code>icons</code> property. This takes a list of icons and their sizes, format, and target screen density. Having these optional properties makes icon selection powerful, because it provides a responsive image solution for icons – which can help avoid unnecessary downloads and helps to make sure your icons always look great across a range of devices and screen densities.</p>

<pre><code>{
	"icons": [
		{
			"src": "icon/lowres",
			"sizes": "64x64",
			"type": "image/webp"
		},
		{
			"src": "icon/hd_small",
			"sizes": "64x64"
		},
		{
			"src": "icon/hd_hi",
			"sizes": "128x128",
			"density": 2
		}
	]
}
</code></pre>

<p>In Opera, the icon will be fetched from the manifest (if there is one),
regardless of HTTP/HTTPS status. if there is no manifest, the first favicon or alternatively, a generic fallback icon is used.</p>

<h3 id="defining-the-name">Defining the name</h3>

<p>If your app is hosted on HTTPS, the manifest is parsed and the <code>short_name</code> is displayed on the Android home screen. Keep it short — a truncated name isn’t a good user experience, and doesn’t look very professional.</p>

<p>If Opera can’t find a <code>short_name</code>, it’ll use <code>name</code> and, if that’s not present, the HTML <code>title</code> is used.</p>

<h3 id="display-modes">Display modes</h3>

<p>The specification defines <a href="https://w3c.github.io/manifest/#display-modes">display modes</a>, which are different ways to show your web app.</p>

<p>Opera for Android supports</p>

<ul>
  <li><code>fullscreen</code> — the app will take all the screen; hardware keys and the status bar will not be shown. Note, this is not the same as HTML5 <code>fullscreen</code> mode.</li>
  <li><code>standalone</code> — no browser UI is shown, but the hardware keys and status bar will be displayed.</li>
  <li><code>browser</code> — the app will be shown with normal browser UI, ie. as a normal website. Note that custom orientations are not yet supported in this mode.</li>
</ul>

<p>The <code>minimal-ui</code> mode is not supported; it falls back to <code>browser</code> as the spec requires.</p>

<p>In Opera for Android, only sites on HTTPS can be displayed in <code>fullscreen</code> or <code>standalone</code> mode. Insecure sites are always displayed in <code>browser</code> mode, regardless of the manifest definition, to better protect the user; we show the URL bar so the user can always see the real address of insecure sites (hackers could, for example, spoof a bank site). Note that this is different from the behaviour of the current Chrome for Android (Chrome 45).</p>

<p>In modes without browser UI, Opera supports pull-to-refresh, making it feel more app-like.</p>

<h3 id="start-url">Start URL</h3>

<p>Sometimes you want to make sure that when the user starts up an app, they always go to a particular page first. The <code>start_url</code> property gives you a way of indicating this.</p>

<pre><code>{
	"start_url": "/firstPage.html"
}
</code></pre>

<p>With this, you can include the manifest on every page of your web app so the user can install it from wherever they are, but send them to a common home page when they start it from the Home screen, rather than returning them to the page from which it was installed.</p>

<h3 id="themecolor"><code>theme_color</code></h3>

<p>The manifest <a href="https://w3c.github.io/manifest/#theme_color-member"><code>theme_color</code></a> is not yet supported. Use the HTML meta tag to set it in Opera and Chrome:</p>

<pre><code>&lt;meta name="theme-color" content="#ababab"&gt;
</code></pre>

<p>This will colour your app’s toolbar and make it more distinguishable in system functions such as task switching. You probably want to choose the predominant colour of your page or branding.</p>

<h3 id="navigating-outside-the-apps-scope">Navigating outside the app’s scope</h3>

<p>If the user follows a link that takes them outside the domain of an installed web app, the browser will flash 68 times, the device will vibrate like a demonically-possessed hippopotamus, and a klaxon will sound (your device may not support this). On all devices, the externally linked site will open in a new tab in Opera, showing the address bar, so you know where you are.</p>

<h3 id="differences-between-opera-and-chrome-for-android">Differences between Opera and Chrome for Android</h3>

<p>Opera’s implementation currently differs from Chrome’s in four main ways:</p>

<ul>
  <li>HTTP-hosted sites will only display with browser UI, regardless of what the manifest states</li>
  <li>when the user follows a link that takes the user out of the domain of the installed app, a new tab is spawned, with browser chrome. (Chrome shows a small address at the top of a standalone-app. We prefer to make it more obvious to the user that they have gone outside your app.)</li>
  <li>Opera doesn’t (yet) support <a href="https://developers.google.com/web/updates/2015/09/using-web-app-manifest-to-set-solid-color-loading-screen"><code>background_color</code></a>; this will be added in a forthcoming release.</li>
  <li>Chrome has a mechanism to suggest to a user that they add a site to Home screen called <a href="https://developers.google.com/web/updates/2015/03/increasing-engagement-with-app-install-banners-in-chrome-for-android?hl=en">App Install Banners</a>, depending on certain heuristics. We are experimenting with the suggestion criteria, and expect to include a similar mechanism in a future release. Chrome requires a <code>144x144</code> png icon as one criterion.</li>
</ul>

<h3 id="read-more-see-more">Read more, see more</h3>

<p>Spec author Marcos Cáceres and Bruce documented what goes in the manifest in an HTML5 Doctor article called <a href="http://html5doctor.com/web-manifest-specification/#appname">HTML App Manifest</a>. You can check out the one we made for Dev.Opera on <a href="https://github.com/operasoftware/devopera/blob/master/src/.webmanifest">GitHub</a>. The Chrome team has compiled a list of resources on <a href="https://developers.google.com/web/progressive-web-apps">Progressive Web Apps</a>.</p>

<p>You can also check out how it works on sites with a manifest, for example:</p>

<ul>
  <li><a href="https://dev.opera.com/">Dev.Opera</a></li>
  <li><a href="http://www.flipkart.com/">Flipkart Lite</a> (also see their <a href="http://tech-blog.flipkart.net/2015/11/progressive-web-app/">engineering blog</a> on how they made it)</li>
  <li><a href="https://m.oumy.com/">Oumy</a></li>
  <li><a href="https://airhorner.com/">Airhorner</a></li>
  <li><a href="https://medium.com/">Medium</a></li>
  <li><a href="https://twitter.com/">Twitter</a></li>
  <li><a href="https://jakearchibald.github.io/svgomg/">svgomg</a></li>
  <li><a href="https://voice-memos.appspot.com/">Voice Memos</a></li>
  <li><a href="https://guitar-tuner.appspot.com/">Guitar Tuner</a></li>
  <li><a href="https://abc.xyz/">abc.xyz</a></li>
</ul>

<h2 id="conclusion">Conclusion</h2>

<p>At Opera, we’re excited to promote Web Apps to be “first-class citizens” on Android devices and beyond, with visibility alongside native apps; we love the Web and we want to see it thrive.</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/houdini-f2f-report/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/houdini-f2f-report/"/><title>Houdini Task Force meeting report</title><published>2015-09-04T00:00:00+00:00</published><updated>2015-09-04T00:00:00+00:00</updated><author><name>Bruce Lawson</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<p>Houdini is a joint W3C Technical Architecture Group and CSS Working Group initiative to specify hooks into existing CSS. Its primary aim isn’t to give us “new CSS” but to add API hooks into the browsers’ built-in CSS capability so developers can hook into it, use the native implementation where we want (rather than duplicate it) and extend it. It’s applying the Extensible Web Manifesto’s philosophy to CSS. (If you’d like to know more about the aims and back story, read <a href="https://dev.opera.com/articles/houdini/">Sex, Houdini and the Extensible Web by Brian Kardell</a>.)</p>

<p>The Houdini Task Force held <a href="https://wiki.css-houdini.org/planning/sydney-2015">its first meeting</a> in Sydney in February 2015 and a follow-up in the beautiful offices of Mozilla, Paris in August 2015.</p>

<p>I attended as an observer, as I’ve been excited and intrigued by the project since its inception. In attendance were delegates from Apple, Opera, Mozilla, Microsoft, Google, Adobe, HP, and invited experts like Florian Rivoal and Lea Verou. (See the full <a href="https://wiki.css-houdini.org/planning/paris-2015#participants">participants list</a>.)</p>

<p>What follows isn’t a full record of the meeting, but my notes on the main questions I had; much of the meeting was taken up with discussion of implementation details and, as I wasn’t representing an implementor, they weren’t of primary interest to me. <a href="http://twitter.com/zcorpan">Simon Pieters</a> was formally representing Opera.</p>

<p>(You can read the full IRC logs of <a href="http://logs.csswg.org/irc.w3.org/houdini/2015-08-28/">day 1</a> and <a href="http://logs.csswg.org/irc.w3.org/houdini/2015-08-29/">day 2</a>.)</p>

<p>It’s important to note that many of the <a href="https://drafts.css-houdini.org/">specs discussed</a> are very nascent; some of them are little more than boilerplate prose.</p>

<p>I came to the meeting with a concrete set of use-cases that developers had told me they wanted, against which I attempted to measure the utility of the extensions discussed. After all, although one of the recurring jokes of the meeting was “Houdini Group: not immediately useful”, there’s no point in extending CSS for purely philosophical satisfaction; the outcome must be useful to developers at the end of the process.</p>

<p>Sample questions I had:</p>

<ul>
  <li>Will I be able to do sane (but currently impossible) layouts that depend on arbitrary element foo “knowing about” arbitrary element bar and match it/ react to it?</li>
  <li>Will I be able to do something as simple and desirable as the proposed (and rejected) <a href="https://blogs.adobe.com/webplatform/2013/01/30/balancing-text-for-better-readability/">text-wrap: balance</a>? (Update: I’m wrong; it wasn’t rejected. It’s in <a href="https://drafts.csswg.org/css-text-4/">CSS Text Level 4</a>.)</li>
  <li>Will I be able to do the much-requested h1 {font-size: just-make-it-big-enough-and-kern-it-pleasingly-so-that-it-fits-the-width} (For example, see <a href="http://fittextjs.com/">fittext.js</a>.)</li>
  <li>Can I polyfill <a href="http://www.w3.org/TR/css-regions-1/">CSS Regions</a>?</li>
</ul>

<h2 id="css-script-api">CSS Script API</h2>

<p>The first thing on the agenda was the <a href="http://bfgeek.com/css-houdini-drafts/css-script-api/Overview.html">CSS Script API</a>, AKA “CSS Worker” (or maybe “Isolated Worker”; bikeshedding continues) which is a bedrock that much of Houdini depends.</p>

<p>It’s an “API for running scripts in stages of the rendering pipeline independent of the main execution environment. This allows other APIs such as Style/Layout/Paint which effect [sic] different parts of the rendering pipeline to be exposed to the author safely, without major changes to the main execution environment APIs.” Similar to Service Worker, “the CSSWorkerGlobalScope may be destroyed / created at anytime. “</p>

<p>There was concern over performance; Simon Fraser
 (from Apple) was reluctant to add too many hooks into CSS that people can hang JavaScript on and slow down the pages, preferring to see declarative methods of achieving effects that the browser can optimise.</p>

<p>I agree, primarily because declarative methods are easier for authors; for sought-after use cases, we shouldn’t require developers to start scripting CSS or downloading libraries. (Also, as <a href="https://twitter.com/moreati/status/637176796811759616">Andrea Moreati told me</a> as I was live-tweeting, “CSS and <code>&lt;p&gt;</code> zero days are a lot rarer than JavaScript zero days”.)</p>

<p>But that ship’s already sailed — already, sane additions to HTML like <a href="https://html.spec.whatwg.org/multipage/tables.html#table-sorting-model"><code>&lt;table sortable&gt;</code></a> are already <a href="https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/07v_yMErc_A/vMaLz90VOJkJ">batted away</a> with “someone should create a web components library”.</p>

<p>Nevertheless, Ian Kilpatrick (the editor), said that Google have a prototype of CSS Workers and the Custom Layout spec that allows them to replicate a subset of Flexbox in unoptimised JavaScript that’s about half as fast as native.</p>

<h2 id="custom-layout-api">Custom layout API</h2>

<p>The <a href="https://drafts.css-houdini.org/css-layout-api/">Custom layout API</a> has a minimum set of features balancing making it useful for authors while not striking terror into the hearts of implementors:</p>

<ul>
  <li>Expose minInlineContent/maxInlineContent</li>
  <li>AbsPos is handled automatically (in the same fashion as flex/grid).</li>
  <li>The custom layout container establishes a formatting context, which implies that:
    <ul>
      <li>Floats cannot intrude into the custom layout</li>
      <li>Margins do not collapse</li>
    </ul>
  </li>
  <li>Blockify all children (similar to flex/grid)</li>
  <li>Float does not have any effect on children of a custom layout container (similar to flex/grid).</li>
  <li>No changing paint order (like the CSS order property on flex/grid).</li>
</ul>

<p>I initially read the latter point (no changing paint order) to suggest that I couldn’t lay out stuff independent of source order (thinking “no” forbade an equivalent to CSS order property). That would be pretty lame; it’s hard to think of an exciting new layout that slavishly follows source order. But I’m a buffoon and W3C’s <a href="https://twitter.com/svgeesus/status/637287345105018880">Chris Lilley set me right</a>: “paint order meaning order in which overlapping items are painted; not layout position.”</p>

<p><a href="https://twitter.com/sil/status/637179440640999424">Stuart Langridge grumbled</a> “hrm. That’s scripting. I already have scripting. Providing more hooks for js to use is nice, but it’s not CSS”. That’s true; any kind of polyfill/prollyfill uses script to simulate a native implementation.</p>

<p>The difference with Houdini is that you don’t have to emulate <em>everything</em>. You can get the information you need about boxes, heights, widths etc direct from the CSS Engine, via Houdini APIs, rather than have to jump through horrible hacky hoops with JavaScript. Ian Kilpatrick mentioned a previous version of Google Docs in which a font was copied to an off-screen iframe and then measured with JS; in the future™, that information will be available with the Houdini APIs.</p>

<p>Ian explained (after the meeting): “the iframe in Google Docs is subtle. It’s not just specific to Docs. The iframe is used to limit the amount of layout work that is needed to query the element’s width/height. Docs &amp; others who perform layout use this “trick” to contain the amount of layout work, (as the browser only has to layout a small iframe, rather than a large page). They can’t use a trick like FastDom as these layouts are usually iterative. So to do the custom layout, they layout thrash, but only on a small DOM. Custom layout you are performing this layout as part of the layout pass so, querying a child’s width/height is contained to just that subtree (and hence fast).”</p>

<p>Then you plug in whatever custom things that CSS doesn’t currently support, and the browser’s CSS parser continues doing its job, but with knowledge of what you’ve done. Instead of doing all the work yourself, you’re just plugging the hole rather than replicating the entire CSS in JavaScript.</p>

<h2 id="css-custom-paint-api">CSS Custom Paint API</h2>

<p>The <a href="https://drafts.css-houdini.org/css-paint-api/">custom paint API</a> allows you to have other things as a background apart from still images. The spec gives an example using canvas and <code>background-image: paint(circle)</code>:</p>

<pre><code>#myElement {
	--circle-color: red;
	background-image: paint(circle);
}
</code></pre>

<p>Notice this uses a <em>custom property</em>, as defined in Houdini’s <a href="https://drafts.css-houdini.org/css-properties-values-api/">Custom Properties and Layout module</a>; the <code>--</code> prefix is an “empty” vendor prefix (eg, not <code>-moz-</code> or <code>-webkit-</code>, as it’s defined by the individual author.
The script to accomplish this is:</p>

<pre><code>this.registerPaint({
	name: 'circle',
	dependencies: ['--circle-color'],
	paintCallback: function(ctx, geom, properties) {
		// Change the fill color.
		var color = properties['--circle-color'];
		ctx.fillStyle = color;

		// Determine the center point and radius.
		var x = geom.width / 2;
		var y = geom.height / 2;
		var radius = Math.min(x, y);

		// Draw the circle \o/
		ctx.beginPath();
		ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
		ctx.fill();
	}
});
</code></pre>

<p>Of course, you could do this with an extra canvas element behind the element that you want to set a background on, but that would require more markup and ensuring that the canvas and the “real” element were always the same size and overlapping.</p>

<p>(Added 15 Sept:) Ian Kilpatrick recently blogged <a href="http://bfgeek.com/houdini/2015/09/14/the-performance-of-houdini-paint/">The Performance of Houdini Paint</a> in response to a question by Stuart.</p>

<h2 id="cssom-20">CSSOM 2.0</h2>

<p>In a new version of CSSOM, value objects would be preferable, but we can’t rely on TC39 standardising those in time, so it’ll use normal objects (strings are too slow). As this is a “framework dev”‘s API, I raided the Mozilla kitchen for 9 kilos of their excellent goat cheese and gave that my attention.</p>

<h2 id="gcss">GCSS</h2>

<p>Lea Verou proposed <a href="https://lists.w3.org/Archives/Public/public-houdini/2015Jul/0003.html">Generalized Cascading Sheets</a> to W3C, so that a general set of rules could be derived so the CSS Parser could be used (hooked into, adapted and — when necessary — over-ridden) by the “proliferation of languages with CSS-like syntax and rules”.</p>

<p>The <a href="https://drafts.css-houdini.org/css-parser-api/">CSS Parser API</a> gives most of the hooks (although shorthands are currently a mess), and Houdini APIs “expose what the browser does to turn characters into CSSOM”. Google reps were reluctant to add the Cascade to that because their implementation isn’t generic, but that’s easy enough to implement in JavaScript, if you can get specificity of a selector from Houdini (and not all CSS-style languages cascade, anyway).</p>

<p>I’m unclear about what (if anything) was resolved as the next step. If I were implementing, I’d want to concentrate on the core Houdini specs that let web authors do more stuff™ before specifying a meta-CSS for non-web authors, with all the research and cross-interest group argy-bargy that would require, although I agree it’s a useful long-term goal.</p>

<h2 id="font-metrics">Font Metrics</h2>

<p>Font metrics API will allow authors to get info about a glyph (and potentially more info about its parent font — does it have an oblique variant, what’s font’s x-height?).</p>

<p>Use cases are things like lining up images with top of a drop cap; exposing font baselines on 2 different things and lining them up.</p>

<p>I think the group didn’t know enough about what designers need to know about fonts to further specify this w/o consulting authors. But it’s early days, and they’d love <a href="https://github.com/w3c/css-houdini-drafts/issues">constructive comments and feedback</a></p>

<h2 id="custom-compositor">Custom Compositor</h2>

<p>Custom Compositor was originally called “UI Worker” — here’s a <a href="https://www.youtube.com/watch?v=Kgy6XBJB_jI">video from BlinkOn3</a> with the basic use-case spelled out.</p>

<p>Later on it became “CompositorWorker” (and elsewhere, “Async Style”; like I said, bikeshedding continues) with an <a href="https://docs.google.com/document/d/18GGuTRGnafai17PDWjCHHAvFRsCfYUDYsi720sVPkws/edit#">explainer document</a> that says “the key problem facing the Web Platform is providing a thread that can run user code, respond to input, and update visuals without janking”.</p>

<p>From the explainer: the goals of this API are to</p>

<ul>
  <li>Interact well with scroll customization, Web Animations, and input,</li>
  <li>Permit custom effects synchronized with threaded scrolling and CSS animations,</li>
  <li>Minimize foot guns, and</li>
  <li>Avoid coupling to current browser architectures.</li>
</ul>

<h2 id="rendering-pipeline">Rendering Pipeline</h2>

<p>There was a proposal for a <a href="https://docs.google.com/document/d/1Mw6qNw8UAEfW96CXaXRVYPPZjqQS3YdK7v57wFttAhs/edit#">standardised rendering pipeline</a> (although this might not fit firmly within the Houdini remit).</p>

<p>The proto-spec says things like “Exactly once per frame, the browser should run the pipeline from start to finish (i.e. left to right).”</p>

<p>I’m all for APIs that give us a common representation of browsers’ different internal structures, but I’m less sure of a specification that requires a particular order of processing at specified intervals. While the text quoted above seems sensible enough, who’s to say that a browser will never come up with a way to optimise speed or CPU by doing things differently? I’m wary of painting ourselves into a corner or forcing Chromium’s workflow on other browsers here.</p>

<h2 id="conclusion">Conclusion</h2>

<p>When it came to prioritisation, I said (from a highly unscientific process of reading what was said by people geeky enough to be tweeting me on a warm Saturday afternoon) that authors seemed most enthused by Custom Paint, Custom Layout, and Font Metrics.</p>

<p>Many attendees expressed concerns about potentially requiring them to re-factor code to homogenise implementations (rather than simply adding hooks to expose information within their current implementations), and all were wary of performance implications of shipping foot-guns.</p>

<p>The ultimate end-result, of paramount importance to me, is that Houdini doesn’t stop development of declarative CSS by batting all new proposals to scripting against Houdini. I hope it functions as a method for developers to try out ideas which are then rolled back into the declarative language for native implementation and optimisation. Time will tell.</p>

<p><em>Thank you to Ian Kilpatrick (Google) for corrections and contributions to this report, to Mozilla for hosting and giving me goat cheese, and to the Houdini Task Force for allowing me to attend and providing me with a comfortable cage.</em></p>
]]></content></entry><entry><id>https://dev.opera.com/articles/on-a-moratorium-on-new-browser-features/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/on-a-moratorium-on-new-browser-features/"/><title>On PPK’s moratorium on new browser features</title><published>2015-08-03T00:00:00+00:00</published><updated>2015-08-03T00:00:00+00:00</updated><author><name>Bruce Lawson</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<p>Famed developer and commentator Peter Paul Koch (PPK) recently called for “a moratorium on new browser features for about a year or so”. If you haven’t read his article <a href="http://www.quirksmode.org/blog/archives/2015/07/stop_pushing_th.html">Stop pushing the web forward</a>, give it a look; he raises interesting points, as he always does.</p>

<p>(Let us say now: we’re all big fans of PPK; he’s undergone <a href="https://twitter.com/ppk/status/626849503321149440">personal attacks</a> for his article — we’re going to disagree with his central thesis, while continuing to love him deeply, and thanking him for starting this discussion.)</p>

<p>In many ways, we Opera devrel folks feel his pain. Each of us is familiar with the feeling of coming back from a vacation and not understanding the Twitter conversations about specs that were launched in the fortnight we were lounging next to a pool / winning hearts with our bachata / touring ancient ruins / having it large in Magaluf / doing emoji poos and wishing we hadn’t eaten so many <code>U+1F364</code>s last night. (Delete as appropriate depending if you’re Bruce, Shwetank, Mathias, Vadim, or Andreas.)</p>

<p>There’s a lot to learn, and the web platform is becoming more complex. Even Ian Hickson, the editor of HTML5, <a href="http://html5doctor.com/interview-with-ian-hickson-html-editor/">said</a>:</p>

<blockquote>
  <p>The platform has been too complex for any one person to fully understand for a long time already. Heck, there are parts of the Web platform that I haven’t even tried to grok — for example, WebGL or IndexDB — and parts that I continually find to be incredibly complicated despite my efforts at understanding them</p>
</blockquote>

<p>…and that was two and a half years ago!</p>

<p>But it’s not necessary to remember the minutiae of every specification. It’s necessary to know what’s possible, and have access to a search engine to find the spec or tutorials to find details. How many of us memorise the syntax for CSS gradients, or remember every piece of the Web Audio API syntax? But that doesn’t stop us using them when we need to.</p>

<p>But PPK’s complaint isn’t primarily about complexity:</p>

<blockquote>
  <p>We should focus on the web’s strengths: simplicity, URLs and reach. The innovation machine is running at full speed in the wrong direction.</p>
</blockquote>

<p>PPK cites an example:</p>

<blockquote>
  <p>To me, Navigation Transitions exemplifies what’s wrong with new browser features today. Its purpose is to allow for a smooth transition from one web page to another, to the point of synchronising the animations on the source and destination pages […] We’ve done without for years. More importantly, end users have done without for years, and are quite used to a slight delay when they load another page […] But why do web developers want navigation transitions? In order to emulate native apps, of course. To me, that’s not good enough.</p>
</blockquote>

<p>But the point here is that users <em>do</em> want such things, because they’ve now become used to experiences available in native apps. And we know that consumers love the app experience; in April 2014, the mobile analytics firm <a href="http://flurrymobile.tumblr.com/post/115191864580/apps-solidify-leadership-six-years-into-the-mobile">Flurry reported</a></p>

<blockquote>
  <p>Apps continued to cement their lead, and commanded 86% of the average US mobile consumer’s time, or 2 hrs and 19 minutes per day. Time spent on the mobile web continued to decline and averaged just 14% of the US mobile consumer’s time, or 22 minutes per day.</p>
</blockquote>

<p>Many of the new “features” coming to the web, like <a href="https://jakearchibald.com/2014/service-worker-first-draft/">Service Worker</a> or <a href="https://dev.opera.com/blog/installable-web-apps/">Installable Web Apps</a>, are designed to enhance the web experience for end users — experiences they’ve become accustomed to from native apps but weren’t achievable previously on the web. That’s a win.</p>

<p>We also respectfully disagree with PPK that there’s a dichotomy between adding native-like user experiences and protecting the web’s core strengths of simplicity, URLs and reach.</p>

<p>Let’s address those core strengths in reverse order:</p>

<h2 id="reach">Reach</h2>

<p>We’re reaching the point when some organisations are willing to forfeit the reach of the web because they want the features of native. For instance, Myntra does this — and its parent company Flipkart is planning to do so soon as well; they have disabled their site on mobile and urge people to use the app (although you can still use the site on desktop).</p>

<p>Uber’s service is only available through the app. Arguably, that’s understandable because sometimes the Geolocation API is not very accurate on web, and really accurate location info is critical to a taxi hailing service. But that’s an argument for making the Geolocation API better, rather than stopping development.</p>

<p>If we slow development of the web, we risk losing more services to native, thereby diminishing the web’s reach.</p>

<h2 id="urls">URLs</h2>

<p>If you get a great big saucepan, and boil the web in it all weekend, periodically skimming off the scum of YouTube comments, porn and photographs of horrible kittens (tautology?), when you look under the lid on Sunday night you’ll find you’re left with URLs. (Or URIs. Or URNs. Who cares what the difference is?)</p>

<p>It’s called “the web” because it’s a network that joins resources together, and those resources are individually addressable.</p>

<p>Modern standards are designed to preserve URLs. Take Service Worker, for example; the explainer document for Navigation Controller (the previous name for what’s become Service Worker) <a href="https://github.com/sole/NavigationController/blob/master/explainer.md">says</a></p>

<blockquote>
  <p>It forces you to have URLs! Some modern apps platforms have forsaken this core principle of the web and suffer for it. The web should never make the same mistake.</p>
</blockquote>

<p>Similarly, the <a href="http://html5doctor.com/web-manifest-specification/">Web Manifest spec</a> defines a web app’s start and scope in terms of good old-fashioned vitally-important URLs. The proposed <a href="https://w3c.github.io/webappsec/specs/upgrade/">Upgrade Insecure Requests spec</a> tries to ensure that no links break if a developer upgrades their server to HTTPS in order to provide a better (more secure) user experience.</p>

<p>There’s a lot the web can learn from native (without slavishly <em>emulating</em> it), but linkability is something that native needs to emulate from the web; see the Rube Goldberg machine-like <a href="https://developers.facebook.com/docs/applinks">App Links</a> proposal to see how Facebook is trying to bring “deep linking to content in your mobile app”. We have URLs; PPK is right that we need to jealously preserve them, so modern standards attempt to do just that.</p>

<h2 id="simplicity">Simplicity</h2>

<p>There’s a deeper complexity to the modern web platform than the sheer volume of features. It’s to do with the way the specs were written, the timescale over which they’ve been written and the fact that some features that we rely on have never been specified at all.</p>

<p>One example is HTML5 Parsing. For years, developers had to deal with the different DOMs that browsers constructed from invalid markup (which, as we know, is the vast majority of the web). This was allowed because HTML 4 never specified what to do with bad markup, so browsers were free to do as they saw fit.</p>

<p>HTML5 changed that, and now all browsers worth shaking an angle bracket at produce the same DOM regardless of the validity of the markup. This has produced a huge boost in interoperability, benefitting consumers and saving developers megatons of heartache.</p>

<p>A more current example is <code>XMLHttpRequest</code> which was never formalised and standardised until years after Microsoft implemented it and everyone else reverse-engineered it and copied it.</p>

<p>XHR is hardly a beautiful API, and will be replaced by the <a href="https://fetch.spec.whatwg.org/">Fetch Standard</a> which aims to simplify and unify network requests. Its preface says</p>

<blockquote>
  <p>At a high level, fetching a resource is a fairly simple operation. A request goes in, a response comes out. The details of that operation are however quite involved and used to not be written down carefully and differ from one API to the next.</p>
</blockquote>

<blockquote>
  <p>Numerous APIs provide the ability to fetch a resource, e.g. HTML’s <code>img</code> and <code>script</code> element, CSS’ <code>cursor</code> and <code>list-style-image</code>, the <code>navigator.sendBeacon()</code> and <code>self.importScripts()</code> JavaScript APIs. The Fetch Standard provides a unified architecture for these features so they are all consistent when it comes to various aspects of fetching, such as redirects and the CORS protocol.</p>
</blockquote>

<p>Modern standards are all about explaining the platform to simplify development, and ensuring a solid, understandable foundation upon which to build.</p>

<p>This is built on a design philosophy called the Extensible Web Manifesto. It’s too much to explore here, but The Chair of the W3C Extensible Web Community Group, Brian Kardell, wrote us an article about it called <a href="https://dev.opera.com/articles/houdini/">Sex, Houdini and the Extensible Web</a>.</p>

<h2 id="immediacy">Immediacy</h2>

<p>A central pillar of the web that PPK doesn’t mention is what I call “immediacy”. When you make a change to a web site, the next visitor gets the updated version immediately. With native apps you have to publish to an App Store, your user is alerted that there’s an updated version and, when they have Wi-Fi, they’ll update it. Maybe.</p>

<p>Installable Web Apps give us an app-like experience — an icon on the homescreen, potentially working even while offline — but retain the immediacy of the web because the app is hosted on a server. In fact, the app is actually — wait for it — <em>a web site</em> with a URL pointed to by the homescreen icon. We combine the strengths of the web with the user experience of native.</p>

<h2 id="conclusion">Conclusion</h2>

<p>At Opera, a lot our developers work on bringing the web to people who otherwise wouldn’t get it, <a href="https://dev.opera.com/articles/making-sites-work-opera-mini/">either with Opera Mini</a>, or by <a href="https://dev.opera.com/blog/reducing-memory-use/">reducing Chromium’s memory consumption</a> so that it works on the lower-specification devices that most of the world uses.</p>

<p>We know that the <a href="http://qz.com/466089/the-fastest-growing-mobile-phone-markets-barely-use-apps/">fastest growing mobile phone markets don’t use apps</a>, so by artificially slowing the pace of evolution on the web, we’re deciding that these people should get a second-class online experience.</p>

<p>It’s imperative, we believe, for the web to continue to add new features — like Service Workers and Installable Web Apps, just as we added native video, the Audio API, the <code>&lt;picture&gt;</code> element, Storage APIs — that extend what the web can do so that it continues to grow and provide the reach that PPK wants, and that we want.</p>

<p>Opera welcomes new developments that make the web better for users. We’re the only browser manufacturer that isn’t also trying to sell an Operating System or locked-down device. So for us, it’s vital that the web continues to thrive — and we believe it’s vital for everybody.</p>

<p><em>This was written by Bruce Lawson, with input from the rest of Opera’s Developer Relations team. Disagree? Please, write a commentary post and <a href="https://twitter.com/odevrel">tweet us</a> the link!</em></p>

<p>Other people have been commenting, too:</p>

<ul>
  <li>Simultaneously with our publishing, Google Chrome evangelist Jake Archibald wrote <a href="https://jakearchibald.com/2015/if-we-stand-still-we-go-backwards/">If we stand still, we go backwards</a></li>
  <li>Paul Kinlan wrote <a href="https://paul.kinlan.me/slice-the-web/">SLICE: the web</a> on the positive aspects of the web as a platform for users and developers</li>
  <li>Nicolas Bevacqua wrote <a href="http://ponyfoo.com/articles/fast-forwarding-the-web-platform">Fast-forwarding the Web Platform</a></li>
  <li>Mariano Viola wrote <a href="http://www.marianoviola.com/blog/mobile-web-isnt-broken-yet">Mobile Web Isn’t Broken, Yet</a></li>
  <li><a href="http://www.aaron-gustafson.com/notebook/ramblings-on-new-browser-features-interoperability-craft-and-the-future-of-the-web/">Ramblings on New Browser Features, Interoperability, Craft, and the Future of the Web</a> is Aaron Gustafson’s take on it. (Microsoft)</li>
</ul>

<p>18 August: PPK’s response <a href="http://www.quirksmode.org/blog/archives/2015/08/stop_pushing_re.html">Stop pushing redux</a> was published.</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/making-animated-themes/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/making-animated-themes/"/><title>Making Animated Themes For Opera</title><published>2015-07-24T00:00:00+00:00</published><updated>2015-07-24T00:00:00+00:00</updated><author><name>Shwetank Dixit</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<p>Support for themes has been there for <a href="https://dev.opera.com/articles/themes-in-opera-18-and-higher/">quite a long time</a>, but it was using JPG, PNG or other such non-animated images. However with Opera 32 and above, you have support for animated themes in which you can use a WebM video file or an animated WebP file.</p>

<p>In the video below, you can see an example of animated themes in action.</p>

<figure block="figure">
	<video elem="media" controls="" cover="/articles/making-animated-themes/video.jpg" width="760" height="419">
		<source src="/articles/making-animated-themes/video.mp4" type="video/mp4" />
		<source src="/articles/making-animated-themes/video.webm" type="video/webm" />
	</video>
</figure>

<p>You can download the <a href="/articles/making-animated-themes/still-lake.zip">Still Lake</a> (6 MB) &amp; <a href="/articles/making-animated-themes/forest.zip">Silent Forest</a> (10 MB) animated themes used in the video above. Feel free to check out the contents of the theme files. The videos used in those themes are courtesy of <a href="http://natureclip.co.nr/">NatureClip</a>, and have been shared under a <a href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.</p>

<p>In the above video, you can see the <em>Still Lake</em> animated theme being installed by dragging the .zip file to the <code>opera://themes</code> page, after which you can see the theme in action when we go to the speed dial page. Later in the video, we open up the preferences page. You will notice that the background theme is applied there too. In fact, the background theme will be visible on all such internal pages.</p>

<p>All themes you install will be visible in the <em>My Themes</em> section of the <code>opera://themes</code> page.</p>

<p>The maximum file size supported for WebM and animated WebP files in themes is 50 MB. Animated GIFs and animated PNGs are not supported.</p>

<h2 id="making-an-animated-theme">Making an animated theme</h2>

<p>There are four simple steps to make your animated theme and to test it out on your local machine:</p>

<ol>
  <li>Add the required WebM or animated WebP file(s) in a directory.</li>
  <li>Specify details about the theme in a <code>persona.ini</code> file.</li>
  <li>Zip up the <code>persona.ini</code> file along with the WebM or animated WebP file(s).</li>
  <li>Go to <code>opera://themes</code>. Drag and drop the <code>.zip</code> file to the window.</li>
</ol>

<p>If all things are valid, your theme should be installed in the Opera browser running on your local machine.</p>

<p>You can easily make an animated theme using the <em>theme creator</em> in Opera.</p>

<ol>
  <li>Open Opera and go to <code>opera://themes</code>.</li>
  <li>On the left hand side menu, click on <em>Create your theme</em>.</li>
  <li>Enter relevant details and select the WebM or animated WebP file you want.</li>
  <li>Click on the <em>Create</em> button.</li>
</ol>

<h3 id="the-personaini-file">The <code>persona.ini</code> file</h3>

<p>The <code>persona.ini</code> file is just a file which lists essential details about the theme. This includes the theme name, the author, name of the <code>.webm</code> file(s) you want included in the theme, and other such things. Let’s see a sample <code>persona.ini</code> from Still Lake theme to know more.</p>

<pre><code>; Licensed under CC-BY
; Video by NatureClip
; http://natureclip.co.nr/

[Info]
Name				= Still Lake
Author				= Vadim Makeev
Author URL			= http://pepelsbey.net
Version				= 2

[Start Page]
Background			= video.webm
Position			= center bottom
First Frame Image 	= firstframe.jpg

[Web UI Pages]
Background			= cover.jpg
Position			= center bottom
</code></pre>

<p>The <code>[Info]</code> section contains all the information about the extension. The things you lists under it are the following:</p>

<ul>
  <li><strong>Name</strong>: Title of the theme.</li>
  <li><strong>Author</strong>: Author name.</li>
  <li><strong>Author URL</strong>: A URI that points to the author’s home page or e-mail. Valid schemes are <code>http</code>, <code>https</code>, and <code>mailto</code>.</li>
  <li><strong>Version</strong>: Version 2 indicates themes for Opera 18 and higher.</li>
</ul>

<p>The <code>[Start Page]</code> category lists the details required for the theme when start page is displayed. The start page is the page displayed whenever you open a new tab (this typically includes the speed dial view you see). You need to list the following things under this section.</p>

<ul>
  <li><strong>Background</strong>: File name of the image that goes behind Speed Dial.</li>
  <li><strong>Position</strong>: Position of the start page image — optional, any CSS keyword for position: <code>left</code>, <code>top</code>, <code>right</code>, <code>bottom</code>, <code>center</code>.</li>
  <li><strong>First Frame Image</strong>: An image of the first frame of the video. This is useful as a fallback image in case the video takes a slight delay to come up. (Note: This fallback image will automatically created by the server if you have upload your animated theme to the <a href="https://addons.opera.com">Opera add-ons catalog</a>, so you only really need to mention this if you don’t plan to share your animated theme through the <a href="https://addons.opera.com">add-ons catalog</a>). This is available on Opera 35 and above.</li>
</ul>

<p>The <code>[Web UI Pages]</code> section lists the things needed for the other web UI pages. For example, the downloads, settings, and extension management pages.</p>

<ul>
  <li><strong>Background</strong>: File name of the image that goes behind other pages.</li>
  <li><strong>Position</strong>: See above for positioning details.</li>
</ul>

<p>In the above section, we just used a <em>.jpg</em> image here. However, we could use another video here too (and even include a <em>First Frame Image</em> file as a fallback for it if we desire).</p>

<p>You can includes comments in the <code>persona.ini</code> page as well. They need to be in a separate line of their own, and need to be started by a semi-colon <code>;</code>.</p>

<p>Keep in mind you can set different resources for the Start Page and the Web UI pages. So you can have, say, a video file for the Start Page (this will also be reflected in the history, tabs, bookmarks page and themes management page) and another video (or even image) for the Web UI pages (which will be reflected on the downloads, settings, plug-ins, password management page, and extension management page).</p>

<p>It is important to note that the video or animated WebP only consumes resources when it is in view. When you are not browsing an Opera internal page, then the theme will not be visible, and hence will not consume resources.</p>

<h2 id="choosing-the-right-background-animation">Choosing the right background animation</h2>

<p>There are a few things to consider when making an animated theme. The video being used should look nice as a background, and preferably should look good when played in a loop. If you intend to submit the theme to the <a href="https://addons.opera.com/">Opera Addons Catalog</a>, then it should abide by all the relevant <a href="https://dev.opera.com/extensions/tut_publishing_guidelines.html#acceptance-criteria">acceptance criteria</a>. If the source video requires attribution, then please provide that in the description text in the addons page (and if you want, then as a comment in the <code>persona.ini</code> file as well.)</p>

<p>There are a lot of resources on the internet where you can find high-quality videos to use in your animated themes. For example, check out <a href="https://vimeo.com/creativecommons">Vimeo’s Creative Commons Page</a>, <a href="http://www.openfootage.net">Open Footage</a>, <a href="https://archive.org/details/movies">Archive.org</a>, <a href="https://videos.pexels.com/">Pexels</a>, <a href="http://mazwai.com/">Mazwai</a> and <a href="http://gfycat.com">Gfycat</a>.</p>

<h2 id="testing-and-uploading-to-the-opera-add-ons-catalog">Testing and uploading to the Opera Add-ons catalog</h2>

<p>Once you have zipped up the <code>persona.ini</code> file along with required <code>.webm</code> or animated WebP files, and have tested it out by installing the theme in your local Opera install, you’re ready to publish it on the <a href="https://addons.opera.com/">Opera Add-ons catalog</a>.</p>

<p>Just head over to the <a href="https://addons.opera.com/developer/upload/">Upload Add-on</a> section of the Opera Add-ons catalog, and submit your theme. Once the moderator approves, it will be published on the Opera Add-ons catalog.</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/making-sites-work-opera-mini/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/making-sites-work-opera-mini/"/><title>Making websites that work well on Opera Mini</title><published>2015-06-03T00:00:00+00:00</published><updated>2015-06-03T00:00:00+00:00</updated><author><name>Bruce Lawson</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<p>I recently gave a keynote talk at Velocity conference called “Ensuring a Performant Web for the Next Billion People” about the importance of developing economies and their use of proxy browsers such as Opera Mini.</p>

<p><a href="https://brucelawson.github.io/talks/2015/velocity/">Slides are available</a> and here’s the 20 minute YouTube video made by the organisers.</p>

<figure block="figure">
	<iframe elem="media" width="560" height="315" src="https://www.youtube.com/embed/BHO70H9tvqo" allowfullscreen=""></iframe>
</figure>

<p>The most common question I got in the hallways was “How can I make my site work well in Opera Mini?”. The answer is simple: use the development methodology known as Progressive Enhancement.</p>

<p><em>Note that throughout this article, when we refer to “Opera Mini” we mean the full proxy version: that is, Opera Mini/iOS in Opera Mini mode, Opera Mini/Android in Extreme Mode, and any version of Opera Mini on Windows Phone or feature phones. When testing your sites on iOS or Android, please ensure your device is in these modes. (<a href="https://dev.opera.com/articles/browsers-modes-engines/">More on Opera Mini modes</a>.)</em></p>

<h2 id="progressive-enhancement">Progressive Enhancement</h2>

<p><a href="http://christianheilmann.com/2015/02/18/progressive-enhancement-is-not-about-javascript-availability/">Progressive Enhancement</a> is not a new technique; in fact, it’s built into the very fabric of the web’s original design, and ensures your website works everywhere — not just on Opera Mini and other proxy browsers.</p>

<h3 id="send-html-to-the-device">Send HTML to the device</h3>

<p>HTML is a lightweight text format that allows the browser to get to work straight away. It’s become bizarrely fashionable to send JavaScript (with a framework such as Angular, for example) which must be parsed and executed before it can do the same job as plain HTML. This slows the site down and uses more CPU.</p>

<p>Therefore, Progressive Enhancement is better for all users. <a href="http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product/">Airbnb wrote</a>:</p>

<blockquote>
  <p>We’ve launched our first Holy Grail app into production! […] It looks exactly the same as the app it replaced, however initial pageload feels drastically quicker because we serve up real HTML instead of waiting for the client to download JavaScript before rendering.</p>

  <p>Plus, it is fully crawlable by search engines. […] It feels 5× faster.</p>
</blockquote>

<h3 id="use-svg-rather-than-icon-fonts">Use SVG rather than icon fonts</h3>

<p>Opera Mini doesn’t download web fonts; these are often large files, and are for aesthetic/branding purposes. Fallback fonts are used instead. On many low-specced devices, system fonts are carefully optimised for the device and give a better user experience.</p>

<p>However, icon fonts are sometimes used by developers and these won’t be displayed; this can mean some important information or navigation items are invisible. Use SVG images instead; these can be compressed to become smaller than icon fonts, and can be made <a href="https://dev.opera.com/blog/how-media-queries-allow-you-to-optimize-svg-icons-for-several-sizes/">responsive with media queries</a>.</p>

<p>This doesn’t just benefit Opera Mini users; many people with mild dyslexia have a <a href="http://en.wikipedia.org/wiki/Dyslexie#Research">special system font</a> to aid legibility, which breaks icon fonts. See Seren Davies’ presentation <a href="https://speakerdeck.com/ninjanails/death-to-icon-fonts">Death to icon fonts</a> which explains how icon fonts impact her dyslexia.</p>

<h3 id="style-your-html-with-css">Style your HTML with CSS</h3>

<p>Opera Mini deliberately disables some CSS which would otherwise need to be converted to bitmap images and would therefore bloat page size.</p>

<p>Most notably, CSS <code>border-radius</code> isn’t rendered. CSS animations are similarly disabled, to preserve battery life.</p>

<p>CSS gradients are also disabled. Ensure that, if you’re using a gradient as a background, that you also set a CSS color for the <code>background</code> that contrasts well with text. A common error is white text on a gradient and leaving the default white background unchanged; in Opera Mini this results in illegible white-on-white text. So, for example:</p>

<pre><code>button {
	background: black;
	/*
		Fallback for Mini and other browsers
		that don’t support CSS gradients
	*/
	background: linear-gradient(
		to bottom right,
		red, rgba(255, 0, 0, 0)
	);
	color: white;
}
</code></pre>

<p>Opera Mini is sent a black background for the white text, and so the button’s text is visible; this is overridden in browsers that support CSS gradients.</p>

<h3 id="test-your-site-without-javascript">Test your site without JavaScript</h3>

<p>Test your HTML and CSS site with JavaScript disabled. In Opera Desktop, for example, open the Developer Tools (right-click anywhere, choose “inspect element”, click the settings cog icon, check “Disable JavaScript”).</p>

<p>Everything should still work, although it will probably be much more clunky. That’s OK; if your site works clunkily and your competitors’ sites don’t work at all, you’ll get the business.</p>

<p>Ensuring your site functions without JavaScript doesn’t only benefit proxy browser users; research by GDS, the UK Government’s Digital Services agency, shows that <a href="https://gds.blog.gov.uk/2013/10/21/how-many-people-are-missing-out-on-javascript-enhancement/">1.1% of browsers don’t run JavaScript</a> for various reasons: the user may have disabled it, or corporate firewalls block it, for example.</p>

<p>Opera Mini runs some JavaScript on page load, but JavaScript-only APIs don’t work. Treat JavaScript as an enhancement to your core HTML site, not as a pre-requisite.</p>

<p>Read more about <a href="https://dev.opera.com/articles/opera-mini-and-javascript/">Opera Mini and JavaScript</a>.</p>

<h3 id="make-your-site-performant">Make your site performant</h3>

<p>Making sure your site loads <em>fast</em> is a must — for all browsers, not just Opera Mini. To help you, Google published <a href="https://developers.google.com/web/fundamentals/performance/index?hl=en">Optimizing Performance</a> in their Web Fundamentals course.</p>

<h3 id="other-considerations">Other considerations</h3>

<p>If you rely on some sort of Geo IP tool for detecting a visitor’s location, note that the IP address you find in the headers is that of our compression proxy. The user’s original IP address is passed on via the <code>X-Forwarded-For</code> HTTP header. (Read more about <a href="/articles/opera-mini-request-headers/">Opera Mini request headers</a>.)</p>

<h3 id="a-note-on-version-numbers">A note on version numbers</h3>

<p>Because Opera Mini renders on our servers, all Opera Mini clients use the same server version, so all use the same Presto version. JavaScript and CSS support is therefore identical on all clients, with the exception that user may enable Small Screen Rendering which removes a lot of CSS rules.</p>

<p>Version numbers refer to different versions of the client UI and capabilities (whether it supports night mode, private tabs, progressive loading, etc.)</p>

<p>Opera Mini 4.x clients load the whole transcoded page at once, as they have no progressive loading. This slightly reduces the <a href="https://dev.opera.com/articles/opera-mini-and-javascript/">time allowed for JavaScript execution</a> (including XHRs). With newer clients, the transcoder is more generous, since it is able to send the compressed page to the client in chunks.</p>

<h2 id="testing-in-opera-mini">Testing in Opera Mini</h2>

<p>There are several ways to do this.</p>

<h3 id="download-opera-mini">Download Opera Mini</h3>

<p>You can download Opera Mini onto your device, of course. Point your pocket-dwelling chum at <a href="http://m.opera.com/">m.opera.com</a> and download it for Android, iOS, Windows Phone or any generic feature phone — Opera Mini works on 3000+ different devices.</p>

<h2 id="set-the-browser-to-the-correct-mode">Set the browser to the correct mode</h2>

<p>If you’re using the iOS version, note that you have to switch it to Mini mode to go through Opera’s Mini servers (this mode is not the default). Tap the red “O” menu, and choose “Opera Mini”. Opera Mini for iOS also compresses videos. See <a href="https://dev.opera.com/blog/opera-mini-8-for-ios/">more information about Opera Mini for iOS</a>.</p>

<p>If you’re using Opera Mini 11 for Android (or later), ensure that the browser is set to Extreme (this is the default). Tap the red “O” menu, and ensure that “Savings mode” next to the Data Meter is set to “Extreme”; tap to change if not. (<a href="https://www.opera.com/blogs/mobile/2015/09/choose-high-or-extreme-savings-new-opera-mini-android/">More about Opera Mini 11 for Android</a>.)</p>

<h3 id="test-from-desktop">Test from Desktop</h3>

<p>For development and testing purposes, it can be useful to install Opera Mini on your computer. You’ll need Java and MicroEmulator, in which you’ll run an instance of Opera Mini for J2ME-enabled feature phones. <a href="https://dev.opera.com/articles/installing-opera-mini-on-your-computer/">Installing Opera Mini on Your Computer</a> has all the information you need.</p>

<p><a href="https://dev.opera.com/articles/opera-mini-chrome-os/">You can even run Opera Mini on a Chromebook.</a> Yes, you read that right.</p>

<h3 id="test-local-web-sites-using-ngrok">Test local web sites using ngrok</h3>

<p>Many developers choose to use <a href="https://ngrok.com/">ngrok</a> to securely expose a local web server to the internet. As their website explains, “ngrok creates a tunnel from the public internet (<code>https://subdomain.ngrok.com/</code>) to a port on your local machine. You can give this URL to anyone to allow them to try out a web site you’re developing without doing any deployment”. Then you simply point Opera Mini at <code>subdomain.ngrok.com</code> to test your site. ngrok is open source, and also provides a paid-for service.</p>

<h3 id="alternatives-to-ngrok">Alternatives to ngrok</h3>

<p>An alternative to ngrok is <a href="http://localtunnel.me/">localtunnel</a>.</p>

<p>Some people might want to do their SSH tunnelling. Read <a href="http://blog.trackets.com/2014/05/17/ssh-tunnel-local-and-remote-port-forwarding-explained-with-examples.html">SSH Tunnel — Local and Remote Port Forwarding Explained With Examples</a> for information on how to do this.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Using Progressive Enhancement makes your site <em>better for all users</em> and enables the 275 million users of Opera Mini worldwide.</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/browsers-modes-engines/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/browsers-modes-engines/"/><title>Opera Browsers, Modes &amp; Engines</title><published>2015-06-02T00:00:00+00:00</published><updated>2015-06-02T00:00:00+00:00</updated><author><name>Andreas Bovens</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<p>The Opera browser is available on a wide range of platforms, in a number of flavors with different modes, engines and levels of standards support. As things can get somewhat confusing — did you know that Opera Mini on iOS comes with three rendering modes, one of which is powered by <code>UIWebView</code> &amp; Opera Turbo? — we decided to create a simple product overview that details some of these technical differences.</p>

<p>We’ll keep this table as up-to-date as possible, so be sure to bookmark this page for later reference!</p>

<figure block="figure">

<table>
<tr>
	<th>OS</th>
	<th>Browser</th>
	<th>Mode</th>
	<th>Engine</th>
	<th>Proxy</th>
	<th>Standards</th>
</tr>
<tr>
	<td rowspan="4">Android</td>
	<td rowspan="2"><a href="https://play.google.com/store/apps/details?id=com.opera.browser">Opera</a></td>
	<td>Normal</td>
	<td>Chromium</td>
	<td>No</td>
	<td>Full</td>
</tr>
<tr>
	<td>Data savings *</td>
	<td>Chromium</td>
	<td>Yes</td>
	<td>Full</td>
</tr>
<tr>
	<td rowspan="2"><a href="https://play.google.com/store/apps/details?id=com.opera.mini.native">Opera Mini</a> (11+)</td>
	<td>Extreme</td>
	<td>Presto, server-side</td>
	<td>Yes</td>
	<td>Limited</td>
</tr>
<tr>
	<td>High *</td>
	<td><a href="https://developer.chrome.com/multidevice/webview/overview">Android WebView</a></td>
	<td>Yes †</td>
	<td>Full</td>
</tr>

<tr>
	<td rowspan="5">iOS</td>
	<td rowspan="3"><a href="https://itunes.apple.com/app/id363729560">Opera Mini</a></td>
	<td>Normal</td>
	<td>WebKit, system</td>
	<td>No</td>
	<td>Full</td>
</tr>
<tr>
	<td>Opera Turbo *</td>
	<td>WebKit, system</td>
	<td>Yes</td>
	<td>Full</td>
</tr>
<tr>
	<td>Opera Mini</td>
	<td>Presto, server-side</td>
	<td>Yes</td>
	<td>Limited</td>
</tr>
<tr>
	<td rowspan="2"><a href="https://itunes.apple.com/app/id674024845">Coast</a></td>
	<td>Normal</td>
	<td>WebKit, system</td>
	<td>No</td>
	<td>Full</td>
</tr>
<tr>
	<td>Opera Turbo *</td>
	<td>WebKit, system</td>
	<td>Yes</td>
	<td>Full</td>
</tr>
<tr>
	<td>J2ME</td>
	<td><a href="https://www.opera.com/mobile/mini/other">Opera Mini</a></td>
	<td>Opera Mini</td>
	<td>Presto, server-side</td>
	<td>Yes</td>
	<td>Limited</td>
</tr>
<tr>
	<td>Windows Phone</td>
	<td><a href="http://www.windowsphone.com/en-us/store/app/opera-mini-beta/b3bf000a-e004-4ecb-a8fb-9fc817cdab90">Opera Mini</a></td>
	<td>Opera Mini</td>
	<td>Presto, server-side</td>
	<td>Yes</td>
	<td>Limited</td>
</tr>
<tr>
	<td rowspan="2">Desktop</td>
	<td rowspan="2"><a href="https://www.opera.com/computer">Opera</a></td>
	<td>Normal</td>
	<td>Chromium</td>
	<td>No</td>
	<td>Full</td>
</tr>
<tr>
	<td>Opera Turbo</td>
	<td>Chromium</td>
	<td>Yes</td>
	<td>Full</td>
</tr>
</table>

</figure>

<p>Notes:</p>

<ul>
  <li>
    <ul>
      <li>: these modes (powered by our Opera Turbo servers) also have a <a href="https://www.opera.com/blogs/mobile/2014/11/new-opera-mini-for-iphone-ipad-less-buffering-free-download-appstore/">Video Boost</a> compression option.</li>
    </ul>
  </li>
  <li>† : when in High mode and connected to Wi-Fi, data savings are disabled, unless the user has explicitly opted in by activating the Wi-Fi data savings option in Settings.</li>
  <li>Opera Turbo mode compresses data up to 80%. Opera Mini mode compresses data up to 90%.</li>
  <li>If you’re doing IP-based geo-detection, you should always check if there is an <code>X-Forwarded-For</code> header. That way, you can also correctly locate browser users using proxy functionality, powered by Opera Mini and Opera Turbo.</li>
  <li>Opera Mini comes with <a href="https://dev.opera.com/articles/making-sites-work-opera-mini/">“limited” standards support</a>: this means that advanced JavaScript, CSS and other dynamic elements might not work as expected, due to the peculiarities of server-side rendering and limited client capabilities.</li>
  <li>Older Presto-powered Opera products that are no longer under active development, such as Opera 12 for computers, Opera Mobile Classic, etc. are not listed here.</li>
</ul>
]]></content></entry><entry><id>https://dev.opera.com/articles/drum-sounds-webaudio/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/drum-sounds-webaudio/"/><title>Synthesising Drum Sounds with the Web Audio API</title><published>2015-05-26T00:00:00+00:00</published><updated>2015-05-26T00:00:00+00:00</updated><author><name>Chris Lowis</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<h2 id="the-web-audio-api">The Web Audio API</h2>

<p>The Web Audio API is a new way of working with audio on the web. It provides a way to playback pre-recorded audio, synthesise arbitrary new sounds and control the precise moment of sound generation accurately and reliably, irrespective of what else is happening in your application.</p>

<p>In this article, we’re going to learn more about the API by building <a href="https://chrislo.github.io/drum_synthesis/">a simple drum machine</a>. We’ll learn just enough about the API to play a simple loop constructed from sounds we synthesise ourselves, and we’ll see how to use recordings of real-life sounds too. From these bare bones, you’ll be able to extend the machine yourself, or apply the techniques you’ve learnt to other applications. Let’s get started!</p>

<h3 id="sampling-or-synthesising">Sampling or synthesising?</h3>

<p>Early on, we have a decision to make. Shall we synthesise the sounds of our drum kit from scratch in the computer, or shall we use a recording of real-life sounds — a technique also known as “sampling”? There are pros and cons to both approaches.</p>

<p>Synthesising, recreating the sound of a drum using a model of its acoustics and attempting to recreate that model in code, gives us infinite control, but it can be very difficult to accurately synthesise a realistic sounding drum. Sampling on the other hand means we can start with any sound we like, but we are limited to just that sound, perhaps with some simple transformations (playing the sound back faster or slower, or applying some effects, for example).</p>

<p>In this article we’ll try and create something that sounds a bit like the classic electronic drum machine, Roland’s TR-808. We’ll synthesise the kick and snare, and create a hi-hat sound from a recording of the original machine.</p>

<h3 id="the-kick">The kick</h3>

<p>We’ll kick off with the basis of all good drum loops, the kick drum. To generate audio using the Web Audio API, your browser needs to know about the sound producing device available to your computer, and what capabilities it has. This information is contained in the <code>AudioContext</code>.</p>

<pre><code>var context = new AudioContext;
console.log(context.sampleRate);
// → 44100
console.log(context.destination.channelCount);
// → 2
</code></pre>

<p>We can describe audio digitally as a series of numbers. Each number describes the amplitude of the sound at a particular point in time. We call each one of these numbers a “sample”. (“Sampling” gets its name from the process of turning a recording of a real sound into a series of samples.) Calling <code>context.sampleRate</code> tells us how many samples per second our device can produce. A typical sample rate is 44,100 samples/second, as this is sufficient to reproduce sounds at frequencies as high as we humans can perceive. <code>context.destination.channelCount</code> gives the number of simultaneous channels of audio our device can produce — on my computer that’s two: one for the left speaker, and one for the right.</p>

<p>It would be possible, but not very user-friendly, to create the sound we want to make by giving the computer 44,100 numbers per second, if we knew which numbers to give it to create the sound of a kick drum. But the Web Audio API makes the process easier by providing us with a higher level, declarative set of commands to describe to the computer how to make the sound we want.</p>

<pre><code>var oscillator = context.createOscillator();
oscillator.frequency = 261.6;

oscillator.connect(context.destination);

oscillator.start(0);
</code></pre>

<p>If you type the code above into your developer console, you should hear a low-pitched, single frequency tone at 261.6 Hz (if you’re a musician, that’s a middle C).</p>

<p>Make it stop? OK.</p>

<pre><code>oscillator.stop(0);
</code></pre>

<p>There’s a few things to note in the code above. Firstly <code>createOscillator</code> is a method on <code>context</code> — it needs to know about the audio environment it’s operating in to generate the sound. All of the applications you build with Web Audio will work within an <code>AudioContext</code>.</p>

<p>Secondly, we <code>connect</code> the oscillator to the <code>destination</code> of the <code>context</code>. This is an important concept within the Web Audio API. We call <code>oscillator</code> and <code>destination</code> instances of “nodes” and by connecting them together we create a graph. (This diagram was generated using the Web Audio developer tools in Firefox Developer Edition.)</p>

<figure block="figure">
	<img elem="media" src="/articles/drum-sounds-webaudio/context-oscillator.png" alt="Node graph of oscillator connected to destination" />
	<figcaption elem="caption">Node graph of oscillator connected to destination</figcaption>
</figure>

<p>Thirdly, calls to <code>start</code> and <code>stop</code> take the time as an argument. <code>0</code> means to perform the operation immediately, but we can supply any argument and it will be interpreted as the number of seconds from now. What time is now?</p>

<pre><code>console.log(context.currentTime);
// → 1182.5980952380953
</code></pre>

<p>If you’ve worked with other timing mechanisms in JavaScript before, such as <code>setTimeout</code>, this concept of time may be slightly unfamiliar. Here, when we say <code>start(0.5)</code> the browser will attempt, as much as it can, to play the sound in half a second, and unlike <code>setTimeout</code>, will not interrupt this as much as practical. This is essential for our drum machine, as we want to schedule sounds precisely and with an exact rhythm.</p>

<p>Back to our kick drum. A lot of people have researched the acoustics of drums and how they make sound. I’ve included some further reading at the end of this article if you’re interested in this fascinating subject. For two-skinned drums, such as the kick drum, they’ve noticed that the sound starts at a higher frequency — the ‘attack’ phase when the striker hits the skin — and then rapidly falls away to a lower frequency. While this is happening, the volume of the sound also decreases. Once we’ve struck the drum there’s nothing to keep producing sound so it simply decays. Let’s tackle the latter part, the “envelope” of the sound, first.</p>

<pre><code>var oscillator = context.createOscillator();
oscillator.frequency = 150;

var gain = context.createGain();

oscillator.connect(gain);
gain.connect(context.destination);

var now = context.currentTime;

gain.gain.setValueAtTime(1, now);
gain.gain.exponentialRampToValueAtTime(0.001, now + 0.5);
oscillator.start(now);
oscillator.stop(now + 0.5);
</code></pre>

<p>In the code above, we’ve created this audio graph:</p>

<figure block="figure">
	<img elem="media" src="/articles/drum-sounds-webaudio/oscillator-envelope.png" alt="Node graph for an oscillator with an envelope" />
	<figcaption elem="caption">Node graph for an oscillator with an envelope</figcaption>
</figure>

<p>A <code>gain</code> node is like a volume control. We can use that to control the amplitude of our oscillator over time. It has a parameter <code>gain</code> which we can automate. We do that by calling the functions <code>setValueAtTime</code>, which sets the gain to be <code>1</code> at time <code>0</code> and <code>exponentialRampToValueAtTime</code> which decreases the gain to close to zero over the next <code>0.5</code> seconds. Any parameter on any node in the Web Audio API can be automated in this way if it implements the <code>AudioParam</code> interface:</p>

<pre><code>console.log(gain.gain);
// → AudioParam { defaultValue: 1, value: 1, setValueAtTime: function, linearRampToValueAtTime: function, exponentialRampToValueAtTime: function… }
</code></pre>

<p>Armed with this knowledge, we now know how to complete our kick drum synthesis: by dropping the frequency of the oscillator rapidly after the initial attack.</p>

<pre><code>oscillator.frequency.setValueAtTime(150, now);
oscillator.frequency.exponentialRampToValueAtTime(0.001, now + 0.5);
</code></pre>

<p>If you’ve been following along with the code in this article, you may have noticed that once you call <code>stop</code> on an oscillator, it’s impossible to call <code>start</code> again. This is intentional — it allows the browser to garbage-collect the nodes more efficiently in large audio graphs — but it does make working with these drum sounds more complicated as we’d like a way to trigger them multiple times. We can solve this by wrapping the code we’ve written in a simple object:</p>

<pre><code>function Kick(context) {
	this.context = context;
};

Kick.prototype.setup = function() {
	this.osc = this.context.createOscillator();
	this.gain = this.context.createGain();
	this.osc.connect(this.gain);
	this.gain.connect(this.context.destination)
};

Kick.prototype.trigger = function(time) {
	this.setup();

	this.osc.frequency.setValueAtTime(150, time);
	this.gain.gain.setValueAtTime(1, time);

	this.osc.frequency.exponentialRampToValueAtTime(0.01, time + 0.5);
	this.gain.gain.exponentialRampToValueAtTime(0.01, time + 0.5);

	this.osc.start(time);

	this.osc.stop(time + 0.5);
};
</code></pre>

<p>We store a reference to the audio context when we create the kick, and then each time we trigger the kick sound we can pass in a time, which creates the audio graph and schedules the parameter changes.</p>

<pre><code>var kick = new Kick(context);
var now = context.currentTime;
kick.trigger(now);
kick.trigger(now + 0.5);
kick.trigger(now + 1);
</code></pre>

<h3 id="the-snare-drum">The Snare Drum</h3>

<p>A snare drum has a rigid shell holding two, taut drum membranes. When the top membrane is struck, a series of wire springs held underneath the lower membrane rattle in sympathy. There’s a complexity to the snare sound that makes it more challenging to synthesise. But we can tackle it in stages to make the process easier.</p>

<p>First, the rattle of the wire snare underneath the drum can be synthesised using a burst of noise. We can create noise using a random number generator.</p>

<pre><code>function Snare(context) {
	this.context = context;
};

Snare.prototype.noiseBuffer = function() {
	var bufferSize = this.context.sampleRate;
	var buffer = this.context.createBuffer(1, bufferSize, this.context.sampleRate);
	var output = buffer.getChannelData(0);

	for (var i = 0; i &lt; bufferSize; i++) {
		output[i] = Math.random() * 2 - 1;
	}

	return buffer;
};
</code></pre>

<p>In this code we create a “buffer” of individual samples, which we can later trigger at a precise time. The call to <code>createBuffer</code> specifies that the buffer has a single channel, 44100 individual samples, at a sample rate of 44100 Hz. That is, 1 second of audio in total. This should be sufficient for our purposes since the sound of an individual snare hit is very short.</p>

<p>We fill the buffer with random numbers between <code>-1</code> and <code>1</code>. This even distribution of random numbers creates “white” noise, which is noise with equal energy at every frequency. Removing some of the lowest frequency sound from this noise creates a more realistic sounding snare. We can do that using a filter:</p>

<pre><code>Snare.prototype.setup = function() {
	this.noise = this.context.createBufferSource();
	this.noise.buffer = this.noiseBuffer();
	var noiseFilter = this.context.createBiquadFilter();
	noiseFilter.type = 'highpass';
	noiseFilter.frequency.value = 1000;
	this.noise.connect(noiseFilter);
	// …
};
</code></pre>

<p>We set the cutoff <code>frequency</code> of the filter at 1000 Hz. This means noise below 1000 Hz will be removed. We also need to shape the amplitude of the noise burst using an envelope, as we did before with the snare drum.</p>

<pre><code>// …
this.noiseEnvelope = this.context.createGain();
noiseFilter.connect(this.noiseEnvelope);

this.noiseEnvelope.connect(this.context.destination);
// …
</code></pre>

<p>A short burst of filtered noise on its own doesn’t create a very good sounding snare. Adding a sharp “snap” to the front of the sound helps to make the snare sound more percussive. We can achieve this using an oscillator set to generate a triangle waveform, and again shape that using a <code>GainNode</code> as an envelope.</p>

<pre><code>// …
this.osc = this.context.createOscillator();
this.osc.type = 'triangle';

this.oscEnvelope = this.context.createGain();
this.osc.connect(this.oscEnvelope);
this.oscEnvelope.connect(this.context.destination);
</code></pre>

<p>We have created this graph of nodes for our snare sound:</p>

<figure block="figure">
	<img elem="media" src="/articles/drum-sounds-webaudio/snare.png" alt="Node graph for an synthesised snare" />
	<figcaption elem="caption">Node graph for an synthesised snare</figcaption>
</figure>

<p>Now we just need to provide some parameters for each of the nodes. After some fiddling, I found these parameters created quite a satisfying, snappy snare:</p>

<pre><code>Snare.prototype.trigger = function(time) {
	this.setup();

	this.noiseEnvelope.gain.setValueAtTime(1, time);
	this.noiseEnvelope.gain.exponentialRampToValueAtTime(0.01, time + 0.2);
	this.noise.start(time)

	this.osc.frequency.setValueAtTime(100, time);
	this.oscEnvelope.gain.setValueAtTime(0.7, time);
	this.oscEnvelope.gain.exponentialRampToValueAtTime(0.01, time + 0.1);
	this.osc.start(time)

	this.osc.stop(time + 0.2);
	this.noise.stop(time + 0.2);
};
</code></pre>

<h3 id="the-hi-hat">The hi-hat</h3>

<p>Synthesising a realistic-sounding hi-hat is hard. When you strike a disk of metal the sound that is produced is a complex mixture of unevenly-spaced harmonics which decay at different rates. It’s not an impossible task, and if you’re interested there’s some further reading below, but for this post we’re going to cheat a little by sampling an existing sound. By doing this you’ll also learn how sampling, taking short recordings of sound and using them as the basis of new sounds, can be achieved with the Web Audio API.</p>

<p>Our basic instrument is simple:</p>

<pre><code>function HiHat(context, buffer) {
	this.context = context;
	this.buffer = buffer;
};

HiHat.prototype.setup = function() {
	this.source = this.context.createBufferSource();
	this.source.buffer = this.buffer;
	this.source.connect(this.context.destination);
};

HiHat.prototype.trigger = function(time) {
	this.setup();
	this.source.start(time);
};
</code></pre>

<p>When we instantiate the <code>HiHat</code> object, we give it a buffer of samples. The <code>setup</code> function assigns the buffer of samples to a <code>BufferSource</code> node, and calling <code>trigger</code> plays the samples back at the given time.</p>

<p>Where do we get our source buffer of samples from? Remember from our snare drum example earlier, we generated a buffer using a random number generator. But we can also create one by loading a file:</p>

<pre><code>var sampleLoader = function(url, context, callback) {
	var request = new XMLHttpRequest();
	request.open('get', url, true);
	request.responseType = 'arraybuffer';
	request.onload = function() {
		context.decodeAudioData(request.response, function(buffer) {
			callback(buffer);
		});
	};
	request.send();
};
</code></pre>

<p>This function takes a URL of a sound file and makes an asynchronous GET request for it using <code>XMLHttpRequest</code>. When the data is loaded, the call to <code>context.decodeAudioData</code> turns the audio file into a buffer of samples, and triggers a callback. The file formats that <code>decodeAudioData</code> understand are the same as those supported by the <code>&lt;audio&gt;</code> tag in your browser. In Opera, OGG, WAV and MP3 are supported, for example.</p>

<p>Remember that the network and decoding requests are asynchronous, so we have to wait until they are completed before we can create the <code>HiHat</code> that uses the loaded buffer:</p>

<pre><code>sampleLoader('./hihat.wav', context, function(buffer) {
	var hihat = new HiHat(context, buffer);
	hihat.trigger(context.currentTime);
});
</code></pre>

<h2 id="timing">Timing</h2>

<p>In this final section, we’re going to combine the three drum sounds we’ve made into a simple loop. As we’ve seen, the Web Audio API provides a precise timing mechanism which allows you to schedule audio events to happen relative to the <code>AudioContext</code>’s <code>currentTime</code>.</p>

<p>Internally, the browser is executing these events on a thread that is separate to the thread in which normal JavaScript events are run. This means that there is overhead in passing data between the two threads. For this reason, it is not possible to create a callback that fires when an audio event happens (such as when one of our drum sounds starts or stops playing), and register changes in reaction to this (such as scheduling a new drum sound to play).</p>

<p>To build a loop, especially one where we have control over the tempo, the parameters, and which notes play, we have to listen for changes in the main thread, and schedule those changes to happen in the future on the audio thread. We don’t want to schedule them too far in the future though, as this makes our application unresponsive. Scheduling them too soon is also a problem — we might cause glitches in the sound if something happens in the rest of our application and we miss the scheduling of the changes.</p>

<p>In <a href="http://www.html5rocks.com/en/tutorials/audio/scheduling/">this HTML5 Rocks</a> article, Chris Wilson describes the issues with timing in more detail and gives some code examples of good and bad practice. Other developers have taken these ideas and wrapped them up in libraries that make working with time in Web Audio applications much easier:</p>

<ul>
  <li><a href="https://github.com/sebpiq/WAAClock">WAAClock</a> packages the ideas from Chris Wilson’s article into a library, with a simple interface	and some clear examples.</li>
  <li><a href="https://github.com/adamrenklint/dilla">Dilla</a> is a timing library specialised for building drum machines. It models the concept of beats, bars, and loops and has a notation language for describing the timing of sounds in the loop.</li>
  <li><a href="https://github.com/TONEnoTONE/Tone.js">Tone.js</a> is a comprehensive set of libraries for making all kinds of sounds. As well as a timing library, it also has built-in synthesisers and effects processors which provide abstractions over more complicated Web Audio node graphs.</li>
</ul>

<p>All of these libraries make it easy to build a simple loop, and it’s a fun exercise to try each one and see which one is the best fit for you and the application you are building. As an example, I’ll use <code>Tone.js</code> to build a simple loop.</p>

<pre><code>var play = function(buffer) {
	var kick = new Kick(context);
	var snare = new Snare(context);
	var hihat = new HiHat(context, buffer);

	Tone.Transport.bpm.value = 120;

	Tone.Transport.setInterval(function(time){ kick.trigger(time) }, '4n');
	Tone.Transport.setInterval(function(time){ snare.trigger(time) }, '2n');
	Tone.Transport.setInterval(function(time){ hihat.trigger(time) }, '8t');

	Tone.Transport.start();
};

sampleLoader('./hihat.wav', context, play);
</code></pre>

<p>In this code, <code>Tone.Transport</code> is the interface to the <code>Tone.js</code> <a href="https://github.com/TONEnoTONE/Tone.js/wiki/Transport">timing library</a>. We set a tempo for our loop using the <code>bpm</code> property — here 120 beats per minute. The <code>Transport.setInterval</code> method is used to schedule repeating events. We can think of it as working like a regular <code>setInterval</code> but for scheduling of events relative to the audio clock. The time value passed to <code>Transport.setInterval</code> can be expressed, as here, in a musical way rather than in seconds. <code>4n</code> means 4 beats to the bar, <code>2n is two beats</code> and <code>8t</code> creates eighth-note triplets on the hi-hat. The value is converted into seconds and passed in as the <code>time</code> parameter to our <code>trigger</code> methods, so we don’t need to modify our code to work with this library.</p>

<p>Finally, we call the <code>play</code> method when the hi-hat sample has loaded, which starts our loop. We haven’t loaded <code>Tone.js</code> into this page, so if you’re following along in the console, try the code <a href="https://chrislo.github.io/drum_synthesis/">on the demo site</a>.</p>

<h2 id="conclusion">Conclusion</h2>

<p>In this article we’ve seen how to synthesise and sample drum sounds and combine them as a loop. We’ve learnt the basics of the Web Audio API and seen how to solve some common problems. If you’d like to play with the code and hear it in action, I’ve <a href="https://chrislo.github.io/drum_synthesis/">put it on GitHub</a>, and if this article has piqued your interest in the Web Audio API, you might be interested in my weekly newsletter <a href="http://blog.chrislowis.co.uk/waw.html">Web Audio Weekly</a> where I share links, tips and news from the Web Audio community.</p>

<h2 id="further-reading">Further Reading</h2>

<p>We’ve only scratched the surface of drum synthesis in this article. For further details you might find these resources helpful:</p>

<ul>
  <li>The Synth Secrets series from Sound on Sound magazine is a goldmine of interesting articles on synthesis using hardware synthesisers. With some thought, many of the techniques can be recreated using the nodes provided by the Web Audio API. The articles on synthesising a <a href="http://www.soundonsound.com/sos/Mar02/articles/synthsecrets0302.asp">snare drum</a>, <a href="http://www.soundonsound.com/sos/Feb02/articles/synthsecrets0202.asp">kick drum</a> and <a href="http://www.soundonsound.com/sos/jul02/articles/synthsecrets0702.asp">cymbal</a> were very useful for this blog post.</li>
  <li>The <a href="http://www.amazon.co.uk/gp/product/0415825644/ref=as_li_tl?ie=UTF8&amp;camp=1634&amp;creative=19450&amp;creativeASIN=0415825644&amp;linkCode=as2&amp;tag=chrislowis-21&amp;linkId=JVUM7JCHQB7DC7XO">Dance Music Manual</a> by Rick Snoman is an in-depth look at electronic music production and has a very informative section of drum machine synthesis.</li>
</ul>
]]></content></entry><entry><id>https://dev.opera.com/articles/fixing-the-scrolltop-bug/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/fixing-the-scrolltop-bug/"/><title>Fixing the <code>scrollTop</code> bug</title><published>2015-05-20T00:00:00+00:00</published><updated>2015-05-20T00:00:00+00:00</updated><author><name>Simon Pieters</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<p>The <a href="http://dev.w3.org/csswg/cssom-view/">CSSOM View</a> specification has a handful of widely-implemented properties on the <code>Element</code> interface related to scrolling: <code>scrollTop</code>, <code>scrollLeft</code>, <code>scrollWidth</code>, <code>scrollHeight</code>. These give the current scroll position of the element, and the size of the scrolling area. <code>scrollTop</code> and <code>scrollLeft</code> can also be set to cause a scroll. When these are used on the root element, they instead reflect the scroll position and scroll area of the viewport. The <code>clientWidth</code> and <code>clientHeight</code> properties similarly reflect the viewport dimensions instead of the element’s dimensions for the root element.</p>

<p>However, <a href="https://bugs.webkit.org/show_bug.cgi?id=5991">WebKit</a> (Safari) and <a href="https://code.google.com/p/chromium/issues/detail?id=157855">Blink</a> (Chrome and Opera) do not behave this way. They make the <code>body</code> element reflect the viewport instead, and the root element returns <code>0</code> and does nothing on setting. IE11 and Firefox follow the specification. This is an interoperability problem that Web developers have to work around in some way, possibly by UA sniffing.</p>

<p>We want to fix this bug, but <strong>we need your help</strong> to fix sites that rely on the bug based on UA sniffing.</p>

<h2 id="whats-bad-about-the-webkitblink-behavior">What’s bad about the WebKit/Blink behavior?</h2>

<p>In general, we want to avoid special-casing the <code>body</code> element and just let the root element be “the viewport element”. Also, the <code>body</code> element can be independently scrollable from the viewport, by setting the <code>overflow</code> property on both <code>html</code> and <code>body</code> to something other than <code>visible</code>. In WebKit and Blink, the scrolling APIs on <code>body</code> in this case still reflect the viewport, rather than the <code>body</code> element itself.</p>

<p>Both WebKit and Blink have previously tried to fix this bug, but had to revert because there were Web pages that expected the buggy behavior when the browser identified as “WebKit”.</p>

<h3 id="project-spartan--edge">Project Spartan / Edge</h3>

<p>Microsoft’s latest browser engine, codenamed <a href="http://blogs.windows.com/bloggingwindows/2015/03/30/introducing-project-spartan-the-new-browser-built-for-windows-10/">Project Spartan</a> and used in the upcoming Edge browser, also identifies as “WebKit”, like WebKit and Blink, and so they have to copy WebKit/Blink’s bugs in order to be compatible with the Web.</p>

<h2 id="quirks-mode">Quirks mode</h2>

<p><a href="https://hsivonen.fi/doctype/">Quirks mode</a> is the mode that browsers use for documents without a doctype or an “old” doctype, to be more compatible with the behavior of old browsers. In quirks mode, all browsers use the <code>body</code> element to reflect the viewport for the scrolling APIs. This is also specified in the CSSOM View specification. (However, contrary to the behavior of current WebKit and Blink, if the <code>body</code> is independently scrollable, the scrolling APIs will reflect the element itself instead of the viewport.)</p>

<h2 id="typical-workarounds">Typical workarounds</h2>

<p>There are several strategies for dealing with this interoperability problem, but they are all problematic in one way or another.</p>

<h3 id="using-apis-on-window-instead">Using APIs on <code>window</code> instead</h3>

<p><code>scrollX</code>/<code>scrollY</code> or <code>pageXOffset</code>/<code>pageYOffset</code> give the viewport’s scroll position and <code>window.scrollTo(x, y)</code> scrolls the viewport. This is what e.g. <a href="https://github.com/jquery/jquery/blob/002240a6eb1cee2fcd886d5cf44893eb67f246f1/src/offset.js#L169-L192">jQuery</a> does.</p>

<p>Problem: <code>scrollX</code>, <code>scrollY</code>, <code>pageXOffset</code>, and <code>pageYOffset</code> are not supported in IE8 and below.</p>

<h3 id="using-both-elements">Using both elements</h3>

<p>For example, for getting:</p>

<pre><code>var y = document.documentElement.scrollTop || document.body.scrollTop;
</code></pre>

<p>or</p>

<pre><code>var y = document.documentElement.scrollTop + document.body.scrollTop;
</code></pre>

<p>and setting:</p>

<pre><code>document.documentElement.scrollTop = y;
document.body.scrollTop = y;
</code></pre>

<p>Problem: it is annoying to have to use both elements.</p>

<h3 id="setting-offsettop-on-documentbody-and-checking-if-it-caused-scrolling-then-reverting-the-scroll-position">Setting <code>offsetTop</code> on <code>document.body</code> and checking if it caused scrolling, then reverting the scroll position</h3>

<p>This is what e.g. <a href="https://github.com/mathiasbynens/jquery-smooth-scrolling/blob/da4e3636000a37c96f96b9a5ae93923d00179ac0/jquery.smoothscroll.js#L4-L21">@mathiasbynens’ jquery-smooth-scrolling script</a> does.</p>

<p>Problem: This is expensive and can cause a visual flash.</p>

<h3 id="comparing-scrollheight-to-determine-the-scrolling-element">Comparing <code>scrollHeight</code> to determine the scrolling element</h3>

<p>This is what e.g. <a href="https://gist.github.com/dperini/ac3d921d6a08f10fd10e">@dperini’s <code>getScrollingElement</code> script</a> does.</p>

<p>Problem: This doesn’t work if the document is not scrollable.</p>

<h3 id="determining-the-scrolling-element-in-an-iframe">Determining the scrolling element in an <code>iframe</code></h3>

<p>This is what <a href="https://github.com/mathiasbynens/document.scrollingElement/blob/b936f521b86e01512922ac3f51ca9773bea1f1ee/scrollingelement.js#L50-L59">@mathiasbynens’ <code>scrollingElement</code> polyfill</a> does. It works regardless of the document itself since it checks in an <code>iframe</code>.</p>

<p>Problem: It is complex/expensive.</p>

<h3 id="ua-sniffing">UA sniffing</h3>

<p>This is what e.g. <a href="https://github.com/google/closure-library/blob/32365aba43acb36c5d693256ef5d4dbe3bddddfe/closure/goog/dom/dom.js#L632">Closure</a> currently does.</p>

<p>Problem: This prevents browsers from fixing the bug. We need to fix this!</p>

<h2 id="how-do-i-know-if-my-site-is-affected">How do I know if my site is affected?</h2>

<ol>
  <li>Is your page in quirks mode? Check <code>document.compatMode</code> in the console in the browser’s web developer tools. If it says <code>BackCompat</code>, you’re not affected (but you <a href="https://hsivonen.fi/doctype/#choosing">should not use quirks mode</a>!).</li>
  <li>Run Chrome or Opera with <code>chrome://flags/#enable-experimental-web-platform-features</code> enabled (or more specifically with the <code>--enable-blink-features=ScrollTopLeftInterop</code> command line flag). This makes Chrome/Opera use <code>html</code> as the scrolling element (in standards mode).</li>
  <li>See if your site still works. If something is now broken, possibly your site is using UA sniffing to determine <code>html</code> vs <code>body</code> for scrolling APIs.</li>
</ol>

<h2 id="towards-a-fix-documentscrollingelement">Towards a fix: <code>document.scrollingElement</code></h2>

<p>In order to have a reliable alternative to UA sniffing, we are introducing a new API to get the right element for scrolling the viewport.</p>

<ul>
  <li>Use <a href="https://github.com/mathiasbynens/document.scrollingElement">the <code>document.scrollingElement</code> polyfill</a> and switch from <code>document.documentElement</code> or <code>document.body</code> to <code>document.scrollingElement</code> when using e.g. <code>scrollTop</code> to scroll the viewport.</li>
  <li>Feature-check for <code>scrollingElement</code> support and fall back to your current workaround (falling back to a UA check is OK).</li>
</ul>

<h2 id="testing">Testing</h2>

<ol>
  <li>Use <a href="https://www.google.com/chrome/browser/canary.html">Chrome Canary</a>, or <a href="https://www.opera.com/en/developer">Opera developer</a>, based on Chromium 44 or later, or <a href="http://windows.microsoft.com/en-us/windows/preview-download">Microsoft Edge</a>. These browsers have native <code>document.scrollingElement</code> support.</li>
  <li>Check that your site still works.</li>
</ol>

<h2 id="reporting-issues">Reporting issues</h2>

<p>If you notice that a JS library uses UA sniffing to get “the scrolling element”, or that a site is broken with <code>chrome://flags/#scroll-top-left-interop</code> enabled in Chrome or Opera, please file an issue in <a href="https://code.google.com/p/chromium/issues/list">Chromium’s bug tracker</a>. Include “ScrollTopLeftInterop” in the summary. Thank you!</p>

<h2 id="summary">Summary</h2>

<p>Browsers disagree on whether <code>html</code> or <code>body</code> reflects the viewport for <code>scrollTop</code> et al. Some sites are using UA sniffing to decide which to use. Browsers want to align and use <code>html</code> (in standards mode), so sites that UA sniff need to be changed. Use the <code>document.scrollingElement</code> API if available, and fall back to a polyfill or UA sniffing. If you notice any problems, let us know!</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/worldreader-interview/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/worldreader-interview/"/><title>Spreading knowledge in the developing world for free: An interview with the Worldreader team</title><published>2015-05-18T00:00:00+00:00</published><updated>2015-05-18T00:00:00+00:00</updated><author><name>Shwetank Dixit</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<p>I recently got to ask some questions with the team from <a href="http://worldreader.org">Worldreader</a> — a non-profit organization which provides free e-books to people in developing countries. It’s fascinating work, and something which presents its own challenges and rewards. Their target demographic is unusual for most web developers, especially those who live in developed economies.</p>

<p>The following interview will highlight some aspects of their work and their organization.</p>

<figure block="figure">
	<iframe elem="media" width="560" height="315" src="https://www.youtube.com/embed/PzRt7xTa4hE" allowfullscreen=""></iframe>
</figure>

<p><strong>Please let our readers know about what Worldreader is, as an organization?</strong></p>

<p>Worldreader is a global non-profit organization providing access to free e-books in the developing world, be that digital textbooks in schools, children’s leveled readers in libraries, or novels and short stories on mobile phones. The organization was established in 2010 and has since built a digital library of over 15,000 culturally relevant books, distributed on nearly 10,000 Kindles to students across sub-Saharan Africa, and via two mobile phone apps that have been downloaded on more than 2 million low-end feature and smart phones across the world. Through our efforts and our partnerships with device manufacturers, mobile operators, teachers, governments, and the communities where we work, Worldreader is working towards a world in which every child and her family have the books they need to improve their lives, the practice of reading is commonplace, and where illiteracy is a thing of the past.</p>

<p><strong>What is your app, Worldreader Mobile, all about?</strong></p>

<p>Worldreader Mobile is a single place to discover, read, and collect free e-books in a variety of languages, from different parts of the world. It’s an app that enables reading anywhere, anytime since it’s available on any internet-enabled mobile phone, including the simplest of feature phones. Readers from all over the world, and especially in areas facing poor connectivity and shortage of physical books, can enjoy a library of digital books in 70 genres and 44 languages. From textbooks, to fiction novels, to health information, to short stories — all books on Worldreader Mobile are designed to empower and improve people’s lives.</p>

<p><strong>You already have native applications for Worldreader, but now you’ve placed heavy emphasis on the web platform too. What, in your opinion, makes the web such an attractive platform, especially for an application like yours? What are the advantages that the web provides, compared to other platforms?</strong></p>

<p>Our goal is to reach as many people as possible with the books they need to succeed in life. A web app, by nature, is the right choice for working towards reaching this goal since it breaks down barriers of access. Web apps are device agnostic and require no app stores. Users of our reading application only need a connected mobile device, a browser and they’re on their way to getting lost in the world of e-books.</p>

<p><strong>Proxy based browsers like Opera Mini are really popular amongst the target demographic of Worldreader. What steps did you take to ensure a great reading experience, especially for proxy browsers like Opera Mini?</strong></p>

<p>Proxy browsers are commonly used on small-screen devices, so we took that into account when laying out the book for reading. We formatted the text so that it didn’t have any large tables or images that would break the layout. The user interaction capabilities also needed to be taken into account; everything was to be formatted in a single column to avoid the need for horizontal scrolling and, on keypad devices, keeping the scrolling consistent with link selection. The goal was to make it so you only have to use the down and center buttons to read a book. In addition, we added some tips to Opera Mini’s shortcuts to remind people how to scroll one page at a time.</p>

<figure block="figure">
	<img elem="media" mod="half, first" src="/articles/worldreader-interview/mini-1.png" alt="Worldreader: Categories" />
	<img elem="media" mod="half, second" src="/articles/worldreader-interview/mini-2.png" alt="Worldreader: Book details" />
	<figcaption elem="caption">Worldreader categories &amp; book details in Opera Mini</figcaption>
</figure>

<p>The buttons were designed in such a way that accommodates how fast users can scroll from the top of the page to the buttons. This was mainly for the bracket-based navigation, which is still used in older versions. We placed one menu link at the top of the page instead of multiple links to avoid users having to press a new button to skip each link before being able to scroll. Many of our users have inexpensive mobile devices with lower quality touchscreens and so, to ensure the experience remained optimal for these users, we produced larger buttons that facilitate navigation on all devices.</p>

<p><strong>What are some of the challenges you faced when making the web app, and what approaches did you take to solve them?</strong></p>

<p>While building the offline readability function for the web application, some challenges were faced. It was essential that our users be able to download books and read them offline. In the Opera Mini setting, programing logic to the page to enable offline reading was not possible. To work around this, we created a solution leveraging the built-in saved pages functionality in Opera Mini. To read a book offline now,  the user goes to a specific “Save for offline” version of the book, which he or she can then save to the browser’s saved pages as if it’s a single page.</p>

<p>Keyboard input is another feature we took into consideration. From previous feedback we knew that users often get discouraged when required to type in excessive amounts of personal details. Therefore, the app allows readers to immediately start reading a book without a user account. If they do choose to create an account in order to benefit from extended features, they simply need a username and password.</p>

<p><strong>What improvements or changes (whether it was performance, or other factors) did you see with the web application?</strong></p>

<p>One of the biggest differences we see with our web app, in comparison with our other native apps, is the reach. The amount of people reading on a daily basis using the web app has significantly increased. This is primarily thanks to our partnership with Opera, who have exposed our app to their users in Africa. We also see a lot of social interaction on the web app: our users like to share their current reads with friends through social media.</p>

<p><strong>What is next for the Worldreader web app? What improvements could users expect with further updates?</strong></p>

<p>We are continuously working on improving the overall user experience. Further updates will work towards creating a lighter and faster reading experience with improved design and the option for readers to localize the app in several languages: initially Arabic, French, Spanish and Swahili.  The content of the library will also continue to expand, with relevant content, in an increasing range of languages. Lastly, we aim to encourage a culture of reading by adding features that give rise to social activities related to books, such as reading clubs.</p>

<p><strong>Best of luck for the future. Worldreader has touched the lives of so many, and we hope it continues to do so for millions more.</strong></p>

<p>Thank you!</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/houdini/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/houdini/"/><title>Sex, Houdini and the Extensible Web</title><published>2015-05-11T00:00:00+00:00</published><updated>2015-05-11T00:00:00+00:00</updated><author><name>Brian Kardell</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<h2 id="the-backstory">The backstory</h2>

<p>When the Web was created, it was a really big idea: Tim Berners-Lee proposed (it wasn’t a standard yet) a worldwide system to retrieve documents coded in such a way that one document could link to another document. Although the idea was big, it was really simple. It was declarative and forgiving and had a clear, familiar mental model. Nearly everyone was familiar with a book, nearly everyone had written (or at least gotten) a letter, nearly every business was built around paper, so it was designed similarly.</p>

<p>Here is what the first website looked like, and for a little while it was representative of the state of the art. It was what the small handful of users that Tim convinced to try it out expected from the Web.</p>

<figure block="figure">
	<img elem="media" src="/articles/houdini/www.png" />
	<figcaption elem="caption">Screenshot of the <a href="http://info.cern.ch/hypertext/WWW/TheProject.html">original website</a></figcaption>
</figure>

<h3 id="ideas-have-sex">Ideas have sex…</h3>

<p>The simplicity and high-level aspects of the Web were an incredible boon. As more hobbyists learned that they could create content, they did. More content to draw people to the Web, in turn lent more credibility and encouraged more people still to have a look and get involved.</p>

<p>As they did, a number of people brought new ideas about how it should work. They extended the language and very quickly, as author Matt Ridley explained in his <a href="http://www.ted.com/talks/matt_ridley_when_ideas_have_sex">2006 TED Talk</a>: Their ideas had sex. They mixed and combined, inspiring new, more complex and better innovations making both the user and developer experience markedly better. This is natural because sexual reproduction is, in biological and evolutionary terms, one of the key ingredients that allows nature to arrive at logarithmically complex design. Through sharing of ideas we very quickly added things like forms, images, image maps, and tables. We also got started on CSS. Within just a year or two from the earlier picture, the state of the art looked more like this:</p>

<figure block="figure">
	<img elem="media" src="/articles/houdini/nyt.png" />
	<figcaption elem="caption">Screenshot of the <a href="https://web.archive.org/web/19961112181513/http://www.nytimes.com/">New York Times homepage from 1996</a>, thanks to the Internet Archive</figcaption>
</figure>

<p>So ideas bloomed, but almost as importantly: Some things entirely failed to catch on. They just weren’t right. <a href="http://info.cern.ch/hypertext/WWW/MarkUp/Tags.html">Tim’s original proposal for HTML</a> contained only 20 tags and more than a third of them (7) weren’t ultimately standardized.</p>

<p>As the Web grew, the impact of this positive feedback loop increased, and the need for stability became apparent: If the Web starting fragmenting, the feedback loop would be broken and the whole thing would be doomed. Thus, the W3C was formed to ensure that the Web remains built on free and open standards.</p>

<h3 id="a-paradigm-shift">A paradigm shift</h3>

<p>Some interesting things happened between then and now: The DOM was introduced, and it was scriptable. Standards remained stable for a long time while the W3C worked on a potential successor (XHTML2) and in this stability developers turned to solving problems for themselves.</p>

<p>Previously, “innovation” happened by vendors creating proprietary extensions which, by nature, were incompatible. Now, however, innovation was happening in libraries. Libraries were built on standards, so they would work for everyone. Freed from processes, their ideas again had sex: They combined, competed and improved.</p>

<p>Once again, some things failed, but all of them (successful or not) were wrapped up in non-standard libraries. It was an interesting trade-off and introduced new dynamics: Instead of being able to get increasingly better at using standard APIs, many people got increasingly better at using a library, like jQuery. Since no standards were settling at the low levels where there was agreement, each higher level of innovation had increasingly deep dependencies.</p>

<p>Imagining high level abstractions remained just as difficult and error prone as ever because they required giant leaps and had to get everything right, or be mostly useless. This was a keystone that many worried could break the positive cycle that set the Web in motion in the first place.</p>

<p>Then, suddenly, browsers began developing again. Library makers got involved with Web standards. In 2010, <a href="https://remysharp.com/2010/10/08/what-is-a-polyfill">Remy Sharp introduced the idea of polyfills</a> and more recently browsers began auto-updating. The whole game was dramatically shifting.</p>

<h2 id="enter-the-extensible-web">Enter the Extensible Web</h2>

<p>By 2011, the community at large seemed dissatisfied and a conversation began. By 2013, this conversation led to an agreement on expression of core philosophy agreed to by 21 people called <a href="https://extensiblewebmanifesto.org/">The Extensible Web Manifesto</a>.</p>

<p>It posits that we need to recognize what has changed, plug into its strengths and its community in new ways. It aims to create a virtuous cycle capable of building up complexity and adapting to needs. It suggests that the necessary ingredients for success involve — wait for it…. The ability to experiment and fail fast, the ability for ideas to have sex and gain key improvements, and the ability for ideas to compete amongst developers, developing standards on data and success rather than prescription. Wherever possible, it suggests that we <em>prollyfill</em> standards — that is, to provide a useful implementation that works everywhere before it is a standard and gain that data. As an early (and imperfect) example, see Google’s Polymer library which prollyfills various Web Components specifications, allowing authors to see what worked and what didn’t, and tweak the spec (and adjust the prollyfill) accordingly.</p>

<p>The manifesto is crafted to correct what is historically a hard incentive imbalance: Developers were disincentivized to look at standards until they are already available because of their (often) years-long time frame and inability to experiment. Once delivered, those standards often fell short of actual developer expectations because working groups don’t really understand the needs and desires of real developers. AppCache, for example, is a famous whipping boy, but one could make the argument that it does exactly what it was designed to do (as <a href="http://html5doctor.com/interview-with-ian-hickson-html-editor/#appcache">Ian Hickson explained</a>).</p>

<p>However, if developers are provided with something useful that solves their problems now, with the potential of becoming standardized, they are incentivized not only to try it, but to try to help make it better before it does so.</p>

<p>For the past couple of years, the community and standards bodies have been working hard on projects and efforts to do that: Transpilers helped us provide early access to many ES6 features. Custom Elements have a number of prollyfills that allow people to use custom tags in HTML and help us build up new proposals or look across sites for common vernacular.</p>

<h2 id="magic">Magic</h2>

<p>Note that a lot of the Web is high-level, even simple seeming things contain “magic” that browsers all know about but are not specified. Lots and lots of things have to fetch data, stream it and so on — but none of this is currently explained. This creates a kind of “unspoken” architecture that makes it hard to polyfill or even to add new features and limits the number of ways/places that we (or browsers) can plug in.</p>

<p>Therefore, the Extensible Web Manifesto argues that explaining the underlying magic in the platform, minimizing the introduction of new magic and enabling the sort of environment where this sort of evolution can take place should be the immediate priority of standards bodies. The <a href="https://fetch.spec.whatwg.org/">Fetch</a> and <a href="https://streams.spec.whatwg.org/">Streams</a> standards are examples of specs trying to do just that.</p>

<p>In practical terms, when we have a new proposal, we should first look to unexposed aspects that lie hidden in the existing platform first. When we can’t find anything, we should find what lower-level thing would allow explanation of not only the larger problem, but related problems by defining it and how it fits into the larger picture. Not only should the end-result be better, but developers increase their familiarity through participation and standardization should be easier and faster.</p>

<h3 id="abracadabra-css">Abracadabra CSS</h3>

<p>Things like <a href="http://www.w3.org/TR/dom/#mutation-observers">MutationObservers</a>, <a href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/">Service Workers</a>, <a href="http://w3c.github.io/webcomponents/spec/custom/">Custom Elements</a>, Fetch and Streams provide the raw materials and basic workings that allow an author to plug into reasonably-well explained systems. If you had an idea for a new element, there’s a pretty high chance you could provide something pretty close for people to experiment with in high-level fashion with reasonable forward compatibility safeguards. If you wanted to polyfill an element which was supported in three browsers, you could. That’s incredible. It’s awesome.</p>

<p>But what do you do if you want to propose a new pseudo element for CSS? What if you had an excellent idea for a new layout module? What if you wanted to polyfill something?</p>

<p>Here’s what you’d do historically: Forget it.</p>

<p>CSS contains so much magic that we might have more aptly named it “Hogwarts”. First, you need to be able to parse the stuff because the parser drops unknown rules entirely. Unknown properties or values are dropped too — believe me, it’s non-trivial. Second, you need to make sense of it all: specificity, inheritance, imports and at-rules. You need to understand that all modules have shorthands which expand to long hands. The list goes on just to parse it. In some cases though, you need to serialize modifications back out. And in most cases, of course, you need to actually apply it <em>live, any time someone changes the DOM and as the page is still loading</em>.</p>

<p>The browser itself, of course, knows how to do all of this and has a host of optimizations to make it efficient — but it’s all just magic on the outside. If you need any piece of it, you’ve got to understand and recreate all the underlying magic yourself.</p>

<p>The W3C Technical Architecture Group (or TAG for short) are tasked with kind of making sure that the long term vision of the Web and stuff that the W3C is working on is healthy and on a good track. They’ve taken note of this problem — the disconnect between the Extensible Web ideas that are permeating everything else, and the inability to apply them well to CSS, so they’ve formed a joint TAG/CSS WG task force to work on this problem.</p>

<h2 id="enter-houdini">Enter Houdini</h2>

<p>This new task force is codenamed “Project Houdini”. Around the turn of the 20th century, Harry Houdini became the world’s most famous magician. There seemed to be no way to contain him. He could escape from anything: Handcuffs, straitjackets, chains, and boxes, even when suspended upside down or underwater. He was also repulsed by the growing practice of people using tricks and illusions and playing on people’s emotions to extort money, so began to investigate and explain their “magic”; he even testified before the US Congress trying to criminalize such practices. So — boxes, sealed, explaining magic — “Houdini” sounded like an excellent name.</p>

<p>The Houdini task force recently held its <a href="https://wiki.css-houdini.org/planning/sydney-2015">inaugural, 3-day long meeting</a> in Sydney, Australia (incidentally, Houdini also made the first manned flight over Australia) to discuss what could or should be done. The full minutes are available from the meeting link, but I’ll attempt to sum it up here. First, this captures the sentiment pretty nicely:</p>

<blockquote>
  <p>Show that we care about extending the browser, and continue to iterate on it. I don’t think we can fix or even think of everything to fix from the beginning, it needs to evolve.</p>
</blockquote>

<p><cite>Daniel Glazman, CSS WG co-chair</cite></p>

<p>And, more importantly, this wasn’t a radical statement, it was the norm. At the next TAG meeting, Travis Leithead from Microsoft asked the question “what was the most exciting thing?” to which the response was:</p>

<blockquote>
  <p>[The most exciting thing was] that nobody was arguing. We’ve wanted a lot of this since the 90s and now is the first time when someone hasn’t said “no” or “it can’t be done”.</p>
</blockquote>

<p><cite>Peter Linns (TAG co-chair, CSS WG co-chair)</cite></p>

<p>The task force agreed to begin work on eight new drafts whose aim it is to explain and expose different aspects of CSS. In reality, it’s more like ten as there were already two underway (custom properties and aliases/custom-pseudo classes). We’ve set up a <a href="https://wiki.css-houdini.org/">really basic wiki</a>, a <a href="https://lists.w3.org/Archives/Public/public-houdini/">public mailing list</a> and a <a href="https://github.com/w3c/css-houdini-drafts">home on github</a>. It’s still very early days, and it will take some time to get rolling as people close out existing work and make ways to prioritize, but it’s a start.</p>

<p>These drafts, which involve everything from the parser to fragmentation and layout, should begin closing the gap between CSS and everything else, making it increasingly plausible to polyfill CSS and innovate/experiment — our ideas can have sex, becoming better/richer than any one of us dreamed.</p>

<h3 id="the-specs-and-what-they-enable">The specs and what they enable</h3>

<h4 id="parser-api">Parser API</h4>

<p>If you can’t parse CSS, you can’t do much — even editors and code highlighters need this functionality and as I explained: it’s really hard to do accurately or and near impossible to do with any kind of comparative performance. Once parsed, you’ve got to actually do something with the information, which means you need a standard way of understanding the parsed stuff. All existing pre-processors and polyfills have to do this and they aren’t fully capable, fully compatible and they don’t agree on the output. A similar problem existed in ECMAScript: transpilers, editors and syntax highlighters for JavaScript are essentially the same problem, and so they created <a href="http://esprima.org/">Esprima</a>. This allows us to gain so many of the benefits of the extensible web.</p>

<h4 id="css-property-and-value-extensions-api">CSS Property and Value Extensions API</h4>

<p>Of course, the browser has already parsed things and you don’t necessarily want to do it again if you can avoid it. Furthermore, the browser’s parser also fundamentally has to be a little more capable security-wise. More ideally, in many cases it would be better to plug into the existing system instead with a definition of what should be done. At the very least, it would help define something that the browser shouldn’t throw away as an invalid property or value. This is one of the key features that will allow us to build prollyfills and polyfills. Proposals that satisfy similar use cases as CSS Regions, but which are currently way too hard, suddenly become plausible. This proposal would also expose the ability to do custom <code>@rules</code>.</p>

<h4 id="css-aliases-and-custom-pseudo-classes">CSS Aliases and Custom Pseudo-classes</h4>

<p>This one didn’t come from Houdini itself, so it already has an editor and a <a href="http://tabatkins.github.io/specs/css-aliases/index.html">rough draft</a>, but Houdini expands its scope a bit. Its aim is to make it possible for authors to create simple aliases for selectors or even wholly new pseudo-classes.</p>

<p>CSS lacks the ability to create something like a constant that you can refer in a much simpler way later; this creates an explosion of repeated selectors and it’s one of the reasons that people use pre-processors even for very trivial things. An extremely trivial example is something like selecting a button — there are a couple of ways to make a button and you don’t want to the various selectors every time — you just want to define a simple (author-defined) shortcut like <code>:--button</code> and then use it. In the current proposal that might look something like this:</p>

<pre><code>@custom-selector :--button
	input[type='button'],
	input[type='submit'],
	input[type='reset'],
	button, [role='button'];

:--button { color: green; }
.foo &gt; :--button { color: blue; }
</code></pre>

<p>A quick note on the syntax of CSS: CSS has always had forward-compatible parsing rules in which the syntax has been designed with room for extension. Originally this was for vendor prefixes in the format <code>-vendor-*</code>, but they were a <a href="https://the-pastry-box-project.net/bruce-lawson/2012-september-1">really bad idea</a>. Houdini introduces author prefixes, which simply have an empty (<code>""</code>) vendor, and thus are written as <code>--foo</code>.</p>

<p>In addition to aliases, this spec let us define things that are more complex — for example, a pseudo-class for dealing with numeric attributes as <em>numbers</em> instead of strings. Given something like the selector plugin architecture in jQuery this is pretty trivial to do, but these things are really hard to define in CSS. There are selectors and pseudo-classes which have been in proposal status for more than a decade — given something like this, we give authors immediate benefit and gain data about what is useful and streamline the standards process.</p>

<h4 id="font-metrics-api">Font Metrics API</h4>

<p>A lot of times the thing that you need to calculate require context and information which is not currently available to you. Take, for example, drop-caps. Adobe worked hard on creating <a href="https://github.com/adobe-webplatform/dropcap.js">dropcap.js</a> which is worth a look (including the linked blog post) if you want to understand the complexity and challenges and compromises we currently have to make to do something as “simple” as drop-caps. The Font-Metrics API would work on exposing the necessary information one would need to help fill things that involve font-oriented information.</p>

<h4 id="custom-layout">Custom Layout</h4>

<p>CSS has all kinds of crazy layout modes and still, it’s really hard to do some things that it shouldn’t be so hard to do — so, for example, we have alternative proposals like <a href="http://gridstylesheets.org/">Grid Stylesheets (GSS)</a> which use a constraint-based layout. Figuring out this stuff is hard and it takes an astoundingly inordinate amount of work to get it specified, correct and interoperable. Custom layouts will allow us to register a custom display value and own layout computations making whole classes of new proposals possible to figure out in the community and without impossibly complex barriers.</p>

<h4 id="custom-paint">Custom Paint</h4>

<p>At some point you have to paint — that is, actually splat colors onto the screen for CSS to render text and DOM atop. There are any number of challenges which currently involve abusing DOM to get correct visual effects like effects and gradients. Custom paint will allow you to do this.</p>

<h4 id="input-extensions">Input Extensions</h4>

<p>Lots of things affect how your app responds or paints, user input like scrolling, for example. Simple things like pull to refresh interfaces involve things like physics and sometimes that makes a really big difference. The Input Extensions spec aims to allow us to plug into that and make it increasingly possible to create really good custom or experimental user experiences that work with this kind of input.</p>

<h4 id="async-style">Async Style</h4>

<p>This one is still a little bit vague, but essentially the idea is to figure out how we create ways to introduce limited asynchrony and isolation in the DOM. While the description I’m giving is lacking, the ability to identify things that can be pushed into workers or threads is a potentially giant gain for everything from mashups to synchronized effects. Currently almost all work is done on the same main thread — this means that the Web can’t take good advantage of all those cores that your machine (even your cell phone) have which makes effective UIs hard. It will be really interesting to see what comes out of this research.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Of course, this is just a high level view of things and it’s still early days for Houdini — anything is subject to radical re-thinking, but the commitment from so many to dig down and explain the platform in order to make it extensible and adaptable, and to work to build a healthier process around standards is intensely positive.</p>

<p>The Extensible Web isn’t about abandoning declarative HTML and making everything JavaScript; the declarative nature of HTML was what made it so successful in the first place.</p>

<p>It means that rather than spending years on high-level APIs and getting them wrong, high-level ideas can compete — they can have sex and deliver real value along the way. I believe that ultimately, this extensibility and ability to adapt, refine and share sensible high-level features are the cornerstone on which we will allow the Web not just to generally improve, but to remain interesting and competitive for decades — and recapture some of the most important things that made it successful in the first place.</p>

<p>Update September 2015: Bruce wrote a report on the second <a href="https://dev.opera.com/articles/houdini-f2f-report/">Houdini Task Force meeting</a>.</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/wifi-ble-javascript/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/wifi-ble-javascript/"/><title>Electronics for the JavaScript Developer using Wi-Fi and Bluetooth LE</title><published>2015-04-22T00:00:00+00:00</published><updated>2015-04-22T00:00:00+00:00</updated><author><name>Sayanee Basu</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>The <a href="http://en.wikipedia.org/wiki/Internet_of_Things">Internet of Things</a> is gaining momentum in the recent years as more embedded computing devices are being connected to the Internet. What does this mean for us web developers? This article will explore two common wireless protocols, <a href="http://en.wikipedia.org/wiki/Wi-Fi">Wi-Fi</a> and <a href="http://en.wikipedia.org/wiki/Bluetooth_low_energy">BLE</a> and will take you through the starting steps in connecting sensors and servo motors to the Internet. Then we will learn how to control these devices and access the sensor data using JavaScript!</p>

<p>In this article we will explore two platforms: <a href="https://www.spark.io/">Spark</a> for Wi-Fi and <a href="http://www.ti.com/ww/en/wireless_connectivity/sensortag/index.shtml?INTC=SensorTag&amp;HQS=sensortag">TI Sensor Tag</a> for BLE with practical examples. At any time, you can also look at the <a href="https://github.com/operasoftware/devopera/tree/master/articles/wifi-ble-javascript/code">complete annotated code for each example</a>. It will be fun!</p>

<h3 id="pre-requisites">Pre-requisites</h3>

<p>This article assumes that you are already an intermediate to advanced level JavaScripter. We will primarily use <a href="https://nodejs.org/">node</a> and <a href="https://www.npmjs.com/">npm</a> for server side and simple frontend JavaScript to create some control UI on a web browser. You don’t need any prior knowledge of electronics. Seeing you can effect change and gather data from the physical world can be exciting and I hope through this article you will get that first excitement to dive into the fun world of electronics and web technologies! Let’s get started!</p>

<h2 id="spark-and-wi-fi">Spark and Wi-Fi</h2>

<p>One of the reasons why <a href="https://www.spark.io/">Spark</a> is a great platform especially for any electronics beginner are its <a href="http://docs.spark.io/">detailed documentation</a> as well as the <a href="https://community.spark.io/">community forum</a>. In this section, we will play with a light sensor and then control a servo from the web browser. Let’s first list the electronics components you will need so that you can buy them if you want to physically follow through the examples:</p>

<h3 id="spark-core">Spark Core</h3>

<ul>
  <li><a href="http://docs.spark.io/assets/images/spark-pinout.png">Pinout diagram</a></li>
  <li><a href="http://docs.spark.io/start/#step-3-connect-your-core-to-the-cloud">LED colors/actions and their meanings</a></li>
</ul>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/spark.png" />
</figure>

<p><a href="https://store.spark.io/?product=spark-core">Spark store</a></p>

<h3 id="breadboard">Breadboard</h3>

<p><a href="http://en.wikipedia.org/wiki/Breadboard">Wikipedia</a></p>

<p>Horizontal rows</p>

<ul>
  <li>Red: HIGH or Vin (~6V)</li>
  <li>Blue / Black: LOW or Ground (0V)</li>
</ul>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/breadboard.jpg" alt="" />
	<img elem="media" src="/articles/wifi-ble-javascript/img/wiring.png" alt="" />
	<figcaption elem="caption">Wiring pattern in a breadboard.</figcaption>
</figure>

<p>You will <a href="http://docs.spark.io/start/">get a breadboard when you buy the Spark Core</a></p>

<h3 id="micro-b-to-usb-cable">Micro-B to USB cable</h3>

<p>You will <a href="http://docs.spark.io/start/">get this cable when you buy the Spark Core</a> or this might be your mobile charger.</p>

<h3 id="jumper-cables">Jumper cables</h3>

<p><strong>Tip:</strong> Use the same color wires as the schematic so that it will be faster to trace the wires for debugging. E.g. use <em>Red</em> for power and <em>Black</em> for ground.</p>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/cables-pic.jpg" />
	<img elem="media" src="/articles/wifi-ble-javascript/img/cables.png" />
</figure>

<p><a href="http://www.adafruit.com/product/758">Adafruit</a> or <a href="https://www.sparkfun.com/products/8431">Sparkfun</a></p>

<h3 id="light-dependent-resistor-ldr-or-photocell">Light dependent resistor: LDR or photocell</h3>

<p><strong>Tip:</strong> LDR has no polarity, so either leg can be connected to the analog pin or the ground.</p>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/ldr.jpg" />
</figure>

<p><a href="http://www.adafruit.com/product/161">Adafruit</a> and <a href="https://www.sparkfun.com/products/9088">Sparkfun</a></p>

<h3 id="k-ohm-resistor">1k ohm resistor</h3>

<p><strong>Tip:</strong> Resistor has no polarity, so either leg can be connected to the analog pin or the ground.</p>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/resistor-schematic.png" />
</figure>

<p><a href="https://www.sparkfun.com/products/8980">Sparkfun</a></p>

<h3 id="servo">Servo</h3>

<ul>
  <li><a href="http://en.wikipedia.org/wiki/Servo_(radio_control)">Wikipedia</a></li>
  <li><a href="http://docs.spark.io/shields/#setting-up-the-shield-8-micro-servo-1">Spark and servo</a></li>
</ul>

<p><strong>Tip:</strong> For wiring — <em>Yellow</em> is Signal, <em>Orange</em> is +5V (VIN), <em>Brown</em> is ground</p>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/servo.jpg" />
</figure>

<p><a href="http://www.adafruit.com/product/169">Adafruit</a> or <a href="https://www.sparkfun.com/products/9065">Sparkfun</a></p>

<h3 id="micro-farad-capacitor">10 micro Farad Capacitor</h3>

<ul>
  <li><a href="http://en.wikipedia.org/wiki/Capacitor">Wikipedia</a></li>
  <li><a href="http://docs.spark.io/shields/#setting-up-the-shield-2-electrolytic-capacitor-100uf-5">Capacitors</a></li>
</ul>

<p><strong>Tip:</strong> The capacitor used in this example has polarity. On the plastic above one of the pins you’ll see a light colored strip with a negative sign <code>–</code> on it. Always connect that pin to GND pins or rails.</p>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/capacitor.jpg" />
</figure>

<h3 id="setup">1. Setup</h3>

<p>In this section, we will connect the Spark Core to your Spark account and then connect it to the local Wi-Fi. To setup the Spark Core, <a href="https://www.spark.io/signup">signup for an account</a>. Then connect the Spark Core to your laptop via the USB cable. You should see a fast-paced blinking blue light which means the Spark Core is waiting for Wi-Fi credentials.</p>

<figure block="figure">
	<iframe elem="media" src="https://vine.co/v/hFHPMue5lgd/embed/simple" width="360" height="360"></iframe>
	<script src="https://platform.vine.co/static/scripts/embed.js"></script>
</figure>

<p>To associate the Spark Core with your account (also known as “claiming the core”), we will use the <code>spark-cli</code> module. Next, we will give the Spark Core our local Wi-Fi credentials so it can connect to the Wi-Fi network.</p>

<pre><code>$ npm install -g spark-cli
$ spark setup # connect the Spark Core to your account
$ spark setup Wi-Fi # connect the Spark Core to your Wi-Fi
</code></pre>

<p>If you have setup the Spark Core correctly, you will see a breathing cyan light as shown below.</p>

<figure block="figure">
	<iframe elem="media" src="https://vine.co/v/hFwubhA3JXV/embed/simple" width="360" height="360"></iframe>
	<script src="https://platform.vine.co/static/scripts/embed.js"></script>
</figure>

<p>Next, we will note down two important values (device id and access token) for your Spark Core that will be needed for any secure communication. Open <a href="https://www.spark.io/build">Spark’s web editor</a>, Spark Build for this and note down these 2 values.</p>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/device-id-access-token.jpg" alt="" />
</figure>

<p>In the next couple of sections we will go through two examples. These two examples show two different ways you can use Spark:</p>

<ol>
  <li>Sensing with an LDR (light dependent resistor) with:
    <ul>
      <li><a href="http://docs.spark.io/firmware/">firmware code</a> that will publish the sensor values</li>
      <li><a href="https://www.npmjs.com/package/spark">spark npm module</a> to pick up the values periodically</li>
    </ul>
  </li>
  <li>Moving a servo with buttons on a web browser with:
    <ul>
      <li>pre-built firmware code <a href="https://github.com/voodootikigod/voodoospark">voodootiki spark</a></li>
      <li><a href="https://www.npmjs.com/package/express">express</a>, <a href="https://www.npmjs.com/package/spark-io">spark-io</a> and <a href="https://www.npmjs.com/package/johnny-five">johnny-five</a> npm modules to built a simple button that can turn the servo from the browser</li>
    </ul>
  </li>
</ol>

<h3 id="sensing-photocell-values">2. Sensing photocell values</h3>

<p>Blink the on-board <code>D7</code> LED.</p>

<p>As the very first step, we will learn how to blink an LED. This is the <code>hello world</code> of electronics. <a href="https://www.spark.io/build">Open the Spark web editor</a> and <a href="code/spark-blinky/blinky.ino">copy the simple blinking LED code</a>. Here it uses a <a href="http://docs.spark.io/firmware/">simple firmware code</a> to blink the on-board LED <code>D7</code> every 1 second. To flash the firmware code onto your Spark Core, click the <code>flash</code> icon at the top of the left sidebar and wait for the LED on board to come back to the breathing cyan pattern. You should see the LED <code>D7</code> blinking.</p>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/flash.png" alt="" />
</figure>

<p>Wire up the breadboard for detecting photocell values.</p>

<p>Here we will need a couple of jumper wires, one photocell and 1kΩ resistor. We will firstly wireup the <code>Red</code> wire to pin <code>Vin</code> and the horizontal lines <code>+</code>. And similarly, the <code>Black</code> wire to pin <code>Gnd</code> and the horizontal line <code>-</code>. Next we will connect the photocell (or LDR) to pin <code>A0</code> on the Spark Core and the ground, horizontal line <code>-</code>. LDRs do not have any polarity, so we can connect either of the legs to <code>Gnd</code>. Finally, with the 1kΩ resistor, we will connect to pins <code>A0</code> and <code>Vin</code> on the Spark Core. This circuit might remind you of your <a href="http://www.build-electronic-circuits.com/ldr-circuit-diagram/">high school physics voltage divider circuit</a>.</p>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/ldr-circuit.png" alt="" />
</figure>

<p>Flash the firmware code to read the photocell values</p>

<p>While you see the breathing cyan on the Spark Core, take the <a href="code/spark-ldr/ldr.ino">LDR firmware code</a> and flash it onto the Spark Core with the <a href="https://www.spark.io/build">web ide</a>. The firmware code does a couple of things. Every 200ms, it take the analog reading from pin <code>A0</code>, to which we connected the LDR and then publishes it as a <code>Variable</code> on the Spark Cloud which can then be queried using standard Web APIs. For easy detection and debugging we are also turning on and off the on-board LED <code>D7</code> to indicate our code is running.</p>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/ldr-actual.jpg" alt="" />
</figure>

<p>Install the npm module <a href="https://www.npmjs.com/package/spark">spark</a></p>

<pre><code>$ npm install spark
</code></pre>

<p>Use JavaScript to query the sensor values.</p>

<p>Here’s now the fun part and we will query the sensor values using the simple spark code in a file <code>ldr.js</code></p>

<pre><code>var spark = require('spark');

spark.login({
	username: process.env.EMAIL,
	password: process.env.PASSWORD
}).then(
	function(token) {
		// Your program can successfully connect
		// to the published data from the sensor
		console.log('Connected to your light sensor successfully!');
		// console.log('Access Token: ' + token.access_token);
		spark.listDevices().then(
			function(devices){
				// console.log('\nDevices: ', devices);
				var device = devices[0];
				// With every published event getLight,
				// display the sensor value
				device.onEvent('getLight', function(reply) {
					var now = new Date();
					if (reply &amp;&amp; reply.data) {
						// Some fun derivations based on the sensor value
						if (parseInt(reply.data) &lt; 1000) {
							// Shine a torch light on the LDR
							// amend 1000 according to your environment
							console.log(
								now.getSeconds() + ': ' +
								reply.data + ' bright!'
							);
						} else if (parseInt(reply.data) &gt; 2000) {
							// Cover the LDR amend 2000
							// according to your environment
							console.log(
								now.getSeconds() + ': ' +
								reply.data + ' dark! '
							);
						} else {
							console.log(
								now.getSeconds() + ': ' +
								reply.data
							);
						}
					}
				});
			},
			function(err) {
				console.log('List devices call failed: ', err);
			}
		);
	}, function(err) {
		console.log('Ooops error: ' + err);
	}
);
</code></pre>

<p>Let’s run this code from the command line using your Spark account’s email and password:</p>

<pre><code>$ EMAIL="{SPARK_EMAIL_ADDRESS}" PASSWORD="{SPARK_ACCOUNT_PASSWORD}" node ldr.js
</code></pre>

<p>You should next see a stream of sensor data. Shine a torch light on the LDR and the value should change and a comment would be displayed. Cover the LDR totally and you will see another comment! So now whatever you do physically in the real world can be sensed with node and JavaScript! Such sensors can be used to sense open/close cupboard doors and light levels in rooms.</p>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/ldr-result.jpg" alt="" />
</figure>

<p>This is just the start in playing with the <a href="http://docs.spark.io/javascript/#getting-started-logging-in">Spark JavaScript API</a> for the server-side. There are many more <a href="https://www.spark.io/build#libraries">firmware code libraries</a> available that you can instantly flash to your SparkCore and collect the results via the <a href="http://docs.spark.io/javascript/#supported-commands-events">events api</a>.</p>

<h3 id="control-a-servo">3. Control a Servo</h3>

<p>Let’s wire up the breadboard with a servo this time!</p>

<p>We will use a servo motor and a capacitor. Wire up the Black / Brown wire to the <code>Gnd</code> pin of the Spark Core, Orange / Red to the <code>Vin</code> of the Spark Core and finally the Yellow wire will be used to wire up to the analog pin <code>A0</code> of the Spark Core. We will also use a capacitor between the <code>Vin</code> of the Spark Core and <code>Gnd</code> of the Spark Core to stabilize the power to the servo. Capacitor is optional, but it’s good to have it for stability.</p>

<p>The control of the servo is fairly easy. It can rotate 180 degrees. So, when the signal is <code>0V</code>, it will rotate to 0 degrees and at the other end, when the signal is <code>5V</code> it will rotate to 180 degrees. To help us do the analog output of these signals, we will use a firmware called VoodooSpark.</p>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/servo-circuit.png" alt="" />
</figure>

<p>Flash the pre-built firmware <a href="https://raw.githubusercontent.com/voodootikigod/voodoospark/master/firmware/voodoospark.cpp">Voodoospark</a> using the <a href="https://www.spark.io/build">Spark web editor</a>	 and wait for the breathing cyan light</p>

<p><a href="https://github.com/voodootikigod/voodoospark">VoodooSpark</a> will allow a local TCP connection instead of the usual HTTP protocol that we used in the earlier example. This allows controlling the Spark Core in real-time. Finally, we will use Express to create the routes that will trigger the rotation of the servo through an <code>html</code> page.</p>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/servo-actual.jpg" alt="" />
</figure>

<p>Use JavaScript to send signals to the servo via a web browser</p>

<pre><code>$ npm install express johnny-five spark-io
</code></pre>

<p>We will need 3 modules. <a href="https://github.com/rwaldron/spark-io">Spark-io</a> to output the TCP packets which VooDooSpark firmware on the Spark Core understands. <a href="https://github.com/rwaldron/johnny-five">Johnny-Five</a> package uses Spark-io and <a href="https://github.com/rwaldron/johnny-five/tree/master/lib">provides higher level interfaces</a> to many devices such as sensors, motors, switches, etc. And finally <a href="https://github.com/strongloop/express">Express</a> to serve a webpage and pass HTTP requests from the browser to the Spark Core.</p>

<p>Store the Spark device id and access token in config file.</p>

<p>Create file <code>~/.sparkrc</code> to <a href="https://github.com/rwaldron/spark-io#getting-started">store your config</a> and add the file to your profile with <code>source ~/.sparkrc</code>:</p>

<pre><code>export SPARK_TOKEN="{SPARK_ACCESS_TOKEN}"
export SPARK_DEVICE_ID="{SPARK_DEVICE_ID}"
</code></pre>

<p>Create the JavaScript code in file <code>servo.js</code>.</p>

<pre><code>var express = require('express')
var five = require('johnny-five');
var Spark = require('spark-io');
var app = express();
var servo;

// Connect to the Spark Core with the authentication info
var board = new five.Board({
	io: new Spark({
		token: process.env.SPARK_TOKEN,
		deviceId: process.env.SPARK_DEVICE_ID
	})
});

// Use analog pin A0
board.on('ready', function() {
	servo = new five.Servo({
		pin: 'A0'
	});
	console.log('Servo is ready!');

});

app.use(express.static(__dirname));

// Move to servo to a certain degree
// github.com/rwaldron/johnny-five/blob/master/lib/servo.js#L241-251
app.get('/rotate/:deg', function (req, res) {
	if (servo) {
		servo.to(parseInt(req.params.deg))
		console.log('Rotate ' + req.params.deg + 'deg');
	}
})

var server = app.listen(3000, function () {
	console.log(
		'Control the servo at http://localhost:' + server.address().port
	);
})
</code></pre>

<p>Finally we will create the super simple html page <code>index.html</code> which will call the routes for the different angles.</p>

<pre><code>&lt;a href="/rotate/10"&gt;10 deg&lt;/a&gt;
&lt;a href="/rotate/170"&gt;170 deg&lt;/a&gt;
</code></pre>

<p>Run the code with the node server and click the angles to make the servo move in the physical world!</p>

<pre><code>$ node servo.js
</code></pre>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/servo-output.jpg" alt="" />
</figure>

<p>This example is just the tip of the iceberg in how you can control many other devices such as motors and switch with the web interface. I find the <a href="https://github.com/rwaldron/johnny-five/tree/master/lib">Johnny-Five</a> library files very useful to peek into many more things we can hook up and play with!</p>

<figure block="figure">
	<video elem="media" controls="" loop="">
		<source src="/articles/wifi-ble-javascript/servo.mp4" type="video/mp4" />
	</video>
</figure>

<h2 id="ti-sensor-tag-and-ble">TI Sensor Tag and BLE</h2>

<p>In this section, we will use the Bluetooth Low Energy (BLE) protocol with the <a href="http://www.ti.com/ww/en/wireless_connectivity/sensortag/index.shtml?INTC=SensorTag&amp;HQS=sensortag">TI SensorTag</a>, which is designed for developers to play with various sensors and BLE. The SensorTag comes with a BLE chip on-board along with sensors such as IR temperature sensor, humidity sensor, pressure sensor, accelerometer, etc in a compact handy device. The advantage of using BLE is its low power consumption. The SensorTag can be powered with just a coin cell potentially for years.</p>

<p>To play with the TI SensorTag, you need a couple of things:</p>

<ol>
  <li><a href="http://processors.wiki.ti.com/index.php/Simplelink_SensorTag">TI SensorTag</a> powered with a single coin cell</li>
  <li>The machine on which you will run the JavaScript code should have BLE hardware.</li>
</ol>

<p>The main npm module that we will be using to interface with the SensorTag is <a href="https://www.npmjs.com/package/sensortag">senstortag</a> which is based on an underlying generic node BLE central module, <a href="https://www.npmjs.com/package/noble">noble</a>. We will attempt to read the IR temperature from the SensorTag and log the gyroscope data while rotating the sensortag. Let’s get started by requiring the modules and connecting to the sensortag.</p>

<p>Create a file <code>sensortag.js</code>, connect, discover and then disconnect the device:</p>

<pre><code>var async = require('async');
var SensorTag = require('sensortag');

SensorTag.discover(function(sensorTag) {

	sensorTag.on('disconnect', function() {
		console.log('Disconnected!');
		process.exit(0);
	});

	async.series([
		function(callback) {
			console.log('Connect!');
			sensorTag.connect(callback);
		},
		function(callback) {
			console.log('Discovered');
			sensorTag.discoverServicesAndCharacteristics(callback);
		},
		function(callback) {
			console.log('Disconnected');
			sensorTag.disconnect(callback);
		}
	]);

});
</code></pre>

<p>Because the events <code>connect</code>, <code>discovered</code> and <code>disconnected</code> should happen sequentially when the previous event is done, we will use the npm module <code>async</code> to deal with callbacks.</p>

<p>Read the IR Temperature once between the events <code>discovered</code> and <code>disconnected</code>:</p>

<pre><code>function(callback) {
	console.log('IR Temperature enabled');
	sensorTag.enableIrTemperature(callback);
},

function(callback) {
	console.log('readIrTemperature');
	sensorTag.readIrTemperature(
		function(objectTemperature, ambientTemperature) {
			console.log(
				'\tobject temperature = %d °C',
				objectTemperature.toFixed(1)
			);
			console.log(
				'\tambient temperature = %d °C',
				ambientTemperature.toFixed(1)
			);
			callback();
		}
	);
},
</code></pre>

<p>Finally, we will add in the gyroscope reading and when the SensorTag is physically rotated, the JavaScript should output the updated values from the gyroscope. We hook onto the gyroscope events after the IR temperature reading. We have to specifically enable the gyroscope readings using the <code>notifyGyroscope</code> API.</p>

<pre><code>// readIRTemperature
function(callback) {
	console.log('Gyroscope enabled');
	sensorTag.enableGyroscope(callback);
},

function(callback) {
	setTimeout(callback, 1000);
},

function(callback) {
	sensorTag.on('gyroscopeChange', function(x, y, z) {
		console.log('On Gyrosope change: '
			+ x.toFixed(1) + '°/s[X]\t'
			+ y.toFixed(1) + '°/s[Y]\t'
			+ z.toFixed(1) + '°/s[Z]');
	});

	sensorTag.notifyGyroscope(function() {
		console.log('Start tracking gyroscope!');
	});
}

// Comment out disconnect
// function(callback) {
// 	console.log('Disconnected');
// 	sensorTag.disconnect(callback);
// }
</code></pre>

<p>You can refer to the <a href="https://github.com/operasoftware/devopera/tree/master/articles/wifi-ble-javascript/code/sensor-tag">entire code here</a>. Let’s run it!</p>

<pre><code>$ node sensortag.js
</code></pre>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/sensortag-output.jpg" alt="" />
</figure>

<p>That is just a tiny example on how to interface with a BLE device. To dabble more, have a look at <a href="https://github.com/sandeepmistry/node-sensortag/blob/master/test.js">all the sensors data you can query</a> in the SensorTag as well as the underlying <a href="https://github.com/sandeepmistry/noble">noble module</a>. The author of both these modules, <a href="https://github.com/sandeepmistry?tab=repositories">Sandeep Mistry</a> has open sourced many more BLE related npm packages such as the ones we can interface with <a href="https://github.com/sandeepmistry/node-bleacon">iBeacons</a> or <a href="https://github.com/sandeepmistry/arduino-BLEPeripheral">Arduino library</a>. Have a go at them!</p>

<h2 id="more-resources">More resources</h2>

<p>The easiest way to start learning to interface web technologies with electronics is to choose a hardware platform which already comes with a JavaScript API. Here are some examples of more such platforms other than the Spark and SensorTag that we covered:</p>

<ul>
  <li><a href="https://tessel.io/">Tessel</a> — <a href="https://tessel.io/docs/hardwareAPI">hardware api</a></li>
  <li><a href="http://arduino.cc/en/Main/ArduinoBoardYun?from=Products.ArduinoYUN">Arduino Yun</a> — <a href="https://github.com/rwaldron/johnny-five">Johnny-Five</a></li>
  <li><a href="http://www.raspberrypi.org/">Raspberry PI</a> — <a href="https://nodejs.org/dist/v0.10.28/">node.js build for Linux arm pi</a>, <a href="https://iojs.org/dist/">io.js builds for armv6l and armv7l</a></li>
</ul>

<p>Hardware and electronics interfacing might be daunting at first, but the good news is there are many community events, forums, blog posts and modules/libraries available online. Here are some to check out:</p>

<ul>
  <li><a href="http://nodebots.io/">Nodebots</a> — JavaScript based robotics events around the world</li>
  <li><a href="http://www.nodecopter.com/">Nodecopter</a> — Node and drones community hacking events</li>
  <li><a href="http://cylonjs.com/">CyclonJS</a> — JavaScript framework for robotics</li>
  <li><a href="https://github.com/voodootikigod/node-serialport">Serial port</a> — Along with Wi-Fi and BLE, try out interfacing with the <a href="http://www.z-wave.com/modules/ZwaveStart/">Z-Wave</a> and <a href="http://www.zigbee.org/">Zigbee</a></li>
  <li><a href="https://github.com/nonolith/node-usb">USB</a> — communicate with USB devices</li>
</ul>

<figure block="figure">
	<img elem="media" src="/articles/wifi-ble-javascript/img/nodeboats.jpg" alt="" />
	<figcaption elem="caption"><a href="https://twitter.com/shurru">Shurthi</a>, <a href="https://www.facebook.com/media/set/?set=a.615900415180712.1073741830.224477610989663&amp;type=3">NodeBoats workshop</a> facilitator at <a href="http://2014.jsconf.asia/">JS Conf Asia 2014</a>, tracking a participant’s boat controlled with Spark Core, VoodooSpark, Spark-io and Johnny Five.</figcaption>
</figure>

<p>I hope this article gave you not only the initial steps for getting started, but plenty of resource to hack on your own or even get involved with the community! It might be challenging at start, but seeing your code literally come to life in the physical world will be immensely rewarding.</p>

<p>Come and hack away with electronics and JavaScript!</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/ux-accessibility-aria-label/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/ux-accessibility-aria-label/"/><title>UX accessibility with aria-label</title><published>2015-04-09T00:00:00+00:00</published><updated>2015-04-09T00:00:00+00:00</updated><author><name>Heydon Pickering</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<p>WAI-ARIA, the accessibility extension technology for HTML, has a reputation for being complex — if not entirely impenetrable — in its specification.</p>

<p>How WAI-ARIA’s suite of attributes relate to one another, the underlying HTML and the circumstances under which they are set or mutated is not a trivial affair. And that’s before you try to establish the differing interaction conventions of desktop versus web applications or begin to reconcile the notion of interoperable state with your visual design process.</p>

<p>Basically, it’s a big bum ache. An interesting and ennobling bum ache, but a bum ache nonetheless.</p>

<p>However, while integrated WAI-ARIA widgets, which require an exacting deployment of interrelated HTML attributes and key bindings, can be daunting prospects, not all of WAI-ARIA is organized in such a strict fashion. The <code>aria-label</code> attribute, on account of being a <a href="http://www.w3.org/TR/wai-aria/states_and_properties#global_states">global property</a>, can be called upon anywhere in a page, independently of any other WAI-ARIA features, as and when you need it.</p>

<p>As I shall describe, <code>aria-label</code> is a useful tool to ensure a good user experience for assistive technology users, elevating your design from merely technically compliant to well signposted and usable. There’s also more than one “effect” that <code>aria-label</code> can be used to achieve.</p>

<h2 id="the-virtue-of-text">The virtue of text</h2>

<p>Here is a rule of thumb:</p>

<blockquote>
  <p>Whenever you communicate anything on the web not using text, you’re probably doing so inaccessibly</p>
</blockquote>

<p>The Web is a conduit for text and web accessibility is about making sure that text is — really and truly — text. Not pictures of text, but text. It’s not <em>quite</em> that simple because there’s focus management to worry about, but that’s pretty much it.</p>

<ul>
  <li>Text nodes are accessible because they are text</li>
  <li>Semantic HTML elements are accessible because they prompt the interface to announce descriptive text</li>
  <li>WAI-ARIA property and state attributes are a standardized means of supplementing content with qualifying, assistive-technology-announceable… text</li>
</ul>

<p>The <code>aria-label</code> property falls into the third of these three camps.</p>

<p>Why is text so central to accessibility? Because text is highly <em>interoperable</em>. That is, systems of letters can be translated into code points and interpreted by all sorts of different software. Oh and humans understand text already, of course.</p>

<p>Because different machines can all read and write text, information can be interpreted and conveyed to humans in different ways. Primarily visually (in letter forms) but also aurally (as synthesized speech) and even by touch (refreshable Braille displays, for instance).</p>

<h2 id="accessible-names">Accessible names</h2>

<p>HTML elements have roles and names. These are both bits of text. If you were to think of them as people, you could say their role is <em>who they are</em> and their name is <em>what they have to say</em>. Regarding interactive elements like <code>&lt;button&gt;</code>s, names are important because they tell you what the element is for and what it will do. Their role is “button” and their name might be “press me to do x”.</p>

<p>The “button” role piece of text is provided simply by using the <code>&lt;button&gt;</code> element, but the name must be written manually, by the author. The easiest (and best) way to supply a name for an element is to <strong>write some text between the opening and closing tags</strong>, like so:</p>

<pre><code>&lt;button&gt;Launch missile at my own face&lt;/button&gt;
</code></pre>

<p>Text nodes are great because you can read them by looking at them or have them read to you. (Mostly) everyone has access to text nodes.</p>

<p>Astonishingly, some web developers seem to spend a lot of their time trying to avoid using text nodes in their interfaces. To them, using <em>text</em> for the purpose of <em>using text</em> is all too obvious. They like to use vectors, rasters or inexplicable pictograms instead.</p>

<p>It is in this circumstance that someone has to add an <em>accessible name</em> separately.</p>

<h3 id="accessible-name-calculation">Accessible name calculation</h3>

<p>So common is the practice of not using text in <strong>a medium principally designed for the conveyance of text</strong> that, over the years, we have devised a number of ways to add remedial text after a visual design has been “finished”. This adding of an invisible accessible name usually employs one of the following:</p>

<ul>
  <li>The <code>title</code> attribute</li>
  <li>The <code>alt</code> attribute</li>
  <li>The <code>aria-label</code> attribute</li>
  <li>The <code>aria-labelledby</code> attribute</li>
  <li>Some text in a hidden <code>&lt;span&gt;</code> that’s been flung off the side of the screen by an excessive 9 million pixels just in case screen resolutions get so high that this floating bit of text becomes visible to the 8 people who can afford that super-high-resolution model of Apple™ computer.</li>
</ul>

<p>Some of the attributes are <a href="http://blog.silktide.com/2013/01/i-thought-title-text-improved-accessibility-i-was-wrong/">incredibly unreliable</a> (<code>title</code>) and others can only legally — and successfully — be used on certain elements (<code>alt</code>), leaving the two dedicated ARIA attributes <code>aria-label</code> and <code>aria-labelledby</code>.</p>

<p>In <a href="http://www.w3.org/TR/html-aam-1.0/">the calculation</a> of which bit of (remedial) text should take precedence when more than one is present, <code>aria-label</code> and <code>aria-labelledby</code> also rank most highly, overriding the other methods.</p>

<h2 id="providing-an-accessible-name-with-aria-label">Providing an accessible name with <code>aria-label</code></h2>

<p>If no accessible name is available, screen readers try their best to come up with something based on the element and its attributes. This, inevitably, leads to some utterly perplexing results.</p>

<p>Have you observed the habit of using <code>&lt;a&gt;</code> elements as buttons? Then perhaps you’ve seen a spoof <code>href</code> like <code>#</code> here and there?</p>

<pre><code>&lt;a href="#" class="button"&gt;&lt;/a&gt;

.button {
	background-image: url(button-with-fake-text.png);
}
</code></pre>

<p>It may surprise you that when focusing this “button” the screen reader JAWS announces “number link”. Number? Yes, the screen reader, bereft of an accessible name, desperately blurts out the <code>href</code> value, which it interprets as “number” — as in “<a href="https://shop.smashingmagazine.com/apps-for-all-coding-accessible-web-applications.html">the #1 book on web application accessibility</a>”. “Number link”? What on earth does that mean?</p>

<p>The <code>aria-label</code> attribute can be used to easily add a proper name to the element, like so:</p>

<pre><code>&lt;a href="#" class="button" aria-label="Launch missile at my own face"&gt;&lt;/a&gt;
</code></pre>

<p>It’s still the wrong type of element because it’s a link and launching a missile at one’s own face is not a <em>linking action</em>, but at least the name tells you what the interactive element will do. Now screen reader users get the same warning that the button will launch a self destructive missile.</p>

<p>Support for <code>aria-label</code> is also dependable, making our missile warning system still more robust. The ‘aria-label` attribute works across the full gamut of popular browser and screen reader combinations including NVDA, JAWS and VoiceOver paired with Internet Explorer, Firefox, Chrome and others.</p>

<h2 id="providing-better-text-with-aria-label">Providing <em>better</em> text with <code>aria-label</code></h2>

<p>As I already covered, <code>aria-label</code> is favored in accessible name calculation. Apart from <code>aria-labelledby</code>, it will override all additional naming methods. This means you can use it to provide <em>better</em> text for assistive technologies without altering text intended for visual users.</p>

<p>When would you want to do this? There are a couple of scenarios worth considering.</p>

<h3 id="interpreting-icons">Interpreting icons</h3>

<p>It’s rarely wise to rely entirely on icons in your design lexicon. Even those who can actually see the icons are liable to waste valuable time trying to guess what they are supposed to mean. Nonetheless, there are some conventions that are well understood, like the <code>&amp;times;</code> symbol used to denote a close button.</p>

<p>The trouble is, “button multiplication”, “button times” and such are not very helpful labels as substitutes for the visual signifier. So we supply an <code>aria-label</code> to override the text node of <code>&amp;times;</code> without disturbing the actual letterform:</p>

<pre><code>&lt;button aria-label="close"&gt;&amp;times;&lt;/button&gt;
</code></pre>

<p>Now the “accessibility layer” of the interpreted interface includes the instruction to tell assistive technologies to use the “close” name, prompting them to announce “button close” or something similar.</p>

<h3 id="improving-non-visual-context">Improving non-visual context</h3>

<p>It has become popular to use the so-called “hamburger icon” to denote a button that opens a site’s main navigation menu. The <code>≡</code> character used for this purpose is often a unicode character meaning “identical to” in mathematics. Screen readers like NVDA do not understand the symbol so just ignore it (or unhelpfully read out “symbol 8801” in certain modes). JAWS simply says “equals”.</p>

<p><a href="https://lmjabreu.com/post/why-and-how-to-avoid-hamburger-menus/">Myself and others are not convinced</a> that everyone understands even the visual symbol to mean “the main menu of this site” and resolve to add an adjacent “menu” to clarify:</p>

<pre><code>&lt;button&gt;≡ menu&lt;/button&gt;
</code></pre>

<p>Now, when you focus that button using JAWS it will read “button equals menu” which, depending on how you look at it, is either a lie (the button itself is <em>not</em> the menu) or a tautology (“this menu button is the menu button”).</p>

<p>You could use the global <code>aria-hidden</code> property to clear up confusion by eliminating the “equals” announcement:</p>

<pre><code>&lt;button&gt;&lt;span aria-hidden="true"&gt;≡&lt;/span&gt; menu&lt;/button&gt;
</code></pre>

<p>But I prefer to exploit an opportunity to give some extra context:</p>

<pre><code>&lt;button&gt;&lt;span aria-label="site navigation"&gt;≡&lt;/span&gt; menu&lt;/button&gt;
</code></pre>

<p>Because the span has no semantics — no role to be announced — focusing this button would now read “(button) site navigation menu” as a seamless run of speech.</p>

<p>If the design is successful, the position of the button in the visual layout and the use of the <code>≡</code> symbol already imply that this particular menu is the site’s navigation menu. We’ve now made this context explicit in a paradigm where visual clues cannot be relied upon. This is the essence of accessible User Experience Design.</p>

<h2 id="adding-context-using-containers">Adding context using containers</h2>

<p>In the last two examples, we exploited <code>aria-label</code>’s ability to override text nodes, but there is a way to provide contextual information via <code>aria-label</code> while preserving the text node of the focused element. This is by supplying an <code>aria-label</code> to a parent (container) element.</p>

<h3 id="multiple-navigation-landmarks">Multiple navigation landmarks</h3>

<p>The navigation landmark (<code>role="navigation"</code> in ARIA speak or <code>&lt;nav&gt;</code> in basic HTML) is most frequently used just once per page, to denote the site’s main navigation. It’s what would hide behind the hamburger icon, if you will.</p>

<p>However, as <a href="http://www.w3.org/WAI/PF/aria/20091214/roles#navigation">the spec’ suggests</a>, navigation landmarks can be used <em>“for navigating the document or related documents”</em>.</p>

<p>Why not both? Why indeed. You could have a navigation landmark to navigate between pages and one to navigate around the current page. The trick is in differentiating the two upon entering either landmark. This is where <code>aria-label</code> comes in once again.</p>

<p>Consider these two, complementary navigation landmarks, one for the site and the other for just the about page:</p>

<pre><code>&lt;nav role="navigation" aria-label="Site"&gt;
	&lt;ul&gt;
		&lt;li&gt;&lt;a href="/"&gt;Home&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/about"&gt;About&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/blog"&gt;Blog&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/contact"&gt;Contact&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;
&lt;/nav&gt;

&lt;nav role="navigation" aria-label="About page"&gt;
	&lt;ul&gt;
		&lt;li&gt;&lt;a href="#intro"&gt;Introduction&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="#what-I-do"&gt;What I do&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="#testimonials"&gt;Testimonials&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="#get-a-quote"&gt;Get a quote&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;
&lt;/nav&gt;
</code></pre>

<p>When navigating by keyboard and entering one of these landmarks, you will focus the first of the links provided. But it’s not just the link role and its name that will be announced. The landmark will also be identified, as well as the existence of the list (handy for informing the user that there are multiple links).</p>

<p>In our case, the label will be prepended to the announcement as well, telling the user what sort of navigation landmark they are in. Each of these little bits of information helps to paint a clearer picture of the interface in hand.</p>

<p>So, when the user focuses the first of the links in the “site” navigation landmark, the NVDA screen reader — for example — will announce <em>“site navigation landmark, list of four items, home link.”</em> By the same token, when the “about page” landmark is entered the output is <em>“about page navigation landmark, list of four items, introduction same page link.”</em> (Note how the <code>#</code> in the about page links’ <code>href</code>s prompts the NVDA reader to clarify that the link is to a location on that same page.)</p>

<h2 id="conclusion">Conclusion</h2>

<p>In that final example, a number of techniques — ARIA role deployment, accessible naming, semantic HTML and known AT convention — were combined to make the interface clearer and therefore provide a better experience for the user. But, in effect, we were just composing a sentence, piece by piece. The introduction of <code>aria-label</code> to that sentence improves the UX by labelling that part of the interface.</p>

<p>WAI-ARIA is not intended to affect the behavior of HTML interfaces. In ARIA widgets like tab interfaces, it’s the JavaScript that actually changes the state of the widget as you use it. Behavior is a part of UX, of course, but its much the same whether you are using the interface visually, aurally or both at the same time.</p>

<p>A state change is a state change. But it’s with the provision of text, labels, <em>words</em> that the nature and the state of an interface can be made accessible. It’s worth bearing that in mind when you embark on designing more complex ARIA-based patterns. Hopefully, things will fall into place more easily.</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/media-features/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/media-features/"/><title>Interaction Media Features and their potential (for incorrect assumptions)</title><published>2015-03-23T00:00:00+00:00</published><updated>2015-03-23T00:00:00+00:00</updated><author><name>Patrick H. Lauke</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<p>The <a href="http://dev.w3.org/csswg/mediaqueries-4/#mf-interaction">Media Queries Level 4 Interaction Media Features</a> — <code>pointer</code>, <code>hover</code> and the more recent <code>any-pointer</code> and <code>any-hover</code> — are meant to allow sites to implement different styles and functionality (either CSS-specific interactivity like <code>:hover</code>, or even JavaScript behaviours, when queried using <code>window.matchMedia</code>), depending on the particular characteristics of a user’s input modalities.</p>

<p><strong>Note:</strong> the <a href="http://dev.w3.org/csswg/mediaqueries-4/#mf-interaction">Media Queries Level 4 Interaction Media Features</a> are still at the Working Draft stage, so some of the wording/functionality – as well as the way in which it is implemented in browsers – may still change before they become stable recommendations. This article is based on the specification’s <em>Editor’s Draft, 24 March 2015</em>.</p>

<p>Common use cases cited for interaction media features are often “make controls bigger/smaller depending on whether the users has a touchscreen device or is using a mouse/stylus” and “only use a CSS dropdown menu if the user has an input that allows <code>:hover</code>-based interactions”.</p>

<figure block="figure">

  <figcaption elem="caption">
	Some classic use cases for <code>pointer</code> or <code>hover</code>
</figcaption>

  <pre><code>@media (pointer:fine) {
	/* ok to use small buttons/controls */
}

@media (hover:hover) {
	/* ok to use :hover-based menus */
}

@media (pointer:coarse) {
	/* make buttons and other “touch targets” bigger */
}

@media (hover:none), (hover:on-demand) {
	/* suppress :hover-based menus */
}
</code></pre>

</figure>

<h2 id="whats-the-primary-input">What’s the <em>primary</em> input?</h2>

<p>One of the problems with <code>pointer</code> and <code>hover</code> is that, by design, they only expose the characteristics of what a browser deems to be the <em>primary</em> input device – and current browser implementations may, in some cases, not be as smart as they should in making this assessment, since what constitutes a primary input may not always be obvious.</p>

<p>Traditionally, we could say that a phone/tablet’s primary input is the touchscreen. But on desktop/laptop devices, any hard distinction already becomes blurry: these devices usually have both a keyboard and mouse/trackpad. What is the <em>primary</em> input in this case? Currently, browsers make the assumption that in these situations, it’s the mouse/trackpad. But what if I’m actually a user who navigates only using the keyboard (which, depending on how things are coded, can be considered a <code>pointer:fine</code> — for focusable elements like links and buttons — or <code>pointer:none</code> device — in the case of custom interfaces, reliant on JavaScript events with coordinates, such as a <code>&lt;canvas&gt;</code> — lacking <code>:hover</code>)? This particular case is (sort of) acknowledged in the spec:</p>

<blockquote>
  <p>For accessibility reasons, even on devices whose pointing device can be described as fine, the UA may give a value of coarse or none to this media query, to indicate that the user has difficulties manipulating the input device accurately or at all.</p>
</blockquote>

<p>At the time of writing, there are no options in browsers/UAs that let a user explicitly say “I’m a keyboard user” (let’s not even mention the “I’m a user with reduced mobility” scenario, where a user may in fact be using a mouse/trackpad — or even an alternative input method such as a head wand, or a virtual mouse, which translates back to actual mouse inputs — but with great difficulty and reduced accuracy).</p>

<p>Beyond the accessibility angle, there are further issues with the concept of <em>primary</em> inputs. What about devices like a Microsoft Surface, with a touchscreen, stylus and (with addition of a type cover) a trackpad and keyboard? Arguably, these devices blur the definition of <em>primary</em> input completely (though there is potential here for browsers to implement heuristics — consider Windows 10’s ability to switch to “Tablet mode”, which browsers could take as indication to treat any available touchscreen as primary).</p>

<p><strong>Note:</strong> For a similar take on this problem, see <a href="http://www.stucox.com/blog/the-good-and-bad-of-level-4-media-queries/">Stu Cox: The Good &amp; Bad of Level 4 Media Queries</a>, although his post refers to an earlier iteration of the spec, which only contained <code>pointer</code> and <code>hover</code> and a requirement for these features to report the <em>least capable</em>, rather than the <em>primary</em>, input device.</p>

<p>So, right out of the gate, the fact that <code>pointer</code> and <code>hover</code> only relate to what the browser believes to be the <em>primary</em> input may lead to wrong results on devices with potentially two or more different primary inputs.</p>

<p>Fundamentally then, the problem with the original <code>pointer</code> and <code>hover</code> is that they don’t always adequately cover multi-input scenarios, and rely on the browser to be able to be able to correctly pick a single <em>primary</em> input. A user may for instance have paired a bluetooth mouse to their phone/tablet — suddenly, instead of a pointing device with <code>pointer:coarse</code> and <code>hover:none</code>, they have an additional <code>pointer:fine</code>, <code>hover:hover</code> capable one. But in all current implementations, browsers will still regard the touchscreen as the <em>primary</em> input. If a web developer relies purely on <code>pointer</code> and <code>hover</code> to add specific styling or functionality, no extra media queries based on these capabilities would kick in.</p>

<figure block="figure">

  <table>
    <thead>
      <tr>
        <th>feature</th>
        <th>touchscreen</th>
        <th>touchscreen + mouse</th>
        <th>desktop/laptop</th>
        <th>desktop/laptop + touchscreen</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><code>pointer:none</code></td>
        <td>false</td>
        <td>false</td>
        <td>false</td>
        <td>false</td>
      </tr>
      <tr>
        <td><code>pointer:coarse</code></td>
        <td><strong>true</strong></td>
        <td><strong>true</strong></td>
        <td>false</td>
        <td>false</td>
      </tr>
      <tr>
        <td><code>pointer:fine</code></td>
        <td>false</td>
        <td>false</td>
        <td><strong>true</strong></td>
        <td><strong>true</strong></td>
      </tr>
      <tr>
        <td><code>hover:none</code></td>
        <td>false</td>
        <td>false</td>
        <td>false</td>
        <td>false</td>
      </tr>
      <tr>
        <td><code>hover:on-demand</code></td>
        <td><strong>true</strong></td>
        <td><strong>true</strong></td>
        <td>false</td>
        <td>false</td>
      </tr>
      <tr>
        <td><code>hover:hover</code></td>
        <td>false</td>
        <td>false</td>
        <td><strong>true</strong></td>
        <td><strong>true</strong></td>
      </tr>
    </tbody>
  </table>

</figure>

<p><strong>Note:</strong> from my (admittedly limited to Android/Blink) testing, it seems that on touchscreen devices, <code>hover:on-demand</code>, rather than <code>hover:none</code>, returns true — probably a conscious decision on the part of Blink, related to the fact that <code>:hover</code> (and even compatibility mouse events like <code>mouseover</code>) can be triggered by a touchscreen “tap”.</p>

<p>That’s where <code>any-pointer</code> and <code>any-hover</code> are supposed to come into play.</p>

<h2 id="testing-the-capabilities-of-all-inputs">Testing the capabilities of all inputs</h2>

<p>Instead of focusing purely on the <em>primary</em> input, <code>any-pointer</code> and <code>any-hover</code> report the capabilities of <em>all</em> available inputs. Going back to the original use cases for the interaction media features, instead of basing our decision to provide larger/smaller inputs or to enable/disable <code>:hover</code>-based functionality only on the characteristics of the <em>primary</em> input, we can make that decision based on the characteristics of <em>any</em> available inputs. Roughly translated, instead of saying “only offer a CSS menu if the primary input has <code>hover:hover</code>”, we can build media queries that equate to “only offer a <code>:hover</code> based menu if at least one of the inputs available to the user has <code>hover:hover</code> capability”.</p>

<p>Per the specification, user agents should re-evaluate media queries in response to changes in the user environment. Once properly implemented, the <code>any-pointer</code> and <code>any-hover</code> interaction media features will change dynamically when inputs are added/removed — so a site/app could immediately react to, say, a mouse being paired with a touchscreen device.</p>

<p><strong>Note:</strong> in Chrome’s current implementation, the values for these media features are not updated dynamically, and even remain the same after a refresh — see my video <a href="https://www.youtube.com/watch?v=nAh80QI8vlI">Chrome 42 Beta: any-pointer/any-hover MQ feature issue</a> and the related Chromium bug <a href="https://code.google.com/p/chromium/issues/detail?id=442418">Issue 442418: Support dynamic values for interaction media queries</a>.</p>

<p>In order to support multi-input scenarios, where different inputs may have different characteristics, in the case of <code>any-pointer</code> and <code>any-hover</code></p>

<blockquote>
  <p>more than one of their values can match, if different input devices have different characteristics</p>
</blockquote>

<p>(compared to <code>pointer</code> and <code>hover</code>, which only ever refer to the capabilities of the <em>primary</em> input). In current implementations, these media features evaluate as follows:</p>

<figure block="figure">

  <table>
    <thead>
      <tr>
        <th>feature</th>
        <th>touchscreen</th>
        <th>touchscreen + mouse</th>
        <th>desktop/laptop</th>
        <th>desktop/laptop + touchscreen</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><code>any-pointer:none</code></td>
        <td>false</td>
        <td>false</td>
        <td>false</td>
        <td>false</td>
      </tr>
      <tr>
        <td><code>any-pointer:coarse</code></td>
        <td><strong>true</strong></td>
        <td><strong>true</strong></td>
        <td>false</td>
        <td><strong>true</strong></td>
      </tr>
      <tr>
        <td><code>any-pointer:fine</code></td>
        <td>false</td>
        <td><strong>true</strong></td>
        <td><strong>true</strong></td>
        <td><strong>true</strong></td>
      </tr>
      <tr>
        <td><code>any-hover:none</code></td>
        <td>false</td>
        <td>false</td>
        <td>false</td>
        <td>false</td>
      </tr>
      <tr>
        <td><code>any-hover:on-demand</code></td>
        <td><strong>true</strong></td>
        <td><strong>true</strong></td>
        <td>false</td>
        <td><strong>true</strong></td>
      </tr>
      <tr>
        <td><code>any-hover:hover</code></td>
        <td>false</td>
        <td><strong>true</strong></td>
        <td><strong>true</strong></td>
        <td><strong>true</strong></td>
      </tr>
    </tbody>
  </table>

</figure>

<figure block="figure" mod="right">
	<img elem="media" mod="half" src="/articles/media-features/android-touchscreen-mouse.png" alt="Interaction Media Features in Opera on an Android phone with paired bluetooth mouse" />
	<figcaption elem="caption">Interaction Media Features in Opera on an Android phone with paired bluetooth mouse</figcaption>
</figure>

<p><strong>Note:</strong> you can <a href="http://patrickhlauke.github.io/touch/pointer-hover-any-pointer-any-hover/">see how the interactive media features are evaluated</a> on your specific device. Currently, interaction media features are supported in Blink (since M-21 for <code>pointer</code>/<code>hover</code>, although it was somewhat broken until M-41 — <a href="https://code.google.com/p/chromium/issues/detail?id=123062">Issue 123062: Support pointer and hover CSS media features for touch screens</a> and <a href="https://code.google.com/p/chromium/issues/detail?id=441613">Issue 441613: @media (hover: none) should be false on a traditional desktop/laptop computer</a> — and M-41 for <code>any-pointer</code>/<code>any-hover</code> — <a href="https://code.google.com/p/chromium/issues/detail?id=398943">Issue 398943: Ship <code>any-pointer</code> and <code>any-hover</code> Media Queries</a>) and the preview release of Internet Explorer/Spartan (<a href="https://status.modern.ie/mediaquerieslevel4interactionmediafeaturespointerandhover">status.modern.ie</a>). Safari should have support for these soon (<a href="http://trac.webkit.org/changeset/179055">Changeset 179055</a>). There does not appear to be any movement on implementing these features in Firefox yet.</p>

<h2 id="potential-for-incorrect-assumptions">Potential for incorrect assumptions</h2>

<p>Certainly, it’s valuable for a developer to be able to know the characteristics of <em>any</em> input device that the user has at their disposal. However, as with similar feature detection methods, developers need to be aware of what exactly they’re detecting (in a similar way to the problem I outlined in my article on <a href="https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how/">Detecting touch: it’s the “why”, not the “how”</a>) and to understand the fundamental limitations of the current approach: that in many cases, it doesn’t matter so much what inputs (and their specific characteristics) are <em>potentially</em> available to a user — what matters, in my opinion at least, is what input the user is using <em>right now</em>.</p>

<p>Take the example of a phone/tablet with a paired mouse: <code>any-hover:hover</code> will be true, as there is a hover-capable input present — but does that mean that we can now rely on hover-based functionality? What if the user, regardless of the mouse, is still using the touchscreen?</p>

<figure block="figure">

  <figcaption elem="caption">
	Assumptions based on <code>any-pointer</code> or <code>any-hover</code>
</figcaption>

  <pre><code>@media (any-pointer:fine) and (any-hover:hover) {
	/* at least one device is mouse-like…
	we can use small buttons and :hover-based menus, right?
	what if they’re using a touchscreen… */
}
</code></pre>

</figure>

<h2 id="targeting-the-least-capable-input">Targeting the least capable input</h2>

<p>Since we cannot know for sure which input is currently being used, I would suggest that <code>any-pointer</code> and <code>any-hover</code> are most valuable for checking the <em>lowest common denominator</em>, the least “capable” input. In the example of the phone/tablet with a paired mouse, we’d still only be able to use the information provided by <code>any-pointer</code> and <code>any-hover</code> to determine that yes, even though there are different inputs available, one of them is still coarse and does not support hover.</p>

<figure block="figure">

  <figcaption elem="caption">
	Use <code>any-pointer</code> or <code>any-hover</code> for lowest common denominator
</figcaption>

  <pre><code>@media (any-pointer:coarse) {
	/* at least one input is “coarse”
	make buttons and other “touch targets” bigger */
}

@media (any-hover:none), (any-hover:on-demand) {
	/* at least one input has no or (usually clunky)
	“on-demand” hover suppress :hover-based menus */
}
</code></pre>

</figure>

<p>Instead of testing for the presence of a particular capability, we could of course test for the <em>absence</em> of less capable inputs, and suppress styles that would otherwise be needed if those limited input types were present. However, the limited way in which the logical <code>not</code> works in <a href="http://www.w3.org/TR/css3-mediaqueries/#media0">Media Queries Level 3</a> (which don’t support chaining multiple tests together with a comma — the logical <code>or</code> — and negating the whole resulting expression) makes this unnecessarily cumbersome, since we can effectively only test for the absence of <em>one</em> of the values at a time:</p>

<figure block="figure">

  <figcaption elem="caption">
	Explicitly test for absence of “less capable” inputs
</figcaption>

  <pre><code>@media not all and (any-pointer:coarse) {
	/* no inputs are “coarse”
	they may be “fine” or “none” */
}

@media not all and (any-hover:on-demand) {
	/* no input with “on-demand” hover is present
	they either have “hover” or “none” */
}

@media not all and (any-hover:none) {
	/* no input without hover is present
	they either have “hover” or “on-demand” */
}
</code></pre>

</figure>

<p><strong>Note:</strong> normally, the <code>all and</code> part would be superfluous, but it seems that in many current browser implementations, <code>not</code> only works correctly with an explicit media type as part of the query.</p>

<p>We could try to work around the limitations of <code>not</code> by using <a href="http://www.w3.org/TR/css3-conditional/#contents-of">nested <code>@media</code> blocks</a>, but this further increases complexity and has the potential for cross-browser incompatibilities at this point:</p>

<figure block="figure">

  <figcaption elem="caption">
	Nested <code>@media</code> queries
</figcaption>

  <pre><code>@media not all and (any-hover:none) {
	@media not all and (any-hover:on-demand) {
		/* neither “none” nor “on-demand” hover inputs are present
		meaning all inputs have `hover:hover`
		safe to use hover-based features?
		still does not identify keyboard users at the moment */
	}
}
</code></pre>

</figure>

<p>Lastly, we could wait for the “full boolean algebra” approach of <a href="http://dev.w3.org/csswg/mediaqueries-4/#media-conditions">Media Queries Level 4 media conditions</a> — but this is not currently supported in any browser:</p>

<figure block="figure">

  <figcaption elem="caption">
	MQ Level 4 full boolean algebra media condition
</figcaption>

  <pre><code>@media not ((any-pointer:none) or (any-pointer:on-demand)) {
	/* as above, but far more readable
	sadly, not supported in any browser yet */
}
</code></pre>

</figure>

<p>Regardless of which specific approach we opt for, in the end, we can use <code>any-pointer</code> and <code>any-hover</code> to find our baseline for the least capable input, rather than trying to determine the most capable one.</p>

<h2 id="query-responsibly">Query responsibly</h2>

<p>For me, the take-away from all this is: <code>pointer</code> and <code>hover</code> tell you about the capabilities of whatever the browser/UA determines to be the primary device. In current implementations this information is mostly useless, as there may be additional input methods, and the browser may have made assumptions which are not correct. <code>any-pointer</code> and <code>any-hover</code> tell you about the capabilities of all connected inputs, and with some degree of media query acrobatics we can even narrow down the overall range of potential capabilities available. But none of these tell you specifically about the capabilities of the input device your user is using <em>right now</em> — and of course, you can only know what specific input a user will be using once they already started an interaction, at which point it’s likely too late to switch around style or functionality.</p>

<p>By all means, you can start using <a href="http://dev.w3.org/csswg/mediaqueries-4/#mf-interaction">Media Queries Level 4 Interaction Media Features</a> to make your site respond to different input device capabilities — but beware false assumptions about what these media features actually tell you, particularly in current browser implementations. Or keep it simple: design for all types of input and/or offer the user an explicit way to switch to their preferred mode.</p>

<p>(With thanks to <a href="https://twitter.com/StuCoxMedia">Stu Cox</a> and <a href="https://twitter.com/frivoal">Florian Rivoal</a> for their invaluable feedback on the early stages of this article)</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/state-of-web-type/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/state-of-web-type/"/><title>The State of Web Type</title><published>2015-03-03T00:00:00+00:00</published><updated>2015-03-03T00:00:00+00:00</updated><author><name>Bram Stein</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<p>Typography has a long and rich history, but much has been lost in the transition to the web. While browser support for typography has advanced a lot in the last couple years, we still have a long way to go. Features print designers take for granted are either nonexistent on the web or have insufficient browser support in order to be useful. Challenges unique to web browsers such as responsive design and web font loading could use some improvement as well. Let’s take a look at some of the features we need for an optimal and beautiful reading experience.</p>

<h2 id="opentype-features">OpenType Features</h2>

<p>Typeface designers often put extra features in a font that can be used to customise text rendering. These are called OpenType features and include character spacing, alignment, ligatures, alternative characters, and so on. There are in fact <a href="https://www.microsoft.com/typography/otspec/featurelist.htm">more than 140 registered OpenType features</a>. Many of these features are optional, but some are actually required to properly render text (e.g. kerning and required ligatures). OpenType features are reasonably well supported by modern web browsers, but still come with a lot of caveats that make them hard to use.</p>

<figure block="figure">
	<img elem="media" src="/articles/state-of-web-type/figure-2.png" alt="" />
	<figcaption elem="caption">From left to right: contextual alternates set in Caflisch Script Pro, ligatures set in Warnock Pro, and small caps set in Chaparral Pro.</figcaption>
</figure>

<p>An important caveat is that not all fonts include all 140+ OpenType features. Most fonts only contain a small subset of features, such as kerning and ligatures. Others may include discretionary features, such as swashes and alternate characters. With the proliferation of web font and subsetting services we can’t always rely on information about OpenType features and character support provided by typeface designers. We need better tools to look inside our font files to see which features and characters are supported and which are not.</p>

<p>If a font includes the features you wish to use, you still need to check if your target browsers support OpenType features. While most modern browsers support either the low-level <code>font-feature-settings</code> syntax or the high level <code>font-variant-*</code> syntax, there are still several browsers in common use that don’t support either syntax. Notable examples are Internet Explorer versions 6 to 9 and all versions of Android WebKit until 4.4. Fortunately, the fallback behaviour for most OpenType features is graceful: text is still readable without them.</p>

<figure block="figure">

  <table>
    <thead>
      <tr>
        <th>Feature</th>
        <th>IE10</th>
        <th>IE11</th>
        <th>Chrome</th>
        <th>Firefox</th>
        <th>Safari</th>
        <th>Opera</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><code>font-feature-settings</code></td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>No</td>
        <td>Yes</td>
      </tr>
      <tr>
        <td>Ligatures (<code>liga</code>)</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
      </tr>
      <tr>
        <td>Swashes (<code>swsh</code>)</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>No</td>
        <td>Yes</td>
      </tr>
      <tr>
        <td>Old style numerals (<code>onum</code>)</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>No</td>
        <td>Yes</td>
      </tr>
      <tr>
        <td>Contextual alternates (<code>calt</code>)</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
      </tr>
      <tr>
        <td>Small caps (<code>smcp</code>)</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>No</td>
        <td>Yes</td>
      </tr>
    </tbody>
  </table>

</figure>

<p>The above table summarizes browser support for the <code>font-feature-settings</code> property and a select number of OpenType features. You can find more browser <a href="http://stateofwebtype.com/#opentype%20features">support data for common OpenType features on the State of Web Type</a>.</p>

<p>Unfortunately, even if a browser supports the OpenType feature syntax it is not always guaranteed that it will support all individual features. A good (or rather bad) example is Safari which technically supports the <code>font-feature-settings</code> syntax, but ignores any value. Instead it explicitly enables a select number of features which you have no way of turning off.</p>

<h2 id="justification--hyphenation">Justification &amp; Hyphenation</h2>

<p>Many web developers think of justification as a solved problem (or worse, one to avoid). Set <code>text-align</code> to <code>justify</code> and you’re done, right? Not quite. The algorithm used in all web browsers is actually a very ineffective justification implementation. Tools like TeX and InDesign use a more sophisticated line breaking algorithm that optimises break points over an entire paragraph, whereas browsers only look at a single line. This leads to suboptimal justification and large spaces between words.</p>

<figure block="figure">
	<img elem="media" src="/articles/state-of-web-type/figure-3.png" alt="" />
	<figcaption elem="caption">Left: a justified paragraph, middle: extraneous word spaces are highlighted, right: word spacing and justification is improved by enabling hyphenation.</figcaption>
</figure>

<p>Browsers could implement the same line breaking algorithm as used in TeX, but have decided not to for performance reasons. This is an odd reason — TeX was developed and runs on computers much less powerful than those commonly used in mobile phones. Another way to improve poor line breaking is by hyphenating words. This introduces more potential line break points and reduces the chance of awkward line breaks. A common misunderstanding is that hyphenation is only useful for justified text. This is not true. Hyphenation is also a useful tool to control the raggedness of center, left, and right aligned text. The CSS <code>hyphens</code> property can be used to control hyphenation. Setting it to <code>auto</code> will enable hyphenation (provided the document or element specifies a language using the <code>lang</code> attribute), while setting it to <code>none</code> disables hyphenation.</p>

<figure block="figure">

  <table>
    <thead>
      <tr>
        <th>IE8</th>
        <th>IE9</th>
        <th>IE10</th>
        <th>IE11</th>
        <th>Chrome</th>
        <th>Firefox</th>
        <th>Safari</th>
        <th>Opera</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>No</td>
        <td>No</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>No</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>No</td>
      </tr>
    </tbody>
  </table>

</figure>

<p>The <a href="http://stateofwebtype.com/#hyphens"><code>hyphens</code> property is supported by almost all modern browsers</a> except those based on the Blink rendering engine. Chrome and Opera previously supported the <code>hyphens</code> syntax but neither browser shipped with hyphenation dictionaries. In a surprising move they recently dropped support for the <code>hyphens</code> syntax completely. The Blink developers decided to <a href="https://groups.google.com/a/chromium.org/d/topic/blink-dev/STiDJjDwVF8/discussion">remove the <code>hyphens</code> property</a> because it was never fully implemented and broke feature detection. While such regressions are not common, they are worrisome. A feature required for correct text layout should be supported everywhere. So, for now, you’ll need to rely on either server-side hyphenation or one of the two client-side hyphenation libraries: <a href="https://github.com/bramstein/hypher">Hypher</a> and <a href="https://code.google.com/p/hyphenator/">Hyphenator</a>.</p>

<h2 id="font-loading">Font Loading</h2>

<p>Web font usage has increased significantly in the past couple years. This is great news. However, it also means that web fonts have become a critical part of web sites and, by extension, a performance bottleneck. You may have experienced the dreaded Flash Of Invisible Text (FOIT) while visiting a website on a slow network connection. The decision by some browsers to block rendering of text until web fonts have downloaded is opposite to the tenets of progressive enhancement. Content should come first and web fonts are an enhancement. After all, you can still read the text, even though it might not render in the intended font (well, unless your browser hides text while it is downloading fonts — better pray it uses a timeout).</p>

<p>Not all browsers hide text while downloading web fonts. For example Internet Explorer always renders text in a fallback font while it is downloading fonts. This has been dubbed the Flash Of Unstyled Text (FOUT). This is a misnomer. The FOUT is a feature and a condition everyone should anticipate and design for. Selecting and testing fallback fonts is an important task while designing and building a site.</p>

<figure block="figure">

  <table>
    <thead>
      <tr>
        <th> </th>
        <th>IE9</th>
        <th>IE10</th>
        <th>IE11</th>
        <th>Chrome</th>
        <th>Firefox</th>
        <th>Safari</th>
        <th>Opera</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>font rendering</td>
        <td>FOUT</td>
        <td>FOUT</td>
        <td>FOUT</td>
        <td>FOIT</td>
        <td>FOIT</td>
        <td>FOIT</td>
        <td>FOIT</td>
      </tr>
      <tr>
        <td>timeout</td>
        <td>n/a</td>
        <td>n/a</td>
        <td>n/a</td>
        <td>3 sec.</td>
        <td>3 sec.</td>
        <td>∞</td>
        <td>3 sec.</td>
      </tr>
    </tbody>
  </table>

</figure>

<p>The above table shows the usage of the FOUT and FOIT across browsers. Note that Safari (and older Android WebKit versions) do not have a timeout. On these browsers, text won’t render until fonts have completely loaded.</p>

<p>Browser vendors are working on a proposal for a new CSS property to control font loading and rendering. It is meant to give developers more control over the blocking and swapping behaviour of web fonts. The <a href="https://tabatkins.github.io/specs/css-font-rendering/">proposed <code>font-rendering</code> property</a> accepts three parameters:</p>

<ul>
  <li><code>block</code>: block rendering of the text while fonts are downloading with an optional timeout;</li>
  <li><code>swap</code>: use a fallback font and render the font when it becomes available with an optional timeout;</li>
  <li><code>optional</code>: use the font if it is cached and otherwise use the fallback font. Do not re-render the page, even if the web font becomes available at a later time.</li>
</ul>

<p>These parameters can also be used to develop custom font loading schemes. For example, for an important and fast loading font we can block text rendering for <code>1s</code>. If the font doesn’t load within that time we can allow up to 10 seconds where it is acceptable to re-render the page.</p>

<pre><code>font-rendering: block 1s swap 10s;
</code></pre>

<p>Browsers should standardize the default font loading behaviour once the <code>font-rendering</code> property is implemented. Ideally the default value should be <code>block 0s swap infinite</code> as used by Internet Explorer (i.e. the Flash of Unstyled Text). Blocking text rendering while loading fonts should be opt-in and not a default. Browser should treat web fonts as progressive enhancement by default and make content available as soon as possible. Opting out of that behaviour is the responsibility of a web developer and not the browser.</p>

<p>Until the <code>font-rendering</code> property is implemented we can use the <a href="https://dev.opera.com/articles/better-font-face/">CSS Font Loading API</a> to implement the same behaviour in JavaScript. The Font Loading API is supported by Chrome, Opera, and soon Firefox. There is also a <a href="https://github.com/bramstein/fontloader">Font Loading API polyfill</a> for browsers that do not support it natively.</p>

<h2 id="looking-to-the-future">Looking to the Future</h2>

<p>This is just the tip of the iceberg. To compete with and surpass the typographic quality of print publications we need support for drop caps, colour fonts, advanced layout (akin to shapes, exclusions and regions), sizing text to fit a container, widows and orphans, balanced text, math typesetting (though MathML is now an officially recommended standard, <a href="https://www.chromestatus.com/features/5240822173794304">Chromium</a> and <a href="https://status.modern.ie/mathml">Internet Explorer</a> have no plans to support it), and so on. Clearly, we need to do better and push browser vendors for these features if we want to improve the web’s reading experience. You can help out by participating in the W3C mailing lists, building demos, implementing polyfills and drafting specifications for features <em>you</em> want to see. Don’t worry about getting it right the first time. Sometimes the best thing to come out of a specification is a new and better specification.</p>

<figure block="figure">
	<a href="http://stateofwebtype.com/"><img elem="media" src="/articles/state-of-web-type/figure-1.png" alt="" /></a>
</figure>

<p>Another way to contribute is to draw attention to partially implemented specifications and bugs by keeping track of what works and what doesn’t. That’s why I recently launched a new project called the <a href="http://stateofwebtype.com/">State of Web Type</a>. Its goal is to contain up to date browser support data for all type and typography features on the web. The project is <a href="https://github.com/bramstein/stateofwebtype">open source</a> and contributions and corrections are more than welcome. Let’s work together to make the web a better platform for publishing and reading!</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/web-notifications-pubnub/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/web-notifications-pubnub/"/><title>Working with Web Notifications using PubNub’s Realtime Data Stream</title><published>2015-02-24T00:00:00+00:00</published><updated>2015-02-24T00:00:00+00:00</updated><author><name>Tomomi Imura</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<p>Notifications are a great way for apps to indicate that they have something to tell you, for example, that you’ve received a new Twitter message.</p>

<p>The <a href="http://www.w3.org/TR/notifications/">W3C Web Notifications API</a> allows your web browser to display notifications as well: it is a great way to engage with your users because these notifications can be displayed even when the page is not active — note however that the page must be opened in a background tab for the notification to be triggered. The W3C doesn’t specify how notifications should look, so Opera has chosen to use native notifications so that your browser feels completely integrated with your operating system.</p>

<figure block="figure">
	<img elem="media" src="/articles/web-notifications-pubnub/web-notification-screen.png" alt="" />
</figure>

<p>Web Notifications have been supported by Opera since version 25. The article <a href="https://dev.opera.com/blog/web-notifications-in-opera-developer-25/">Web Notifications in Opera Developer 25</a> describes the basic use of the API.</p>

<p>Today, I am going to show you how to use Web Notifications by creating an interactive multi-user app using PubNub’s realtime data stream JavaScript APIs.</p>

<h2 id="what-is-the-pubnub-data-stream-network">What is the PubNub Data Stream Network?</h2>

<p><a href="http://www.pubnub.com">PubNub</a> is a secure global Data Stream Network that enables developers to build, scale, and manage realtime functionality for their applications and <abbr title="Internet of Things">IoT</abbr> devices. It uses a publish/subscribe model, and its APIs are straightforward to use. (Full disclosure: I work for PubNub)</p>

<figure block="figure">
	<img elem="media" src="/articles/web-notifications-pubnub/pubnub-publish-subscribe-paradigms.png" alt="" />
	<figcaption elem="caption">Common publish/subscribe messaging paradigms</figcaption>
</figure>

<h2 id="what-well-be-building">What we’ll be building</h2>

<p>For this article, I made an alternative version of the “Yo” app, which allows you to send the message “Yo” to your friends. With the <a href="http://pubnub.github.io/oi-web-notifications/">“Oi” web app</a>, instead of sending a message to your friends, you can send “Oi” to strangers online.</p>

<p>Let’s get started!</p>

<h2 id="checking-for-api-support">Checking for API support</h2>

<p>The first step is checking if the Web Notifications API is supported by the user’s browser. This feature detection step is good practice and currently needed since <a href="http://caniuse.com/#feat=notifications">not all browsers support the API</a> yet.</p>

<p>For this exercise, let’s just simply terminate the app when the browser doesn’t support the API, since this app is useless without notification capability. When you’re building a real web app, you should of course try to provide a nice fallback for an optimal user experience.</p>

<pre><code>if (!window.Notification) {
	alert('Oops, your browser does not support the Web Notifications API!');
} else {
	// Go ahead and use the Web Notification API.
}
</code></pre>

<h2 id="requesting-permission">Requesting permission</h2>

<p>Each browser provides a built-in permission UI for the Web Notification API, so that you can control which web pages can send you notifications. When your page is loaded for the first time, a browser-specific permission dialog is shown to the user. After the user has granted permission, your page can send notifications, otherwise (denied), it can’t.</p>

<figure block="figure">
	<img elem="media" src="/articles/web-notifications-pubnub/web-notification-permission.png" alt="" />
</figure>

<pre><code>Notification.requestPermission(function() {
	if (Notification.permission === 'granted') {
		// Now your page can send the user notifications!
	}
});
</code></pre>

<p>Try for yourself and see. You can always reset the permission setting by going to opera://settings, selecting Websites from the left column, and scrolling down to the Notifications section.</p>

<figure block="figure">
	<img elem="media" src="/articles/web-notifications-pubnub/web-notification-permission-preference.gif" alt="" />
</figure>

<h2 id="connecting-users-using-pubnub-data-stream">Connecting users using PubNub Data Stream</h2>

<p>Once the user has granted permission, the next interaction you expect is that they enter a name in order to get started.</p>

<pre><code>&lt;input type="text" placeholder="Type your name to start" autofocus&gt;
</code></pre>

<p>When the user enters a name, then hits the return key (we’re listening for a keyup event with a <code>keyCode === 13</code>), we send the username to the PubNub stream to register the user.</p>

<pre><code>document.querySelector('[type="text"]').addEventListener('keyup', function(event) {
	if (event.keyCode !== 13) return;
	if (!input.value) return;
	username = input.value;
	// Connect PubNub and register the user …
});
</code></pre>

<h2 id="initializing-pubnub-with-user-info">Initializing PubNub with user info</h2>

<p>This requires your own PubNub API keys, so you need to <a href="http://www.google.com/url?q=http%3A%2F%2Fwww.pubnub.com%2Fget-started%2F&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNHpCZe5gALKuYikUrFqQaySKaNdDA">sign up for a free account</a>. Your publish/subscribe keys are in the <a href="https://www.google.com/url?q=https%3A%2F%2Fadmin.pubnub.com%2F&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNFSTvUrfox_eUQqqUYfryvoRQKP8Q">Developer’s Admin Dashboard</a>.</p>

<p>Then, include the PubNub JavaScript libraries in your HTML.</p>

<pre><code>&lt;script src="https://cdn.pubnub.com/pubnub.min.js"&gt;&lt;/script&gt;
</code></pre>

<p>Now, let’s initialize the PubNub client API environment, with the user’s username as a uuid (unique identifier). Also, we create a channel called “oi”.</p>

<pre><code>var channel = 'oi';
var pubnub = PUBNUB.init({
	subscribe_key: 'your_sub_key',
	publish_key: 'your_pub_key',
	uuid: username
});
</code></pre>

<h2 id="populate-a-list-of-users-using-presence-detection-apis">Populate a list of users using presence detection APIs</h2>

<p>You can subscribe the channel for the client to the PubNub network to create an open TCP socket and begin listening for messages.</p>

<p>PubNub also provides “presence detection”, which allows you to check up on your users’ presence status, for instance, when they come online and when they leave. This feature is useful to populate an up-to-date list of every user currently subscribed to a channel.</p>

<p>In this demo, we update the DOM with the current list of users you can send “Oi” messages to, using PubNub’s <code>here_now</code> APIs. The following function is called each time each time a user joins or leaves. (The subscribe API is explained later).</p>

<pre><code>var updateList = function() {
	pubnub.here_now({
		channel: channel,
		callback: function(m) {
			// get current users and update DOM
		}
	});
};
</code></pre>

<p>To make this article simple and focus more on the essential parts, I’m skipping the details of presence detection, but you can always take a look at the <a href="https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Fpubnub%2Foi-web-notifications%2F&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNHoZZAiZe0tlv-KoObduXXynqcjpA">source code</a> to see how it is done!</p>

<h2 id="sending-messages">Sending messages</h2>

<p>When the user clicks a username in the list, the app will publish a message. The publish() function is used to send a message to all subscribers of a channel. You can simply pass an object as a message payload. In this demo, only from and to info is passed but you can send any messages in the object.</p>

<pre><code>var list = document.querySelector('.list');
list.addEventListener('click', function(event) {
	if (!event.target.id) return;
	pubnub.publish({
		channel: channel,
		message: {
			from: username,
			to: event.target.id
		}
	});
});
</code></pre>

<p>You can pass an object with any data you want as the message. So instead of the default “Oi!” message, you can also modify the script and allow your users to send custom messages.</p>

<h2 id="receiving-messages">Receiving messages</h2>

<p>When somebody sends the user a message, the web app will trigger the browser to display a notification.</p>

<p>To make to this demo very simple, rather than establishing a 1-to-1 private connection, we let our web app broadcast messages to all users simultaneously. However, only a designated person will receive a web notification.</p>

<figure block="figure">
	<img elem="media" src="/articles/web-notifications-pubnub/publish-subscribe-oi.png" alt="" />
</figure>

<p>To retrieve the live messages, you simply use PubNub subscribe() API. If the message is sent to a particular user, that user will see a notification.</p>

<pre><code>pubnub.subscribe({
	channel: channel,
	callback: function(message) {
		if (message.to === username) {
			showNotification(message);
		}
	}
});
</code></pre>

<h2 id="displaying-a-notification">Displaying a notification</h2>

<p>Creating a web notification is super-simple: just call the Notification constructor.</p>

<pre><code>var notification = new Notification(title, options);
</code></pre>

<p>The title must be a string, and options may contain an object with the properties:</p>

<ul>
  <li><code>dir</code> (direction, can be either <code>auto</code>, <code>ltr</code>, or <code>rtl</code>. Used with bidirectional text)</li>
  <li><code>lang</code> (language)</li>
  <li><code>body</code> (extra text)</li>
  <li><code>tag</code> (used to coordinate multiple instances)</li>
  <li><code>icon</code> (the URL of an icon image)</li>
</ul>

<p>Let’s complete the <code>showNotification</code> function. This displays a notification, and closes it after 30 seconds. If you would like to leave it until the user dismisses the popup, just omit the last part.</p>

<p>The tag member is used by each instance to coordinate how many notifications to show. For example, even if you have the app opened in multiple tabs with the same username, you only receive one notification popup when they share the same tag.</p>

<pre><code>function showNotification(data) {
	var notification = new Notification('Oi!', {
		body: 'From: ' + data.from,
		tag: channel,
		icon: 'images/oi.png'
	});
	notification.onshow = function() {
		setTimeout(notification.close, 30000);
	};
}
</code></pre>

<figure block="figure">
	<img elem="media" src="/articles/web-notifications-pubnub/web-notification.png" alt="" />
</figure>

<p>Ta-da! Now you can annoy random strangers online by sending them an “Oi!” message. The entire source code is available on <a href="https://github.com/pubnub/oi-web-notifications/">GitHub</a>.</p>

<p>This demo is very basic, and quite frankly, a bit silly, but web notifications can be really interactive and useful when you use them wisely!</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/appearin-workshop/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/appearin-workshop/"/><title>Appear.in workshop and extensions</title><published>2015-01-28T00:00:00+00:00</published><updated>2015-01-28T00:00:00+00:00</updated><author><name>Andreas Bovens</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<h2 id="background">Background</h2>

<p>In early December 2014, we invited the team behind the fantastic WebRTC-powered <a href="https://appear.in/">appear.in</a> video chat service for a 1-day workshop in Opera’s Oslo office: for about 6 hours, we sat together with engineers, designers and product people from both companies — mostly powered by good coffee and tasty pepperkake — and came up with a number of experiments using <a href="https://appear.in/">appear.in</a>.</p>

<figure block="figure">
	<img elem="media" src="/articles/appearin-workshop/panorama.jpg" alt="Appear.in and Opera team workshop" />
	<figcaption elem="caption">The Appear.in and Opera workshop in December</figcaption>
</figure>

<p>A number of these experiments focused on various backend improvements, but we also looked at a number of interesting frontend tweaks: most of these were implemented as extensions as this allowed us to quickly prototype functionality on top of the existing appear.in service, without making major changes to the underlying code.</p>

<p>We’ve polished these extensions a bit more and have published them to the Opera extensions catalog. Here’s an overview.</p>

<h2 id="appearin-pop">Appear.in Pop</h2>

<p><a href="https://addons.opera.com/extensions/details/appearin-pop/">extension page</a>, <a href="https://github.com/operasoftware/appearin-pop">source</a></p>

<p>This is a simple extension to quickly create an appear.in room. Simply click the appear.in icon, and then “Go to room”. The extension remembers your three most recent rooms, and allows you to edit the suggested room name to something of your liking. Super simple, but we found it comes in handy for starting an appear.in call within seconds.</p>

<figure block="figure">
	<img elem="media" src="/articles/appearin-workshop/pop.jpg" alt="The Appear.in Pop extension" />
	<figcaption elem="caption">The Appear.in Pop extension in action</figcaption>
</figure>

<h2 id="appearin-social">Appear.in Social</h2>

<p><a href="https://addons.opera.com/extensions/details/appearin-social/">extension page</a>, <a href="https://github.com/operasoftware/appearin-social">source</a></p>

<p>This extension adds a small appear.in icon in Facebook chat and Twitter DM, which you can use to quickly generate an appear.in link for your contacts to use. Instant video chat gratification!</p>

<figure block="figure">
	<img elem="media" src="/articles/appearin-workshop/social.jpg" alt="The Appear.in Social extension" />
	<figcaption elem="caption">The Appear.in Social extension integrated in Facebook chat</figcaption>
</figure>

<h2 id="appearin-handoff">Appear.in Handoff</h2>

<p><a href="https://addons.opera.com/extensions/details/appearin-handoff/">extension page</a>, <a href="https://github.com/operasoftware/appearin-handoff">source</a></p>

<p>This extension allows you to easily transfer an ongoing appear.in video chat from your desktop browser to your Android phone. Check out the video below for a demonstration of the desktop-to-mobile flow.</p>

<figure block="figure">
	<iframe src="https://www.youtube.com/embed/d7hQIgj13UE" width="570" height="320" allowfullscreen="" elem="media"></iframe>
</figure>

<h2 id="its-up-to-you">It’s up to you!</h2>

<p>If you’re interested in creating your own extension, you can start with the <a href="https://developer.appear.in/">Appear.in API documentation</a> and our <a href="https://dev.opera.com/extensions">extension docs</a> and take it from there.</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/perfect-javascript-framework/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/perfect-javascript-framework/"/><title>In search of the perfect JavaScript framework</title><published>2014-10-28T00:00:00+00:00</published><updated>2014-10-28T00:00:00+00:00</updated><author><name>Krasimir Tsonev</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<p>Nowadays, in front-end development, we have many frameworks and libraries. Some of them are good, some of them are not. Often we only like a particular concept, module or maybe a certain syntax. The truth is that there is no universal instrument. This article is about the future framework — the framework that does not exist yet. I’ve summarized the pros and cons of some of the available JavaScript frameworks and I dare to dream about the perfect solution.</p>

<h2 id="abstraction-is-dangerous">Abstraction is dangerous</h2>

<p>We all like simple tools. Complexity kills. It makes our work difficult and gives us much steeper learning curve. Programmers need to know how things work. Otherwise, they feel insecure. If we work with a complex system, then we have a big gap between “I am using it” and “I know how it works”. For example, code like this hides complexity:</p>

<pre><code>var page = Framework.createPage({
	'type': 'home',
	'visible': true
});
</code></pre>

<p>Let’s say that this is a real framework. Behind the scenes, <code>createPage</code> generates a new <em>view</em> class that loads the <code>home.html</code> template. Based on the <code>visible</code> parameter we append (or not) the newly created DOM element to the tree. Now, let’s put ourselves in the developer’s shoes. We read in the documentation that this creates a new page with a certain template. We do not know any particular details because this is an abstraction.</p>

<p>Some of today’s frameworks have not one, but many levels of abstractions. Sometimes, in order to use the framework properly, we have to know the details. Abstracting, in fact, is a powerful instrument because it wraps functionalities. It encapsulates design decisions. However, it should be used wisely because it leads to untraceable processes.</p>

<p>What if we transform the above example to the following:</p>

<pre><code>var page = Framework.createPage();
page
	.loadTemplate('home.html')
	.appendToDOM();
</code></pre>

<p>Now the developer knows what is going on. The template and the appending are exposed to different API methods. So, he/she can do something in between and control the processes.</p>

<p>Let’s take <a href="http://emberjs.com/">Ember.js</a>. It is a great framework. It gives us the power of building single page applications with just a few lines of code. However, this comes at its own price. It defines several classes behind the scenes. For example:</p>

<pre><code>App.Router.map(function() {
	this.resource('posts', function() {
		this.route('new');
	});
});
</code></pre>

<p>The framework creates three routes, and each one of them has a controller attached. You may or may not use these classes, but they exist. The framework needs them to power up the application.</p>

<p>Very often, our project requires custom functionality. There is no framework that covers all use cases. So, we meet problems that do not have simple solutions. We have to understand how everything works in order to find the right way of doing things. Every other direction that we take looks more like hacking the framework and not playing with it.</p>

<p><a href="http://backbonejs.org/">Backbone.js</a>, for example, introduces just a few predefined objects. They contain the core functionality, but the real implementation is up to the programmer. The <code>DocumentView</code> class below extends <code>Backbone.View</code>. That’s it. We have only one level between the code that we use and the framework’s core features.</p>

<pre><code>var DocumentView = Backbone.View.extend({
	'tagName': 'li',
	'events': {
		'mouseover .title .date': 'showTooltip',
		'click .open': 'render'
	},
	'render': function() { … },
	'showTooltip': function() { … }
});
</code></pre>

<p>Personally, I prefer to use a framework that doesn’t have many levels of abstractions — a framework that provides transparency.</p>

<h2 id="the-missing-constructor">The missing constructor</h2>

<p>Some of the frameworks accept our class definitions, but they do not produce constructors. The framework decides where and when to create an instance. I would like to see more frameworks that let us do exactly this. For example, in <a href="http://knockoutjs.com/">Knockout</a>:</p>

<pre><code>function ViewModel(first, last) {
	this.firstName = ko.observable(first);
	this.lastName = ko.observable(last);
}
ko.applyBindings(new ViewModel("Planet", "Earth"))
</code></pre>

<p>We define our model, and we initialize it. In AngularJS, for example, it is a bit different:</p>

<pre><code>function TodoCtrl($scope) {
	$scope.todos = [
		{ 'text': 'learn angular', 'done': true },
		{ 'text': 'build an angular app', 'done': false }
	];
}
</code></pre>

<p>We, again, define our class, but we are not running it. We just say that this is our controller, and the framework decides how to process it. We may find this confusing because we lose the key points — the key points that we use to visualize the application’s flow.</p>

<h2 id="dom-manipulations">DOM manipulations</h2>

<p>Whatever we do, we need to interact with the DOM. It is important how we do it, because typically, every manipulation of the nodes on the page fires a reflow or a repaint, which can be expensive operations. Let’s, for example, consider the usage of the following JavaScript class:</p>

<pre><code>var Framework = {
	'el': null,
	'setElement': function(el) {
		this.el = el;
		return this;
	},
	'update': function(list) {
		var str = '&lt;ul&gt;';
		for (var i = 0; i &lt; list.length; i++) {
			var li = document.createElement('li');
			li.textContent = list[i];
			str += li.outerHTML;
		}
		str += '&lt;/ul&gt;';
		this.el.innerHTML = str;
		return this;
	}
}
</code></pre>

<p>This little framework generates an unordered list with given data. We send the DOM element, which will host a list, and call the <code>update</code> function that shows the data to the screen.</p>

<pre><code>Framework
	.setElement(document.querySelector('.content'))
	.update(['JavaScript', 'is', 'awesome']);
</code></pre>

<p>The result after running the code is as follows:</p>

<figure block="figure">
	<img elem="media" src="/articles/perfect-javascript-framework/repaint-1.jpg" alt="" />
</figure>

<p>In order to illustrate why this is bad design, we will add a link to the page and will attach a <code>click</code> event listener. The function will call the <code>update</code> method again but with different items.</p>

<pre><code>document.querySelector('a').addEventListener('click', function() {
	Framework.update(['Web', 'is', 'awesome']);
});
</code></pre>

<p>We’re sending almost the same data; we only change the first element of the array. However, because we are using <code>innerHTML</code>, a repaint is triggered after each click. The browser does not know that we need to modify only the first row. It repaints the whole list. Let’s use Opera’s DevTools and run the profile. Check out the following animated GIF demonstrating the result:</p>

<figure block="figure">
	<img elem="media" src="/articles/perfect-javascript-framework/repaint-2.gif" alt="" />
</figure>

<p>Notice that after each click the whole content is repainted. This is a problem, especially if we use the same technique heavily on the page.</p>

<p>It is much better if we remember the created <code>&lt;li&gt;</code> nodes and only update their content. That way, we are not modifying the whole list but only its children. The first change that we have to make is in <code>setElement</code>:</p>

<pre><code>setElement: function(el) {
	this.list = document.createElement('ul');
	el.appendChild(this.list);
	return this;
}
</code></pre>

<p>Like this, we do not need a reference to the host element anymore. We just need to create a new <code>&lt;ul&gt;</code> element and append it once.</p>

<p>The logic that improves the performance is in the body of the <code>update</code> method:</p>

<pre><code>'update': function(list) {
	for (var i = 0; i &lt; list.length; i++) {
		if (!this.rows[i]) {
			var row = document.createElement('LI');
			row.textContent = list[i];
			this.rows[i] = row;
			this.list.appendChild(row);
		} else if (this.rows[i].textContent !== list[i]) {
			this.rows[i].textContent = list[i];
		}
	}
	if (list.length &lt; this.rows.length) {
		for (var i = list.length; i &lt; this.rows.length; i++) {
			if (this.rows[i] !== false) {
				this.list.removeChild(this.rows[i]);
				this.rows[i] = false;
			}
		}
	}
	return this;
}
</code></pre>

<p>The first <code>for</code> loop goes through the data that is passed in and creates <code>&lt;li&gt;</code> elements if necessary. <code>this.rows</code> keeps the created tags. If there is a node at a certain index, the framework updates its <code>textContent</code> property when applicable. The loop at the end removes nodes if the passed array has fewer elements than the current one.</p>

<p>Here is the result:</p>

<figure block="figure">
	<img elem="media" src="/articles/perfect-javascript-framework/repaint-3.gif" alt="" />
</figure>

<p>The browser repaints only the part that is changed.</p>

<p>The good news is that frameworks like <a href="https://facebook.github.io/react/">React</a> are already handling the DOM manipulations correctly. The browsers become smarter and they also apply tricks to decrease the repaints. However, it is always good to have this in mind and check what our framework of choice provides.</p>

<p>I hope that in the near future we will be able to stop thinking about such problems: frameworks should automatically cover them for us.</p>

<h2 id="dom-events-handling">DOM events handling</h2>

<p>JavaScript based applications usually communicate with the users through DOM events. The elements on the page dispatch messages and our code processes them. Here is a piece of Backbone.js code that performs an action when the user interacts with the page:</p>

<pre><code>var Navigation = Backbone.View.extend({
	'events': {
		'click .header.menu': 'toggleMenu'
	},
	'toggleMenu': function() {
		// …
	}
});
</code></pre>

<p>So, there should be an element matching the <code>.header.menu</code> selector and once the user clicks on it we have to toggle the menu. The problem with this design is that we bind the JavaScript object to one particular DOM item. If we tweak the HTML and change <code>.menu</code>. to <code>.main-menu</code> we have to modify the JavaScript too. I believe that our controllers should be independent, and we should decouple them from the DOM.</p>

<p>By defining functions, we delegate tasks to our JavaScript classes. If these tasks are handlers of DOM events, then it makes sense to construct them in the HTML.</p>

<p>I like how AngularJS handles events:</p>

<pre><code>&lt;a href="#" ng-click="go()"&gt;click me&lt;/a&gt;
</code></pre>

<p><code>go</code> is a function registered in our controller. Following this approach, we do not have to think about DOM selectors. We just apply behavior directly to the HTML nodes. It is a powerful approach because we skip the boring interaction with the DOM.</p>

<p>In general, I would like to see such kind of logic inside HTML. Interestingly, we spent ages convincing developers to split the content (HTML) and the behavior (JavaScript); we taught them to avoid inline styling and scripting. However, now I see that doing this actually can save us much time and makes our components flexible. Of course, I don’t mean code like this:</p>

<pre><code>&lt;div onclick="javascript:App.doSomething(this);"&gt;banner text&lt;/div&gt;
</code></pre>

<p>Instead, I’m talking about descriptive attributes that control the behavior of the element. For example:</p>

<pre><code>&lt;div data-component="slideshow" data-items="5" data-select="dispatch:selected"&gt;
	…
&lt;/div&gt;
</code></pre>

<p>It should not be like JavaScript coding in HTML, but more like setting configurations.</p>

<h2 id="dependency-management">Dependency management</h2>

<p>Managing the dependencies is an important job in our development process. We usually depend on external functions, modules or libraries. In fact, we are producing dependencies all the time. We don’t write everything into one method. We split the application’s tasks into functions and wire them. In the ideal case, we want to encapsulate logic into modules that behave like black boxes. They know details only about their job and nothing else.</p>

<p><a href="http://requirejs.org/">RequireJS</a> is one of the popular instruments for resolving dependencies. The idea is to wrap your code in a closure that accepts the needed modules:</p>

<pre><code>require(['ajax', 'router'], function(ajax, router) {
	// …
});
</code></pre>

<p>In the example above, our function needs two modules — <code>ajax</code> and <code>router</code>. The magical <code>require</code> method reads the passed array and calls our function with the proper arguments. The definition of the <code>router</code> looks like this:</p>

<pre><code>// router.js
define(['jquery'], function($) {
	return {
		'apiMethod': function() {
			// …
		}
	}
});
</code></pre>

<p>Notice that we have another dependency here — jQuery. It’s also important to mention that we have to return our module’s public API. Otherwise, the code which requires our module can’t access the defined functionalities.</p>

<p>AngularJS goes a little bit further by giving us something called <em>factory</em>. We register our dependencies there, and they are <a href="http://krasimirtsonev.com/blog/article/Dependency-injection-in-JavaScript#the-reflection-approach">magically</a> available in our controllers. For example:</p>

<pre><code>myModule.factory('greeter', function($window) {
	return {
		'greet': function(text) {
			alert(text);
		}
	};
});
function MyController($scope, greeter) {
	$scope.sayHello = function() {
		greeter.greet('Hello World');
	};
}
</code></pre>

<p>In general, this approach simplifies our job. We don’t have to use a function like <code>require</code> to fetch the dependency. All we have to do is to type the right words in the arguments’ list.</p>

<p>Ok, these two ways of dependency injection work, but they are bound to a specific style of code writing. In the future, I would like to see frameworks that eliminate this constraint. It will be much elegant if we are able to apply metadata during the variables’ definition. The language right now doesn’t offer such capabilities. It will be nice if the following is possible:</p>

<pre><code>var router:&lt;inject:Router&gt;;
</code></pre>

<p>Placing the dependency along with the variable’s definition means that we will perform the injection only if needed. RequireJS and AngularJS for example work on a functional level. So, you may use a module only in specific cases, but the initialization and its injection happen every time. There is also a specific place where we have to define our dependencies. We are bound to that.</p>

<h2 id="templates">Templates</h2>

<p>We use template engines a lot. And we do so because we need to distinguish the data from the HTML markup. How do today’s frameworks handle templates? Here are the most popular approaches:</p>

<h3 id="the-template-is-defined-in-a-script">The template is defined in a <code>&lt;script&gt;</code></h3>

<pre><code>&lt;script type="text/x-handlebars"&gt;
	Hello, &lt;strong&gt; &lt;/strong&gt;!
&lt;/script&gt;
</code></pre>

<p>This is used often because the template is placed in the HTML. It looks natural, and it makes sense because HTML naturally contains tags. The browser doesn’t render the contents of <code>&lt;script&gt;</code> elements so it doesn’t mess up the page’s layout.</p>

<h3 id="the-template-is-loaded-using-ajax">The template is loaded using Ajax</h3>

<pre><code>Backbone.View.extend({
	'template': 'my-view-template',
	'render': function() {
		$.get('/templates/' + this.template + '.html', function(template) {
			var html = $(template).tmpl();
		});
	}
});
</code></pre>

<p>We place our code into external HTML files and avoid the usage of additional <code>&lt;script&gt;</code> tags. However, this means that we need more HTTP requests which is not always appropriate (at least not until HTTP2 becomes more widespread).</p>

<p>The template is part of the page’s markup — the framework reads the template from the DOM tree. It relies on already generated HTML. We don’t have to perform additional HTTP requests, create a new file or add additional <code>&lt;script&gt;</code> elements.</p>

<h3 id="the-template-is-part-of-the-javascript">The template is part of the JavaScript</h3>

<pre><code>var HelloMessage = React.createClass({
	render: function() {
		// Note: the following line is invalid JavaScript.
		return &lt;div&gt;Hello {this.props.name}&lt;/div&gt;;
	}
});
</code></pre>

<p>This approach introduced by React uses its own parser that converts the invalid part of the JavaScript to valid code.</p>

<h3 id="the-template-is-not-html">The template is not HTML</h3>

<p>Some frameworks don’t use HTML directly at all. They use templates in the form of JSON or YAML.</p>

<h3 id="final-thoughts-about-templates">Final thoughts about templates</h3>

<p>Ok, where do we go from here? The framework of the future should make us think only about the data and only about the markup. Nothing in between. We don’t want to deal with loading HTML strings or passing data to special functions. We want to apply values to variables and get the DOM updated. The popular <em>two-way data binding</em> should not be a feature, but a <em>must-have</em> core functionality.</p>

<p>In fact, AngularJS is close to the desired behavior. It reads the template from the provided page’s content and has the magical data binding implemented. However, it is still not ideal. Sometimes there is a flickering effect. It happens when the browser renders the HTML but AngularJS’s boot mechanisms are still not fired. Also, AngularJS uses <em>dirty checking</em> to find out what is changed. This approach could cost a lot in some cases. Hopefully <a href="http://www.html5rocks.com/en/tutorials/es7/observe/"><code>Object.observe</code></a> will soon be supported in all browsers, so that we have better data binding.</p>

<p>The question about dynamic templates comes up to every developer sooner or later. For sure, we have parts of our application that appear after the bootstrapping. The framework ought to handle that easily. We shouldn’t think about Ajax requests, and we should work with an API that makes the process look synchronous.</p>

<h2 id="modularity">Modularity</h2>

<p>I like the idea of turning features off and on. If we don’t use something, then why is it in our code base? It would be nice if the framework has a builder that generates a version containing only modules that we need. Like, for example <a href="http://yuilibrary.com/yui/configurator/">YUI</a>, which has a configurator. We choose the modules that we want and get a minified JavaScript file ready to use.</p>

<p>Even now, there are frameworks that have something usually called <em>core</em>. Additionally we are able to use bunch of plugins (or modules). However, we could improve that. The process of choosing the needed features shouldn’t involve downloading files. We should not include them manually in the page. It ought to be somehow part of the framework’s code.</p>

<p>After having appropriate setup capabilities, the perfect environment must provide extensibility. We should be able to write our own modules and share them with other developers. In other words, there should be a friendly environment for creating modules. We can’t develop a strong community without the existence of a proper developer environment.</p>

<h2 id="public-apis">Public APIs</h2>

<p>So far, most of the frameworks provide APIs for their core functionalities. However, these APIs give access to parts that vendors think we need. And that’s the place where hacking becomes an option. We want to achieve something, but we don’t have the right instruments. We trick the framework with some ugly workarounds. Let’s have a look at the following example:</p>

<pre><code>var Framework = function() {
	var router = new Router();
	var factory = new ControllerFactory();
	return {
		'addRoute': function(path) {
			var rData = router.resolve(path);
			var controller = factory.get(rData.controllerType);
			router.register(path, controller.handler);
			return controller;
		}
	}
};
var AboutCtrl = Framework.addRoute('/about');
</code></pre>

<p>We have a framework that has a built-in router. We define a path, and our controller is automatically initialized. Once the user goes to the right URL, our router fires the <code>handler</code> method of the controller. That’s great, but what happens if we need to execute a simple JavaScript function as a response to the URL matching? For some reason, we don’t want to create a new controller. This is not possible with the current API.</p>

<p>We could use another design like this one, for example:</p>

<pre><code>var Framework = function() {
	var router = new Router();
	var factory = new ControllerFactory();
	return {
		'createController': function(path) {
			var rData = router.resolve(path);
			return factory.get(rData.controllerType);
		}
		'addRoute': function(path, handler) {
			router.register(path, handler);
		}
	}
}
var AboutCtrl = Framework.createController({ 'type': 'about' });
Framework.addRoute('/about', AboutCtrl.handler);
</code></pre>

<p>Notice that we are not exposing our router. It is not visible, but now we have control of the two processes — creating the controller and registering a route. Of course, the proposed design matches our personal use case. We may find this approach much complex because we have to create controllers manually. While we design APIs, we have to think about the <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle">single responsibility principle</a> and the idea of <em>doing one thing and doing it right</em>. I’m seeing that more and more frameworks decentralize their functionalities. They split the complex methods in smaller and smaller pieces. That’s a good sign, and I hope that we will see more of this in the future.</p>

<h2 id="testability">Testability</h2>

<p>There is no need to convince you to write tests for your code. The point is not only in writing tests, but writing testable code. Sometimes this is extremely difficult and takes time. I’m sure that if we miss a test for something, even small, that’s the exact place where our application will start getting buggy. This is especially the case if we talk about client-side JavaScript. Several browsers, several operating systems, new specs, new features and their polyfills: there are so many reasons to start using test-driven development.</p>

<p>There is something else that we get from having tests. We are not only proving that our framework (application) works today. We make sure that it will work tomorrow and even after that. If there is a new feature that has to land in the code base, we write a test for it. And it is important that we make this test pass. However, it is also important that our previous tests pass as well. This is how we guarantee that we didn’t break anything.</p>

<p>I’d like to see more standardized tools and methods for testing. I wish I could use only one tool and test every framework with it. It’s also good if the testing is somehow integrated into the development process. Services like <a href="https://travis-ci.org/">Travis</a> need more attention. They act as an indicator not only for the programmer that makes the changes but also for the other contributors.</p>

<p>I’m still working with PHP. I had to deal with frameworks like WordPress for example. And a lot of people are asking me how I test my applications: what testing framework do I use? How do I run my tests? Do I even have unit tests? The truth is that I don’t. And that’s because I don’t have units. The same goes for some JavaScript frameworks. It is difficult to test some parts of them because they do not have units. The developers should also think in this direction. Yes, they have to give us smart, elegant and working code. But that code should be testable, too.</p>

<h2 id="documentation">Documentation</h2>

<p>I believe that without good documentation any project will die sooner or later. We have so many frameworks and libraries coming out every week. Documentation is the first thing that the developers see. No one wants to spend hours searching about what the certain tool is doing or what its features are. Only listing of the main functionalities is not enough. Especially for a big framework.</p>

<p>I could split the successful documentation into three parts:</p>

<ul>
  <li><strong>What you can do</strong> section — the documentation has to teach the users, and it should do it right. No matter how awesome and powerful our framework is, there really has to be a proper explanation. Some people prefer watching video clips, others — reading articles. In both cases, the vendor should lead the developers from the very basic stuff to the advanced components of the framework.</li>
  <li><strong>API documentation</strong> — this is usually included. It’s a list of all the public methods of the framework, their parameters, what they return and maybe an example usage.</li>
  <li><strong>How it works</strong> section — usually this section is missing. It’s nice if someone explains the structure of the framework — even a simple schema of the core functionalities and their relation will help. This will make the code transparent. It will help the developers who want to make custom modifications.</li>
</ul>

<h2 id="summary">Summary</h2>

<p>It is, of course, difficult to predict the future. What we can do though is to dream about it! It is important that we talk about what we expect and what we need from JavaScript frameworks! If you have any feedback or want to share your thoughts, tweet them using the <a href="https://twitter.com/hashtag/jsframeworks">#jsframeworks</a> hashtag.</p>
]]></content></entry><entry><id>https://dev.opera.com/articles/opera-mini-chrome-os/</id><link type="text/html" rel="alternate" href="https://dev.opera.com/articles/opera-mini-chrome-os/"/><title>Opera Mini on your Chromebook for fun and bandwidth</title><published>2014-10-14T00:00:00+00:00</published><updated>2014-10-14T00:00:00+00:00</updated><author><name>Vlad Filippov</name></author><content type="html" xml:base="https://dev.opera.com/"><![CDATA[<figure block="figure">
	<img elem="media" src="/articles/opera-mini-chrome-os/great-success.jpg" alt="Opera Mini running on a Chromebook" />
	<figcaption elem="caption">Opera Mini running on a Chromebook</figcaption>
</figure>

<figure block="figure" mod="right">
	<img elem="media" mod="half" src="/articles/opera-mini-chrome-os/installing.jpg" alt="Opera Mini installing on Chrome OS" />
	<figcaption elem="caption">Opera Mini installing on Chrome OS</figcaption>
</figure>

<p>This summer Google previewed a way to run Android applications on Chromebooks using ARC — App Runtime for Chrome. At this time there are only a handful of applications that work on Chrome OS through official channels. However, there are tools and workarounds that allow users to run their favorite Android applications on Chromebooks. One of the applications that works well on Chrome OS is the Opera Mini browser.</p>

<p>It might sound a bit insane at first — why would you want to run a browser inside of a browser? Beside the mind-blowing “inception” factor, using Opera Mini on your Chromebook can actually help you save bandwidth when you are browsing using a cellular data plan. Developers can also utilize this Chromebook capability to easily test websites and see how well the web works with Opera Mini. Besides all that, it is a fun hack to play around with.</p>

<h2 id="running-opera-mini-on-chrome-os">Running Opera Mini on Chrome OS</h2>

<p>Here’s the fastest way to get Opera Mini running on your Chromebook, using an Android device and a custom runtime called <em>ARChon</em> (the difference in runtimes is explained later in the article):</p>

<figure block="figure">
	<iframe src="https://www.youtube.com/embed/FA2UDyTB7lI" width="570" height="320" allowfullscreen="" elem="media"></iframe>
	<figcaption elem="caption">Quick demo of Opera Mini with ARC</figcaption>
</figure>

<ol>
  <li><a href="https://play.google.com/store/apps/details?id=com.opera.mini.android&amp;hl=en">Download Opera Mini</a> and <a href="https://play.google.com/store/apps/details?id=me.bpear.archonpackager&amp;hl=en">the ARChon Packager</a> onto your Android device from Google Play. (Alternatively, <a href="https://www.opera.com/mobile/download/versions/">the Opera Mini APK can be downloaded here</a>.)</li>
  <li><a href="https://github.com/vladikoff/chromeos-apk/blob/master/archon.md#instructions">Download the appropriate ARChon runtime</a> to your Chromebook from GitHub.</li>
  <li>Use the ARChon Packager on your Android device to convert Opera Mini for your Chromebook. This will generate a ZIP file. Transfer the ZIP file to your Chromebook. Use the “Tablet mode” and “Landscape” orientation when you are converting the application to get the best experience out of Opera Mini.</li>
  <li>Unpack both ZIP files (the runtime and the application), navigate to
 <code>chrome://extensions/</code>, enable “Developer mode” and load the two unpacked directories as “Unpacked extensions”. Make sure to load the runtime first. After you load the two directories just press “Launch” in the Opera Mini extension. The application will also be added to your Chrome OS launcher.</li>
</ol>

<figure block="figure">
	<img elem="media" src="/articles/opera-mini-chrome-os/chrome-os-launcher.jpg" alt="Chrome OS launcher integration" />
	<figcaption elem="caption">Chrome OS launcher integration</figcaption>
</figure>

<p>If you already use the official Android applications on Chrome OS, <a href="https://github.com/vladikoff/chromeos-apk#setup-for-chrome-os--app-conversion">follow the instructions on GitHub</a> to get Opera Mini working with the official runtime. At this time the official runtime can only run up to four applications on Chrome OS. If you do not have an Android device, then obtain the Opera Mini APK file and follow the instructions of the <a href="https://github.com/vladikoff/chromeos-apk"><code>chromeos-apk</code></a> project to get Opera Mini working using a Node.js conversion tool.</p>

<figure block="figure">
	<img elem="media" src="/articles/opera-mini-chrome-os/opera-mini-web-page.jpg" alt="Opera Mini browsing in style" />
	<figcaption elem="caption">Opera Mini browsing in style</figcaption>
</figure>

<p>Most Opera Mini features, such as “Downloads” and “Find in page” work really well on Chrome OS. When you restart the application, your settings and history get saved. If you remove and reinstall the application, you get a fresh copy with all settings reset.</p>

<p>Most of the screenshots in this article are taken on a Chromebook Pixel. However, using the ARChon runtime for 32-bit and ARM devices you can try out Opera Mini on older hardware. This screenshot below is taken on a 32-bit Samsung Series 5 Chromebook from 2011:</p>

<figure block="figure">
	<img elem="media" src="/articles/opera-mini-chrome-os/old-hardware.jpg" alt="Opera Mini on older Chromebooks" />
	<figcaption elem="caption">Opera Mini on older Chromebooks</figcaption>
</figure>

<h2 id="the-technology">The Technology</h2>

<p>The ARC (App Runtime for Chrome) is powered by the Native Client technology. This allows ARC to execute native compiled code in the browser. In this case, the Opera Mini application window is a basic HTML page with an embedded Native Client plugin component.</p>

<p>The runtime ships in three different flavors, for 64-bit, 32-bit and ARM processors. ARC consists of an ARM instructions translator, which allows Android applications to run in the plugin environment. There are also several libraries that emulate the Dalvik Virtual Machine and graphics hardware.</p>

<p>The custom runtime, called ARChon, is a forked version of ARC. ARChon is developed as part of the <a href="https://github.com/vladikoff/chromeos-apk/blob/master/archon.md"><code>chromeos-apk</code> project</a> and allows running an unlimited number of Android applications on Chrome OS. ARChon also works on some Linux, Windows and OS X devices — this means you can try running Opera Mini on your desktop machine.</p>

<p>Currently it is not possible to run other complex browsers in these runtimes because of the native library requirement. Opera Mini does not have issues with native libraries and works outside of the box. It is also possible to tweak the application environment by editing the <code>manifest.json</code> file in the application directory. You can make the Opera Mini application window resizable or make the browser open files with different extensions. In addition, developers can turn on ADB (Android Debug Bridge) to take full control fo the sandboxed emulator for this specific application. The list of available runtime options is <a href="https://github.com/vladikoff/chromeos-apk/blob/master/manifest.md">documented on GitHub</a>.</p>

<h2 id="useful-links">Useful Links</h2>

<ul>
  <li>The <a href="https://github.com/vladikoff/chromeos-apk/blob/master/archon.md"><code>chromeos-apk</code> project</a>, the original conversion tool for Android applications to run on Chrome OS.</li>
  <li><a href="https://github.com/vladikoff/chromeos-apk/blob/master/archon.md">ARChon runtime</a> documentation and the community developed <a href="https://play.google.com/store/apps/details?id=me.bpear.archonpackager&amp;hl=en">ARChon packager</a>.</li>
  <li><a href="http://www.reddit.com/r/chromeapks">r/chromeapks</a> - the <code>chromeos-apk</code> Reddit community.</li>
</ul>

<p>Happy hacking!</p>
]]></content></entry></feed>