Mozilla

Demos

Sort by:

View:

  1. 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!

  2. offline web applications

    The network is a key component of any web application, whether it is used to download JavaScript, CSS, and HTML source files and accompanying resources (images, videos, …) or to reach web services (XMLHttpRequest and <forms>).

    Yet having offline support for web applications can be very useful to users. Imagine, for example, a webmail application that allows users to read emails already in their inbox and write new messages even when they are not connected.

    The mechanism used to support offline web applications can also be used to improve an application’s performance by storing data in the cache or to make data persistent between user sessions and when reloading and restoring pages.

    Demo: a To Do List Manager

    To see an offline web application in action, watch Vivien Nicolas’ demo (OGV, MP4), which shows a to do list manager working online and offline on an N900 running Firefox.

    You can also check out the live demo of the application.

    Creating your Own Offline Application

    For a web application to work offline, you need to consider three things:

    Let’s see how to use each of these components.

    Storage: Persistent Data

    DOM storage lets you store data between browser sessions, share data between tabs and prevent data loss (for example from page reloads or browser restarts). The data are stored as strings (for example a JSONified JavaScript object) in a Storage object.

    There are two kinds of storage global objects: sessionStorage and localStorage.

    • sessionStorage maintains a storage area that’s available for the duration of the page session. A page session lasts for as long as the browser is open and survives over page reloads and restores. Opening a page in a new tab or window causes a new session to be initiated.
    • localStorage maintains a storage area that can be used to hold data over a long period of time (e.g. over multiple pages and browser sessions). It’s not destroyed when the user closes the browser or switches off the computer.

    Both localStorage and sessionStorage use the following API:

    window.localStorage and window.sessionStorage {
      long length; // Number of items stored
      string key(long index); // Name of the key at index
      string getItem(string key); // Get value of the key
      void setItem(string key, string data); // Add a new key with value data
      void removeItem(string key); // Remove the item key
      void clear(); // Clear the storage
    };

    Here is an example showing how to store and how to read a string:

    // save the string
    function saveStatusLocally(txt) {
      window.localStorage.setItem("status", txt);
    }
     
    // read the string
    function readStatus() {
       return window.localStorage.getItem("status");
    }

    Note that the storage properties are limited to an HTML5 origin (scheme + hostname + non-standard port). This means that window.localStorage from http://foo.com is a different instance of window.localStorage from http://bar.com. For example, http://google.com can’t access the storage of http://yahoo.com.

    Are We Offline?

    Before storing data, you may want to know if the user is online or not. This can be useful, for example, to decide whether to store a value locally (client side) or to send it to the server.

    Check if the user is online with the navigator.onLine property.
    In addition, you can be notified of any connectivity changes by listening to the online and offline events of the window element.

    Here is a very simple piece of JavaScript code, which sends your status to a server (à la twitter).

    • If you set your status and you’re online, it sends the status.
    • If you set your status and you’re offline, it stores your status.
    • If you go online and have a stored status, it sends the stored status.
    • If you load the page, are online, and have a stored status, it sends the stored status.
    function whatIsYourCurrentStatus() {
      var status = window.prompt("What is your current status?");
      if (!status) return;
      if (navigator.onLine) {
        sendToServer(status);
      } else {
        saveStatusLocally(status);
      }
    }
     
    function sendLocalStatus() {
      var status = readStatus();
      if (status) {
        sendToServer(status);
        window.localStorage.removeItem("status");
      }
    }
     
     
    window.addEventListener("load", function() {
       if (navigator.onLine) {
         sendLocalStatus();
       }
    }, true);
     
    window.addEventListener("online", function() {
      sendLocalStatus();
    }, true);
     
    window.addEventListener("offline", function() {
      alert("You're now offline. If you update your status, it will be sent when you go back online");
    }, true);

    Offline Resources: the Cache Manifest

    When offline, a user’s browser can’t reach the server to get any files that might be needed. You can’t always count on the browser’s cache to include the needed resources because the user may have cleared the cache, for example. This is why you need to define explicitly which files must be stored so that all needed files and resources are available when the user goes offline: HTML, CSS, JavaScript files, and other resources like images and video.

    The manifest file is specified in the HTML and contains the explicit list of files that should be cached for offline use by the application.

    <html manifest="offline.manifest">

    Here is an example of the contents of a manifest file:

    CACHE MANIFEST
    fonts/MarketingScript.ttf
    css/main.css
    css/fonts.css
    img/face.gif
    js/main.js
    index.xhtml

    The MIME-Type type of the manifest file must be: text/cache-manifest.

    See the documentation for more details on the manifest file format and cache behavior.

    Summary

    The key components you should remember to think about when making your application work offline are to store the user inputs in localStorage, create a cache manifest file, and monitor connection changes.

    Visit the Mozilla Developer Center for the complete documentation.

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

  6. pointer-events for HTML in Firefox 3.6

    The pointer-events CSS property has long been available as part of SVG as a way to control if a mouse event should be sent to the element directly underneath the mouse or passed through to an element underneath it. In Firefox 3.6 we’ve extended the property to allow it to apply to normal HTML content as well.

    For SVG you can set the pointer-events property to one of several values, but for HTML you can only set it to one of two values: auto or none.

    .foo {
      pointer-events: none;
    }

    When pointer-events is set to none, pointer events are passed through the target element and are instead sent to the element that is underneath it.

    .foo {
      pointer-events: auto;
    }

    When pointer-events is set to auto, pointer events are handled normally. That is, the element blocks the events from being passed down to a lower element.

    Here’s a real world example from Paul Rouget. You will need a Firefox 3.6 beta to see it in action.

    Click the pointer-events: none checkbox under the image to see it change.

    He’s replicated the tag list that’s on the front page of twitter.com. (Note: you have to not be logged in to see the tag list.) If you go and look at it on twitter you’ll notice that it fades off on the right hand side. This is done with a transparent, faded image that sits on top of the underlying box. The tags underneath are clickable links but the image blocks events from being sent to the ones underneath the fade.

    What Paul has done is show how you can use the pointer-events property to allow you to click on the underlying links even with a fade on top of it.

  7. building beautiful buttons with css gradients

    A special thanks to Ryan Doherty for building this demo and making it easy for me to turn it into a tutorial.

    In this demo we’ll walk through a simple use case for the new gradient capabilities coming in Firefox 3.6 (see related article). We’ll build a nice-looking embossed and beveled button using gradients and existing CSS properties. The button in question was developed for the next version of our Personas site.

    Using a CSS-based method to generate buttons is a huge upgrade for web site developers. It means you don’t have to regenerate images every time you change text, pages will load much faster because you don’t have to download separate images and it allows text to be easily localized. In this case it also makes the page better from an accessibility standpoint – the text contained in the <a href> can add context.

    You can see the final version of this demo, or follow along with the steps outlined here.

    Creating the Button

    A button is just a rectangular space with a link in it. We can create that with a very simple chunk of HTML:

      <a class="linear" href="http://getpersonas.com">
        <span>Get Personas for Firefox</span>
        <span class="info">It's free and installs in seconds</span>
      </a>

    This creates a paragraph element and sets a fixed width. The internal “button” is actually a simple <a> link that contains text.

    Once we have the width set on the button we need to force the <a> to act like a block element so that the text inside will flow as part of a single element instead of showing up as two distinct parts:

    display: block;

    We want to choose some nicer fonts and a nicer style:

    font-family: Helvetica, Arial, sans-serif;
    font-weight: bold;
    font-size: 138.5%;
     
    text-align: center;
    text-decoration: none;

    And add some padding around the text and set rounded corners:

    padding: 10px;
    -moz-border-radius: 10px;

    We set a border around the button and set a background color as a fallback for other browsers. (Except, of course, for IE. See the note below.)

    border: 1px solid #659635;
    background: #99ca28;

    We also want to set the color of the text and add a nice drop shadow to make the text look embossed onto the button:

    text-shadow: -1px -1px 2px #777777;
    color: #ffffff;

    Once we have that we can use the -moz-linear-gradient CSS property to define the gradient so that it has a nice bevel look at the top:

    background: -moz-linear-gradient(top, #CFE782 0%,
                                          #9BCB2A 2%,
                                          #5DA331 97%,
                                          #659635 100%);

    The syntax here is pretty simple. The “top” means that it starts at the top of the area and heads down to the bottom of the button. The rest of the syntax defines what are called “color stops.” These allow you define gradient transitions that actually transition across more than two colors. This is used in this case because the bevel effect requires a non-linear transition from one color to the next.

    In the syntax above, it defines a starting color (0%), an bevel effect (2%), most of the transition (97%) and the border color to finish (100%.) This creates the effect where it’s very light at the top as if there was a light source moving to a darker color near the bottom.

    IE Note:

    A pithy note about our good friend, Internet Explorer. While older versions of Firefox and Safari both handle the background: -moz-linear-gradient gracefully by not affecting background rendering when they run into a property they don’t know how to handle, IE just shows a white background. One possible work around for this is to include a later background: property for IE in a separate style sheet that’s loaded once this style sheet is loaded. There are probably other ways of handling this, but it’s worth noting that this is an issue.

  8. font_dragr: a drag and drop preview tool for fonts

    This demo is from our good friend Ryan Seddon who came up with a demo that seems deeply appropriate for this week, given our focus on the future of fonts on the web.

    If you’ve ever been editing a page and wanted to know what a particular font looked like without having to upload files to a web server and update CSS (so tedious, that!) then this demo is for you.

    He’s come up with a demo that shows what’s possible when you’ve got downloadable fonts, drag and drop and editable content. (If you want to know more about drag and drop we suggest you read his excellent overview of using drag and drop to do file uploading.)

    From Ryan’s description:

    Font dragr is an experimental web app that uses HTML5 & CSS3 to create a useful standalone web based application for testing custom fonts, once you visit it for the first time you don’t need to be online to use it after the initial visit. It allows you, in Firefox 3.6+, to drag and drop font files from your file system into the drop area. The browser will then create a data URL encoded copy to use in the page and render the content in the dropped font.

    You can either read the full description, which contains a lot of useful technical information about how the demo works, or you can view the demo below. Either way, it’s nice to see the excellent HTML5 support in Firefox 3.6 coming together with everything else we’ve added to bring a lot of new capabilities to web developers and users.

    Thanks, Ryan!

  9. after Firefox 3.6 – new font control features for designers

    Note: the discussion below applies to work in progress that might show up in Firefox 3.7. It does not describe features in Firefox 3.6.

    This post is from Jonathan Kew and John Daggett. He’s supplied a 5 minute video that shows some of the features on the fly. If you’re a total font nerd and you enjoy a soothing British accent, you might want to watch it.

    Using @font-face allows web designers a wide palette of font choices and with commercial font vendors supporting the WOFF font format, the set of font choices should improve even more. So the next step is clearly to try and make better use of features available in these fonts.

    For many years, “smart” font formats such as OpenType and AAT have provided font designers ways of including a rich set of variations in their fonts, from ligatures and swashes to small caps and tabular figures. The OpenType specification describes these features, identifying each with a unique feature tag. But these have typically only been available to those using professional publishing applications such as Adobe InDesign. Firefox currently renders using font defaults; it would be much more interesting to provide web authors with a way of controlling these font features via CSS.

    Håkon Wium Lie of Opera, based on discussions with Tal Leming and Adam Twardoch, proposed extending the CSS ‘font-variant’ property to include values for font features. Mozilla is actively working on a new proposal along these lines. This is a fairly big addition to CSS, so it will most likely involve some complex discussions about how best to support these features.

    Experimental Implementation

    As part of this effort, Jonathan Kew has been working on porting a portion of the Pango library for use with handling complex scripts and to enable the use of font features on all supported platforms. He currently has an experimental build that uses a special CSS property to associate a list of OpenType features with specific elements in a page. This is not the proposed format, it simply provides a better way of discussing possible sets of font-variant properties and the OpenType feature settings to which they should map.

    .altstyles {
      /* format: feature-tag=[0,1] with 0 to disable, 1 to enable */
      -moz-font-feature-opentype: "dlig=1,ss01=1";
    }

    The feature setting string above implies rendering with discretionary ligatures (dlig) and the first set of stylistic alternates (ss01). An example using Jack Usine’s MEgalopolis Extra:

    This font makes extensive use of OpenType features; the homepage of the font contains a sample rendering that uses many of these features. Below is a rendering of the same sample written in HTML with OpenType features enabled:

    Tabular Figures for Numerical Alignment

    OpenType features also enable better control over alignment. When numbers are listed in tabular form, proportional forms often result in the misalignment of digits across rows, making the list harder to scan. With tabular alignment enabled, individual digits are rendered using a fixed width so that digits align across rows:

    Automatic Fractions

    Automatic fractions are also possible with OpenType features, note the inline use of fractional forms in the recipe ingredient list below:

    Language Sensitivity

    OpenType also includes support for features on a per-language basis. This is important for rendering text correctly in some languages. For example, Turkish uses both a dotted-i and a dotless-i, so the distinction needs to be preserved when rendering ligatures or small caps. Below is the same text in English and Turkish, with both default and language-sensitive renderings shown for the Turkish text:

    Historical Text

    The way text is rendered constantly evolves; glyphs once in common use often morph into other forms, making the historical forms distinct from their modern forms. Below is the text of an old Massachusetts Bay Colony law, taken from a book in the Daniel R. Coquillette Rare Book Room of the Boston College Law Library.

    Original scanned image:

    Below is the same text rendered in HTML using the Fell Types revival fonts by Igino Marini with OpenType features enabled. Note the ‘ct’ ligature and the contextual form of the ‘s’:

    More resources

    Font feature support in CSS proposal
    OpenType font feature list
    Fell Types revival fonts by Igino Marini