Mozilla

HTML5 Articles

Sort by:

View:

  1. HTML5: The difference between an App and a Page.

    HTML5 is only one part of the”Stack”

    HTML5 is really more than one thing. In the strictest sense, HTML5 is fifth major revision of the W3C specification of the markup language that is used to create web pages.

    But in a practical sense, HTML5 is far more than that. For developers, HTML is a wave of technologies that are evolving and gaining browser implementations along roughly the same time-line as the markup language itself. Many of the related technologies are being spearheaded by the Web Hypertext Application Technology Working Group (whatwg.org), but still other technologies in this genre are driven from elsewhere. For example WebGL, the 3D rendering engine for Web Apps, is driven at Khronos, and Mozilla’s WebAPI team is leading a collection of relevant API work including a comprehensive array of device-specific APIs. And the W3C was a Device APIs Working Group

    Mozilla is also investing heavily in an initiative to facilitate the use of standards-based Web technologies to build applications that can be installed and used in the same way a “native” applications would be.

    There are many reasons that doing so might be desirable, not the least of which is the ability to build much or all of your application for use on many different devices and platforms using a single set of development technologies.

    Developers can already build HTML Applications (with help from the HTML5 Apps documentation ) and submit their applications to the Mozilla Marketplace.

    App versus Page ?

    When people start talking about building apps with HTML5, one of the early questions that comes to the conversation is “What’s the difference between an app and a page?”

    This is bit of a difficult question to answer because of the very wide range of answers which can all be true, but which may be completely different.

    While your HTML5 app should be more than a simple HTML5 page, technically speaking it doesn’t have to be. Using the steps outlined in the guide “Getting Started with making (HTML5) apps”, you could simply create an apps manifest file and submit your HTML page as an app.

    When an Open Web app runs, the Mozilla Web Runtime installs local copies of the HTML5 markup and all of the other web assets that are specified using an HTML5 Cache Manifest ( read here ).

    If a Web page is dynamically generated, as in an ASP.NET, PHP, etc., application, any cached version represents a snapshot of a single point in time. When submitted as an app, the page actually “becomes” an app, getting a launcher item similar to native apps on whatever the host operating system is. When the app is launched, the local assets are used if there is no Internet connection or if the caching mechanism determines that the assets have not changed since they were last downloaded.

    By doing the above we have not added any additional functionality to our application. All we have done by declaring our page to be an app is to get the run-time to copy the bits locally and to run those local bits if the device is off line or if the bits haven’t changed.

    Does this get us anything ?

    Is there value in just this simple step ?

    Yes, it gets us three valuable improvements:

    • Users can see our page even if they are not connected because the run-time renders the cached version if there is no Internet connection.
    • Processor cycles and bandwidth consumption from our infrastructure or hosting are greatly reduced because new bits are only fetched when they are needed.
    • Performance improves because resources are loaded locally by default.

    Many organizations are starting with this approach because very little technical effort is necessary and it can be done very quickly. In most cases all you need to do is to create an app manifest file ( more info here ) and to submit  the app to the marketplace. Developers can submit apps now at the Mozilla marketplace Developer Submission site so that they will be available to consumers when the “buy side” of the marketplace opens later this year.)

    But if that’s all you do with your app, you are missing the opportunity.

    Take a look at http://caniuse.com/ for a snapshot view of technologies that are available to developers using the modern web runtime.

    Whether we are building a real Open Web App from scratch or we are converting an HTML page to an app and then adding modern features, HTML5 era technologies let us really start to developer client / server applications that utilize the browser and its host resources, thereby reducing our server requirements while improving the end user’s experience.

    Developers can do things like :

    • Read and write data locally and sync with a server when appropriate.
    • Run multiple threads of execution at the same time.
    • Exchange content with other applications, or share logic with them.
    • Interact with the device on which their app is running.
      • Touch user interface
      • GPS
      • Camera
      • Richly integrate multimedia.
      • And much more…..

    Since apps’ source code is deployed to a single URL and is updated on the device on which the app runs only when updates are necessary, versioning is low cost and friction free. This makes it easy to start by making a page and then iteratively adding features one after another.

    Lets do it !

    Since this model makes it so easy to get started, why not give at a try?

    Follow the guidance here : https://developer.mozilla.org/en/Apps/Getting_Started

    And submit your app here : https://marketplace.mozilla.org/

  2. BrowserQuest – a massively multiplayer HTML5 (WebSocket + Canvas) game experiment

    It’s time for some gaming action with a new HTML5 game demo: BrowserQuest, a massively multiplayer adventure game created by Little Workshop (@glecollinet & @whatthefranck) and Mozilla.

    Play the game: browserquest.mozilla.org
    BrowserQuest

    BrowserQuest is a tribute to classic video-games with a multiplayer twist. You play as a young warrior driven by the thrill of adventure. No princess to save here, just a dangerous world filled with treasures to discover. And it’s all done in glorious HTML5 and JavaScript.

    Even better, it’s open-source so be sure to check out the source code on GitHub!

    Watch a screencast:

    A multiplayer experience

    BrowserQuest screenshot

    BrowserQuest can be played by thousands of simultaneous players, distributed across different instances of the in-game world. Click on the population counter at any time to know exactly how many total players are currently online.

    Players can see and interact with each other by using an in-game chat system. They can also team up and fight enemies together.

    BrowserQuest is a game of exploration: the more dangerous the places you go, the better the rewards.

    Powered by WebSockets

    WebSockets are a new technology enabling bi-directional communication between a browser and a server on the web.

    BrowserQuest is a demo of how this technology can be used today to create a real-time multiplayer game in a single webpage. When you start to play, your browser opens up a WebSocket connection to one of several load-balanced game servers. Each server hosts multiple world instances and handles the player synchronization and game logic within all instances. Because the server code is running on Node.js, both the server and client codebases share a small portion of the same JavaScript source code.

    Server code is available on Github.

    BrowserQuest screenshot

    Built on the Web platform

    BrowserQuest makes extensive use of different web technologies, such as:

    • HTML5 Canvas, which powers the 2D tile-based graphics engine.
    • Web workers, allowing to initialize the large world map without slowing down the homepage UI.
    • localStorage, in which the progress of your character is continually saved.
    • CSS3 Media Queries, so that the game can resize itself and adapt to many devices.
    • HTML5 audio, so you can hear that rat or skeleton die!

    Available everywhere

    Since BrowserQuest is written in HTML5/JavaScript, it is available across a lot of different browsers and platforms. The game can be played in Firefox, Chrome and Safari. With WebSockets enabled, it’s also playable in Opera. Moreover, it’s compatible with iOS devices, as well as tablets and phones running Firefox for Android.

    BrowserQuest screenshot

    The mobile versions are more experimental than the desktop experience, which has richer features and performance, but it’s an early glimpse of what kind of games will be coming to the mobile Web in the future. Give it a try with your favorite mobile device!

    Join the adventure

    Want to be part of BrowserQuest? Create your own character and venture into the world. Fight enemies by yourself or with friends to get your hands on new equipment and items. You might even stumble upon a couple of surprises along the way…

  3. There is no simple solution for local storage

    TL;DR: we have to stop advocating localStorage as a great opportunity for storing data as it performs badly. Sadly enough the alternatives are not nearly as supported or simple to implement.

    When it comes to web development you will always encounter things that sound too good to be true. Sometimes they are good, and all that stops us from using them is our notion of being conspicuous about *everything* as developers. In a lot of cases, however, they really are not as good as they seem but we only find out after using them for a while that we are actually “doing it wrong”.

    One such case is local storage. There is a storage specification (falsely attributed to HTML5 in a lot of examples) with an incredibly simple API that was heralded as the cookie killer when it came out. All you have to do to store content on the user’s machine is to access the navigator.localStorage (or sessionStorage if you don’t need the data to be stored longer than the current browser session):

    localStorage.setItem( 'outofsight', 'my data' );
    console.log( localStorage.getItem( 'outofsight' ) ); // -> 'my data'

    This local storage solution has a few very tempting features for web developers:

    • It is dead simple
    • It uses strings for storage instead of complex databases (and you can store more complex data using JSON encoding)
    • It is well supported by browsers
    • It is endorsed by a lot of companies (and was heralded as amazing when iPhones came out)

    A few known issues with it are that there is no clean way to detect when you reach the limit of local storage and there is no cross-browser way to ask for more space. There are also more obscure issues around sessions and HTTPS, but that is just the tip of the iceberg.

    The main issue: terrible performance

    LocalStorage also has a lot of drawbacks that aren’t quite documented and certainly not covered as much in “HTML5 tutorials”. Especially performance oriented developers are very much against its use.

    When we covered localStorage a few weeks ago using it to store images and files in localStorage it kicked off a massive thread of comments and an even longer internal mailing list thread about the evils of localStorage. The main issues are:

    • localStorage is synchronous in nature, meaning when it loads it can block the main document from rendering
    • localStorage does file I/O meaning it writes to your hard drive, which can take long depending on what your system does (indexing, virus scanning…)
    • On a developer machine these issues can look deceptively minor as the operating system cached these requests – for an end user on the web they could mean a few seconds of waiting during which the web site stalls
    • In order to appear snappy, web browsers load the data into memory on the first request – which could mean a lot of memory use if lots of tabs do it
    • localStorage is persistent. If you don’t use a service or never visit a web site again, the data is still loaded when you start the browser

    This is covered in detail in a follow-up blog post by Taras Glek of the Mozilla performance team and also by Andrea Giammarchi of Nokia.

    In essence this means that a lot of articles saying you can use localStorage for better performance are just wrong.

    Alternatives

    Of course, browsers always offered ways to store local data, some you probably never heard of as shown by evercookie (I think my fave when it comes to the “evil genius with no real-world use” factor is the force-cached PNG image to be read out in canvas). In the internal discussions there was a massive thrust towards advocating IndexedDB for your solutions instead of localStorage. We then published an article how to store images and files in IndexedDB and found a few issues – most actually related to ease-of-use and user interaction:

    • IndexedDB is a full-fledged DB that requires all the steps a SQL DB needs to read and write data – there is no simple key/value layer like localStorage available
    • IndexedDB asks the user for permission to store data which can spook them
    • The browser support is not at all the same as localStorage, right now IndexedDB is supported in IE10, Firefox and Chrome and there are differences in their implementations
    • Safari, Opera, iOS, Opera Mobile, Android Browser favour WebSQL instead (which is yet another standard that has been officially deprecated by the W3C)

    As always when there are differences in implementation someone will come up with an abstraction layer to work around that. Parashuram Narasimhan does a great job with that – even providing a jQuery plugin. It feels wrong though that we as implementers have to use these. It is the HTML5 video debate of WebM vs. H264 all over again.

    Now what?

    There is no doubt that the real database solutions and their asynchronous nature are the better option in terms of performance. They are also more matured and don’t have the “shortcut hack” feeling of localStorage. On the other hand they are hard to use in comparison, we already have a lot of solutions out there using localStorage and asking the user to give us access to storing local files is unacceptable for some implementations in terms of UX.

    The answer is that there is no simple solution for storing data on the end users’ machines and we should stop advocating localStorage as a performance boost. What we have to find is a solution that makes everybody happy and doesn’t break the current implementations. This might prove hard to work around. Here are some ideas:

    • Build a polyfill library that overrides the localStorage API and stores the content in IndexedDB/WebSQL instead? This is dirty and doesn’t work around the issue of the user being asked for permission
    • Implement localStorage in an asynchronous fashion in browsers – actively disregarding the spec? (this could set a dangerous precedent though)
    • Change the localStorage spec to store asynchronously instead of synchronously? We could also extend it to have a proper getStorageSpace interface and allow for native JSON support
    • Define a new standard that allows browser vendors to map the new API to the existing supported API that matches the best for the use case?

    We need to fix this as it doesn’t make sense to store things locally and sacrifice performance at the same time. This is a great example of how new web standards give us much more power but also make us face issues we didn’t have to deal with before. With more access to the OS, we also have to tread more carefully.

  4. Presentation: HTML5 and friends at Mobile World Congress 2012

    As part of the WIP Jam at the Mobile World Congress in Barcelona, Spain we were asked to give and introduction to HTML5 so we sent Chris Heilmann and Joe Stagner to set the record straight in terms of what HTML5 is and what you can do with it.

    The presentation was on the last day of the conference and both of us had spent long hours explaining all Mozilla technologies on our booth and really not enough hours sleeping in between. In addition to that the room was a boiling 30 degrees and packed with lots of developers. It seems we did a good job regardless as nobody left and we had a lot of great questions afterwards.

    The slides (well, the HTML5 document) are available for you to see:

    Slides for HTML5 and friends

    However, they make much more sense when you see them in context, which is why we also provide you with a screencast of the talk:

    All in all it was a lot of fun talking to people at MWC and Boot to Gecko showed that HTML5 is the future of mobile as much as it is already the present technology of choice on the desktop.

  5. Mozilla's Boot to Gecko – The Web is the Platform

    Mozilla’s Boot to Gecko (B2G) is about building a complete, standalone operating system for the open web. It aims at making web technologies the number one choice for applications on desktop and mobile, and we believe it can displace proprietary, single-vendor stacks for application development. And we have made some exciting progress that we want to share with you!

    Continued…

  6. Creating thumbnails with drag and drop and HTML5 canvas

    HTML5 Canvas is a very cool feature. Seemingly just an opportunity to paint inside the browser with a very low-level API you can use it to heavily convert and change image and video content in the document. Today, let’s take a quick look at how you can use Canvas and the FileReader API to create thumbnails from images dropped into a browser document.

    The final code is available on GitHub and you can see an online demo here. There is also a screencast available on YouTube:

    Step 1: Getting the files into the browser

    The first step to resize images in the browser is to somehow get them. For this, we can just add an element in the page and assign drag and drop event handlers to it:

    s.addEventListener( 'dragover', function ( evt ) {
      evt.preventDefault();
    }, false );
    s.addEventListener( 'drop', getfiles, false );

    Notice that we only prevent the default behaviour when we drag things over the element. This is to prevent the browser from just showing the images when we drag them in.

    The getfiles() function then does the hard work of reading all the files in and sending them on to the functions that do the resizing and image generation:

    function getfiles( ev ) {
      var files = ev.dataTransfer.files;
      if ( files.length > 0 ) {
        var i = files.length;
        while ( i-- ) {
          var file = files[ i ];
          if ( file.type.indexOf( 'image' ) === -1 ) { continue; }
          var reader = new FileReader();
          reader.readAsDataURL( file );
          reader.onload = function ( ev ) {
            var img = new Image();
            img.src = ev.target.result;
            img.onload = function() {
            imagetocanvas( this, thumbwidth, thumbheight, crop, background );
            };
          };
        }
      }
      ev.preventDefault();
    };

    The drop event gives us a property called dataTransfer which contains a list of all the files that have been dropped. We make sure that there was at least one file in the drop and then iterate over them.

    If the file type was not an image (or in other words the type property of the file does not contain the string “image”) we don’t do anything with the file and continue the loop.

    If the file is an image we instantiate a new FileReader and tell it to read the file as a Data URL. When the reader successfully loaded the file it fires its onload handler.

    In this handler we create a new image and set its src attribute to the result of the file transfer. We then send this image to the imagetocanvas() function with the parameters to resize (in the demo these come from the form):

    function imagetocanvas( img, thumbwidth, thumbheight, crop, background ) {
      c.width = thumbwidth;
      c.height = thumbheight;
      var dimensions = resize( img.width, img.height, thumbwidth, thumbheight );
      if ( crop ) {
        c.width = dimensions.w;
        c.height = dimensions.h;
        dimensions.x = 0;
        dimensions.y = 0;
      }
      if ( background !== 'transparent' ) {
        cx.fillStyle = background;
        cx.fillRect ( 0, 0, thumbwidth, thumbheight );
      }
      cx.drawImage(
        img, dimensions.x, dimensions.y, dimensions.w, dimensions.h
      );
      addtothumbslist( jpeg, quality );
    };

    This function gets the desired thumbnail size and resizes the canvas to these dimensions. This has the added benefit of wiping the canvas so that no old image data would be added to our thumbnail. We then resize the image to fit into the thumbnail using a resize() function. You can see for yourself what this one does in the source code, it just means the image gets resized to fit. The function returns an object with the width and the height of the new image and the x and y position where it should be positioned onto the canvas.

    If we don’t want the full-size thumbnail but instead crop it we resize the canvas accordingly and reset x and y to 0.

    If the user requested a background we fill the canvas with the colour. After that we put the image on the canvas with the x and y coordinates and the new width and height.

    This takes care of creating a new thumbnail on the canvas, but we haven’t got it as an image in the document yet. To this end, we call addtothumbslist():

    function addtothumbslist( jpeg, quality ) {
      var thumb = new Image(),
          url = jpeg ? c.toDataURL( 'image/jpeg' , quality ) : c.toDataURL();
      thumb.src = url;
      thumb.title = Math.round( url.length / 1000 * 100 ) / 100 + ' KB';
      o.appendChild( thumb );
    };

    This one creates a new image and checks if the users wanted a JPG or PNG image to be created. PNG images tend to be better quality but also bigger in file size. If a JPG was requested we call the canvas’ toDataURL() method with two parameters: the requested JPEG mime type and the quality of the image (ranging between 0 and 1 with 1 being best quality). If a PNG is wanted, we can just call toDataURL() without any parameters as this is the default.

    We set the src of the image to the generated url string and add a title showing the size of the image in KB (rounded to two decimals). All that is left then is to add the thumb to the output element on the page.

    That’s it, you can now drag and drop images into the browser to generate thumbnails. Right now, we can only save them one at a time (or if you have some download add-ons all at once). Would be fun to add Zip.js to the mix to offer them as a zip. I dare you! :)

    More reading: