Mozilla

Found 445 results for “html5”

Sort by:

View:

  1. 2014: Mozilla Hacks looks back

    Wherever you live, it’s a season of work holidays, school vacations, year-end blog posts, and lists. The Hacks blog will be back in early January 2015 to continue writing for developers about the products and technologies created by Mozilla and by builders of the Open Web around the world.

    In the (chronological) list below, we celebrate some 2014 milestones and memorable moments for Mozilla, Firefox, and the web platform:

    • The new improved Firefox Sync launched early in 2014, built atop Firefox Accounts. Here’s a deeper look at the new Sync protocol.
    • Mozilla worked with the Apache Cordova team to integrate Firefox OS with Cordova’s open source device APIs, enabling mobile app developers to access native device functions from JavaScript, and release Cordova apps for the Firefox OS platform. Cordova is the underlying software in Adobe PhoneGap: the integration made it possible for PhoneGap developers to easily port their apps to the Firefox Marketplace.
    • Mozilla Research made great progress on Servo, a prototype browser engine. Servo is written in Rust, a systems programming language designed to support concurrency and parallelism for modern hardware. Another Big Milestone for Servo—Acid2 was reported in the spring.
    • Australis was the codename for our major redesign of the Firefox Desktop browser, which launched in late April. Designer Stephen Horlander wrote a post about the process, titled (Re)Designing Firefox.
    • The summer release of Firefox 31 brought new capabilities for game developers, including access to emscripten for compiling to JavaScript. In Resources for HTML5 game developers, we described some of the tools and techniques for coding and debugging sophisticated, performant HTML5 games. On the Mozilla blog, we featured the first commercial games to leverage asm.js, demonstrating the readiness of HTML5 as a game platform.
    • In October, we shared a Preview of Firefox Hello, a WebRTC-powered voice/video chat service.
    • As part of the festivities surrounding Firefox’s 10th birthday, Mozilla Research launched MozVR to help bring virtual reality to the Web. Grab your oculi and hold on to your hats.
    • At the same time, the Firefox Developer Tools team released Firefox Developer Edition, the first browser created specifically for developers. Though still in its early days, the Developer Edition features Valence, an integrated add-on to let you develop and debug your app across multiple browsers and devices, as well as WebIDE, providing an editing environment for app development and remote debugging.
    • The evolution of asm.js continued with the release of Massive, an open source benchmarking tool that measures asm.js performance specifically. You can run Massive here.
    • Mozilla and partners announced the formation of the Internet Security Research Group (ISRG) and launched the Let’s Encrypt initiative. Let’s Encrypt is a new Certificate Authority that’s free, automated, and open. It’s due to arrive in summer 2015.
    • Our friends at Telenor introduced Gonzo, an ongoing project which explores the use of Firefox OS as an embedded platform. Telenor engineer and Firefox OS evangelist Jan Jongboom is hacking together a wireless camera and sharing what he learns along the way.
    • Firefox OS Expands to Nearly 30 Countries – It’s been an expansive year. At last count, Firefox OS is now up and running on 16 smartphones offered in 29 countries. And in December news, Mozilla and KDDI announced the release of Japan’s first Firefox OS smartphone, which went on sale on December 25. The Fx0 is the first high-spec Firefox OS smartphone and it’s a beauty!

    If you’re interested in writing for the Hacks blog in 2015, we’d love to hear from you. Email us. In the meantime, have a safe and hacky holiday!

  2. You can’t go wrong watching JavaScript talks

    Late last week, I was collecting suggestions for year-end Hacks blog posts. As she headed out for the winter holidays, apps engineer Soledad Penadés gifted me “a bunch of cool talks I watched this year.”

    In fact, it’s a curated collection of presentations from JSConf, JSConf EU, and other recent developer conferences. Presenters include notable Mozillians and opinionated friends: hackers, JavaScripters, teachers, preachers, and hipsters. Many talks come with links to slides. They cover diverse topics: software development, developer culture and practices, developer tools, open source, JavaScript, CSS, new APIs.

    Part 1: Sole’s list

    Part 2: Making video better on Firefox

    Binge-watching JavaScript talks not your idea of a holiday break? If you’re watching video at all, Mozilla could use your help improving the video experience on Firefox.

    Here’s how you can contribute: Download Firefox Nightly, and help us test the implementation of Media Source Extensions (MSE) to support YouTube videos running in HTML5. Over recents weeks, Firefox engineers have been working hard addressing top bugs. To get this into the hands of users as quickly as possible, we need more help testing the experience. Here’s a detailed description of the testing task, thanks to Bugmaster Liz Henry from the QA team.

    File bugs using this link. Describe your platform, OS, and the steps needed to reproduce the problem.

    Thank you for helping to make the Firefox Desktop video experience awesome. See you in the new year.

  3. Videos and Firefox OS

    Before HTML5

    Those were dark times Harry, dark times – Rubeus Hagrid

    Before HTML5, displaying video on the Web required browser plugins and Flash.

    Luckily, Firefox OS supports HTML5 video so we don’t need to support these older formats.

    Video support on the Web

    Even though modern browsers support HTML5, the video formats they support vary:

    In summary, to support the most browsers with the fewest formats you need the MP4 and WebM video formats (Firefox prefers WebM).

    Multiple sizes

    Now that you have seen what formats you can use, you need to decide on video resolutions, as desktop users on high speed wifi will expect better quality videos than mobile users on 3G.

    At Rormix we decided on 720p for desktop, 360p for mobile connections, and 180p specially for Firefox OS to reduce the cost in countries with high data charges.

    There are no hard and fast rules — it depends on who your market audience is.

    Streaming?

    The best streaming solution would be to automatically serve the user different videos sizes depending on their connection status (adaptive streaming) but support for this technology is poor.

    HTTP live streaming works well on Apple devices, but has poor support on Android.

    At the time of writing, the most promising technology is MPEG DASH, which is an international standard.

    In summary, we are going to have to wait before we get an adaptive streaming technology that is widely accepted (Firefox does not support HLS or MPEG DASH).

    DIY Adaptive streaming

    In the absence of adaptive streaming we need to try to work out the best video quality to load at the outset. The following is a quick guide to help you decide:

    Wifi or 3G

    Using a certified Firefox OS app you can check to see if the user is on wifi or not.

    var lock    = navigator.mozSettings.createLock();
    var setting = lock.get('wifi.enabled');
     
    setting.onsuccess = function () {
      console.log('wifi.enabled: ' + setting.result);
    }
     
    setting.onerror = function () {
      console.warn('An error occured: ' + setting.error);
    }

    https://developer.mozilla.org/en-US/docs/Web/API/Settings_API

    There is some more information at the W3C Device API.

    Detecting screen size

    There is no point sending a 720p video to a user with a screen smaller than 720p. There are many ways to get the different bounds of a user’s screen; innerWidth and width allow you to get a good idea:

    function getVidSize()
    {
      //Get the width of the phone (rotation independent)
      var min = Math.min($(window).innerHeight(),$(window).innerWidth());
      //Return a video size we have
      if(min < 320)      return '180';
      else if(min < 550) return '360';
      else               return '720';
    }

    http://www.quirksmode.org/m/tests/widthtest.html

    Determining internet speed

    It is difficult to get an accurate read of a user’s internet speed using web technologies — usually they involve loading a large image onto the user’s device and timing it. This has the disadvantage of having to send more data to the user. Some services such as: http://speedof.me/api.html exist, but still require data downloads to the user’s device. (Stackoverflow has some more options.)

    You can be slightly more clever by using HTML5, and checking the time it takes between the user starting the video and a set amount of the video loading. This way we do not need to load any extra data on the user’s device. A quick VideoJS example follows:

    var global_speedcount = 0;
    var global_video = null;
    global_video = videojs("video", {}, function(){
    //Set up video sources
    });
     
    global_video.on('play',function(){
      //User has clicked play
      global_speedcount = new Date().getTime();
    });
     
    function timer()
    {
      var diff = new Date().getTime() - global_speedcount;
      //Remove this handler as it is run multiple times per second!
      global_video.off('timeupdate',timer);
    }
     
    global_video.on('timeupdate',timer);

    This code starts timing when the user clicks play, and when the browser starts to play the video it sends timing information to timeupdate. You can also use this function to detect if lots of buffering is happening.

    Detect high resolution devices

    One final thing to determine is whether or not a user has a high pixel density screen. In this case even if they have a small screen it can still have a large number of pixels (and therefore require a higher resolution video).

    Modernizr has a plugin for detecting hi-res screens.

    if (Modernizr.highresdisplay)
    {
      alert('Your device has a high resolution screen');
    }

    WebP Thumbnails

    Not to get embroiled in an argument, but at Rormix we have seen an average decrease of 30% in file size (WebP vs JPEG) with no loss of quality (in some cases up to 50% less). And in countries with expensive data plans, the less data the better.

    We encode all of our thumbnails in multiple resolutions of WebP and send them to every device that supports them to reduce the amount of data being sent to the user.

    Mobile considerations

    If you are playing HTML5 videos on mobile devices, their behavior differs. On iOS it automatically goes to full screen on iPhones/iPods, but not on tablets.

    Some libraries such as VideoJS have removed the controls from mobile devices until their stability increases.

    Useful libraries

    There are a few useful HTML5 video libraries:

    Mozilla links

    Mozilla has some great articles on web video:

    Other useful Links

  4. An easier way of using polyfills

    Polyfills are a fantastic way to enable the use of modern code even while supporting legacy browsers, but currently using polyfills is too hard, so at the FT we’ve built a new service to make it easier. We’d like to invite you to use it, and help us improve it.

    Image from https://www.flickr.com/photos/hamur0w0/6984884135

    More pictures, they said. So here’s a unicorn, which is basically a horse with a polyfill.

    The challenge

    Here are some of the issues we are trying to solve:

    • Developers do not necessarily know which features need to be polyfilled. You load your site in some old version of IE beloved by a frustratingly large number of your users, see that the site doesn’t work, and have to debug it to figure out which feature is causing the problem. Sometimes the culprit is obvious, but often not, especially when legacy browsers also lack good developer tools.
    • There are often multiple polyfills available for each feature. It can be hard to know which one most faithfully emulates the missing feature.
    • Some polyfills come as a big bundle with lots of other polyfills that you don’t need, to provide comprehensive coverage of a large feature set, such as ES6. It should not be necessary to ship all of this code to the browser to fix something very simple.
    • Newer browsers don’t need the polyfill, but typically the polyfill is served to all browsers. This reduces performance in modern browsers in order to improve compatibility with legacy ones. We don’t want to make that compromise. We’d rather serve polyfills only to browsers that lack a native implementation of the feature.

    Our solution: polyfills as a service

    To solve these problems, we created the polyfill service. It’s a similar idea to going to an optometrist, having your eyes tested, and getting a pair of glasses perfectly designed to correct your particular vision problem. We are doing the same for browsers. Here’s how it works:

    1. Developers insert a script tag into their page, which loads the polyfill service endpoint.
    2. The service analyses the browser’s user-agent header and a list of requested features (or uses a default list of everything polyfillable) and builds a list of polyfills that are required for this browser
    3. The polyfills are ordered using a graph sort to place them in the right dependency order.
    4. The bundle is minified and served through a CDN (for which we’re very grateful to Fastly for their support)

    Do we really need this solution? Well, consider this: Modernizr is a big grab bag of feature detects, and all sensible use cases benefit from a custom build, but a large proportion of Modernizr users just use the default build, often from cdnjs.com or as part of html5boilerplate. Why include Modernizr if you aren’t using its feature detects? Maybe you misunderstand the purpose of the library and just think that Modernizr “fixes stuff”? I have to admit, I did, when I first heard the name, and I was mildly disappointed to find that rather than doing any actual modernising, Modernizr actually just defines modernness.

    The polyfill service, on the other hand, does fix stuff. There’s really nothing wrong with not wanting to spend time gaining intimate knowledge of all the foibles of legacy browsers. Let someone figure it out once, and then we can all benefit from it without needing or wanting to understand the details.

    How to use it

    The simplest use case is:

    <script src="//cdn.polyfill.io/v1/polyfill.min.js" async defer></script>

    This includes our default polyfill set. The default set is a manually curated list of features that we think are most essential to modern web development, and where the polyfills are reasonably small and highly accurate. If you want to specify which features you want to polyfill though, go right ahead:

    <!-- Just the Array.from polyfill -->
    <script src="//cdn.polyfill.io/v1/polyfill.min.js?features=Array.from" async defer></script>
     
    <!-- The default set, plus the geolocation polyfill -->
    <script src="//cdn.polyfill.io/v1/polyfill.min.js?features=default,Navigator.prototype.geolocation" async defer></script>

    If it’s important that you have loaded the polyfills before parsing your own code, you can remove the async and defer attributes, or use a script loader (one that doesn’t require any polyfills!).

    Testing and documenting feature support

    This table shows the polyfill service’s effect for a number of key web technologies and a range of popular browsers:

    Polyfill service support grid

    The full list of features we support is shown on our feature matrix. To build this grid we use Sauce Labs’ test automation platform, which runs each polyfill through a barrage of tests in each browser, and documents the results.

    So, er, user-agent sniffing? Really?

    Yes. There are several reasons why UA analysis wins out over feature detection for us:

    • In some cases, we have multiple polyfills for the same feature, because some browsers offer a non-compliant implementation that just needs to be bashed into shape, while others lack any implementation at all. With UA detection you can choose to serve the right variant of the polyfill.
    • With UA detection, the first HTTP request can respond directly with polyfill code. If we used feature detection, the first request would serve feature-detect code, and then a second one would be needed to fetch specific polyfills.

    Almost all websites with significant scale do UA detection. This isn’t to say the stigma attached to it is necessarily bad. It’s easy to write bad UA detect rules, and hard to write good ones. And we’re not ruling out making a way of using the service via feature-detects (in fact there’s an issue in our tracker for it).

    A service for everyone

    The service part of the app is maintained by the FT, and we are working on expanding and improving the tools, documentation, testing and service features all the time. The source is freely available on GitHub so you can easily host it yourself, but we also host an instance of the service on cdn.polyfill.io which you can use for free, and our friends at Fastly are providing free CDN distribution and SSL.

    We’ve made a platform. We need the community’s help to populate it. We already serve some of the best polyfills from Jonathan Neal, Mathias Bynens and others, but we’d love to be more comprehensive. Bring your polyfills, improve our tests, and make this a resource that can help move the web forward!

  5. Massive: The asm.js Benchmark

    asm.js is a subset of JavaScript that is very easy to optimize. Most often it is generated by a compiler, such as Emscripten, from C or C++ code. The result can run at very high speeds, close to that of the same code compiled natively. For that reason, Emscripten and asm.js are useful for things like 3D game engines, which are usually large and complex C++ codebases that need to be fast, and indeed top companies in the game industry have adopted this approach, for example Unity and Epic, and you can see it in action in the Humble Mozilla Bundle, which recently ran.

    As asm.js code becomes more common, it is important to be able to measure performance on it. There are of course plenty of existing benchmarks, including Octane which contains one asm.js test, and JetStream which contains several. However, even those do not contain very large code samples, and massive codebases are challenging in particular ways. For example, just loading a page with such a script can take significant time while the browser parses it, causing a pause that is annoying to the user.

    A recent benchmark from Unity measures the performance of their game engine, which (when ported to the web) is a large asm.js codebase. Given the high popularity of the Unity engine among developers, this is an excellent benchmark for game performance in browsers, as real-world as it can get, and also it tests large-scale asm.js. It does however focus on game performance as a whole, taking into account both WebGL and JavaScript execution speed. For games, that overall result is often what you care about, but it is also interesting to measure asm.js on its own.

    Benchmarking asm.js specifically

    Massive is a benchmark that measures asm.js performance specifically. It contains several large, real-world codebases: Poppler, SQLite, Lua and Box2D; see the FAQ on the massive site for more details on each of those.

    Massive reports an overall score, summarizing it’s individual measurements. This score can help browser vendors track their performance over time and point to areas where improvements are needed, and for developers it can provide a simple way to get an idea of how fast asm.js execution is on a particular device and browser.

    Importantly, Massive does not only test throughput. As already mentioned, large codebases can affect startup time, and they can also affect responsiveness and other important aspects of the user experience. Massive therefore tests, in addition to throughput, how long it takes the browser to load a large codebase, and how responsive it is while doing so. It also tests how consistent performance is. Once again, see the FAQ for more details on each of those.

    Massive has been developed openly on github from day one, and we’ve solicited and received feedback from many relevant parties. Over the last few months Massive development has been in beta while we received comments, and there are currently no substantial outstanding issues, so we are ready to announce the first stable version, Massive 1.0.

    Massive tests multiple aspects of performance, in new ways, so it is possible something is not being measured in an optimal manner, and of course bugs always exist in software. However, by developing Massive in the open and thereby giving everyone the chance to inspect it and report issues, and by having a lengthy beta period, we believe we have the best possible chance of a reliable result. Of course, if you do find something wrong, please file an issue! General feedback is of course always welcome as well.

    Massive performance over time

    Massive is brand-new, but it is still interesting to look at how it performs on older browsers (“retroactively”), because if it measures something useful, and if browsers are moving in the right direction, then we should see Massive improve over time, even on browser versions that were released long before Massive existed. The graph below shows Firefox performance from version 14 (released 2012-07-17, over 2 years ago) and version 32 (which became the stable version in September 2014):

    Higher numbers are better, so we can indeed see that Massive scores do follow the expected pattern of improvement, with Firefox’s Massive score rising to around 6x its starting point 2 years ago. Note that the Massive score is not “linear” in the sense that 6x the score means 6x the performance, as it is calculated using the geometric mean (like Octane), however, the individual scores it averages are mostly linear. A 6x improvement therefore does represent a very large and significant speedup.

    Looking more closely at the changes over time, we can see which features landed in each of those versions of Firefox where we can see a significant improvement:

    There are three big jumps in Firefox’s Massive score, each annotated:

    • Firefox 22 introduced OdinMonkey, an optimization module for asm.js code. By specifically optimizing asm.js content, it almost doubled Firefox’s Massive score. (At the time, of course, Massive didn’t exist; but we measured speedups on other benchmarks.)
    • Firefox 26 parses async scripts off of the main thread. This avoids the browser or page becoming nonresponsive while the script loads. For asm.js content, not only parsing but also compilation happens in the background, making the user experience even smoother. Also in Firefox 26 are general optimizations for float32 operations, which appear in one of the Massive tests.
    • Firefox 29 caches asm.js code: The second time you visit the same site, previously-compiled asm.js code will just be loaded from disk, avoiding any compilation pause at all. Another speedup in this version is that the previous float32 optimizations are fully optimized in asm.js code as well.

    Large codebases, and why we need a new benchmark

    Each of those features is expected to improve asm.js performance, so it makes sense to see large speedups there. So far, everything looks pretty much as we would expect. However, a fourth milestone is noted on that graph, and it doesn’t cause any speedup. That feature is IonMonkey, which landed in Firefox 18. IonMonkey was a new optimizing compiler for Firefox, and it provided very large speedups on most common browser benchmarks. Why, then, doesn’t it show any benefit in Massive?

    IonMonkey does help very significantly on small asm.js codebases. But in its original release in Firefox 18 (see more details in the P.S. below), IonMonkey did not do well on very large ones – as a complex optimizing compiler, compilation time is not necessarily linear, which means that large scripts can take very large amounts of time to compile. IonMonkey therefore included a script size limit – over a certain size, IonMonkey simply never kicks in. This explains why Massive does not improve on Firefox 18, when IonMonkey landed – Massive contains very large codebases, and IonMonkey at the time could not actually run on them.

    That shows exactly why a benchmark like Massive is necessary, as other benchmarks did show speedups upon IonMonkey’s launch. In other words, Massive is measuring something that other benchmarks do not. And that thing – large asm.js codebases – is becoming more and more important.

    (P.S. IonMonkey’s script size limit prevented large codebases from being optimized when IonMonkey originally launched, but that limit has been relaxed over time, and practically does not exist today. This is possible through compilation on a background thread, interruptible compilation, and just straightforward improvements to compilation speed, all of which make it feasible to compile larger and larger functions. Exciting general improvements to JavaScript engines are constantly happening across the board!)

  6. Matchstick Brings Firefox OS to Your HDTV: Be the First to get a Developer Stick

    The first HDMI streaming stick powered by Firefox OS has arrived. It’s called Matchstick and we’re looking for your help to create apps for this new device.

    Background

    Matchstick stems from a group of coders that spent way too much time mired in the guts of platforms such as Boot to Gecko, XBMC, and Boxee. When Google introduced Chromecast we were excited about the possibilities but ultimately were disappointed when they pulled back on the device’s ultimate promise – any content on any HD screen, anywhere, anytime.

    We decided to make something better and more open, and to accomplish this we had to choose an operating system that would become the bedrock for the adaptable and open-sourced platform that is Matchstick. That platform is Firefox OS, which allows us to build the first streaming stick free of any walled garden ecosystem.

    Matchstick and Firefox OS combined offers a totally open platform (both software and hardware), that lets developers explore content and applications from video to games, and bring it right into the living room. That’s right Developers! An open SDK means you can build out your own personalized streaming and interactive experiences without the need for approval or review.

    Apps for Matchsticks

    We have opened up a full developer site with access to everything you need to begin working with Matchstick. Support for Firefox OS will be available at launch, and we look forward to adding TV applications to the Firefox OS Marketplace. For now, we have included a full API library, of sender apps with support for Android and iOS, as well as receiver apps that are compatible with the Matchstick Receiver.

    When we say Apps for Matchsticks, we mean both sender and receiver apps. You can use the sender APIs to enable your Firefox OS, Android or iOS device to discover a Matchstick device, then communicate with your receiver app. It’s not difficult to embed sender APIs into existing apps or create new sender apps, please refer to the sample code we have included with the SDK.

    Matchstick sender apps typically follow this execution flow:

    1. Scan for Matchstick
      The sender app searches for Matchstick devices residing in the same Wi-Fi network as the sender device. The scanning reveals a friendly display name, model and manufacturer, icon, and the device’s IP address. Presented with a list, a user may then select a target device from all those discovered.
    2. Connect to Matchstick
      We support both TLS and NON-TLS communication between sender and receiver.
    3. Launch Receiver App
      The sender initiates a negotiation with the target device, launching a receiver app either with the URL of a HTML5 receiver app, or even a Chromecast App ID.
    4. Establish Message Channels
      With the receiver app now launched, Matchstick establishes message channels between the sender and receiver. In addition to a media control channel common to all Matchstick and Chromecast apps, you may establish any number of application-specific channels to convey whatever customized data that your app might require.

    The receiver app is a combination of HTML5, CSS and Javascript, loaded into a “receiver container” which is a certified app of Firefox OS. To use the Matchstick receiver APIs, you need only include fling_receiver.js in your app.

    Here is an example of a simple video receiver app:

    <!DOCTYPE html>
    <html>
        <head>
         <title>Example simplest receiver</title>
         <meta charset="UTF-8">
         <!--(need) include matchstick receiver sdk-->
         <script src="//fling.matchstick.tv/sdk/libs/receiver/2.0.0/fling_receiver.js"></script>
        </head>
        <body>
         <!--(need) Give a video tag-->
         <video id="media"></video>
         <script>
             // (need) Get video element
             window.mediaElement = document.getElementById("media");
             // (need) For media applications, override/provide any event listeners on the MediaManager.
             window.mediaManager = new fling.receiver.MediaManager(window.mediaElement);
     
             // (need) Get and hold the provided instance of the FlingReceiverManager.
             // Override/provide any event listeners on the FlingReceiverManager.
             window.flingReceiverManager = fling.receiver.FlingReceiverManager.getInstance();
     
             // (need) Call start on the FlingReceiverManager to indicate the receiver application is ready to receive messages.
             window.flingReceiverManager.start();
         </script>
        </body>
    </html>

    Matchsticks for Apps

    Rather than relying on emulators, we want to be sure developers can get their hands on Matchstick prototypes and start coding without delay. As a result, we are inviting app developers who will commit to building and porting apps for Firefox OS on Matchstick to apply for a free developer-preview device through our Matchsticks for Apps program.

    Similar to the phones-for-apps program launched by Mozilla, our Matchsticks for Apps program is aimed at developers who have built apps for Firefox OS, Chrome, Android, iOS …. Even for Chromecast! Let’s bring those visions to the big screen.

    image

    Developer (pre-production) version of Matchstick (pic by Christian Heilmann)

    We are now looking for good ideas, video content, new channels, as well as games, tools, utilities, pictures, even skins for the UI. If you have a plan to build apps or do something for Matchstick, please share your plan and we’ll send you a stick so you can start coding ASAP.

    Who Should Apply:

    • Those interested in building apps on a big screen TV
    • Those with existing Web or mobile apps, who would like to expand to the big screen
    • HDMI dongle developers, who want to build their own Matchstick
    • Chromecast developers, who want to port their apps to an open platform
    • You!

    Matchstick workshop in November

    On Tuesday, November 18th, we plan to host an invitation-only Firefox OS App Workshop for Matchstick in the Mozilla office in San Francisco. The enrollment form is open and we are accepting applications from qualified developers.

    Apply now for the San Francisco workshop!

    If you don’t live near San Francisco, don’t worry! We plan to offer several other app workshops in the near future and we’ll announce them here, of course!

    Happy Hacking!

  7. 350 posts on Hacks in 2 years!

    Two years ago, we made a number of changes to the Mozilla Hacks blog. Since then we’ve had over three million unique visitors and 350 quality posts in just less than two years – almost one every second day!

    Part of these changes included:

    • A clear focus on learning about the Open Web & open source – more detail in What Mozilla Hacks is
    • A dedicated Editor, me, working with ensuring consistency, quality & versatility of the articles
    • Articles covering both interesting technologies and possibilities but also learning lessons of how to build exciting solutions and work with a number of different technical opportunities
    • To be a credible and independent go-to resource for developers

    Testimonials

    I’ve gathered a few testimonials from authors behind the most popular articles during this time, with their experiences writing for Mozilla Hacks.

    And you know what? You could write for Hacks too!

    If you have experience with a great solution or idea for the Open Web/open source, just let me know and Mozilla can help you share it with a lot of developers out there! Send an e-mail to robert [at] mozilla [dot] com or talk to me via @robertnyman on Twitter and we’ll talk!

    Here are the thoughts from Peter Cooper of HTML5 Weekly & JavaScript Weekly, Dave Camp, Director of Firefox Developer Tools and Thorben Bochenek from Opera on writing for Mozilla Hacks.

    Austin Hallock from Clay.io:

    My co-founder Zoli and I have both written articles for Mozilla Hacks and we agree that it was a very worthwhile experience. The process of getting our posts on the site was easy and both articles generated more response than we expected. Mozilla has a fantastic mission, and the Mozilla Hacks blog is a great extension of that.

    Their articles:

    Also, thanks to the authors on Mozilla Hacks for their great contributions! And those in that page are only authors with 2 posts and more – in total we have 230 authors all time who have published a post on Hacks!

    Most popular content

    During these two years, these are the most popular posts, written by Mozilla staff:

    The most popular posts, written by 3rd party developers/writers:

    Read & write

    If you like our articles, please spread the word about them! Ask your friends to read too and follow @mozhacks on Twitter for the latest articles and announcements.

    And if you have experiences and learnings to share, let us know and help you with sharing that knowledge!

  8. Webapplate – Maintainable web app template for Firefox OS and Chrome Apps

    There are many powerful tools and technologies surrounding the Web, and we can reuse them to develop cross platform mobile and desktop apps, especially in light of installable apps appearing on platforms such as Firefox OS. This article looks at the best way to do this, and presents Webapplate, a powerful new template to help facilitate this.

    Why invent the wheel (for the new frontier)

    As is the nature of the whole web, web apps are simple to write but hard to get done right. Even though the Web doesn’t provide an SDK or simple ready-to-use templates like other mobile platforms, you can still come out with a workable web app from candidates like Mozilla Open Web Apps, Chrome Apps, or Apache Cordova. But developers who want to quickly build a web app usually take longer time than say, an iOS developer.

    Here is the state of web app support by those candidates:

    • Firefox (desktop), Firefox OS, Firefox for Android support hosted web apps. Those web apps could be hosted on a static or dynamic web server just like normal web sites. Hosted web apps don’t allow some certified web APIs such as the TCP socket API because of security concerns.
    • Firefox OS and Chrome (desktop) support packaged web apps with different APIs for different purposes, because currently they focus on different types of devices.
    • Cordova provides device adapters for many platforms, including Android, iOS and Firefox OS.
    • Google has its Cordova variant to adapt Chrome App’s specific APIs to run on Android devices.

    In quick summary, the web app concept is not totally unified yet, but powerful enough to compete with native apps. Currently packaged web apps are mainstream because of the security concerns with new web API’s. Mozilla is mainly focusing on exposing new web APIs to mobile devices, Google is developing new web APIs for desktop. Apache Cordova is a good container to expose web APIs to different platforms.

    To make things harder, provided examples are often focused on teaching you how to pick up new web APIs rather than utilizing proper web app concepts with your development process.

    I’ve had the chance to join the development of an evolving web app project called Gaia, the Firefox OS user interface. The Gaia project contains the very first Mozilla installable web app implementation, including apps for music, photo gallery, e-mail, calendar and much more. According to GitHub’s pulse monthly, there are about 850 commits per month to the Gaia web apps. In the Gaia project, Mozilla developers and community members devoted lots of time and effort to bring it from the prototype stage to a shippable product within 2 years, and iteratively make it a competitive option for smartphone consumers. As a living large web app project, there are many lessons that can be learned from it, and applied to general web app development.

    Introducing webapplate

    Like other software projects, there are many things beside commiting code to develop a web app, such as:

    • How to organize the source code
    • How to handle library dependencies
    • How to keep the coding style in convention
    • How to optimize web app load performance
    • How to unit/integrate test your web app
    • How to localize your web app
    • How to automate those processes

    Those are topics that need to be resolved to develop a quality web app. In Gaia we have addressed these issues by utilizing a bunch of build scripts (Makefiles).

    You may wonder why we didn’t use Grunt or gulp for building? The answer: at the time Firefox OS was started, these tools didn’t exist. And the module owner wanted to make the core build process run in a Firefox extension one day.

    For general web app development, we didn’t have to follow those constraints. And we could do some experiments rapidly by reusing 3rd-party tools and libraries. From 2013, I’ve initiated a side project called webapplate, the open-sourced web app template that attempts to make Gaia’s solutions compatible with emerging toolkits like npm, Grunt and Bower. It also tries to transport good practices from Gaia to make new web apps more maintainable.

    How to setup webapplate

    Webapplate utilizes many powerful tools. With node.js, Grunt, Bower, Karma, Mocha and l20n, we come out with a maintainable full stack and self-contained web app template with JavaScript. So you could just copy or download the webapplate from Github, and develop and deploy to a hosting server or correspondent web app store.

    You need to install node.js in your desktop first. With Node.js installed, you’ll have the npm tool to manage Node.js modules. Now run this command:

    $ npm install -g grunt-cli bower karma

    to install the primary tools.

    Grunt is a JavaScript task runner tool (like Make) and grunt-cli is its command interface. Gruntfile.js file is similar to Makefile, but written in Javascript.

    Bower is a management tool for the front-end libraries. It helps developer manage different library versions. In webapplate, Bower will download client side libraries into the public/vendor folder when you run

    $ bower install

    command.

    Karma is the test runner that runs test code for each of the browsers. karma.conf.js defines the detail settings to specify how the test runner goes.

    Next, enter the webapplate folder and run:

    $ npm install

    npm will reference package.json to install all dependent node modules. The command will trigger Bower to install client-side library dependencies as well.

    Then you are all set! What you get is:

    • Pre-commit lint checking
    • Firefox and Chrome web app-compatible templates
    • Library dependency management
    • Client-side localization framework
    • Unit test and mock framework
    • Deployable web server

    If you use Firefox nightly, you could open the webapplate/public folder as a packaged app in the WebIDE developer tool.

    WebIDE allows you to edit, debug or execute your web app in the Simulator or on the device, with your favorite Firefox Developer Tools.

    With the Chrome Apps & Extensions developer tool, you can import the webapplate/public folder as a Chrome App and check the UI on desktop.

    webapplate on Chrome devtool

    Pre-commit lint checking

    The very first good practice that Gaia and webapplate provide is git pre-commit lint checking.

    Since in Gaia every commit needs to get reviewed and verified by the module owner before the code is checked in, we have followed the Google JavaScript style conventions. At that time we used gjslint to test it. It sounds good but actually forcing people to follow the exact same discipline manually is hard; asking the reviewer to pick through those style errors is another waste of time. So some genius introduced a git pre-commit hook to check several kinds of lint errors when the developer tries to commit their code, and provide a whitelist for the code that isn’t fully lint-free but should be allowed. Currently in Gaia we have pre-commit checks for JavaScript, CSS and JSON! This is a big relief.

    Currently webapplate utilizes code quality and style checking for JavaScript, JSON via JSHint, JSCS and JSONLint.

    It has exactly the same settings as Gaia for JSHint and also comes with the whitelist. Gaia is also planning to migrate to jscs to replace gjslint. If you use git for version control, run:

    $ grunt githooks

    to bind the git pre-commit code style check to your development process.

    Firefox OS- and Chrome App- compatible templates

    Webapplate uses HTML5 mobile boilerplate as the template base, and adds web app install helpers, icon links and usemin annotation for web app optimization on top. The main web app source is located in the public/ folder. You could check the webapplate wiki to see the full webapplate structure.

    Currently, Firefox web apps use manifest.webapp and Chrome Apps use manifest.json as the manifest file. The syntaxes are mutually compatible, except the localization part (we’ll address this issue later).

    After you edit one of these files, use:

    # firefox to chrome
    $ grunt f2c

    or

    # chrome to firefox
    $ grunt c2f

    to overwrite manifest.webapp with manifest.json, or viceversa.

    To generate a Firefox OS packaged app or Chrome App, run this command:

    $ grunt pack

    to package your web app to an uploadable zip file. With the default settings, webapplate-generated packaged web apps could be uploaded to the Firefox Marketplace and the Chrome App store.

    Library dependency management

    For Gaia we manage development tools via npm and generally don’t use many 3rd-party client side libraries. We host commonly-used libraries between apps in a shared/ folder, and then copy them in at build time via a build script.

    webapplate defines these libraries in package.json, uses npm to require build tools, and doesn’t assume any app framework (e.g. Backbone or Angular.js, or a UI framework such as Bootstrap.) Client-side libraries could be managed via Bower in bower.json.

    Client side localization framework

    Since web apps might be run without an Internet connection, we can’t count on the server to detect multiple languages. Currently Firefox OS uses navigator.mozL10n and Chrome Apps uses chrome.i18n for localization. Both of them are non-standard.

    In webapplate we take the l20n library to address the client-side localization issue. l20n is crafted by Mozilla and the developers are currently working on enhancing the Firefox OS localization framework as well.

    Check out index.html; the localization syntax looks exactly like what we used in Gaia:

    <h1 data-l10n-id="hello">Hello WebApplate</h1>

    The locale file however is in a different format, locales.en.l20n:

    <projectName "WebApplate">
    <hello "Hello {{ projectName }}">

    Also, check out the Multiple Language Support Framework section for how l20n is integrated with webapplate.

    Unit test and mock framework

    Gaia uses its own test-agent to trigger unit tests on Firefox. Gaia uses the Mocha test framework, Chai assertion library and the Sinon test helper library for unit tests.

    Webapplate uses the above unit test libraries plus the Karma test runner to run unit tests on all mainstream browsers.

    Deployable web server

    For developing Firefox OS hosted web apps, we need a working web server and maybe some dynamic web server support. Now that’s what we call the 21st century: it is possible to write server-side code in JavaScript as well.

    Running the command:

    $ grunt server

    will trigger the Express-powered server with django-like Swig template support. It’s been pre-configured for performance. Measure with YSlow and you’ll get a pretty good grade for your web site.

    Webapplate has been tested on some free dynamic web page hosting providers such as openshift, heroku and appfog. Check the deployment section to find out more details.

    If you like to host your web apps on a static web server, run:

    $ grunt static

    to generate optimized web pages for hosting.

    If you want to deploy your web app on a GitHub page (as a free static hosting server), run:

    $ grunt github

    Start your new web app project with webapplate!

    Webapplate is the web app template that borrows good practices for web app maintenance from the Gaia project. It provides ready-to-use Firefox OS and Chrome App support, an integrated toolbox to optimize your web app and maintain quality, and uses JavaScript through client/server side build/test frameworks. If you are about to make a web app or want to see how to maintain a web app, webapplate is a good start.

    References

  9. Building Interactive HTML5 Videos

    The HTML5 <video> element makes embedding videos into your site as easy as embedding images. And since all major browsers support <video> since 2011, it’s also the most reliable way to get your moving pictures seen by people.

    A more recent addition to the HTML5 family is the <track> element. It’s a sub-element of <video>, intended to make the video timeline more accessible. Its main use case is adding closed captions. These captions are loaded from a separate text file (a WebVTT file) and printed over the bottom of the video display. Ian Devlin has written an excellent article on the subject.

    Beyond captions though, the <track> element can be used for any kind of interaction with the video timeline. This article explores 3 examples: chapter markers, preview thumbnails, and a timeline search. By the end, you will have sufficient understanding of the <track> element and its scripting API to build your own interactive video experiences.

    Chapter Markers

    Let’s start with an example made popular by DVD disks: chapter markers. These allow viewers to quickly jump to a specific section. It’s especially useful for longer movies like Sintel:

    The chapter markers in this example reside in an external VTT file and are loaded on the page through a <track> element with a kind of **chapters. The track is set to load by default:

    <video width="480" height="204" poster="assets/sintel.jpg" controls>
      <source src="assets/sintel.mp4" type="video/mp4">
      <track src="assets/chapters.vtt" kind="chapters" default>
    </video>

    Next, we use JavaScript to load the cues of the text track, format them, and print them in a controlbar below the video. Note we have to wait until the external VTT file is loaded:

    track.addEventListener('load',function() {
        var c = video.textTracks[0].cues;
        for (var i=0; i<c.length; i++) {
          var s = document.createElement("span");
          s.innerHTML = c[i].text;
          s.setAttribute('data-start',c[i].startTime);
          s.addEventListener("click",seek);
          controlbar.appendChild(s);
        }
    });

    In above code block, we’re adding 2 properties to the list entries to hook up interactivity. First, we set a data attribute to store the start position of the chapter, and second we add a click handler for an external seek function. This function will jump the video to the start position. If the video is not (yet) playing, we’ll make that so:

    function seek() {
      video.currentTime = this.getAttribute('data-start');
      if(video.paused){ video.play(); }
    };

    That’s it! You now have a visual chapter menu for your video, powered by a VTT track. Note the actual live Chapter Markers example has a little bit more logic than described, e.g. to toggle playback of the video on click, to update the controlbar with the video position, and to add some CSS styling.

    Preview Thumbnails

    This second example shows a cool feature made popular by Hulu and Netflix: preview thumbnails. When mousing over the controlbar (or dragging on mobile), a small preview of the position you’re about to seek to is displayed:

    This example is also powered by an external VTT file, loaded in a metadata track. Instead of texts, the cues in this VTT file contain links to a separate JPG image. Each cue could link to a separate image, but in this case we opted to use a single JPG sprite – to keep latency low and management easy. The cues link to the correct section of the sprite by using Media Fragment URIs.Example:

    http://example.com/assets/thumbs.jpg?xywh=0,0,160,90

    Next, all important logic to get the right thumbnail and display it lives in a mousemove listener for the controlbar:

    controlbar.addEventListener('mousemove',function(e) {
      // first we convert from mouse to time position ..
      var p = (e.pageX - controlbar.offsetLeft) * video.duration / 480;
     
      // ..then we find the matching cue..
      var c = video.textTracks[0].cues;
      for (var i=0; i<c.length; i++) {
          if(c[i].startTime <= p && c[i].endTime > p) {
              break;
          };
      }
     
      // ..next we unravel the JPG url and fragment query..
      var url =c[i].text.split('#')[0];
      var xywh = c[i].text.substr(c[i].text.indexOf("=")+1).split(',');
     
      // ..and last we style the thumbnail overlay
      thumbnail.style.backgroundImage = 'url('+c[i].text.split('#')[0]+')';
      thumbnail.style.backgroundPosition = '-'+xywh[0]+'px -'+xywh[1]+'px';
      thumbnail.style.left = e.pageX - xywh[2]/2+'px';
      thumbnail.style.top = controlbar.offsetTop - xywh[3]+8+'px';
      thumbnail.style.width = xywh[2]+'px';
      thumbnail.style.height = xywh[3]+'px';
    });

    All done! Again, the actual live Preview Thumbnails example contains some additional code. It includes the same logic for toggling playback and seeking, as well as logic to show/hide the thumbnail when mousing in/out of the controlbar.

    Timeline Search

    Our last example offers yet another way to unlock your content, this time though in-video search:

    This example re-uses an existing captions VTT file, which is loaded into a captions track. Below the video and controlbar, we print a basic search form:

    <form>
        <input type="search" />
        <button type="submit">Search</button>
    </form>

    Like with the thumbnails example, all key logic resides in a single function. This time, it’s the event handler for submitting the form:

    form.addEventListener('submit',function(e) {
      // First we’ll prevent page reload and grab the cues/query..
      e.preventDefault();
      var c = video.textTracks[0].cues;
      var q = document.querySelector("input").value.toLowerCase();
     
      // ..then we find all matching cues..
      var a = [];
      for(var j=0; j<c.length; j++) {
        if(c[j].text.toLowerCase().indexOf(q) > -1) {
          a.push(c[j]);
        }
      }
     
      // ..and last we highlight matching cues on the controlbar.
      for (var i=0; i<a.length; i++) {
        var s = document.createElement("span");
        s.style.left = (a[i].startTime/video.duration*480-2)+"px";
        bar.appendChild(s);
      }
    });

    Three time’s a charm! Like with the other ones, the actual live Timeline Search example contains additional code for toggling playback and seeking, as well as a snippet to update the controlbar help text.

    Wrapping Up

    Above examples should provide you with enough knowledge to build your own interactive videos. For some more inspiration, see our experiments around clickable hot spots, interactive transcripts, or timeline interaction.

    Overall, the HTML5 <track> element provides an easy to use, cross-platform way to add interactivity to your videos. And while it definitely takes time to author VTT files and build similar experiences, you will see higher accessibility of and engagement with your videos. Good luck!

  10. Time to get hacking – Introducing Rec Room

    It’s no secret that the best frameworks and tools are extracted, not created out of thin air. Since launching Firefox OS, Mozilla has been approached by countless app developers and web developers with a simple question: “How do I make apps for Firefox OS?” The answer: “It’s the web; use existing web technologies.” was—and still is—a good answer.

    But if you don’t already have an existing toolchain as a web developer, I’ve been working on extracting something out of the way I’ve been creating web apps at Mozilla that you can use to write your next web app. From project creation to templating to deployment, Mozilla’s Rec Room will help you create awesome web apps in less time with more ease.

    Rec Room is a Node.js utility belt you can wear to build client side web apps. It includes:

    • Brick to add components like appbars and buttons to your UI.
    • Ember for your app’s controllers, models, and views.
    • Handlebars to write your app’s templates.
    • Grunt to run the tasks for your app, including building for production.
    • I18n.js to localize your app.
    • Mocha to test your app.
    • Stylus to write your CSS.
    • Yeoman to scaffold new code for your app’s models and templates.

    In this post I’ll walk through how to create a simple world clock web app with Rec Room, how to deploy it, and how you can try out Rec Room for yourself.

    Where Does Rec Room Come From?

    Much of Rec Room came from a recent rewrite of the HTML5 podcast app. I started working on this app well over a year ago, but its original version wasn’t as easy to work on; it had a lot of global state and a lot of by-hand data-binding. I liked the look of Ember for app development, but back when I started it didn’t quite feel mature enough. These days it’s much better, and I’ve tweaked it in Rec Room to work perfectly without a server.

    I tried to take the best from that system and extract it into a set of tools and documentation that anyone can use.

    Create your own Rec Room app

    Rec Room has just recently been extracted from my experiences with Podcasts; it hasn’t been tested by more than a handful of developers. That said: we’d love your help trying to build your own app for Firefox OS using these tools. They integrate well with tools you probably already know and use–like Node.js and Firefox’s own Web IDE.

    To get started, install Rec Room using Node.js:

    npm install -g recroom

    Clock App

    We’ll create a simple clock app with (minimal) time zone support for our example. The app will let you have a clock and compare it with a few time zones.

    The recroom binary is your entry point to all of the cool things Rec Room can do for you. First, create your app using recroom new world-clock. This creates the basic app structure. To see the basic app skeleton that Rec Room creates we can now enter that directory and run our app: cd world-clock and then type recroom run. The app will open in your default browser.

    First, we’ll add the current time to the main tab. Rec Room supports Ember’s MVC app structure, but also offers simple “pages” for a controller without a 1:1 relationship to a model. We’ll generate a new page that will show our actual clock:

    recroom generate page Clock

    We can edit its template by opening app/templates/clock.hbs. Let’s change clock.hbs to include the variable that will output our local time:

    <h2>Local Time: {{localTime}}</h2>

    That won’t do much yet, so let’s add that variable to our ClockController, in app/scripts/controllers/clock_controller.js:

    WorldClock.ClockController = Ember.ObjectController.extend({
        localTime: new Date().toLocaleTimeString()
    });

    You can see that any property inside the controller is accessible inside that controller’s template. We define the 1ocalTime property and it gets carried into our template context.

    Now our clock app will show the current local time when we navigate to http://localhost:9000/#clock. Of course, it just shows the time it was when the controller was initialized; there is no live updating of the time. We should update the time every second inside the controller:

    WorldClock.ClockController = Ember.ObjectController.extend({
        init: function() {
            // Update the time.
            this.updateTime();
     
        // Run other controller setup.
            this._super();
        },
     
        updateTime: function() {
            var _this = this;
     
            // Update the time every second.
            Ember.run.later(function() {
                _this.set('localTime', new Date().toLocaleTimeString());
                _this.updateTime();
            }, 1000);
        },
     
        localTime: new Date().toLocaleTimeString()
    });

    Now we can go to our clock URL and see our clock automatically updates every second. This is thanks to Ember’s data-binding between controllers and templates; if we change a value in a controller, model, or view that’s wired up to a template, the template will automatically change that data for us.

    Adding Timezones

    Next, we want to add a few timezones that the user can add to their own collection of timezones to compare against local time. This will help them schedule their meetings with friends in San Francisco, Buenos Aires, and London.

    We can create a timezone model (and accompanying controllers/routes/templates) with the same generate command, but this time we’ll generate a model:

    recroom generate model Timezone

    We want each timezone we’re to include in our app to have a name and an offset value, so we should add them as model attributes. We use Ember Data for this, inside app/scripts/models/timezone_model.js:

    WorldClock.Timezone = DS.Model.extend({
        name: DS.attr('string'),
        offset: DS.attr('number')
    });

    Next we’ll want a list of all timezones to offer the user. For this we’ll grab a copy of Moment Timezone. It’s an awesome JavaScript library for dealing with dates and times in JavaScript. We’ll install it with bower:

    bower install moment-timezone --save

    And then add it to our app inside app/index.html:

    <!-- build:js(app) scripts/components.js -->
    <!-- [Other script tags] -->
    <script src="bower_components/moment/moment.js"></script>
    <script src="bower_components/moment-timezone/builds/moment-timezone-with-data-2010-2020.js"></script>
    <!-- endbuild -->

    Adding that tag will automatically add moment-timezone-with-data-2010-2020.js to our built app. We’ll add a tab to the page that lets us edit our timezones, on a different screen than the clocks. To add a tab, we just need to open app/templates/application.hbs and add a tab. While we’re there, we’ll change the main tab from the useless {{#linkTo 'index'}} and point it to {{#linkTo 'clock'}}. The new application.hbs should look like this:

    <x-layout>
      <header>
        <x-appbar>
          <h1>{{t app.title}}</h1>
        </x-appbar>
      </header>
      <section>
        {{outlet}}
      </section>
      <footer>
        <x-tabbar>
          <x-tabbar-tab>
            {{#link-to 'clock'}}Clock{{/link-to}}
          </x-tabbar-tab>
          <x-tabbar-tab>
            {{#link-to 'timezones'}}Timezones{{/link-to}}
          </x-tabbar-tab>
        </x-tabbar>
      </footer>
    </x-layout>

    Side note: notice the root URL points to a useless welcome page? We probably want the default route to be our ClockController, so we can set the index route to redirect to it. Let’s do that now, in app/scripts/routes/application_route.js:

    WorldClock.ApplicationRoute = Ember.Route.extend({
        redirect: function() {
            this.transitionTo('clock');
        }
    });

    Interacting with Timezone models

    We’ll keep things simple for our example and allow users to select a timezone from a <select> tag and add it with a button. It will show up in their list of timezones, and they can delete it if they want from there. The clock tab will show all times. First, we’ll add our timezone data from Moment.js into our TimezonesController in app/scripts/controllers/timezones_controller.js. We’re also going to implement two actions: “add” and “remove”. These will be used in our template:

    WorldClock.TimezonesController = Ember.ObjectController.extend({
        init: function() {
            var timezones = [];
     
            for (var i in moment.tz._zones) {
              timezones.push({
                  name: moment.tz._zones[i].name,
                  offset: moment.tz._zones[i].offset[0]
              });
          }
     
          this.set('timezones', timezones);
     
          this._super();
      },
     
      selectedTimezone: null,
     
      actions: {
          add: function() {
              var timezone = this.store.createRecord('timezone', {
                  name: this.get('selectedTimezone').name,
                  offset: this.get('selectedTimezone').offset
              });
     
              timezone.save();
          },
     
          remove: function(timezone) {
              timezone.destroyRecord();
          }
      }
    });

    So we create a list of all available timezones with offsets. Then we add methods that allow us to add or remove timezones from our offline data store. Next we modify the timezones template in app/templates/timezones.hbs to use the actions and variables we created. All we need to utilize these variables is the Ember SelectView and the {{action}} helper to call our add and remove methods:

    <h2>Add Timezone</h2>
     
    <p>{{view Ember.Select content=timezones selection=selectedTimezone
           optionValuePath='content.offset' optionLabelPath='content.name'}}</p>
     
    <p><button {{action add}}>Add Timezone</button></p>
     
    <h2>My Timezones</h2>
     
    <ul>
      {{#each model}}
        <li>{{name}} <button {{action remove this}}>Delete</button></li>
      {{/each}}
    </ul>

    Now we have a Timezones tab that allows us to add and remove Timezones we want to track. This data persists between app refreshes. The last thing we need to do is show these times relative to our local time in our clock tab. To do this we need to load all the Timezone models in the ClockRoute. They’re automatically loaded in the TimezonesRoute, but it’s easy to add them in the ClockRoute (in app/scripts/routes/clock_route.js):

    WorldClock.ClockRoute = Ember.Route.extend({
        model: function() {
            return this.get('store').find('timezone');
        }
    });

    Because of the way our Ember app is wired up, we load all our models in the route and they are sent to the controller once the data store has asynchonously loaded all of the models. The request to find('timezone') actually returns a Promise object, but Ember’s router handles the Promise resolving for us automatically so we don’t have to manage callbacks or Promises ourselves.

    Now we have access to all the user’s Timezones in the ClockController, so we can make times in each timezone the user has requested and show them in a list. First we’ll add each Timezone’s current time to our ClockController in app/scripts/controllers/clock_controller.js using Moment.js:

    WorldClock.ClockController = Ember.ObjectController.extend({
        updateTime: function() {
            var _this = this;
     
            // Update the time every second.
            Ember.run.later(function() {
                _this.set('localTime', moment().format('h:mm:ss a'));
     
                _this.get('model').forEach(function(model) {
                    model.set('time',
                              moment().tz(model.get('name')).format('h:mm:ss a'));
                });
     
                _this.updateTime();
            }, 1000);
        }.on('init'),
     
        localTime: moment().format('h:mm:ss a')
    });

    Our final app/templates/clock.hbs should look like this:

    <h2>Local Time: {{localTime}}</h2>
     
    <p>
      {{#each model}}
        <h3>{{name}}: {{time}}</h3>
      {{/each}}
    </p>

    And that’s it! Now we have an offline app that shows us time zones in various places, saves the data offline, and updates every second without us having to do much work!

    Command Line Tools

    The old Podcasts app used a (rather awful) Makefile. It wasn’t very useful, and I don’t think it ran on Windows without some serious effort. The new build system uses Node so it runs comfortably on Windows, Mac, and Linux. Commands are proxied via the recroom binary, also written in Node, so you don’t have to worry about the underlying system if you don’t need to modify build steps. recroom new my-app creates a new app; recroom serve serves up your new app, and recroom generate model Podcast creates a new model for you.

    To build your app, you just need to run recroom build and a version with minified CSS, JS, and even HTML will be created for you in the dist/ folder. This version is ready to be packaged into a packaged app or uploaded to a server as a hosted app. You can even run recroom deploy to deploy directory to your git repository’s GitHub pages branch, if applicable.

    See the app in action!

    This entire sample app is available at worldclock.tofumatt.com and the source code is available on GitHub.

    Try Using Rec Room for Your Next Web App

    You can try out Rec Room on Github. Right now some docs and tools are still being abstracted and built, but you can start building apps today using it and filing bugs for missing features. We’d really love it if you could give it a try and let us know what’s missing. Together we can build a cohesive and polished solution to the all-too-common question: “How do I build a web app?”