1. Spirit of Indiana (Jones) – syncing HTML5 Video with Maps

    I’ve always been a big fan of the travel/flight sequences in the Indiana Jones movies and judging by the amount of copy attempts on YouTube I am not alone in this. As I don’t own any video editing software I thought it should be possible to create the same effect with web technologies and Google Maps and lo and behold it is:

    See the demo online

    You can download the animation demo for yourself and try it out locally – all you need is a browser that supports HTML5 video. I know – the music is not quite the same as in the movies, but at least this one is not copyright infringing and it came from the heart (5 minutes in a meeting room in the Mozilla office).

    So how was this done and what are problems that needed solving? Here’s how and what.

    Step 1: Find the movie and get it to the right format

    That was the easy part. Archive.org has a lot of awesome public domain movies available for you and they are already in the formats needed to use in an HTML5 video element. In this case, I took the short movie of Charles Lindbergh taking off for his record breaking flight from New York to fly to Paris in 1927.

    Step 2: Displaying the video

    Using the video is pretty simple:

    <div id="stage">
      <video>
        <source src="http://www.archive.org/download/
    CharlesLindbergTakesOff/CharlesLindbergTakesOff_512kb.mp4" 
    type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
        <source src="http://www.archive.org/download/
    CharlesLindbergTakesOff/CharlesLindbergTakesOff.ogv"
     type='video/ogg; codecs="theora, vorbis"'> 
      </video>
    </div>

    The MP4 format will be used by Webkit based browsers and the Ogg version by Firefox and others. As we want to control the video we omit the controls attribute on the video element – instead we create a button to play the video with JavaScript:

    window.addEventListener('load', 
      function() {
        var stage = document.getElementById('stage');
        var v = document.getElementsByTagName('video')[0];
        but = document.createElement('button');
        but.innerHTML = 'Click to see Lindbergh\'s flight';
        stage.appendChild(but);
        but.addEventListener('click',function(e) {
          v.play();
          e.preventDefault();
        },false);
      }, 
    false);

    As the video is markup we can do whatever we please with it – the power of open technologies. For example as we will do here we can set its opacity in CSS and put in on top of a map.

    Step 3: Create the map path animation

    Talking of which, let’s get that moving path done. Google Earth has an API to do that, but it needs a special plugin. Google Maps allows you to paint paths on maps (which actually are SVG, another open standard). Put that in a recursive function and you get the desired effect:

    Animated Google Maps path synced with HTML5 video

    In essence, what I did was take the latitude and longitude of the start and end points and calculate as many points in between the two as I need for the duration of the animation. I store the points in an array called pos and then paint a path from the start to the current point and move the map centre to this point on every iteration.

    spirit.draw = function(){
      var path = new google.maps.Polyline({
            path: [startpos,pos[now]],
            strokeColor: "#c00",
            strokeOpacity: .7,
            strokeWeight: 10
      });
      path.setMap(map);
      map.panTo(pos[now])
      now = now + 1;
      if(now < animationend-1){
        setTimeout(spirit.draw,200);
      }
    }

    Check the highly commented source of the map example for the details. Now, we could use this kind of animation and play the video over it – the problem though is that they may get out of sync. When the movie stalls (as it frequently does on this hotel wireless connection) we don’t want the animation to keep moving, right?

    Step 4: Syncing video and the map movement

    Instead of having two sources of timing information we have to limit ourselves to one source of truth. This is the time stamp of the currently playing movie.

    By the way – you might have noticed that I wrapped the map code in a tilesloaded event handler. This is another safeguard for keeping things in sync. I found that on slow connections the tile loading can delay the whole interface immensely (because of all the subdomain lookups), so I make the whole interface dependent on the loading of the map and only proceed when the tiles have finished loading. As the tilesloaded event also fires when the map pans we need to use a boolean to stop it from starting the effect several times:

    google.maps.event.addListener(map,'tilesloaded',function(){
      if(played === false){
        // [...other code...]
        played = true;
      }
    });

    You can read the current timestamp of a video with video.currentTime and whilst the movie is playing it constantly fires an event called timeupdate. As the event fires a lot we need to throttle it somehow. The trick here is to only take the full seconds and increase a counter when a new second is reached. You can see the timestamp and the second interval firing in the video syncing demo:

    HTML5 video with timestamp

    var now = 0;
    v.addEventListener('timeupdate',function(o){
      log.innerHTML = v.currentTime; /* logging the real timestamp */
      var full = parseInt(v.currentTime);
      if(full >= now) {
        seqlog.innerHTML = now;  /* logging the seconds firing */
        now = now + 1;
      }
    },false);

    That way the movie can lag in between and the sequence still stays in sync. Check the source of this demo on Github.

    Putting it all together

    And that was about it – all I had to do is to set the movie’s opacity at a certain time stamp, start the sound at another and show and hide the copyright complaint at another. As we rely on the timestamp for the other effects we needed a boolean switch to avoid repeated firing:

    v.addEventListener('timeupdate',function(o){
      full = parseInt(v.currentTime);
      if(full === now-1){
        mapelm.style.opacity = .8;
        v.style.opacity = .4;
      }
      if(full === animationstart+1 && audioplay === false){
        a.play();
        audioplay = true;
      }
      if(full === animationstart+2 && hidden === true){
        drmbedamned.style.display = 'block';
        hidden = false;
      }
      if(full === animationstart+3 && hidden === false){
        drmbedamned.style.display = 'none';
        hidden = true;
      }
      if(full >= now) {
        path = new google.maps.Polyline({
            path: [startpos,pos[full]],
            strokeColor: "#c00",
            strokeOpacity: .7,
            strokeWeight: 10
        });
        path.setMap(map);
        map.panTo(pos[full])
        now = now + 1;
      }
    },false);

    Another event we needed to subscribe to was the movie ending so we can stop the music and start to roll the credits:

    v.addEventListener('ended',function(o){
      a.pause();
      spirit.credslist.parentNode.style.display = 'block';
      spirit.creds();
    },false)

    As the theme is too short for the whole animation we need to loop it. This can be done by testing for the ended event and rolling back the time to 0:

    a.addEventListener('ended', function(o) {
      a.currentTime = 0;
    },false);

    Summary

    And there you have it – Indiana Jones style maps using open services and open technologies. A workaround for the copyrighted audio (recorded, edited and converted with the free Audacity sound editor) and using Google’s Web Fonts as graphics.

    You can now take this and change it for even more awesome:

    • Replace Google Maps with Openstreetmap to avoid going over the limit
    • Add a slight curve to the path from NYC to Paris to make it more accurate (but then again the time is not accurate either – it took charles a tad longer)
    • Use a static map and paint the path with Canvas to speed up and smoothen the animation

    Why not have a go – it is free and fun to play.

  2. Delivering the good message of local storage

    As you might know there are an incredible amount of advent calendar blogs out at the moment each delivering one cool article for each day of December until Christmas.

    Today (6/12/11) two calendar blogs delivered an article of mine talking about the benefits of using local storage in browsers and how to implement it.

    You can find the English version on the 24ways.org calendar and a German translation at the Webkrauts calendar.

    In essence, the article explains why it is a good idea to use local storage, explains how to use it, how to work around the issue that local storage can only store strings and gives example code on how to speed up web service use by caching information client-side much like you would do it on a server.

    Have a read and go speed up your own solutions by using what browsers provide you these days.

  3. Results from our Developer Survey #2

    To follow up on the developer survey from last November, we did a second survey this past March after the releases of Firefox 3.6 and Firebug 1.5 to gauge developer reactions to the latest features in the browser and a much improved version of everyone’s favorite developer tool.

    In this post we’ll share the results of our latest survey and provide some data and insights from all the great feedback we have received.  We hope this will help us better understand developers’ needs and continue to build out the Mozilla Developer Network to better engage with them.

    Recap of the November 2009 Survey

    As a refresher, here is a summary of the initial November 2009 survey. The main takeaways were as follows:

    • Our community is made up of a diverse set of developers that cover all aspects of web development from design to back-end work.
    • Open standards are by far the most popular technologies used for web development work.
    • Firefox is the most common browser used first by developers for testing their work, primarily because of the many developer tools and Add-ons available for Firefox and Mozilla’s strong support for web standards.
    • Firebug stood out as the most popular developer tool and many developers agreed that it is “absolutely essential for development.”

    Results from the March 2010 Survey

    Our second developer survey received 2,267 responses over two months from late March to early June.

    For this survey there were several common questions from the previous one  – about browser preferences – so that we could measure satisfaction over time and follow trends in browser adoption following the release of Firefox 3.6.
    We also responded to the overwhelmingly enthusiastic praise of Firebug by asking for feedback on the most recent release.  By obtaining more specific feedback on the latest version of Firebug, we hope to address any remaining issues to make it an even more effective and attractive tool for developers.

    Developer Browser Preferences

    We did not see much change in browser preferences from November 2009 to March 2010.  Even considering a new iteration of Firefox and increasing competition from other browsers, the data still reflect general browser market share trends: the latest versions of Firefox and Chrome gained at the expense of older versions of IE.

    The following data show the primary browsers developers use to test their websites:

    Which browser(s) do you test your web sites against to make sure they are compatible?

    November 2009


    Tested Against
    Percent
    Firefox 3.5 82.03%
    IE 8 74.63%
    IE 7 68.23%
    Chrome 60.23%

    March 2010

    Tested Against Percent
    Firefox 3.6 80.17%
    IE 8 70.23%
    Chrome 62.37%
    IE 7 56.18%

    The numbers are unlikely to shift drastically because regardless of developers’ personal preferences, the top browsers listed above are the ones most commonly used by regular users, as demonstrated by browser market share data. Thus it makes sense that developers test against these browsers most often.

    Firefox isn’t just the most popular browser for developing, according to the data below; it’s also popular for personal usage. It should be noted, however, that this survey was distributed primarily though Mozilla-related channels, so there might be some bias in the results; we address this problem later in the report.

    Note also that the vast majority of developers were quick on the uptake switching from 3.5 to 3.6.

    Have you tried Firefox 3.6?

    Upgrading to Firefox 3.6

    Although the vast majority of developers switched from 3.5 to 3.6, there were still some who did not. In fact, roughly 10% of the March survey respondents still used 3.5. The primary reasons for the continued usage on 3.5, however, had little to do with personal preference. Roughly half of those who still used 3.5 did not even know that 3.6 was released, while the other half responded that they didn’t have time to update.

    One interesting note from the results was that a lot of developers still using Firefox 3.5 were on Linux distros that did not yet have the Firefox 3.6 package available at the time they took the survey.  Given that 23% of respondents develop on the Linux platform, that could explain why so many had not made the jump.

    What operating system do you mainly use for your development environment?

    Unfortunately the data lacked specific details on why developers did not know about 3.6 or why they did not find time to update to the next version.  With that said, regardless of the reasons, it is clear we should focus on facilitating the update process for future iterations of Firefox.  We will start by promoting early betas and announcing new Firefox releases on the MDN website.

    Feedback on Firebug 1.5

    We all know that Firebug is important to developers, so we wanted to focus on getting Firebug-related feedback for this survey. Comments about Firebug echoed those from the November survey: the consensus is that “Firebug is the single most important tool in web development.” Indeed Firebug is considered such a critical tool in the developer’s arsenal that several of you asked us to package Firebug as a built-in component of Firefox instead of just as an Add-on; some users call the duo the “triple F”: Firefox and Firebug.

    While the 1.5 release was a huge improvement from previous versions, developers weren’t shy about sharing their frustrations and feature requests.  Many noted occasional stability issues, such as when Firebug is finding elements in document trees or taking certain Ajax requests. Additionally, we received several suggestions for improving the user interface, such as incorporating more Firefox-native design elements, increasing the size of the “Deactivate Firebug” button, and removing elements like the “Quick Info” and “CSS Overview” boxes.

    One data point that stood out was that about 22% of developers had not tried Firebug 1.5 at the time they took the survey.  Considering that it was released in January and the survey was open from March to June, we would have expected that the adoption of such an important tool to be higher than what the data suggests.  This presents an opportunity to better communicate new releases and raise awareness among developers to make sure they are up-to-date on the latest development happening with Firebug.

    Have you tried Firebug 1.5?

    For those of you who are interested in learning more about documentation, features, and related news, visit the Firebug website.  Along with regular blog posts from the team, the site will host community forums for discussions with community and Firebug team members and offer ways to get involved if you want to contribute to the project.  Firebug 1.6 development is well underway and we’ll continue to see it evolve to meet web developers’ needs.

    Next Steps

    Thus far your feedback via our first two surveys has been invaluable as we strive to build a better open Web through the Mozilla Developer Network.  We now have a decent snapshot of the type of development you do, the technologies and tools you use, and the browsers you prefer for both work and personal use.  The insights we have gained will help us refine the MDN roadmap and guide the programs we develop over of the next year to better engage with developers and build out the MDN website to meet your needs.

    Our next step is to move beyond these initial data to get a larger snapshot of the developer community. We will start by designing an informal survey to get a grasp of what developers here at Mozilla and within our immediate community have to say about the tools and resources they find the most valuable for their work.  We plan to follow that up with more research on the web developer community as a whole by distributing an industry-wide survey.

    The goal for Q3 is to design a survey that can be distributed to a more diverse and unbiased global developer community.   Ultimately our goal is to have the clearest possible picture of the global web developer community and how it views the current “state of the Web”.

    

  4. HTML5 adoption stories: box.net and html5 drag and drop

    This is a guest post from Tomas Barreto, a developer who works at box.net. They recently adopted HTML5 drag and drop as a way to share files with other people using new features in Firefox. The included video is a pitch for the feature and service, but shows how easy it is to do simple HTML5-based upload progress even with multiple files. Tomas gives an overview of the relatively simple JavaScript required to do this, and how improvements in Firefox 4 will make things even easier. Also have a quick look at the bottom of the post for links to additional docs and resources.

    At Box.net, we’re always exploring new ways to help users get content quickly and securely onto our cloud content management platform. So when asked, “What feature would make you use Box more?” during the Box Hack Olympics in April, my colleague CJ and I decided to tackle the most intuitive way to upload files: simply dragging them from the desktop into Box.

    We considered technologies ranging from Gears to Firefox plugins, but only HTML5 had sufficient adoption. By using some of the JavaScript APIs defined in the HTML5 standard, CJ and I could create a seamless drag and drop experience for our users on supporting browsers. Furthermore, using an HTML5-based upload feature would allow us to enable users to select multiple files at once, and also display progress on the client without polling. And with HTML5 adoption across the latest versions of three of the top four browsers, we felt confident about building an upload method based on this new technology without the trade-offs of using a third-party plug-in.

    We rolled out the first rev of our drag and drop feature a few weeks ago, and we’re impressed with how quickly it has been adopted. It’s already one of the most popular ways to get files onto Box, and in its first week it surpassed our old AJAX upload method. You can check out our demo video to get a feel for the feature:

    To build this feature, we referenced a handful of online examples that explained how to use Firefox 3 FileReader object and the drag and drop file event support. Our first implementation used this object to load the file into memory and then took advantage of the latest XMLHttpRequest events to track progress on the client.

    var files = event.originalEvent.dataTransfer.files; // drop event
    var reader = new FileReader();
     
    reader.onload = function(event) {
      var file_contents = event.target.result;
      var request = new XMLHttpRequest();
     
      ... // attach event listeners to monitor progress and detect errors
     
      var post_body = '';
     
      .. // build post body
     
      post_body += file_contents;
     
      .. // finish post body
     
      var url = 'http://example.com/file_upload';
     
      var request = new XMLHttpRequest();
     
      request.open("POST",  url, true); // open asynchronous post request
      request.setRequestHeader('content-type', 'multipart/form-data; boundary=""'); // make sure to set a boundary
      request.send(post_body);
    }
     
    reader.readAsBinaryString(files[0]);

    This approach worked well because we could use the same server processing code that we previously used for uploads. The main disadvantage here is that the FileReader object reads the entire file into memory, which is not optimal for a general upload use case. Our current HTML5 implementation uses this logic and has forced us to restrict drag and drop uploads to just 25mb. However, thanks to recommendations from the Mozilla team, we’ll be taking an alternative approach for V2 of drag and drop, where the file is read chunks as needed by the request. Here’s how we’re going to do it:

    var files = event.originalEvent.dataTransfer.files; // drop event
    var url = 'http://example.com/file_upload';
     
    var request = new XMLHttpRequest();
    request.open("POST",  url, true); // open asynchronous post request
    request.send(files[0]);

    Since this approach is not formatted as a multipart form-data, it will require some adjustments on our back-end to support receiving file uploads in this way. However, it’s definitely worth the trade-off since we’ll get all the benefits of the previous method and we don’t need special file size restrictions. In the future, we’ll consider using yet another way to efficiently upload files that is supported in Firefox 4 and uses the traditional multi-part form:

    var files = event.originalEvent.dataTransfer.files; // drop event
    var url = 'http://example.com/file_upload';
     
    var request = new XMLHttpRequest();
     
    var fd = new FormData;
    fd.append("myFile", files[0]);
     
    request.open("POST",  url, true); // open asynchronous post request
    request.send(fd);

    We’re already exploring more ways to enrich the Box experience using HTML5. With HTML5, we can build faster, richer and more interactive features with native browser support, and bridge the traditional gap between desktop software and web applications. Here are just a few cool new upload-related features on our roadmap:

    • Pause/Resume uploads using the Blob slice API to split files into chunks (this will be a huge robustness boost, especially for large uploads)
    • Allowing uploads to resume even after the browser closes by caching the file using IndexedDB support (possibly in Firefox 4)

    We’d also like to begin a discussion about supporting the reverse drag and drop use case: dragging files from the browser to the desktop. Based on our users’ enthusiasm around the drag and drop upload feature, we think the reverse functionality would well received. If you are interested in contributing to a specification for this feature, please let us know (html5 [-at$] box.net)!

    Resources:

  5. Firefox: 46 features you might not know about

    Ever since the release of Firefox 3 we’ve been doing a lot of work to add new capabilities for web developers. We thought it would be worth it to make a post that actually listed all of the features that we knew about and people might not know about. This contains everything that we’ve done over the last three releases or so, but calls out stuff that’s new in 3.6.

    Enjoy!

    CSS

    @font-face

    Display online fonts (supports WOFF and TTF fonts)

    pointer-events

    Click through elements

    :-moz-locale-dir(ltr/rtl)

    Know if you are in a ltr or rtl context

    :indeterminate pseudo-class

    For “indeterminate” radio and checkboxes

    Media Queries

    Select CSS depending on the media (size, aspect-ratio, colors, orientation, resolution). has new classes to detect if you’re on a touch device.

    Structural pseudo-classes

    :nth-child, :nth-last-child, :nth-of-type, :nth-last-of-type, …

    -moz-border-radius

    Rounded borders

    CSS Transforms

    Scale, translate, skew and rotate your elements

    CSS Gradients

    Use linear and radial gradients as backgrounds

    Multiple Background

    Use images, gradients and other items all as part of the same background

    Background size

    Define the size of your background images

    CSS Columns

    Display your content in columns

    Text Shadow

    Shadow around text

    Box Shadow

    Shadow around elements

    Border image

    Use images as border for your elements

    rem length unit

    Size your elements compared to the root text element

    Image Rendering Algorithm

    Optimize speed or quality for resized images

    XMLHttpRequest

    Cross Domain XMLHttpRequest

    Allows XMLHttpRequest to other domains

    Monitoring Request Progress

    Calculate percentages of uploads or downloads

    Send binary data

    Send non-ASCII content

    Read binary data from a request

    Read binary data sent by a server from an XMLHttpRequest

    Offline

    Offline and online events

    Get notified when the browser goes online or offline

    localStorage

    Store persistent data

    HTML5 Application Cache

    Build an application for offline use in Firefox

    Content

    Video Tag (poster attribute)

    Embed videos directly in your web page

    Audio Tag

    Embed audio files in your web pages

    Canvas Element

    Draw bitmap data with JavaScript

    Animated PNG graphics

    Animate your transparent PNG graphics

    SVG Support

    Draw, manipulate and get events for vector graphics

    ForeignObject

    Add HTML content inside an SVG element

    Apply SVG effects and transforms to plain old HTML content

    CSS mask, clip-path, or filter with SVG

    Interaction

    In-page Drag and Drop

    Cleanly support Drag and Drop inside of your web application

    Drag and Drop files from the Desktop

    Drag and drop files directly from the operating system into your web page

    DNS Pre-fetching

    Speed up web page loading with DNS prefetching

    Geolocation

    Retrieve someone’s GPS coordinates or Street address

    Mouse gesture events

    Swipe, Magnify and Rotate from your mousepad

    Detecting device orientation

    Events for detecting machine orientation

    Web Based protocol handlers

    Set up a web app to support a protocol like “mailto:” or “phone:”

    Detecting document width and height changes

    Figure out when someone changes the size of a document

    Communicate between windows and iframes

    Securely send messages from one document to another

    JavaScript and API

    Native JSON

    Encode and decode JavaScript objects safely and quickly

    Web Workers

    Run JavaScript code in a thread

    File API

    Read the binary content of files from Drag and Drop and File Upload controls

    QuerySelector

    Find an element in the web page through a CSS Selector

    classList

    Easily manipulate the classes of an element

    defer and async attributes for scripts elements

    Improve the performance of page loads with new script attributes
  6. Firefox 3.6 feedback

    Firefox 3.6 was released on Jan 21st and has already been downloaded more than 35 million times! It features a faster JavaScript engine, faster DOM performance and a bunch of new HTML5 features. Highlights for web developers include support for the WOFF font format, new CSS features like gradients and multiple backgrounds, drag and drop, File API, device orientation, and more. Want to see the full list? Look at our Firefox 3.6 for Developers page on developer.mozilla.org.

    We hope that you took the time to test Firefox 3.6 on your web sites before the release. If you didn’t, it’s not too late to let us know about issues. Here are a few problems that we’ve seen in the wild so far:

    • We’ve seen a couple of issues with the FCKEditor component, used widely on the web. It apparently doesn’t handle dates after 2009 properly (this is the first major browser release in 2010, a new decade!) and it also has some problems with document.readyState.
    • People who had the YSlow extension installed saw crashes with Firefox 3.6. YSlow has been updated to version 2.0.6 to fix the issue
    • Some Facebook apps were broken by a change we made to comply with the upcoming HTML5 standard. We updated element.getElementsByTagNameNS and document.getElementsByTagNameNS to no longer case-fold when doing tag name lookups. (We strongly suggest that you only use lower-case for tag names for many reasons, including this.) For more information, please see this note from Henri Sivonen about what’s changed. Facebook has since fixed the issue in their code, but other sites may also be tripping over this.

    We’re looking for feedback on any developer-facing regressions you’ve seen in 3.6 from 3.5. Please comment on this post if you have feedback.

  7. an HTML5 offline image editor and uploader application

    Many web applications use image uploaders: image hosting websites, blog publishing applications, social networks, among many others. Such uploaders have limitations: you can’t upload more than one file at a time and you can’t edit the image before sending it. A plugin is the usual workaround for uploading more than one image, and image modifications are usually done on the server side, which can make the editing process more cumbersome.

    Firefox 3.6 offers many new Open Web features to web developers, including even more HTML5 support. This post describes how to create a sophisticated image editor and uploader built using Open Web technologies.

    See below for a video of the demo with some background.

    Hosted on hacks, publishes to twitpic

    Our web application uploads pictures to twitpic, an image hosting service for Twitter.

    Note that code for this application is actually hosted on the hacks web server but can still upload to Twitpic. Uploading to Twitpic is possible because they opened up their API to Cross Domain XMLHttpRequests for applications like this. (Thank you twitpic!).

    Web Features

    The demo uses the following features from HTML5 included in Firefox 3.6:

    • HTML5 Drag and Drop: You can drag and drop items inside of the web page and drag images from your desktop directly into the browser.
    • HTML5 localStorage: to store the image data across browser restarts
    • HTML5 Application Cache: This allows you to create applications that can be used when the browser isn’t connected to the Internet. It stores the entire app in the browser and also gives you access to online and offline events so you know when you need to re-sync data with a server.
    • HTML5 Canvas: The HTML5 Canvas element is used through this demo to edit and render images.
    • Cross-Origin Resource Sharing to host an application at one site and publish data to another.

    What’s in the demo?

    See the live demo to try the image uploader for yourself. You will need Firefox 3.6 and a twitter account.

    Here’s a full list of the things that this application can do:

    • You can drag images from your desktop or the web into the application.
    • You can see a preview of each image you want to upload.
    • You can drag previews to the trash to delete an image.
    • Images are automatically made smaller if they are bigger than 600px wide.
    • You can edit any of the images before uploading. This includes being able to rotate, flip, crop or turn an image black and white.
    • If you edit an image it’s saved locally so you can still edit when you’re offline. If you close the tab, restart Firefox or your computer they will be there when you load the page again so you can upload when you’re re-connected.
    • It will upload several files at once and provide feedback as the upload progresses.
    • The HTML5 Offline Application Cache makes the application load very quickly since it’s all stored offline.

    Under the Hood

    Let’s quickly go over all of the technology that we’re using in this application.

    Cross-XMLHttpRequest

    Twitpic was nice enough to open their API to allow XMLHttpRequests from any other domain. This means that you can now use their API from your own website and offer your own image uploader.

    If you’re running a web site with an API you want people to use from other web sites, you can do that with Cross-site HTTP requests. In order for you to support it you will need to add an HTTP header to responses from your web server that says which domains you allow. As an example, here’s how twitpic allows access from all domains:

    Access-Control-Allow-Origin: *
    

    It’s important to note that opening your API does have security implications so you should be careful to understand those issues before blindly opening an API. For more details, see MDC documentation on CORS.

    Drag and Drop

    Drag and Drop is a mechanism with two important features:

    • Dragging files from your Desktop to your web page.
    • Native Drag and Drop inside your web page (not just changing the coordinates of your elements).

    The image uploader uses Drag and Drop to allow the user the add files from the Desktop, to remove files (drag them to the trash) and to insert a new image into a current image.

    For more on Drag and Drop, see previous hacks articles, in particular how to use Drag and Drop in your application.

    Canvas to Edit Images

    Once images have been dragged and dropped into the web page, the image uploader lets you edit them before uploading. This is possible because images are actually copied to canvas elements via the File API.

    In this case, the editing process is really basic: rotate, flip, add text, black and white, crop. However, you can imagine offering many other features in your version of the editor (see Pixastic for example, or this inlay feature here).

    Using canvas and the File API also let you resize the image before sending it. Here, every image is converted to a new image (canvas) that is less than 600px.

    localStorage: Save Local Data

    It’s possible to store local data persistently in a web page using localStorage, up to 5Mb of data per domain.

    In the image uploader, localStorage is used to store images and credentials. Since images are actually canvas, you can store them as data URLs:

    var url = canvas.getContext("2d").toDataURL("image/png");
    localStorage.setItem("image1", url);

    LocalStorage support means that you can edit an image, close Firefox, switch off your computer, and the edited image will still be there when you restart Firefox.

    Offline

    If you add a manifest file listing all remote files needed to display your web application it will work even when you aren’t connected to the Internet. A nice side effect is that it will also make your application load much faster.

    Here, the html element refers to a manifest file:

    <html manifest="offline.manifest">

    And the manifest file looks like:

    CACHE MANIFEST
    
    # v2.4
    index.xhtml
    fonts/MarketingScript.ttf
    css/desktop.css
    css/fonts.css
    css/mobile.css
    [...]
    

    You can also catch offline and online events to know if the connection status changes.
    For more information see our last article about offline.

    Conclusion

    Firefox 3.6 allows millions of people to take advantage of modern standards, including HTML5.
    The image uploader described here shows how a web page should really be considered as an application since it interacts with your Desktop and works offline.

    Here are a few tips for writing your next application using Open Web technologies:

    Allow Cross-XMLHttpRequest:
    If it makes sense for your service, allow people to access your API from a different domain, you’ll be amazed at the apps people will come up with.

    Allow multiple input:
    Let people Drag files to your application and use <input type="file" multiple=""> so they can select several files at once. In this demo, we use a multiple input which is visible only in the mobile version, but for accessibility consideration, don’t forget to use it to propose an alternative to Drag’n Drop.

    Use native Drag and Drop:
    Drag and Drop mechanisms are usually simulated (updating coordinates on the mousemove event.) When you can, use the native mechanism.

    Use the File API
    To pre-process a file before even talking to a server.

    Support offline
    Store data and use a manifest to make your application data persistent while offline.

    Use Canvas
    Canvas is the most widely implemented HTML5 element. It works everywhere (even if it has to be simulated), use it!

    Think “Client Side”: HTML5, CSS3 and the new powerful JavaScript engines let you create amazing applications, take advantage of them!

    We look forward to seeing the great new applications you’ll come up with using Open Web technologies!

  8. ClassList in Firefox 3.6

    This article was writt by Anthony Ricaud, French OpenWeb enthusiast.

    Why you need classList

    A dynamic web application usually needs visual feedback from its inner mechanism or needs to display different visual elements based on users’ actions.

    To change the user interface easily, you can add/remove/edit elements through the DOM API (document.createElement, div.removeChild, elt.style.color, …) but it’s easier to just update the elements’ class attribute to change how they are displayed and styled by CSS.

    Let’s take an example. Suppose you want to display a form with two modes: a basic mode, and an expert mode with extra options.

    This can be done with CSS rules: each mode has its own class and set of CSS code.

    #anexpertinput.basic {
      display: none;
    }
    #anexpertinput.expert {
      display: inline;
    }

    To dynamically change the classes of elements, you can use element.className. However, you may want to add, remove, or toggle just one class. There used to be two ways to do this, by using a library or by writing complex code with regular expressions. There is now another way with the new HTML5 API called classList, which is implemented in Firefox 3.6.

    Let’s see how it can simplify your code and improve performance at the same time.

    The classList API

    Here is an example to show you what the classList API looks like:

    // By default, start without a class in the div: <div class=""/>
     
    // Set "foo" as the class by adding it to the classList
    div.classList.add('foo'); // now <div class="foo"/>
     
    // Check that the classList contains the class "foo"
    div.classList.contains('foo'); // returns true
     
    // Remove the class "foo" from the list
    div.classList.remove('foo'); // now <div class=""/>
     
    // Check if classList contains the class "foo"
    div.classList.contains('foo'); // returns false: "foo" is gone
     
    // Check if class contains the class "foo",
    // If it does, "foo" is removed, if it doesn't, it's added
    div.classList.toggle('foo'); // class set to <div class="foo"/>
    div.classList.toggle('foo'); // class set to <div class=""/>

    Demo

    Let’s go back to our initial example of a form with both a basic and an expert mode – check out the live demo to see it in action.

    As you can see in the code below, you can switch between the two modes with one line of JavaScript.

    <button onclick="document.getElementById('box').classList.toggle('expert');">
      Toggle expert mode
    </button>
    <div id="box">
      <label for="nick">Name: <input type="text" id="nick" /></label>
      <label for="status">Status: <input type="text" id="status" /></label>
      <p id="help"> Blablablablabla...</p>
      <label for="postpone">Postpone: <input type="checkbox" id="postpone" /></label>
      <label for="lang">Lang: <input type="text" id="lang" /></label>
    </div>
    #box.expert > #help,
    #box.expert > label[for="postpone"],
    #box.expert > label[for="lang"] {
       display: none;
    }

    See the Mozilla documentation and the HTML5 specification for more details on classList.

    Performance

    Using the classList API is not only easier, it’s also more powerful. Take a look at what we observed using Firefox 3.6.

    benchmark classList

    Interoperability

    Since other browser vendors have not yet implemented the HTML5 classList API, you still need fallback code. You can use this sample code as fallback.

    To know more about the current implementation of classList in well-known JavaScript libraries, see:

  9. industry support for WOFF and Firefox 3.6

    Today we announced the release of Firefox 3.6 and users are starting to upgrade. One of the more important features we included for developers was support for a new font standard called WOFF.

    WOFF has received wide support from the type community and we’re starting to see the results of that. There are a couple of specific instances that we’d like to point out on day zero of our release:

    1. FontFont, one of the largest type foundries in the world, announced a free-as-in-beer demo font in the WOFF format called FF Nuvo Medium Demo. This is part of FontFont’s commitment to support the new format and to start to give people the tools to start to adopt it.

    2. Typekit, a commercial hosting provider for fonts, announced that they will start serving up WOFF fonts to Firefox 3.6 users.

    It’s great to see commercial support already ramping up to support the new format. It’s going to really improve the experience for users on the web.

  10. Firefox 3.6 is here!

    Firefox 3.6 has some cool consumer facing features like Personas and a better Plug-in Updater, but developers have a lot to be excited about too.  Developers will appreciate the increased stability, especially the work done to prevent crashes with third party software.  There are also enhancements like improved JavaScript performance and optimizations to speed up everyday Web tasks to make web applications snappier.  However, what developers will be most interested in are all the new features around CSS3 and HTML5 that bring the future of the Web to Firefox 3.6 today. 

    This is an exciting release because we have built on the progress we made with Firefox 3.5 just a few months ago and have implemented even more cutting-edge features that will make the Web experience more engaging and interactive than ever before.

    Today’s Firefox 3.6 release and the upcoming mobile release of Firefox for Maemo are both based on Gecko 1.9.2 and bring a number of big features including:

    For a more in-depth look at all the changes that developers will want to know about please check out Firefox 3.6 for Developers on MDC. And if you haven’t already, go get Firefox 3.6 now!