XMLHttpRequest Articles

Sort by:


  1. JavaScript Error- and XHR Log Recording With Every Bug Report

    Let’s start with a story. A user story:

    A friend of mine called me in the middle of the day with a very strange request. He told me

    “Could you come over and help me to fill-in a form”.

    I was surprised as filling forms is the easiest thing to do online, isn’t it? Even for not so-tech-savvy people.

    So I went to my friend’s home and surprise, it wasn’t so easy! It took me 25 min to debug what was wrong with this website (a government one, in Bulgaria). The problem was missing validation (via XMLHttpRequest).

    Of course, I called the agency, expecting everything to go to /dev/null/, but surprisingly they were interested in the problem, so I spent another 25 min explaining the problem and sending them all data they needed. These included:

    1. Screen Size
    2. Browser and OS version
    3. Where exactly the problem occurs
    4. Javascript errors and XHR Logs (pasted in an email)
    5. Plugins installed on my friend’s browser

    etc, etc, etc … you know what I am talking about.

    It was exhausting.

    The perfect bug report

    Let’ step aside from the story and think more like developers. What a developer will need to fix the problem quickly, WITHOUT asking the user difficult questions:

    • Screen size, plugins, installed on your browser, URL where the problem happened, OS and Browser version
    • A visual and annotated screenshot showing where exactly is the problem and how it looks like through the user’s eyes with all steps on how to reproduce the bug.


    Wait, something is missing.

    The worst thing about most error reports from users is that they happen on the client-side, in front-end javascript, a cruel, cruel place, far away from the developer trying to fix them.

    Agreed? That’s why a perfect bug report should contain something else – a browsable JavaScript error- and XHR-logs recorder.


    Let’s Talk Code: Recorded JavaScript Errors

    The Usersnap Console Recorder saves every kind of JavaScript error. You can browse through the web developer console in the Usersnap dashboard, as if you would sit right on your user’s browser!

    Every error / log contains a NTP synced timestamp, a full stack including JavaScript source files and line numbers and formatting like the developer console you already know from Firebug

    Every debug log issued by console.log,, console.warn or console.error gets properly formatted (including recursive object/array formatting and browsing).

    Guaranteed no [object Object] hell during debugging!

    Accessing Properties of Undefined/Null Objects

    First example which happens quite often in the wild: a fixed element should be aligned by another element by using the top property during scrolling.

    However, due to a markup rework, the element #inexistent does no longer exist. This leads to offset() returning null and the property top can no longer be accessed:

    function clicky() {"Accessing a property of an undefined object");
        console.log("calculating scroll top %d", $('#inexistent').offset().top);

    Calling Methods of Undefined Objects

    Another rework case here: One tries to call a method on an undefined object.

    function clicky2() {"Calling a method of an undefined object");

    Plain Exceptions

    Sometimes you even know during development that something can break – wouldn’t it be great to know it when it actually breaks?

    function clicky3() {"Throwing an exception");
        throw "Version Mismatch!";

    XHR Errors

    Sometimes, XHRs deliver errors (like 404 Not Found or 500 Internal Server Error). Most of the time, such errors lead to bugs which are very hard to reproduce.

    function clicky4() {"404 on XHR");
            "url": "non_existing.php"

    Cross-Origin XHRs are troublesome. Image someone changes the CORS header and your cross origin XHR does no longer work from one day to another.

    function clicky5() {"Cross-Origin on XHR");
            "url": ""

    XHR and Time Tracking

    Recording the Steps During a Checkout

    Conversion rates are key in most businesses. Any obstacle for the user can lower your rates – e.g. it takes too long to load a page or you even have an error during checkout.

    This short example shows a standard click handler which calls getcheckout.php via XHR. Unfortunately, the second XHR (confirm.php) fails and throws a JavaScript exception. That’s nice, but: the user does not get any feedback. The page just stalls.

    function checkout() {
        console.log("check out clicked!");
            url: "getcheckout.php",
            dataType: "json"
        }).done(function(data) {
            console.log("Checked out: %o", data);
    function confirm() {
            url: "confirm.php"
        }).error(function() {
            throw "internal server error on confirm!";

    Additionally, you will get a full synced time frame of your user’s action (regardless if the time on the user’s browser is correct or not!). The full formatting support for objects (console.log(“Checked out: %o”, data);) is super convenient for debugging.


    Now every developer can have the superpower of understanding what the problem is even on the client-side and stop worrying about “It does not work. Fix it ASAP!” type of communication.

    And now every user will be able to report the issues better, because he/she needs just to press one button to report and issue, using the tools he/she knows well, and the magic will happen in the background.

    Free licenses for FOSS projects

    We at Usersnap support and believe in the FOSS (Free/Libre and Open Source) movement and that’s why Usersnap is free (as in free beer) for any FOSS project to use.

    We utilize a number of open source components like nginx, python, rabbitmq, angular and giving back to the community + improving the quality of your projects is a way to say “Thanks”

    Your project must meet all of the following criteria to be approved:

    • The project is licensed under a license approved by the Open Source Initiative.
    • The project source code is available for download.
    • Your open source project has a publicly accessible website.

    Apply here.

  2. Aurora 6 is here

    What’s new in Aurora 6?

    The most notable addition to this new Aurora are the <progress> element, window.matchMedia API, better APIs for binary data, Server-Sent Events as well as the return of WebSockets.

    Aurora 6 has been published last week and can be downloaded from

    The <progress> element

    screenshot of progress bars as seen on windows
    This element can be used to give a visual cue of something in progress in the page. System progress bars are being used, which means that users of MacOS and Linux will see something different than what is pictured here.


    window.matchMedia() is the javascript equivalent of CSS Media Queries.

    Binary data APIs improvements

    • XHR2 responseType and response attributes allow getting the response from an XHR in the form of efficient Blob or ArrayBuffer.
    • FileReader.readAsArrayBuffer() allow reading files and get the response as an ArrayBuffer.
    • BlobBuilder allow concatenating multiple blobs as well as text and ArrayBuffer into a single Blob.

    Expect to see even more improvements in this area in Aurora 7.

    Server Sent Events

    Server Sent Events are a mean for a server-side script to generate client-side events accompanied with data.

    Messages generated on the server-side with a text/event-stream mime-type and consist of a list of events data.

    data: data generated by the server
    data: this line will generate a second event

    WebSockets are back!

    WebSockets can be used to create an interactive communication channel between a browser and a server. They are already used to build “HTML5” chats, multiplayer games, and much much more.
    Note that this API will be temporarily namespaced in prevision of upcoming changes to the specification.

    Other Interesting Additions

    Learn about what’s new in Aurora 6’s user interface on and let us know what you think.

  3. The shortest image uploader – ever!

    A couple of line of JavaScript. That’s all you need.

    This is a very short Image Uploader, based on API. If you want to do more complex stuff (like resize, crop, drawing, colors, …) see my previous post.

    Back-story. I’ve been talking to‘s owner (Hi Alan!). He recently added Drag’n Drop support to his image sharing website. But also, Alan allows Cross-Domain XMLHttpRequest (thank you!). So basically, you can use his API to upload pictures to his website, from your HTML page, with no server side code involved – at all.

    And here is an example of what you can do:

    (see the full working code on github – live version there )

    (also, you’ll need to understand FormData, see here)

    function upload(file) {
      // file is from a <input> tag or from Drag'n Drop
      // Is the file an image?
      if (!file || !file.type.match(/image.*/)) return;
      // It is!
      // Let's build a FormData object
      var fd = new FormData();
      fd.append("image", file); // Append the file
      fd.append("key", "6528448c258cff474ca9701c5bab6927");
      // Get your own key:
      // Create the XHR (Cross-Domain XHR FTW!!!)
      var xhr = new XMLHttpRequest();"POST", ""); // Boooom!
      xhr.onload = function() {
        // Big win!
        // The URL of the image is:
       // Ok, I don't handle the errors. An exercice for the reader.
       // And now, we send the formdata

    That’s all :)

    Works on Chrome and Firefox 4 (Edit:) and Safari.

  4. How to develop a HTML5 Image Uploader

    HTML5 comes with a set of really awesome APIs. If you combine these APIs with the <canvas> element, you could create a super/modern/awesome Image Uploader. This article shows you how.

    All these tips work well in Firefox 4. I also describe some alternative ways to make sure it works on Webkit-based browsers. Most of these APIs don’t work in IE, but it’s quite easy to use a normal form as a fallback.

    Please let us know if you use one of these technologies in your project!

    Retrieve the images

    Drag and drop

    To upload files, you’ll need an <input type=”file”> element. But you should also allow the user to drag and drop images from the desktop directly to your web page.

    I’ve written a detailed article about implementing drag-and-drop support for your web pages.

    Also, take a look at the Mozilla tutorial on drag-and-drop.

    Multiple input

    Allow the user the select several files to upload at the same time from the File Picker:

    <input type="file" multiple>

    Again, here is an article I’ve written about multiple file selection.

    Pre-process the files

    Use the File API

    (See the File API documentation for details.)

    From drag-and-drop or from the <input> element, you have a list a files ready to be used:

    // from an input element
    var filesToUpload = input.files;
    // from drag-and-drop
    function onDrop(e) {
      filesToUpload = e.dataTransfer.files;

    Make sure these files are actually images:

    if (!file.type.match(/image.*/)) {
      // this file is not an image.

    Show a thumbnail/preview

    There are two options here. You can either use a FileReader (from the File API) or use the new createObjectURL() method.


    var img = document.createElement("img");
    img.src = window.URL.createObjectURL(file);


    var img = document.createElement("img");
    var reader = new FileReader();
    reader.onload = function(e) {img.src =}

    Use a canvas

    Once you have the image preview in an <img> element, you can draw this image in a <canvas> element to pre-process the file.

    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);

    Resize the image

    People are used to uploading images straight from their camera. This gives high resolution and extremely heavy (several megabyte) files. Depending on the usage, you may want to resize such images. A super easy trick is to simply have a small canvas (800×600 for example) and to draw the image tag into this canvas. Of course, you’ll have to update the canvas dimensions to keep the ratio of the image.

    var MAX_WIDTH = 800;
    var MAX_HEIGHT = 600;
    var width = img.width;
    var height = img.height;
    if (width > height) {
      if (width > MAX_WIDTH) {
        height *= MAX_WIDTH / width;
        width = MAX_WIDTH;
    } else {
      if (height > MAX_HEIGHT) {
        width *= MAX_HEIGHT / height;
        height = MAX_HEIGHT;
    canvas.width = width;
    canvas.height = height;
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0, width, height);

    Edit the image

    Now, you have your image in a canvas. Basically, the possibilities are infinite. Let’s say you want to apply a sepia filter:

    var imgData = ctx.createImageData(width, height);
    var data =;
    var pixels = ctx.getImageData(0, 0, width, height);
    for (var i = 0, ii =; i < ii; i += 4) {
        var r =[i + 0];
        var g[i + 1];
        var b =[i + 2];
        data[i + 0] = (r * .393) + (g *.769) + (b * .189);
        data[i + 1] = (r * .349) + (g *.686) + (b * .168)
        data[i + 2] = (r * .272) + (g *.534) + (b * .131)
        data[i + 3] = 255;
    ctx.putImageData(imgData, 0, 0);

    Upload with XMLHttpRequest

    Now that you have loaded the images on the client, eventually you want to send them to the server.

    How to send a canvas

    Again, you have two options. You can convert the canvas to a data URL or (in Firefox) create a file from the canvas.


    var dataurl = canvas.toDataURL("image/png");

    Create a file from the canvas

    var file = canvas.mozGetAsFile("foo.png");

    Atomic upload

    Allow the user to upload just one file or all the files at the same time.

    Show progress of the upload

    Use the upload events to create a progress bar:

    xhr.upload.addEventListener("progress", function(e) {
      if (e.lengthComputable) {
        var percentage = Math.round((e.loaded * 100) /;
        // do something
    }, false);

    Use FormData

    You probably don’t want to just upload the file (which could be easily done via: xhr.send(file)) but add side information (like a key and a name).

    In that case, you’ll need to create a multipart/form-data request via a FormData object. (See Firefox 4: easier JS form handling with FormData.)

    var fd = new FormData();
    fd.append("name", "paul");
    fd.append("image", canvas.mozGetAsFile("foo.png"));
    fd.append("key", "××××××××××××");
    var xhr = new XMLHttpRequest();"POST", "");

    Open your API

    Maybe you want to allow other websites to use your service.

    Allow cross-domain requests

    By default, your API is only reachable from a request created from your own domain. If you want to allow people use your API, allow Cross-XHR in your HTTP header:

    Access-Control-Allow-Origin: *

    You can also allow just a pre-defined list of domains.

    Read about Cross-Origin Resource Sharing.


    (Thanks to Daniel Goodwin for this tip.)

    Also, listen to messages sent from postMessage. You could allow people to use your API through postMessage:

    document.addEventListener("message", function(e){
        // retrieve parameters from
        var key =;
        var name =;
        var dataurl =;
        // Upload
    // Once the upload is done, you can send a postMessage to the original window, with URL

    That’s all. If you have any other tips to share, feel free to drop a comment.

    Enjoy ;)

  5. HTML5 adoption stories: and html5 drag and drop

    This is a guest post from Tomas Barreto, a developer who works at 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, 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 =;
      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 = '';
      var request = new XMLHttpRequest();
  "POST",  url, true); // open asynchronous post request
      request.setRequestHeader('content-type', 'multipart/form-data; boundary=""'); // make sure to set a boundary

    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 = '';
    var request = new XMLHttpRequest();"POST",  url, true); // open asynchronous post request

    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 = '';
    var request = new XMLHttpRequest();
    var fd = new FormData;
    fd.append("myFile", files[0]);
"POST",  url, true); // open asynchronous post request

    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$]!


  6. Firefox 4: easier JS form handling with FormData

    This feature has landed in Mozilla Central (trunk) and only available with a Firefox Nightly Build for the time being.

    XMLHttpRequest Level 2 (editor’s draft) adds support for the new FormData interface. FormData objects provide a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the XMLHttpRequest send() method in “multipart/form-data” format.

    Why FormData?

    When you want to send complex data to a server from a web page (files, non-ASCII content), you must use the multipart/form-data content type. To set the content type in a <form>, you write:

    <form method="post" enctype="multipart/form-data" action="">
    <input type="file" name="media"/>
    <input name="nickname"/>
    <input name="website"/>
    <input type="submit" value="upload"/>

    This is what you usually do to upload a file.

    Starting with Firefox 3.6, you can manipulate files with JavaScript (see File API), and maybe you want to send files using XMLHttpRequest. But if, for example, you want to reproduce this form, it’s really hard because you’ll have to create the multipart/form-data content yourself in JavaScript (see, for example, this code I wrote a while ago implementing a multipart/form-data: ugly and slow).

    This is where FormData is useful: to reproduce the <form> submission mechanism in JavaScript

    The FormData object

    The FormData object lets you compile a set of key/value pairs to send using XMLHttpRequest. This object has only one method:

    append(key, value);

    where key is the name of your value, and where value can be a string or a file.

    You can create a FormData object, append values and then send it through XMLHttpRequest. If you want to simulate the previous form, you write:

    // aFile could be from an input type="file" or from a Dragged'n Dropped file
    var formdata = new FormData();
    formdata.append("nickname", "Foooobar");
    formdata.append("website", "");
    formdata.append("media", aFile);
    var xhr = new XMLHttpRequest();"POST", "");

    FormData and the <form> element

    Firefox extends the HTML form element slightly, adding a getFormData() method that lets you fetch a form’s data as a FormData object. This is not yet part of the HTML standard, but is expected to be added to the specification at some point in the future (although possibly with a different name):

    var formElement = document.getElementById("myFormElement");
    var xhr = new XMLHttpRequest();"POST", "submitform.php");

    You can also add data to the FormData object between retrieving it from a form and sending it, like this:

    var formElement = document.getElementById("myFormElement");
    formData = formElement.getFormData();
    formData.append("serialnumber", serialNumber++);

    This lets you augment the form’s data before sending it along, to include additional information that’s not necessarily user editable on the form.


  7. WebSockets in Firefox

    Here’s the pitch for WebSockets: a low-complexity, low-latency, bi-directional communication system that has a pretty simple API for web developers. Let’s break that down, and then talk about if and when we’re going to include it in Firefox:


    The WebSocket protocol, which is started via an HTTP-like handshake, has a relatively simple model for sending text packets back and forth. The complexity of the protocol is quite low. There’s no multiplexing, no support for binary data, and once the data connection is set up, the actual transport is quite cheap.

    Note that there are people who feel – possibly correctly – that support for multiplexing and binary data should be added. That would obviously increase the complexity but in some cases might be worth the cost. But more on that later.

    Bi-directional Communication

    One of the key aspects of WebSocket is its support for simple bi-directional communication. Servers can easily send updates to clients and clients can send updates to servers. Many of the comet-style applications that people have built will be much simpler and faster with this model because the protocol and API support it directly.

    While allowing for bi-directional communication it also is bound by the HTTP same-origin model. That is, it’s doesn’t give the browser the ability to connect to any site on any port it wants to.

    So WebSocket is really TCP with the HTTP security model.


    This is actually the primary value in WebSockets. The key thing is that the cost of sending a small amount of data is also very small. It’s possible to do bi-directional communication today with comet-style applications, but small amounts of data often require a huge amount of overhead to do so.

    A second-hand story to give you a sense of scale: Google Wave, which tries to do real-time communication with keystrokes has a several-kilobyte overhead for just about every keystroke because of the TCP startup, teardown and HTTP message headers involved with what should be only a few bytes sent over the wire.

    I haven’t tried, but I’m going to guess that if you built Quake on top of HTTP comet that the interactive experience would be poor. So this is where WebSockets really shine.

    Simple API

    The actual API that a developer sees for WebSocket is relatively simple. You can send messages, you can get messages, you get events when sockets open, close or there’s an error. Additional complexity, which I’m sure others will develop, will happen in JavaScript and backend libraries.

    (While this might seem like punting on the issue of complexity, this is actually the model for success we’ve seen for other browser standards: build something relatively simple that others can experiment with. When we understand what’s slow or what’s preventing progress, iterate and improve.)

    When will it be in Firefox?

    We really really want to support WebSockets in the next version of Firefox. And a lot of other people want us to include support too.

    The first set of test patches, written by the wonderful Wellington Fernando de Macedo (one of our most excellent contributors!) was first submitted in April of 2009. Since then we’ve been iterating both on the patches themselves and following the spec as it’s changed.

    Unfortunately, the spec itself is still under revision. WebSockets did ship in Chrome with version 4 and I’m told by Chrome developers that it’s going to be included in Chrome 5, without changes. Unfortunately, the version that Google included in Chrome doesn’t reflect the current draft. The handshake for how to start a WebSocket connection has changed, largely to improve security on servers. There’s also a lot of ongoing discussion on the role of integrated compression, direct support for binary data (instead of encoding binary data as strings), whether or not the protocol should support multiplexing and a number of other issues.

    Since WebSocket isn’t used widely yet, and that Chrome has an uptake rate that’s similar to Firefox, the hope is that once a more recent draft makes it through the process that both Chrome and Firefox can include a more recent version at around the same time.

    So in short: we want to ship it because the promise of WebSockets is great, but we’ll have to see if it’s stable and safe enough to do so. Code isn’t the issue – we’ve had that for a while. It’s whether or not there’s consensus on if the protocol is “done enough” to ship it to a few hundred million people.

  8. 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.


    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.


    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:

    # v2.4

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


    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!

  9. interactive file uploads with Drag and Drop, FileAPI and XMLHttpRequest

    In previous posts, we showed how to access a file through the input tag or through the Drag and Drop mechanism. In both cases, you can use XMLHttpRequest to upload the files and follow the upload progress.


    If you’re running the latest beta of Firefox 3.6, check out our file upload demo.


    XMLHttpRequest will send a given file to the server as a binary array, so you first need to read the content of the file as a binary string, using the File API. Because both Drag and Drop and the input tag allow you to handle multiple files at once, you’ll need to create as many requests as there are files.

    var reader = new FileReader();
    reader.onload = function(e) {
      var bin =;
      // bin is the binaryString

    Once the file is read, send it to the server with XMLHttpRequest:

    var xhr = new XMLHttpRequest();"POST", "upload.php");
    xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');

    You can choose to be notified when specific events, such as error, success, or abort, occur during the request (see the MDC documentation for more details).

    Following the Upload Progress

    The progress event provides the size of the uploaded portion of the binary content. This allows you to easily compute how much of the file has been uploaded.

    Here’s an example showing the percentage of the file that has been uploaded so far:

    xhr.upload.addEventListener("progress", function(e) {
      if (e.lengthComputable) {
        var percentage = Math.round((e.loaded * 100) /;
        // do something
    }, false);