1. the new about:hacks newsletter

    Yesterday, we published the first issue of about:hacks, Mozilla’s newsletter for web developers. If you asked to receive news and updates from Mozilla in our November survey, it should be waiting for you in your inbox.

    abouthacksheader

    About:hacks will be published monthly, and will include demos, tutorials, Firefox release information, the latest on web standards and developer tools, and updates on the Mozilla Developer Network.

    This first issue includes, among other things, a demo that combines Processing and multi-touch, an HTML5 video tutorial, a preview of Firebug 1.5 and Eventbug, and a sneak peek at what’s going on behind the scenes at Mozilla.

    We know you may already be reading the hacks blog, following @mozhacks on Twitter, and maybe even subscribing to mozhacks on YouTube, so we’ll make sure the newsletter is a good mix of original content and a recap of some of the most important things that happened in the previous month.

    This is why your feedback is very important: what did you like? what would you change? what would you like to see in the next issue? Let us know and we’ll make sure to write the newsletter you want to read!

    If you haven’t seen about:hacks, check it out, and if you like it, subscribe to get the next issue in January.

  2. autobuffering video in Firefox

    John Gruber recently wrote up an article titled Why the HTML5 ‘Video’ Element Is Effectively Unusable, Even in the Browsers Which Support It

    He’s mostly upset that browsers don’t respect the autobuffer attribute. Or, really, that browsers autobuffer by default. Safari and Chrome do apparently autobuffer by default, but he incorrectly says that Firefox does as well. Just to be clear: Firefox does not autobuffer by default, nor does it autoplay by default. I’m not sure how his testing led him to believe that it does, but I wrote up some examples to show that it does not. Here are three examples:

    The best way to test this is to load your favorite browser and clear its cache. Then load your favorite network monitor. Then load the page without the autobuffer attribute set. You can see how much bandwidth the browser is actually using via your external tool.

    Of the browsers I tried, only Firefox gives useful feedback on how much is actually buffered as part of its native control set so you have to go to external tools to be able to tell what’s going on with anything else. If you load the page with two videos – one with autobuffer set and one without - you can mouse over them in Firefox and see how one has buffered and one hasn’t.

    The video on that test page is pretty big – around 115mb – so you can really tell when it’s buffering even on a fast network.

    Here’s what my testing shows:

    This is consistent with what I know about Safari. I talked with one of the Apple WebKit engineers a few months ago and he said that Safari for desktops buffered by default and said that Safari for mobile does not.

    There might be some confusion because Firefox does make a couple of network requests when you include a video tag. This is done for two reasons:

    • To get the first frame of the video and it’s size. It will only download a small part of the beginning of the video to get the first frame and then stop downloading.
    • If your server supports byte range requests, it seeks to the end of the video to try and determine the duration of the video. If your server doesn’t support byterange requests, we don’t get the duration. (Ogg was originally designed as a format for streaming, not static files and as such doesn’t include duration information in the header of the file, although there is work underway to add this functionality.)

    If you want to get a sense of how Firefox uses bandwidth, try this bandwidth test I wrote a few months ago. It uses a Firefox-only feature to read progress information on a video as it’s downloaded and give you a rough sense of the amount of bandwidth that particular video element is using. It shows a little traffic when you load the video and then shows how it starts using bandwidth once you press the play button.

    But this shows that we understand John’s point of view and we made the decision not to auto buffer by default for the very reasons he points out.

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

    Demo

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

    Uploading

    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 = e.target.result;
      // bin is the binaryString
    };
    reader.readAsBinaryString(file);

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

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

    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) / e.total);
        // do something
    }, false);
  4. file drag and drop in Firefox 3.6

    In a previous post, we showed you how to upload several files using the input element. In Firefox 3.6, you can let your users drag and drop files directly into your web page, without going through the file picker.

    Demo

    If you’re running the latest Firefox 3.6 beta, check out our interactive demo of drag and drop. It showcases two technologies: the Drag and Drop API and the File API.

    Drag and Drop Events

    To use drag and drop, you first need to tell the browser that a given element can handle dropped objects and will respond to a drop action, using the dragover and drop events.

    You also need to prevent the browser’s default behavior, which is to simply load the dropped object in the browser window.

    dropzone.addEventListener("dragover", function(event) {
      event.preventDefault();
    }, true);
    dropzone.addEventListener("drop", function(event) {
      event.preventDefault();
      // Ready to do something with the dropped object
    }, true);

    You may also want to use the dragenter and dragleave events to be notified when a drag session starts or stops.

    Your element is now ready to receive files with the drop event.

    Manipulating the Files

    On the drop event, you can access the files with the files property of the DataTransfer object:

    dropzone.addEventListener("drop", function(event) {
      event.preventDefault();
      // Ready to do something with the dropped object
      var allTheFiles = event.dataTransfer.files;
      alert("You've just dropped " + allTheFiles.length + " files");
    }, true);

    Once you’ve accessed the files, the File API lets you do much more, like parsing files as a binary array, or displaying a preview of an image by reading the file as a DataURL.

    Of course, you can still drag and drop data other than files (e.g. text, URLs, remote images …) using the drag and drop API.

  5. WebGL Draft Released Today

    Even without a draft specification of WebGL in circulation, we’ve seen some promising 3D content using WebGL appear on the web, put together mainly through developer ingenuity and the fact that Firefox, Chromium, and WebKit are open source projects with early support for the technology. Today, the WebGL Working Group at Khronos released a provisional public draft of the WebGL specification, and we are very excited for what this means for the web.

    For one thing, it means more developers can get involved in the evolution of WebGL. There’s a public mailing list set up, so that you can engage directly with members of the WebGL Working Group, as well as a web forum. It’s important to note that the specification is not yet finalized. Participation from the web community is essential towards finalizing the specification, which we hope to do in the first quarter of 2010.

    It also means that there are implementations of the draft specification that you can begin to test. You can obtain a Firefox nightly that implements the WebGL draft specification, and can turn on WebGL support in that build by following these steps:

    • Type “about:config” in your browser’s URL bar
    • Do a search for “webgl” in the Filter field
    • Double-click the “enabled_for_all_sites” preference to change it to “true

    Other browsers that support the draft WebGL specification are listed on the WebGL Wiki.

    Now of course, this is hardware-accelerated 3D graphics in an early beta, and for now requires an OpenGL 2.0-capable GPU and drivers. In particular, most flavors of Intel’s integrated GPUs will not work straight out of the box (such as the GMA900/GMA950 often found in laptops). Developers who build nightly builds of the browser can induce software rendering using Mesa, and should check out Vlad’s blog post for doing this on Windows. Caveat emptor: building software rendering using Mesa into a Firefox nightly is likely to yield slower performance, and is only for the intrepid.

    WebGL is a royalty-free, cross-platform API that brings OpenGL ES 2.0 to the web as a 3D drawing context within HTML5′s Canvas element, exposed as low-level interfaces within the Document Object Model.

    Developers familiar with the Canvas 2D context will recognize that WebGL is another context for Canvas:

    // get the canvas element in the DOM
    var canvas = document.getElementById("canvas3D");
    var gl = canvas.getContext("experimental-webgl");

    Note that till the specification is finalized, the context is called experimental-webgl.

    WebGL uses the OpenGL shading language, GLSL ES, and can be cleanly combined with other web content that is layered on top or underneath the 3D content. It is an emerging web standard, and is designed to be used with other parts of the web platform. The release of the draft specification is one step in bringing about a plugin free 3D API to the web, usable straight out of the box. People have already begun using it to create compelling libraries. Check out X3DOM, which is a JavaScript library using WebGL that allows users to author content in X3D. We expect developer ingenuity to surprise and awe us, as it always has.

    References

  6. multiple file input in Firefox 3.6

    Firefox 3.6 supports multiple file input. This new capability allows you to get several files as input at once, using standard technologies. This is a big improvement, since you used to be constrained to one file at a time, or needed to use a third party (proprietary) application. This will be particularly useful, for example, for photo uploads.

    The input tag

    To let your user select a local file, use the input tag on your Web page. This will show the file picker to the user:

    <input type="file"/>

    In Firefox 3.6, the input tag has been expanded to support multiple files:

    <input type="file" multiple=""/>

    The user will still see the same file picker, but will be able to select more than one file.

    The form tag

    You can still use the classic form mechanism:

    <form method="post" action="upload.php" enctype="multipart/form-data">
      <input name='uploads[]' type="file" multiple=""/>
      <input type="submit" value="Send">
    </form>

    If the server side code is in PHP, don’t forget to make sure that the value of the name attribute has brackets. The brackets are not from the HTML specification, but are required to manipulate the result of the request as an array (see PHP documentation).

    Here’s an example, which goes through the file list and prints each file name:

    foreach ($_FILES['uploads']['name'] as $filename) {
        echo '<li>' . $filename . '</li>';
    }

    Using File API

    Firefox 3.6 also supports FileAPI. This allows you to do extra processing on the client slide before sending the files to the server. You can access the selected files with the files property of the input DOM element and then manipulate the files using the FileAPI.

    For example, here’s how to get the name of each file selected by the user. This is done on the client side, unlike the previous PHP example.

      var input = document.querySelector("input[type='file']");
      // You've selected input.files.length files
      for (var i = 0; i < input.files.length; i++) {
        // input.files[i] is a file object
        var li = document.createElement("li");
        li.innerHTML = input.files[i].name;
        ul.appendChild(li);
      }

    Demo

    See this mechanism in action in our multiple file input demo. You’ll need Firefox 3.6 (beta).

    Documentation

    To learn more about multiple file input, check out the documentation on MDC.

  7. Firefox 3.6 FileAPI demo: reading EXIF data from a local JPEG file

    Paul Rouget has put together a great demo of the new FileAPI we’re including in Firefox 3.6. It lets you drag a JPG from the desktop into the browser that includes EXIF data and it can extract the GPS coordinates in the image and then load the location of where the photo was taken, entirely from JavaScript.

    If you have the Firefox 3.6 beta, you can view the demo or you can just watch the video below.

  8. W3C FileAPI in Firefox 3.6

    Often, web applications will prompt the user to select a file, typically to upload to a server. Unless the web application makes use of a plugin, file selection occurs through an HTML input element, of the sort <input type="file"/>. Firefox 3.6 now supports much of the W3C File API, which specifies the ability to asynchronously read the selected file into memory, and perform operations on the file data within the web application (for example, to display a thumbnail preview of an image, before it is uploaded, or to look for ID3 tags within an MP3 file, or to look for EXIF data in JPEG files, all on the client side). This is a new API, and replaces the file API that was introduced in Firefox 3.

    It is important to note that even before the advent of the W3C File API draft (which only became a Working Draft in November 2009), Firefox 3 and later provide the ability to read files into memory synchronously but that capability should be considered deprecated in favor of the new implementation in Firefox 3.6 of the asynchronous File API. The deprecated API allowed you synchronously access a file:

    // After obtaining a handle to a file
    // access the file data
    var dataURL = file.getAsDataURL();
    img.src = dataURL;

    While Firefox 3.6 will continue to support code usage of the sort above, it should be considered deprecated since it reads files synchronously on the main thread. For large files, this could result in blocking on the result of the read, which isn’t desirable. Moreover, the file object itself provides a method to read from it, rather than having a separate reader object. These considerations informed the technical direction of the new File API in Firefox 3.6 (and the direction of the specification). The rest of this article is about the newly introduced File API.

    Accessing file selections

    Firefox 3.6 supports multiple file selections on an input element, and returns all the files selected using the FileList interface. Previous versions of Firefox only supported one selection of a file using the input element. Additionally, the FileList interface is also exposed to the HTML5 Drag and Drop API as a property of the DataTransfer interface. Users can drag and drop multiple files to a drop target within a web page as well.

    The following HTML spawns the standard file picker, with which you can select multiple files:

    <input id="inputFiles" type="file" multiple="" />

    Note that if you don’t use the multiple attribute, you only enable single file selection.

    You can work with all the selected files obtained either through the file picker (using the input element) or through the DataTransfer object by iterating through the FileList:

    var files = document.getElementById("inputFiles").files;
     
    // or, for a drag event e:
    // var dt = e.dataTransfer; var files = dt.files
     
    for (var i = 0; i < files.length; i++) {
      var file = files[i];
      handleFile(file);
     
    }

    Properties of files

    Once you obtain a reference to an individually selected file from a FileList, you get a File object, which has name, type, and size properties. Continuing with the code snippet above:

    function handleFile(file) {
        // RegExp for JPEG mime type
        var imageType = /image\/jpeg/;
     
        // Check if match
        if (!file.type.match(imageType)) {
            return false;
        }
       // Check if the picture exceeds set limit
       if(file.size > maxSize) {
          alert("Choose a smaller photo!");
          return false;
       }
      // Add file name to page
      var picData = document.createTextNode(file.name);
      dataGrid.appendChild(picData);
      return true;
    }

    The size attribute is the file’s size, in bytes. The name attribute is the file’s name, without path information. The type attribute is an ASCII-encoded string in lower case representing the media type of the file, expressed as an RFC2046 MIME type. The type attribute in particular is useful in sniffing file type, as in the example above, where the script determines if the file in question is a JPEG file. If Firefox 3.6 cannot determine the file’s type, it will return the empty string.

    Reading Files

    Firefox 3.6 and beyond support the FileReader object to read file data asynchronously into memory, using event callbacks to mark progress. The object is instantiated in the standard way:

    var binaryReader = new FileReader();

    Event handler attributes are used to work with the result of the file read operation. For very large files, it is possible to watch for progress events as the file is being read into memory (using the onprogress event handler attribute to set the event handler function). This is useful in scenarios where the drives in question may not be local to the hardware, or if the file in question is particularly big.

    The FileReader object supports three methods to read files into memory. Each allows programmatic access to the files data in a different format, though in practice only one read method should be called on a given FileReader object:

    • filereader.readAsBinaryString(file); will asynchronously return a binary string with each byte represented by an integer in the range [0..255]. This is useful for binary manipulations of a file’s data, for example to look for ID3 tags in an MP3 file, or to look for EXIF data in a JPEG image.
    • filereader.readAsText(file, encoding); will asynchronously return a string in the format solicited by the encoding parameter (for example encoding = "UTF-8"). This is useful for working with a text file, for example to parse an XML file.
    • filereader.readAsDataURL(file); will asynchronously return a Data URL. Firefox 3.6 allows large URLs, and so this feature is particularly useful when a URL could help display media content in a web page, for example for image data, video data, or audio data.

    An example helps tie this all together:

    if (files.length > 0) {
        if (!handleFile(files[0])) {
            invalid.style.visibility="visible";
            invalid.msg = "Select a JPEG Image";
         }
    }
     
    var binaryReader = new FileReader();
    binaryReader.onload = function(){
       var exif = findEXIFInJPG(binaryReader.result);
       if (!exif) {
          // ...set up conditions for lack of data
       }
       else {
        // ...write out exif data
       }
     
    binaryReader.onprogress = updateProgress;
    binaryReader.onerror = errorHandler;
     
    binaryReader.readAsBinaryString(file);
     
    function updateProgress(evt){
       // use lengthComputable, loaded, and total on ProgressEvent
       if (evt.lengthComputable) {
              var loaded = (evt.loaded / evt.total);
              if (loaded < 1) {
                // update progress meter
                progMeter.style.width = (loaded * 200) + "px";
              }
       }
    }
     
    function errorHandler(evt) {
      if(evt.target.error.code == evt.target.error.NOT_FOUND_ERR) {
       alert("File Not Found!");
      }
    }

    In order to work with binary data, the use of the charCodeAt function exposed on strings will be particularly useful. For instance, an utility of the sort:

    function getByteAt(file, idx) {
        return file.charCodeAt(idx);
    }

    allows extraction of the Unicode value of the character at the given index.

    An example of similar code in action in Firefox 3.6, including use of the readAsDataURL method to render an image, as well as binary analysis of a JPEG for EXIF detection (using the readAsBinaryString method), can be found in Paul Rouget’s great demo of the File API..

    A word on the specification

    The existence of a W3C public working draft of the File API holds the promise of other browsers implementing it shortly. Firefox 3.6′s implementation is fairly complete, but is missing some of the technology mentioned in the specification. Notably, the urn feature on the File object isn’t yet implemented, and neither is the ability to extract byte-ranges of files using the slice method. A synchronous way to read files isn’t yet implemented as part of Worker Threads. These features will come in future versions of Firefox.

    References

  9. css backgrounds in Firefox 3.6

    Firefox 3.6 allows you to do more with CSS backgrounds: you can use gradients, set a background size, and specify multiple backgrounds.

    Custom Background Size

    In Firefox 3.6, you can specify the size of a background image to scale it as a percentage of the element’s size, or to a specific length, using -moz-background-size.

    -moz-background-size:  <bg-size>[, <bg-size>]*

    Percentages. In this example, you can see the effect of setting a size using percentages. On the left, size is set to auto, which maintains the original size of the background image. In the center, size is set to 100%, which scales the background image to 100% of the area (horizontally), even if the original image was smaller than the background positioning area. On the right, size is set to 10%, which scales the image to 10% of the area. The background image is repeated by default.

    css_bgsize_autoto10_fxlogo

     .bg_example_left {
      background: url(http://demos.hacks.mozilla.org/openweb/resources/images/logos/firefox-48.png);
      -moz-background-size: auto;
    }
     .bg_example_center {
      background: url(http://demos.hacks.mozilla.org/openweb/resources/images/logos/firefox-48.png);
      -moz-background-size: 100%;
    }
     .bg_example_right {
      background: url(http://demos.hacks.mozilla.org/openweb/resources/images/logos/firefox-48.png);
      -moz-background-size: 10%;
    }

    Here’s the same example (auto – 100% – 10%) using a different background image. In this case, the original is larger than the background area. As a result, specifying “auto” shows only a portion of the original, and you need to set a size of 100% to make the full image visible.

    css_bgsize_autoto10_flowers

    Horizontal and Vertical Scaling. It it possible to define a size for both horizontal and vertical scaling. Specifying only one size sets horizontal scaling (as in the examples above) and vertical defaults to “auto”. If a second size is specified, it is used for vertical scaling, as in the example below. On the left you can see an image with horizontal scaling of 100% and vertical defaulting to “auto”. On the right, horizontal is set to 100% and vertical is 30%, changing the original appearance of the image because of the change in proportions.

    css_bg_size_vert

      -moz-background-size: 100%;
      -moz-background-size: 100% 30%;

    Custom Size Demo. Try our interactive demo: select the size of a background on the fly. You’ll need the latest beta of Firefox 3.6.

    Multiple Backgrounds

    Firefox 3.6 also enables you to stack multiple backgrounds. This allows you to create cool effects by stacking a gradient on top of an image for example.

    Defining. To define multiple backgrounds, simply list them as follows, using the background CSS property:

    .foo {
      background: background1, background2, ..., backgroundN;
    }

    The order in which you list the backgrounds matters: the first in the list will appear as the top layer, the last one as the bottom layer.

    Setting Properties. For multiple backgrounds, you can set the same properties you would for a single background, such as background-position or background-repeat. Define each background’s behavior by specifying a value for each property. The values need to be listed in the order in which you initially listed the backgrounds.

    So if you defined:

      background: background1, background2, background3;

    List the values in the same order for each property:

      background-position: background1_position, background2_position, background3_position;
      background-repeat: background1_repeat, background2_repeat, background3_repeat;

    Example. Here’s how to stack three different backgrounds: the Firefox logo, a linear gradient, and an image with flowers. If you’re running Firefox 3.6 beta, you can turn on and off any or all of the three backgrounds in our interactive demo.

    css_multibg

     .multi_bg_example {
      background: url(http://demos.hacks.mozilla.org/openweb/resources/images/logos/firefox-48.png), -moz-linear-gradient(left, rgba(255, 255, 255, 0),  rgba(255, 255, 255, 1)), url(http://demos.hacks.mozilla.org/openweb/resources/images/patterns/flowers-pattern.jpg);
      background-repeat: no-repeat, no-repeat, repeat;
      background-position: bottom right, left, right;
    }