Mozilla

Feature Articles

Sort by:

View:

  1. stylish text with text-shadow

    This post is from Frederic Wenzel, who works on Mozilla’s Web Development team.

    The text-shadow CSS property does what the name implies: It lets you create a slightly blurred, slightly moved copy of text, which ends up looking somewhat like a real-world shadow.

    The text-shadow property was first introduced in CSS2, but as it was improperly defined at the time, its support was dropped again in CSS2.1. The feature was re-introduced with CSS3 and has now made it into Firefox 3.5.

    How it Works

    According to the CSS3 specification, the text-shadow property can have the following values:

    none | [<shadow>, ] * <shadow>,

    <shadow> is defined as:

    [ <color>? <length> <length> <length>? | <length> <length> <length>? <color>? ],

    where the first two lengths represent the horizontal and vertical offset and the third an optional blur radius. The best way to describe it is with examples.

    We can make a simple shadow like this, for example:

    text-shadow: 2px 2px 3px #000;
    A simple shadow

    (All of the examples are a live example first, then a picture of the working feature — so you can compare your browser’s behavior with the one of Firefox 3.5 on OSX)

    If you are a fan of hard edges, you can just refrain from using a blur radius altogether:

    text-shadow: 2px 2px 0 #888;
    I don’t like blurs

    Glowing text, and multiple shadows

    But due to the flexibility of the feature, the fun does not stop here. By varying the text offset, blur radius, and of course the color, you can achieve various effects, a mysterious glow for example:

     text-shadow: 1px 1px 5px #fff;
    Glowing text

    or a simple, fuzzy blur:

    text-shadow: 0px 0px 5px #000;
    Blurry text

    Finally, you can add ”more than one shadow”, allowing you to create pretty “hot” effects (courtesy of http://www.css3.info/preview/text-shadow/ css3.info):

    text-shadow: 0 0 4px white, 0 -5px 4px #FFFF33, 2px -10px 6px #FFDD33, -2px -15px 11px #FF8800, 2px -25px 18px #FF2200
    Multiple shadows are hot

    The number of text-shadows you can apply at the same time in Firefox 3.5 is — in theory — unlimited, though you may want to stick with a reasonable amount. Like all CSS properties, you can modify text-shadow on the fly using JavaScript:

    Animated shadows with JavaScript

    Performance, Accessibility and Cross-Browser Compatibility

    The times of using pictures (or even worse, Flash) for text shadows on the web are numbered for two reasons:

    First, there are significant advantages to using text instead of pictures. Not using pictures saves on bandwidth and HTTP connection overhead. Accessibility, both for people who use screen readers and search engines, is greatly improved. And page zoom will work better because the text can be scaled instead of using pixel interpolation to scale up an image.

    Second this feature is largely cross-browser compatible:

    • Opera supports text-shadow since version 9.5. According to the Mozilla Developer Center, Opera 9.x supports up to 6 shadows on the same element.
    • Safari has had the feature since version 1.1 (and other WebKit-based browsers along with it).
    • Internet Explorer does not support the text-shadow property, but the feature degrades gracefully to regular text. In addition, if you want to emulate some of the text-shadow functionality in MSIE, you can use Microsoft’s proprietary ”Shadow” and ”DropShadow” filters.
    • Similarly to MSIE, when other, older browsers do not support the feature (including Firefox 3 and older), they will just show the regular text without any shadows.

    A caveat worth mentioning is the ”drawing order”: While Opera 9.x adheres to the CSS2 painting order (i.e., the first specified shadow is drawn at the bottom), Firefox 3.5 adheres to the CSS3 painting order (the first specified shadow is on top). Keep this in mind when drawing multiple shadows.

    Conclusions

    text-shadow is a subtle but powerful CSS feature that is — now that it is supported by Firefox 3.5 — likely to be widely adopted across the web in the foreseeable future. Due to its graceful degradation in older browsers, it can safely be used by developers and will, over time, be seen by more and more users.

    Finally, some words of wisdom: Like any eye candy, use it like salt in a soup — with moderation, not by the bucket. If the web developers of the world overdo it, text-shadow may die a short, yet painful death. It would be sad if we make users flinch at the sight of text shadows like typography geeks at the sight of “Papyrus”, and thus needed to bury the feature deeply in our treasure chest.

    That being said: Go try it out!

    Further resources

    Documentation

    Examples

  2. Announcing Firefox Aurora 10

    We’re happy to announce the availability of Aurora 10.
    (Download and Test Aurora 10)

    In additional to the normal improvements that you’ve come to expect like performance, security and bug fixes, Aurora 10 focuses in HTML5 enhancements.

    New additions

    Developer Tools

    Aurora 10 also implements incremental enhancements like IndexedDB setVersion API changes. Ongoing detailed attention to evolving specifications help to keep Firefox at the front of the Web revolution. (Read more about IndexedDB on MDN.)

    DOM

    • We now fire a “load” event on stylesheet linking when the sheet load finishes or “error” if the load fails.
    • We turn the POSTDATA prompt into an information page (when navigating in session history).
    • We only forward event attributes on body/frameset to the window if we also forward the corresponding on* property.
    • We no longer allow more than one call to window.open() when we allow popups.
    • We fixed a bug where a success callback never fired when a position update is triggered after getCurrentPosition().
    • We removed replaceWholeText().
    • We fixed an error with createPattern(zero-size canvas).
    • We now handle putImageData(nonfinite) correctly.
    • We now throw INVALID_STATE_ERR when dispatching uninitialized events.
    • We’ve made Document.documentURI readonly.
    • We fixed document.importNode to comply with optional argument omitted.

    Web workers

    • We now allow data URLs.
    • We implemented event.stopImmediatePropagation in workers.
    • We made XHR2 response/responseType work in Web Workers.

    Graphics

    • We implement the WebGL OES_standard_derivatives extension.
    • We implement minimal-capabilities WebGL mode.

    JavaScript

    • The function caller property no longer skips over eval frames.
    • We fixed E4X syntax so that it is not accepted in ES5 strict mode.
    • weakmap.set no longer returns itself instead of undefined.
    • We implemented the battery API.

    Offline: IndexedDB enhancements

    • IndexedDB setVersion API changes
    • Added support for IDBObjectStore/IDBIndex.count
    • Various methods accept both keys and KeyRanges.
    • Added support for IDBCursor.advance.
    • Implemented deleteDatabase.
    • objectStoreNames are no longer updated on closed databases when another connection adds or removes object stores
    • IDBObjectStore.delete and IDBCursor.delete now return undefined.
    • No longer throws an error if there are unknown properties in the options objects to createObjectStore/createIndex.
    • We now the errorCode to “ABORT_ERR” for all pending requests when IDBTransaction.abort() is called.
    • Fixed the sort order for indexes.

    Layout

    • We have updated the current rule for handling malformed media queries.
    • We now support the HTML5 <bdi> element and CSS property unicode-bidi: isolate.
    • The CSS3 implementation now supports unicode-bidi: plaintext.

    Media

    • Implemented Document.mozFullScreenEnabled.
    • Enabled the DOM full-screen API on desktop Firefox by default.
  3. DOM selectors API in Firefox 3.5

    The Selectors API recommendation, published by the W3C, is a relatively new effort that gives JavaScript developers the ability to find DOM elements on a page using CSS selectors. This single API takes the complicated process of traversing and selecting elements from the DOM and unifies it under a simple unified interface.

    Out of all the recent work to come out of the standards process this is one of the better-supported efforts across all browsers: Usable today in Internet Explorer 8, Chrome, and Safari and arriving in Firefox 3.5 and Opera 10.

    Using querySelectorAll

    The Selectors API provides two methods on all DOM documents, elements, and fragments: querySelector and querySelectorAll. The methods work virtually identically, they both accept a CSS selector and return the resulting DOM elements (the exception being that querySelector only returns the first element).

    For example, given the following HTML snippet:

    <div id="id" class="class">
        <p>First paragraph.</p>
        <p>Second paragraph.</p>
    </div>

    We would be able to use querySelectorAll to make the background of all the paragraphs, inside the div with the ID of ‘id’, red.

    var p = document.querySelectorAll("#id p");
    for ( var i = 0; i < p.length; i++ ) {
        p[i].style.backgroundColor = "red";
    }

    Or we could find the first child paragraph of a div that has a class of ‘class’ and give it a class name of ‘first’.

    document.querySelector("div.class > p:first-child")
        .className = "first";

    Normally these types of traversals would be very tedious in long-form JavaScript/DOM code, taking up multiple lines and queries each.

    While the actual use of the Selectors API methods is relatively simple (each taking a single argument) the challenging part comes in when choosing which CSS selectors to use. The Selectors API taps in to the native CSS selectors provided by the browser, for use in styling elements with CSS. For most browsers (Firefox, Safari, Chrome, and Opera) this means that you have access to the full gamut of CSS 3 selectors. Internet Explorer 8 provides a more-limited subset that encompasses CSS 2 selectors (which are still terribly useful).

    The biggest hurdle, for most new users to the Selectors API, is determining which CSS selectors are appropriate for selecting the elements that you desire – especially since most developers who write cross-browser code only have significant experience with a limited subset of fully-working CSS 1 selectors.

    While the CSS 2 and CSS 3 selector specifications can serve as a good start for learning more about what’s available to you there also exist a number of useful guides for learning more:

    Implementations in the Wild

    The most compelling use case of the Selectors API is not its direct use by web developers, but its use by 3rd-party libraries that already provide DOM CSS selector functionality. The trickiest problem towards adopting the use of the Selectors API, today, is that it isn’t available in all browsers that users develop for (this includes IE 6, IE 7 and Firefox 3). Thus, until those browsers are no longer used, we must use some intermediary utility to recreate the full DOM CSS selector experience.

    Thankfully, a number of libraries already exist that provide an API compatible with the Selectors API (in fact, much of the inspiration for the Selectors API comes from the existence of these libraries in the first place). Additionally, many of these implementations already use the Selectors API behind the scenes. This means that you can use using DOM CSS selectors in all browsers that you support AND get the benefit of faster performance from the native Selectors API implementation, with no work to you.

    Some existing implementations that gracefully use the new Selectors API are:

    It’s important to emphasize the large leap in performance that you’ll gain from using this new API (in comparison to the traditional mix of DOM and JavaScript that you must employ). You can really see the difference when you look at the improvement that occurred when JavaScript libraries began to implement the new Selectors API.

    When some tests were run previously the results were as follows:

    You can see the dramatic increase in performance that occurred once the libraries began using the native Selectors API implementations – it’s quite likely that this performance increase will happen in your applications, as well.

    Test Suite

    To coincide with the definition of the Selectors API specification a Selectors API test suite was created by John Resig of Mozilla. This test suite can be used as a way to determine the quality of the respective Selectors API implementations in the major browsers.

    The current results for the browsers that support the API are:

    • Firefox 3.5: 99.3%
    • Safari 4: 99.3%
    • Chrome 2: 99.3%
    • Opera 10b1: 97.5%
    • Internet Explorer 8: 47.4%

    Internet Explorer 8, as mentioned before, is missing most CSS 3 selectors – thus failing most of the associated tests.

    As it stands, the Selectors API should serve as a simple, and fast, way of selecting DOM elements on a page. It’s already benefiting those who use JavaScript libraries that provide similar functionality so feel free to dig in today and give the API a try.

  4. a multi-touch drawing demo for Firefox 3.7

    Firefox Multitouch at MozChile – Drawing Canvas Experiment from Marcio Galli on Vimeo.

    A couple of months ago we featured a video that had some examples of multi-touch working in Firefox. At a recent event in South America, Marcio Galli put together a quick and fun drawing program based on the multi-touch code that we’ll have in a later release of Firefox. What’s really great is that he was able to put this together in just a couple of hours based on the web platform.

    There are three main components to the touch support in Firefox:

    1. Touch-based scrolling and panning for the browser. This allows you, as a user, to scroll web pages, select text, open menus, select buttons, etc. This is part of Firefox 3.6.

    2. Implement a new CSS selector that will tell you if you’re on a touch-enabled device. This is -moz-system-metric(touch-enabled). You can use this in your CSS to adjust the size of UI elements to fit people’s fingers. This is part of Firefox 3.6.

    3. Exposing multi-touch data to web pages. This takes the form of DOM events much like mouse events you can catch today. This isn’t part of Firefox 3.6, but is likely to be part of Firefox 3.7.

    Although not all of this will be in our next release we thought it would be fun for people to see what will be possible with the release after 3.6.

    Note: You can find the sample code on Marcio’s page for the demo.

  5. using web workers: working smarter, not harder

    This article is written by Malte Ubl, who has done a lot of great work with using Web Workers as part of the bespin project.

    In recent years, the user experience of web applications has grown richer and richer. In-browser applications like GMail, Meebo and Bespin give us an impression of how the web will look and feel in the future. One of the key aspects of creating a great user experience is to build applications that are highly responsive. Users hate to wait and they hate those moments where an application seems to work for a while, then stops responding to their input.

    At the core of modern client-side web applications lies the JavaScript programming language. JavaScript and the DOM that it talks to is inherently single-threaded. This means that in JavaScript only one thing can happen at any given time. Even if your computer has 32 cores it will keep only one of those cores busy when it’s doing a long computation.  For example if you calculate the perfect trajectory to get to the moon it won’t be able to render an animation that shows the trajectory at the same time and it won’t be able to react to any user events like clicks or typing on the keyboard while it’s doing that calculation.

    Concurrency

    To maintain responsiveness while performing intense computations concurrency is a part of most modern programming languages. In the past concurrency was often achieved by the use of threads. Threads, however, make it increasingly hard for the programmer to understand the program flow which often leads to very hard to understand bugs and chaotic behavior when different threads manipulate the same data simultaneously.

    Web Workers, which were recommended by the WHATWG, were introduced in Firefox 3.5 to add concurrency to JavaScript applications without also introducing the problems associated with multithreaded programs. Starting a worker is easy – just use the new Worker interface.

    In this example the worker.js file will be loaded and the a new thread will be created to execute that code.

    // Start worker from file "worker.js"
    var worker = new Worker("worker.js");

    Communication between the main UI thread and workers is done by passing messages using the postMessage method. postMessage was added for cross-window communication in Firefox 3. To send a message from the worker back to the page, you just post a message:

    // Send a message back to the main UI thread
    postMessage("Hello Page!");

    To catch the message from the worker, you define an “onmessage” callback on the worker object. Here we just alert the event data that is passed to the callback function. In this case, “event.data” contains the “Hello Page!” string that was sent above.

    worker.onmessage = function (event) {
      alert(event.data);
      // Send a message to the worker
      worker.postMessage("Hello Worker");
    }

    To send a message to the worker we call the postMessage method on the worker object. To receive these messages inside the worker, simply define an onmessage function that will be called every time a message is posted to the worker.

    Error Handling

    There are two levels at which you can recover from runtime errors that occur in a worker. First, you can define an onerror function within the worker. Second, you can handle errors from the outside the worker by attaching an onerror handler on to the worker object:

    worker.onerror = function (event) {
      alert(event.message);
      event.preventDefault();
    }

    The event.preventDefault() method prevents the default action, which would be to display the error to the user or at least show it in the error console. Here we alert the error message instead.

    Shared Nothing

    Workers share absolutely no state with the page they are associated with or with any other workers; the only way they can interact at all is through postMessage. Workers also have no access to the DOM, so they can not directly manipulate the web page. There is thus no risk of problems with data integrity when multiple workers want to manipulate the same data at once.

    A standard setup that is using workers would consist of a page JavaScript component that is listening for user events. When an event occurs that triggers an intensive calculation a message is sent to the worker which then starts the computation. The script on the page, however, can terminate immediately and listen for more user events. As soon as the worker is done, it sends a return message to the page which can then, for example, display the result.


    The unresponsive script warning that is being displayed by browsers when a script is taking a long time to execute is a thing of the past when using web workers.

    The Fibonacci Example

    Next is an example of a worker that calculates the Fibonacci numbers from 0 to 99 in the background. Actually, because calculating Fibonacci numbers using this very inefficient method can take a lot of time for larger numbers (as in greater than something like 30) the script might never finish on your computer (or crash because it blows out the stack), but when doing it in a worker this has no effect on the responsiveness of the main web page. So you can still draw a complex animation to make the waiting time for the next number a little more fun.

    This HTML page contains a script that starts a worker from the file “fib-worker.js”. Messages from the worker are displayed on the browser’s console using console.log.

    <!DOCTYPE html>
    <html>
        <head>
          <title>Web Worker API Demo</title>
          <script type="text/javascript">
            var worker = new Worker("fib-worker.js");
            worker.onmessage = function (event) {
              console.log(event.data.index +" -> " + event.data.value)
            }
          </script>
        </head>
        <body>
        </body>
    </html>

    The JavaScript file that implements the worker contains a loop that calculates Fibonacci numbers and sends the result to the page.

    // File fib-worker.js
    function fib(n) {
       return n < 2 ? n : fib(n-1) + fib(n-2);
    }
     
    for(var i = 0; i < 100; ++i) {
       postMessage({
          index: i,
          value: fib(i)
       })
    }

    In the example above we see that we can also pass complex objects to the postMessage. These objects can contain everything that can be transmitted via JSON. This means that functions cannot be passed across worker boundaries and that the objects are passed by value rather than by reference.

    Worker APIs

    Workers support a function called importScripts. You can use this to load more source files into the worker.

    importScripts("file.js");
    importScripts("foo.js", "bar.js");

    When you pass multiple parameters to the function the scripts will be downloaded in parallel but executed in the order of definition. The function does not return until all scripts have been downloaded and executed.

    Here we load an external JavaScript file that calculates SHA-1 hash sums from strings and then we use it to hash responses from AJAX requests. We also use the standard XMLHttpRequest object to retrieve the content of the URL which is passed in via the onmessage event. The interesting part is that we don’t have to worry about making the AJAX request asynchronous because the worker itself is asynchronous with respect to page rendering, so a little waiting for the HTTP request does not hurt as much.

    importScripts("sha1.js")
     
    function onmessage(event) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', event.data, false);
        xhr.send();
        postMessage(sha1(xhr.responseText));
    }

    Other APIs Available to Workers

    Workers may use XMLHttpRequest for AJAX requests as seen above and access the client sided database using web storage API. Here the APIs are identical to their usage in regular JavaScript.

    The setTimeout and setInterval (and the clearTimeout and clearInterval friends) functions, which enable executing code after a given period of time or at certain intervals, are also available within the worker as is the well known navigator object, which can be inspected to get information about the current browser.

    More APIs may be added in the future.

    Browser Compatibility

    As of this writing (and to the knowledge of the author), Firefox 3.5 is the only browser that supports the ability to pass complex objects via postMessage and that implements the extended APIs defined above. Safari 4 implements a very basic version of the Worker API. For other browsers it is possible to use Workers via Google Gears, which originally introduced the concept to browsers.

    Real World Usage

    In the Bespin project, which is a browser based source code editor, we successfully used workers to implement CPU intensive features like real-time source code error checking and code completion. We also created a shim that implements the Worker API in terms of Google Gears and which adds the missing features to the worker implementation of Safari 4 and also moved to using transparent custom events on top of the postMessage interface. These components will be released as a stand-alone library to be usable in other projects in the future.

    Web Workers will play an important role in making the Open Web an even more powerful platform for sophisticated applications. Because in the end all they do is execute JavaScript, it’s easy to make scripts work on clients which do yet have the luxury of web workers. So go ahead and add them to your applications today to make them feel just a little more responsive and more pleasant to use.

  6. video – more than just a tag

    This article is written by Paul Rouget, Mozilla contributor and purveyor of extraordinary Open Web demos.

    Starting with Firefox 3.5, you can embed a video in a web page like an image. This means video is now a part of the document, and finally, a first class citizen of the Open Web. Like all other elements, you can use it with CSS and JavaScript. Let’s see what this all means …

    The Basics

    First, you need a video to play. Firefox supports the Theora codec (see here to know all media formats supported by the audio and video elements).

    Add the video to your document:

    <video id="myVideo" src="myFile.ogv"/>

    You might need to add some “fallback” code if the browser doesn’t support the video tag. Just include some HTML (which could be a warning, or even some Flash) inside the video tag.

    <video id="myVideo" src="myFile.ogv">
    <strong>Your browser is not awesome enough!</strong>
    </video>

    Here’s some more information about the fallback mechanism.

    HTML Attributes

    You can find all the available attributes here.

    Some important attributes:

    • autoplay: The video will be played just after the page loads.
    • autobuffer: By default (without this attribute), the video file is not downloaded unless you click on the play button. Adding this attribute starts downloading the video just after the page loads.
    • controls: by default (without this attribute), the video doesn’t include any controls (play/pause button, volume, etc.). Use this attribute if you want the default controls.
    • height/width: The size of the video

    Example:

    <video id="myVideo" src="myFile.ogv"
       autobuffer="true" controls="true"/>

    You don’t have to add the “true” value to some of these attributes in HTML5, but it’s neater to do so. If you’re not in an XML document, you can simply write:

    <video id="myVideo" src="myFile.ogv" autobuffer controls/>

    JavaScript API

    Like any other HTML element, you have access to the video element via the Document Object Model (DOM):

    var myVideo = document.getElementById("myVideo");

    Once you obtain a handle to the video element, you can use the JavaScript API for video.

    Here is a short list of some useful methods and properties (and see here for more of the DOM API for audio and video elements):

    • play() / pause(): Play and pause your video.
    • currentTime: The current playback time, in seconds. You can change this to seek.
    • duration: The duration of the video.
    • muted: Is the sound muted?
    • ended: Has the video ended?
    • paused: Is the video paused?
    • volume: To determine the volume, and to change it.

    Example:

    <button onclick="myVideo.play()">Play</button>
    <button onclick="myVideo.volume = 0.5">Set Volume</button>
    <button onclick="alert(myVideo.volume)">Volume?</button>

    Events

    You know how to control a video (play/pause, seek, change the volume, etc.). You have almost everything you need to create your own controls. But you need some feedback from the video, and for that, let’s see the different events you can listen to:

    • canplay: The video is ready to play
    • canplaythrough: The video is ready to play without interruption (if the download rate doesn’t change)
    • load: The video is ready to play without interruption (the video has been downloaded entirely)
    • ended: The video just ended
    • play: The video just started playing
    • pause: The video has been paused
    • seeking: The video is seeking (it can take some seconds)
    • seeked: The seeking process just finished
    • timeupdate: While the video is playing, the currentTime is updated. Every time the currentTime is updated, timeupdate is fired.

    Here’s a full list of events.

    For example, you can follow the percentage of the video that has just been played:

    function init()
    {
      var video = document.getElementById("myVideo");
      var textbox = document.getElementById("sometext");
      video.addEventListener("timeupdate", function() {
      textbox.value = Math.round(100 * (video.currentTime / video.duration)) + "%"; }
     
    }
    <video id="myVideo" src="myFile.ogv"
                autoplay="true" onplay="init()"/>
    <input id="sometext"/>

    Showing all this in action, here’s a nice open video player using the Video API.

    Now that you’re familiar with some of the broad concepts behind the Video API, let’s really delve into the video as a part of the Open Web, introducing video to CSS, SVG, and Canvas.

    CSS and SVG

    A video element is an HTML element. That means you can use CSS to style it.

    A simple example: using the CSS Image Border rule (a new CSS 3 feature introduced in Firefox 3.5). You can view how it works on the Mozilla Developer Wiki.

    And obviously, you can use it with the video tag:

     
    <video id="myVideo" src="myFile.ogv"
    style="-moz-border-image:
               url(tv-border.jpg) 25 31 37 31 stretch stretch;
               border-width: 20px;"/>

    One of my demos uses this very trick.

    Since Firefox 3.5 provides some new snazzy new CSS features, you can do some really fantastic things. Take a look at the infamous washing machine demo, in which I subject an esteemed colleague to some rotation.

    It uses some CSS rules:

    And some SVG:

    Because the video element is like any other HTML element, you can add some HTML content over the video itself, like I do in this demo. As you can see, there is a <div> element on top of the video (position: absolute;).

    Time for a Break

    Well, we’ve just seen how far we can go with the video element, both how to control it and how to style it. That’s great, and it’s powerful. I strongly encourage you to read about the new web features available in Firefox 3.5, and to think about what you can do with such features and the video element.

    You can do so much with the power of the Open Web. You can compute the pixels of the video. You can, for example, try to find some shapes in the video, follow the shapes, and draw something as an attachment to these shapes. That’s what I do here! Let’s see how it actually works.

    Canvas & Video

    Another HTML 5 element is canvas. With this element, you can draw bitmap data (see the canvas reference, and I strongly suggest this canvas overview). But something you might not know is that you can copy the content of an <img/> element, a <canvas/> element and a <video/> element.

    That’s a really important point for the video element. It gives you a way to play with the values of the pixels of the video frames.

    You can do a “screenshot” of the current frame of the video in a canvas.

    function screenshot() {
     var video = document.getElementById("myVideo");
     var canvas = document.getElementById("myCanvas");
     var ctx = canvas.getContext("2d");
     
     ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
    }
    <video id="myVideo" src="myFile.ogv" autoplay="true" with="600" height="400"/>
    <canvas id="myCanvas" with="600" height="400"/>
    <button onclick="screenshot()">Copy current frame to canvas</button>

    You can first apply a transformation to your canvas (see the documentation). You can also copy a thumbnail of the video.

    If you draw every frame in a canvas, your canvas will look like a video element. And you can draw what you want in this canvas, after drawing the frame. That’s what I do in this demo.

    Once you have a video frame in your canvas, you can compute the values of the pixels.

    Some things you should know if you want to compute the pixels values of a frame:

    • you can’t use this mechanism with a video from another domain.
    • you can’t use this mechanism with a video from a file:/// URL (which would be useful during the development of your web application). But you can change this behavior for testing: in about:config, change the value of “security.fileuri.strict_origin_policy” to “false”. But be very careful! editing about:config — that’s an expert feature!
    • There are two ways to display the result of your application on the top of the video:
      • use your canvas as a video (if you draw the frame every time), and then draw directly into the canvas
      • use a transparent canvas on the top of the video
    • the canvas element can be “display: none”
    • the video element can be “display: none”

    About JavaScript

    For the image processing, you will need to do a lot of computation. Here are some tricks:

    • copy your frame in a small canvas. If the canvas is three times smaller than the video, it means nine times fewer pixels to compute.
    • avoid recursion. In a recursion, the script engine doesn’t use the JIT optimization.
    • if you want to do a distance between colors, use the L.A.B colorspace.
    • if you want to find the center of an object, compute its centroid. See the “computeFrame” function that I use in this JavaScript snippet for my demo.
    • if the algorithm is really heavy, you can use a Worker thread, but take into account that you will need to send the content of the canvas to the thread. It’s a big array, and objects are automatically JSONified before being sent. It can take a while.

    Conclusion

    As you can see, you can do powerful things with the video element, the canvas element, CSS3, SVG and the new JavaScript engine. You have everything in your hands to create a completely new way to use Video on the web. It’s up to you now — upgrade the web!

    References

  7. pushing pixels with canvas

    This post was written by Paul Rouget, who is a member of the Mozilla Evangelism team. Paul lives in Paris, France and is well known for some of his amazing work with open video on the web among other things.

    Canvas, at its most simple level, is an easy way to draw bitmap data into an HTML page. It has methods that allow you to draw rectangles, arcs, curves and other simple primitives. However, for some types of effects and drawing you need direct access to the pixels.

    In Firefox 3.5 we’ve added a new method to the canvas element – createImageData. The createImageData call is a convenience method to create a blank set of pixels for manipulation that can eventually be copied back onto a canvas.

    Since we’re talking about a single call we thought that it might be worth it to go through all of the calls that let you read, manipulate and update the pixels directly in a canvas and put createImageData in its full context.

    Retrieving Pixel Data

    You can’t directly manipulate pixels in a canvas. In order to make changes to the data in a canvas you first need to copy the data out, make changes, and copy the changed data back to the target canvas.

    The getImageData call lets you copy a rectangle of pixels out of a canvas. A call to get all of the pixel data out of a canvas looks like this:

    var canvas = document.getElementById('myCanvasElt');
    var ctx = canvas.getContext('2d');
    var canvasData = ctx.getImageData(0, 0, canvas.width, canvas.height);

    The canvasData object contains the pixel data. It has the following members:

    canvasData {
        width: unsigned long, // the width of the canvas
        height: unsigned long, // the height of the canvas
        data: CanvasPixelArray // the values of the pixels
    }

    The data is a flat array of values that has one value for each component in a pixel, organized left to right, top to bottom, with each pixel represented as four values in RGBA order.

    For example, in a 2×2 canvas, there would be 4 pixels represented with 16 values that look like this:

    0,0  0,1  1,0  1,1
    RGBA RGBA RGBA RGBA
    

    So you can calculate the length of that array with the following formula: width * height * 4.

    In a larger canvas if you wanted to know the value of a blue in a pixel at x = 10, y = 20 you would use the following code:

    var x = 10;
    var y = 10;
    var blue = canvasData.data[(y * width + x) * 4 + 2];
    

    Note that each RGB pixel has a value of 0..255 with the alpha bit being 0..255 with 0 being completely transparent and 255 fully opaque.

    Create a new set of pixels

    If you want to create a new matrix from scratch, just use the createImageData call which needs two arguments: the height and the width of the matrix.

    Note that the createImageData call does not copy pixels out of the existing canvas, it produces a blank matrix of pixels with the values set to transparent black (255,255,255,0).

    Here’s an example you want to create a set of pixels that fits the canvas size:

    var canvas = document.getElementById('myCanvasElt');
    var ctx = canvas.getContext('2d');
    var canvasData = ctx.createImageData(canvas.width, canvas.height);

    Note that this is the method that you should use to create pixel data. Previous versions of Firefox allowed you to create a canvasData object out of a simple JavaScript object and use it in later calls to update the canvas data. This call was added to maintain compatibility with WebKit which under the hood uses a specialized object instead of a generic JavaScript object.

    Update the pixels

    Once you have the canvasData object you can update the pixel values through the array. Here’s one example of how to walk through the array reading and updating the values.

    for (var x = 0; x < canvasData.width; x++)  {
        for (var y = 0; y < canvasData.height; y++)  {
     
            // Index of the pixel in the array
            var idx = (x + y * width) * 4;
     
            // If you want to know the values of the pixel
            var r = canvasData.data[idx + 0];
            var g = canvasData.data[idx + 1];
            var b = canvasData.data[idx + 2];
            var a = canvasData.data[idx + 3];
     
            //[...] do what you want with these values
     
            // If you want to update the values of the pixel
            canvasData.data[idx + 0] = ...; // Red channel
            canvasData.data[idx + 1] = ...; // Green channel
            canvasData.data[idx + 2] = ...; // Blue channel
            canvasData.data[idx + 3] = ...; // Alpha channel
        }
    }

    Update the canvas

    Now that you’ve got a set of pixels updated you can use the simple putImageData call. This call takes the canvasData object and the x,y location where you would like to draw the rectangle of pixel data into the canvas:

    var canvas = document.getElementById('myCanvasElt');
    var ctx = canvas.getContext('2d');
    var canvasData = ctx.putImageData(canvasData, 0, 0);

    Full example for getImageData

    Here is code that transforms a color image to a grey scale version of the image. You can also see a live version of this demo on Paul’s site.

    var canvas = document.getElementById('myCanvasElt');
    var ctx = canvas.getContext('2d');
    var canvasData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    for (var x = 0; x < canvasData.width; x++) {
        for (var y = 0; y < canvasData.height; y++) {
            // Index of the pixel in the array
            var idx = (x + y * canvas.width) * 4;
     
            // The RGB values
            var r = canvasData.data[idx + 0];
            var g = canvasData.data[idx + 1];
            var b = canvasData.data[idx + 2];
     
            // Update the values of the pixel;
            var gray = (r + g + b) / 3;
            canvasData.data[idx + 0] = gray;
            canvasData.data[idx + 1] = gray;
            canvasData.data[idx + 2] = gray;
        }
    }
    ctx.putImageData(canvasData, 0, 0);

    Full example for createImageData

    This bit of code will draw a fractal into a canvas. Once again, you can see a live demo of this code on Paul’s site.

    var canvas = document.getElementById('myCanvasElt');
    var ctx = canvas.getContext('2d');
    var canvasData = ctx.createImageData(canvas.width, canvas.height);
     
    // Mandelbrot
    function computeColor(x, y) {
        x = 2.5 * (x/canvas.width - 0.5);
        y = 2 * (y/canvas.height - 0.5);
        var x0 = x;
        var y0 = y;
     
        var iteration = 0;
        var max_iteration = 100;
     
        while (x * x + y * y <= 4 && iteration < max_iteration ) {
            var xtemp = x*x - y*y + x0;
            y = 2*x*y + y0;
            x = xtemp;
            iteration++;
        }
     
        return Math.round(255 * iteration / max_iteration);
    }
     
    for (var x = 0; x < canvasData.width; x++) {
        for (var y = 0; y < canvasData.height; y++) {
            var color = computeColor(x, y);
     
            // Index of the pixel in the array
            var idx = (x + y * canvas.width) * 4;
     
            // Update the values of the pixel;
            canvasData.data[idx + 0] = color;
            canvasData.data[idx + 1] = color;
            canvasData.data[idx + 2] = color;
            canvasData.data[idx + 3] = 255;
        }
    }
     
    ctx.putImageData(canvasData, 0, 0);

    More Documentation

    If you want to know more about Canvas, we strongly encourage you to browse the MDC documentation that we have for canvas:

    We hope that this was useful for everyone and puts the single call in its full context.

  8. shadow boxing with -moz-box-shadow

    Another fun CSS3 feature that’s been implemented in Firefox 3.5 is box shadows. This feature allows the casting of a drop “shadow” from the frame of almost any arbitrary element.

    As the CSS3 box shadow property is still a work in progress, however, it’s been implemented as -moz-box-shadow in Firefox. This is how Mozilla tests experimental properties in CSS, with property names prefaced with “-moz-“. When the specification is finalized, the property will be named “box-shadow.”

    How it works

    Applying a box shadow to an element is straightforward. The CSS3 standard allows as its value:

    none | <shadow> [ <shadow> ]*

    where <shadow> is:

    <shadow> = inset? && [ <length>{2,4} && <color>? ]

    The first two lengths are the horizontal and vertical offset of the shadow, respectively. The third length is the blur radius (compare that to the blur radius in in the text-shadow property). Finally the fourth length is the spread radius, allowing the shadow to grow (positive values) or shrink (negative values) compared to the size of the parent element.

    The inset keyword is pretty well explained by the standard itself:

    if present, [it] changes the drop shadow from an outer shadow (one that shadows the box onto the canvas, as if it were lifted above the canvas) to an inner shadow (one that shadows the canvas onto the box, as if the box were cut out of the canvas and shifted behind it).

    But talk is cheap, let’s look at some examples.

    To draw a simple shadow, just define an offset and a color, and off you go:

     -moz-box-shadow: 1px 1px 10px #00f;

     

    simple box shadow

    (Each of the examples in this article are live examples first, followed by a screen shot from Firefox 3.5 on OSX).

    Similarly, you can draw an in-set shadow with the aforementioned keyword.

    -moz-box-shadow: inset 1px 1px 10px #888;

     

    inset box shadow

    With the help of a spread radius, you can define smaller (or bigger) shadows than the element it is applied to:

    -moz-box-shadow: 0px 20px 10px -10px #888;

     

    box shadow with spread radius

    If you want, you can also define multiple shadows by defining several shadows, separated by commas (courtesy of Markus Stange):

    -moz-box-shadow: 0 0 20px black, 20px 15px 30px yellow, -20px 15px 30px lime, -20px -15px 30px blue, 20px -15px 30px red;

     

    multiple box shadows

    The different shadows blend into each other very smoothly, and as you may have noticed, the order in which they are defined does make a difference. As box-shadow is a CSS3 feature, Firefox 3.5 adheres to the CSS3 painting order. That means, the first specified shadow shows up on top, so keep that in mind when designing multiple shadows.

    As a final example, I want to show you the combination of -moz-box-shadow with an RGBA color definition. RGBA is the same as RGB, but it adds an alpha-channel transparency to change the opacity of the color. Let’s make a black, un-blurred box shadow with an opacity of 50 percent, on a yellow background:

    -moz-box-shadow: inset 5px 5px 0 rgba(0, 0, 0, .5);

     

    box shadow with RGBA

    As you can see, the yellow background is visible though the half-transparent shadow without further ado. This feature becomes particularly interesting when background images are involved, as you’ll be able to see them shining through the box shadow.

    Cross-Browser Compatibility

    As a newer, work-in-progress CSS3 property, box-shadow has not yet been widely adopted by browser makers.

    • Firefox 3.5 supports the feature as -moz-box-shadow, as well as multiple shadows, the inset keyword and a spread radius.
    • Safari/WebKit has gone down a similar route as Firefox by implementing the feature as -webkit-box-shadow. Multiple shadows are supported since version 4.0, while neither inset shadows nor the spread radius feature are supported yet in WebKit.
    • Finally, Opera and Microsoft Internet Explorer have not yet implemented the box shadow property, though in MSIE you may want to check out their proprietary DropShadow filter.

    To achieve the biggest possible coverage, it is advisable to define all three, the -moz, -webkit, and standard CSS3 syntax in parallel. Applicable browsers will then pick and adhere to the ones they support. For example:

     -moz-box-shadow: 1px 1px 10px #00f;
     -webkit-box-shadow: 1px 1px 10px #00f;
     box-shadow: 1px 1px 10px #00f;

    The good news is that the box-shadow property degrades gracefully on unsupported browsers. For example, all the examples above will look like plain and boring boxes with no shadow in MSIE.

    Conclusions

    The CSS3 box-shadow property is not yet as widely available in browsers (and therefore, to users) as, for example, the text-shadow property, but with the limited box shadow support of WebKit as well as the full support provided by Firefox 3.5 (as far as the current status of the feature draft is concerned), more and more users will be able to see some level of CSS box shadows.

    As a web developer, you can therefore use the feature, confident that you are giving users with modern browsers an improved experience while not turning away users with older browsers.

    Further resources
    Documentation

    Examples

  9. Mozilla developer preview (Gecko 1.9.3a2) now available

    We’ve posted a new release of our Mozilla developer preview series as a way to test new features that we’re putting into the Mozilla platform. These features may or may not make it into a future Firefox release, either for desktops or for mobile phones. But that’s why we do these releases – to get testing and feedback early so we know how to treat them.

    Note that this release does not contain two things that have gotten press recently: D2D or the new JavaScript VM work we’ve been doing.

    Since this is a weblog focused on web developers, I think that it’s important to talk about what’s new for all of you. So we’ll jump right into that:

    Out of Process Plugins

    We did an a1 release about three weeks ago in order to get testing on some of the new web developer features (which we’ll list here again.) The biggest change between that release and this one is the inclusion of out of process plugins for Windows and Linux. (Mac is a little bit more work and we’re working on it as fast as our little fingers will type.)

    There are a lot of plugins out there on the web, and they exist to varying degrees of quality. So we’re pushing plugins out of process so that when one of them crashes it doesn’t take the entire browser with it. (It also has lots of other nice side effects – we can better control memory usage, CPU usage and it also helps with general UI lag.)

    If you want to know more about it, have a look at this post by Ben Smedberg who goes over how it works, what prefs you can set and how you can help test it. It would help us a lot of you did.

    (If you really want to get on the testing train we strongly suggest you start running our nightly builds which are the ultimate in bleeding edge but are generally stable enough for daily use.)

    Anyway, on to the feature list and performance improvements taken from the release announcement:

    Web Developer Features

    • Support for Content Security Policy. This is largely complete, minus the ability to disable eval().
    • The placeholder attribute for <input/> and <textarea> is now supported.
    • Support for SMIL Animation in SVG. Support for animating some SVG attributes is still under development and the animateMotion element isn’t supported yet.
    • Support for CSS Transitions. This support is not quite complete: support for animation of transforms and gradients has not yet been implemented.
    • Support for WebGL, which is disabled by default but can be enabled by changing a preference. See this blog post and this blog post for more details.
    • Support for the getClientRects and getBoundingClientRect methods on Range objects. See bug 396392 for details.
    • Support for the setCapture and releaseCapture methods on DOM elements. See bug 503943 for details.
    • Support for the HTML5 History.pushState() and History.replaceState() methods and the popstate event. See bug 500328 for details.
    • Support for the -moz-image-rect() value for background-image. See bug 113577 for more details.

    For the full list of new web developer features please visit our page on Upcoming Features for Web Developers.

    Performance Improvements

    • We’ve removed link history lookup from the main thread and made it asynchronous. This results in less I/O during page loads and improves overall browser responsiveness.
    • Loading the HTML5 spec no longer causes very long browser pauses.
    • A large number of layout performance improvements have been made, including work around DOM access times, color management performance, text area improvements and many other hot spots in the layout engine.
    • The JavaScript engine has many improvements: String handling is improved, faster closures, some support for recursion in TraceMonkey to name a few.
    • Improvements to the performance of repainting HTML in <foreignObject>.
    • Strings are not copied between the main DOM code and web workers, improving performance for threaded JavaScript which moves large pieces of data between threads.
  10. the script defer attribute

    This post is by Olivier Rochard. Olivier does research at Orange Labs in France.

    In HTML, the script element allows authors to include dynamic script in their documents. The defer attribute is boolean attribute that indicates how the script should be executed. If the defer attribute is present, then the script is executed when the page has finished parsing. The element is added to the end of the list of scripts that will execute when the document has finished parsing. Think about a FIFO processing queue : the first script element to be added to the queue will be the first script to be executed, then processing proceeds sequentially in the same order.

    There is one very good reason for using the defer attribute: performance. If you include a script element in your HTML page the script must be evaluated immediately while the page is being parsed. This means that objects have to be created, styles must be flushed, etc. This can make page loading slower. The defer attribute implies that the script has no side effects on the document as it’s being loaded and can safely be evaluated at the end of the page load.

    The defer attribute was first introduced in Internet Explorer 4, and added in the HTML 4 specification.

    A simple test.

    Here is a simple first test to see how the attribute works. The following lines are in the head element of a page:

    ‹script›
    	var test1 = "Test 1 : fail";
    ‹/script›
    ‹script defer›
      	console.log(test1);
    ‹/script›
    ‹script›
    	test1 = "Test 1 : pass";
    ‹/script›

    If the defer attribute for the script element is correctly implemented the browser will:

    1. Render the page.
    2. Execute the second script element after all the others.
    3. Display “Test 1 : pass” on the Firebug console.

    If the console displays “Test 1 : fail” it’s because the scripts are executed in the same order as in the source code.

    Note that the correct syntax for XHTML documents is:

    <script defer="defer"></script>

    A more advanced test

    This second test is a way to see how the feature works in a webpage with multiple script elements inserted:

    • Inline in the head and body elements
    • External via src attribute in head and body elements
    • With dynamic DOM insertion

    Here is partial source code of a webpage that tests how defer affects script loading and parsing order:

    ‹!doctype html›
    ‹html›
        ‹head›
            ‹title› Test 2 ‹/title›
            ‹script› var test2 = "Test 2 :nn"; ‹/script›
            ‹script› document.addEventListener("DOMContentLoaded",
                    function(){
                            test2 += "tDOMContentLoadedn";
                    }, false);
            ‹/script›
            ‹script defer› test2 += "tInline HEAD deferredn"; ‹/script›
            ‹script› test2 += "tInline HEADn"; ‹/script›
            ‹script src="script1.js" defer›
                    // External HEAD deferred (script1.js)
            ‹/script›
            ‹script src="script2.js"›
                    // External HEAD  (script2.js)
            ‹/script›
    	‹script›
                // Dynamic DOM insertion of a script (script3.js)
                head = document.getElementsByTagName('head')[0];
                script3 = document.createElement('script');
                script3.setAttribute('src', 'script3.js');
                head.appendChild(script3);
                // Dynamic DOM insertion of a deferred script (script4.js)
                script4 = document.createElement('script');
                script4.setAttribute('defer', 'defer');
                script4.setAttribute('src', 'script4.js');
                head.appendChild(script4);
    	‹/script›
    	‹script defer›
                // Deferred dynamic DOM insertion of a script (script5.js)
                head = document.getElementsByTagName('head')[0];
                script5 = document.createElement('script');
                script5.setAttribute('src', 'script5.js');
                head.appendChild(script5);
                // Deferred dynamic DOM insertion of a deferred script
                // (script6.js)
                script6 = document.createElement('script');
                script6.setAttribute('defer', 'defer');
                script6.setAttribute('src', 'script6.js');
                head.appendChild(script6);
    	‹/script›
        ‹/head›
        ‹body onload="test2 += 'tBody onLoadn';"›
            ‹script defer› test2 += "tInline BODY deferredn"; ‹/script›
            ‹script› test2 += "tInline BODYn"; ‹/script›
     
    	... other body content ...
     
    		<a onclick="alert(test2);">Launch test 2</a>
     
    	... other body content ...
     
            ‹script src="script7.js" defer›
                    // External BODY deferred (script7.js)
            ‹/script›
            ‹script src="script8.js"›
                    // External BODY (script8.js)
            ‹/script›
        ‹/body›
    ‹/html›

    When you click on the “Launch test 2″ link in the document a pop-up appears with a list in it. This list shows the order of script elements loaded during the session.

    The test also displays the DOMContentLoaded and body.onload events when they are fired.

    If the defer attribute is correctly implemented in the browser, all the deferred lines should be near the bottom of the list.

    Results of the second test for each browser are below (deferred scripts are in green color) :

    • The defer attribute behavior in the Firefox 3.5 browser is correct:

      1. Inline HEAD
      2. External HEAD (script2.js)
      3. Dynamic DOM insertion of a script (script3.js)
      4. Inline BODY
      5. External BODY (script8.js)
      6. Inline HEAD deferred
      7. External HEAD deferred (script1.js)
      8. Dynamic DOM insertion of a deferred script (script4.js)
      9. Inline BODY deferred
      10. External BODY deferred (script7.js)
      11. Deferred dynamic DOM insertion of a script (script5.js)
      12. Deferred dynamic DOM insertion of a deferred script (script6.js)
      13. DOMContentLoaded
      14. Body onLoad
    • The defer attribute behavior in the IE 8 browser is erratic: the order is different at each reload :

      1. Inline HEAD
      2. External HEAD (script2.js)
      3. Inline BODY
      4. External BODY (script8.js)
      5. Dynamic DOM insertion of a script (script3.js)
      6. Dynamic DOM insertion of a deferred script (script4.js)
      7. Inline HEAD deferred
      8. External HEAD deferred (script1.js)
      9. Inline BODY deferred
      10. External BODY deferred (script7.js)
      11. Body onLoad
      12. Deferred dynamic DOM insertion of a script (script5.js)
      13. Deferred dynamic DOM insertion of a deferred script (script6.js)
    • The defer attribute behavior in a WebKit browser (Safari 4.0) is erratic : the order is different at each reload :

      1. Inline HEAD deferred
      2. Inline HEAD
      3. External HEAD deferred (script1.js)
      4. External HEAD (script2.js)
      5. Inline BODY deferred
      6. Inline BODY
      7. External BODY deferred (script7.js)
      8. Deferred dynamic DOM insertion of a script (script5.js)
      9. Dynamic DOM insertion of a deferred script (script4.js)
      10. Deferred dynamic DOM insertion of a deferred script (script6.js)
      11. Dynamic DOM insertion of a script (script3.js)
      12. External BODY (script8.js)
      13. DOMContentLoaded
      14. Body onLoad
    • The defer attribute behavior in the Opera 10.00 Beta browser:

      1. Inline HEAD deferred
      2. Inline HEAD
      3. External HEAD deferred (script1.js)
      4. External HEAD (script2.js)
      5. Dynamic DOM insertion of a script (script3.js)
      6. Dynamic DOM insertion of a deferred script (script4.js)
      7. Deferred dynamic DOM insertion of a script (script5.js)
      8. Deferred dynamic DOM insertion of a deferred script (script6.js)
      9. Inline BODY deferred
      10. Inline BODY
      11. External BODY deferred (script7.js)
      12. External BODY (script8.js)
      13. DOMContentLoaded
      14. Body onLoad

    We hope that this has been a useful introduction to how the defer attribute works in Firefox 3.5. The tests above will also help you predict behavior in other browsers as well.

    Resources