The Mozilla Developer Network has a New Face

Last summer the Mozilla Developer Network (MDN) underwent a massive platform change, moving from a hosted third-party solution to our own custom Django application code-named Kuma. That move laid the ground work for our latest major MDN upgrade: a complete front-end redesign, included many new features as well as usability and accessibility enhancements. Let me provide you with a quick overview of what you can expect to see on the new MDN and what features we’re cooking up for the future!

New MDN Features

Increased Commitment to Search

The majority of MDN users are looking to find documentation the moment they land on the MDN homepage, so we’ve placed search front and center:

We’ve also added search filters to the mix, allowing users to narrow down search results to their specific needs:

From a technical perspective, we’ve moved to Elasticsearch for search, allowing us to continue making indexing and filtering improvements, as well as add new search features at will. We anticipate fine-tuning search as we receive feedback so we’ll continue the push to get you to better documentation faster.

Ease in Navigation

Getting from document to document was a pain point in the previous design, so we’ve fixed that in two ways. The first was creating Content Zones, a method for creating navigation for a given topic. We’ve started with the most prominent parts of MDN, including App Center, Firefox, Firefox OS, Firefox Marketplace, Add-ons, and Persona:

Content Zones

MDN’s new Content Zones provide a complete collection of documentation about a given topic, encompassing the very basics of a topic to API details and advanced techniques. We’ll be kicking off with the following zones:

Firefox OS

Highlights of the Firefox OS zone include:

  • A detailed Platform Guide
  • Build and Install details
  • Hacking Firefox OS
  • App Design & Development
Firefox Marketplace

Highlights of this zone include:

  • App submission and review
  • App publishing and monetization
  • Marketplace API information
App Center

Highlights of the App Center zone include:

  • Quickstart Guide
  • Design and Build tips
  • App publishing guidelines
  • API references

Highlights of the Persona zone include:

  • Guide to using Persona on your site
  • Becoming an identify provider
  • Details on the Persona project

Highlights of the Firefox zone include:

  • A complete Firefox Add-on overview
  • Information on Firefox internals
  • Detailed instructions for building Firefox and contributing

Highlights of the Add-ons zone include:

  • XUL extension information
  • Best practice tips
  • Theming
  • Add-on publishing guidelines

“See Also” Links

We’ve also implemented “See Also” links which may appear in any wiki page, linking to documents which may be relevant based on the document you’re currently viewing.

Both the zone subnavigation and “See Also” link sidebar widgets are built from basic link lists in the wiki document, so adding links and shuffling navigation is easy for anyone looking to contribute to MDN. These link lists can also be built using MDN’s macro language, Kumascript, and our writing team has done a great job automating “See Also” links so that contributors can save on the manual labor of hunting down other relevant documents.

Top level navigation

In the top level navigation, you will have access to five distinct areas:

  • The above-mentioned Content Zones
  • Web Platform, including direct links to more information on technologies, references and guides
  • Developer Program – To be able to help developers and establish long-term relationships and channels, we have created the Mozilla Developer Program. We have a lot of plans and ideas for iteratively expanding the Program, and we want you involved as we do so! So, sign up! You will get a membership, be able to subscribe to our newsletter and get access to features over time as we roll them out.
  • Tools – more information on the Firefox Developer Tools and their features
  • Demos, being a direct link to the Demo Studio

Enhanced Kumascript Macro Features

Kumascript, MDN’s dynamic macro language, was also outfitted with the ability to read external RSS feeds. At present MDN is using the feed reader capability to pull forum posts from StackOverflow and blog posts from the Mozilla Hacks blog. Check out the MDN:Common macro to view the fetchJSONResource and fetchHTTPResource methods which aid in displaying feed content in wiki documents.

Future Features

This visual redesign is just the beginning of our push to make MDN more dynamic and usable. The MDN development and UX teams have plenty more coming in 2014. Here are a few peeks into what you can expect to see!

Dynamic Search Filtering

To improve the efficiency in user search, we plan to implement hashtag-prefixed text filtering which may be added in the initial search — doing so will prevent the need for additional filtering when the user lands on the search results page.

Holly Habstritt Gaal has detailed this query system in detail on her blog. Check out her blog post to see implementation details.

Docs Navigator

So you’ve completed a search and you click the first link you thought would be applicable, but you want to move onward and view other results. Instead of backing out to the search results page again, the wiki page (if the user came from search) will display a doc navigator to move to the next or previous result, or you can view the entire list of results from your original search:


Just another handy way of finding what you need faster!

Demo Studio and Dev Derby Redesign

A redesign to the MDN Demo Studio and Dev Derby will be coming shortly. We have an excellent design in review and we hope to roll that out in early 2014.

If you have a suggestion or find any bugs within the new MDN, please let us know.

Look forward to more from MDN in 2014 and beyond. The MDN platform promises to expand and improve the way we view, write, and experience documentation and web technologies!

View full post on Mozilla Hacks – the Web developer blog

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

The Making of Face to GIF

Face to gif is a simple webapp that lets you record yourself and gives you an infinitely looping animated gif. In this post I will walk you through how it came to be and what I’ve learned from building the small app.

image of the preview window in face to gif

It started with Chris Heilmann’s post about people losing expressiveness to internet memes. At least, that was what I wanted to understand out of it. I thought it really came down to tooling, like most problems do.

It is the year 2000 and something and we still haven’t found a solution to simple problems like sending large files, doing taxes automatically and reliably online or recording an animated gif in your browser. Also, because memes are so popular and easily accessible, why would people even bother trying to create original content when they can make do with a cute kitten image. I thought some things should be easier.

I had already played around with downloading files generated on the client, so I knew text files were trivial and static images were not that hard. But I didn’t find anything about making gif files client side. I thought that I’d figure out the gif part later or even write it myself – how hard could it actually be, right?

The Humble Beginning

Since WebRTC is gaining traction, getUserMedia is becoming a somewhat viable API. Getting a stream from a webcam to be displayed on a video element was very easy.

navigator.getUserMedia({video: true, audio: false}, yes, no);
video.src = URL.createObjectURL(stream);

image of the getUserMedia request dialog in face to gif

I then needed to capture the images that would later make up the gif’s frames. This was not that hard, either. Luckily, you can paint a video element on a canvas context directly using

context.drawImage(video, 0,0, width,height);

This also allows you to scale the captured frames right there, to normalise the different webcam resolutions. Just make sure your canvas element has the correct width and height properties specified, and you should be fine. Also, you should either display: none; it or remove it from the DOM to avoid unnecessary paints.

<canvas width=320 height=240></canvas>

To capture frames, just set an interval at your desired frame rate and cache the frames in an array.

setInterval(function () {
  context.drawImage(video, 0,0, width,height);
  frames.push(context.getImageData(0,0, width,height));
}, 67);

Please note that there is no need to use requestAnimationFrame in this case. The video stream continues to play even when the page it’s on is not visible – so I guess capturing it also makes sense. More importantly, you will need a specific interval between frames that will most probably not end up being 60 frames per second.

After stopping the interval – that is to stop “recording” – you are left with a lot of frames, each frame having a lot of pixel data from the video stream that comes from your webcam. And all that data never leaves the web page that’s being displayed on your computer.

At one point, I was considering to add a “download raw data” button so people could do other things than just make a gif of themselves. I decided to actually solve the gif part first, then think about bells and whistles.

The GIF Writer

After reading too much about the GIF89a and dithering and the LZW algorithm, I cowardly decided to see if I could not find a ready made library. I was lucky to find a demo that combined a series of images into an animated gif – all in JavaScript. I quickly retrofitted the library into my small app and things started moving again.

gifworker.sendMessage({ images: frames, delay: 67 });
gifworker.onmessage = function(event) {
  var img = document.createElement('img');
  img.src = event.data.gifDataString;

What needs to be done from there is as follows:

  1. write a binary header that describes a file as a GIF98a file.
  2. write a block describing the width, height and looping control.
  3. write each frame from the image data list.
  4. write a trailer \59 – aka semicolon.

Using WebWorkers to do the heavy lifting in a separate thread, keeping the UI responsive was a no-brainer. After it’s done processing, the library provides you with a base64 encoded string representing the gif file. That can be used as a data url for an image.

At one point in my life, I was using data urls so intensively, that I would provide clients with mockups consisting of just one HTML file that had images, css and javascript base64`d in and that wouldn’t require and internet connection to work. And that wouldn’t work in IE.

But I was about to face a different set of problems this time around…

Saving the files

Data urls can be saved if they’re small enough. If you want to save a gif that is too long and displayed via data url, the browser will not even let you try do that. Trying to be clever with the download attribute on links didn’t help either.

image of the generated gif and its options in face to gif

While data urls are really cool, there is a limit to how long they can be. I didn’t want to impose what seemed to be a legacy limit on this app.

I altered the library a little to provide me with the raw bytes instead of a base64 string and I used the raw bytes to create a Blob, then used URL.createObjectURL to make something I could set an image’s source attribute to.

var blob = new Blob([uint8array], {type: "image/gif"});
img.src = URL.createObjectURL(blob);

This method of using user generated resources as source attributes is much more reliable and scalable than the old data url method. This also allowed for easier saving of the image.

I use a trick for the download link you will find in my app: I place a simple anchor, with an empty href attribute and I attach a simple ‘click’ event handler. When the user clicks on it, my event handler function simply changes the href attribute to be the same with the source attribute of the image. The browser does the rest.

a.addEventListener('click', function (e) {
    a.href = img.src;
  // the real trick is to let the event bubble up
}, false);

We spend so much time as web developers hijacking control from the browser so we may do our own thing. The truth is, we can most of the time just tell the browser where to go and he’ll do a much better job at getting there on its own than if we would be involved.

Getting back to my app, though, I had gotten it to a place where it was doing what I hoped it would be doing: Recording my face with my webcam and serving me a gif of it.

The Speed

The app was rocking, but it was more like a ballad than a heavy metal song. It took 16 seconds of my life for each 1 second of a gif. This was also because I was writing the gif files at 640×480 originally, but also because it turns out that binary operations on pixel data can be quite slow if not optimised.

I was scrambling for solutions, looking into the library’s TypeScript source code and the generated JavaScript to find ways to improve it, considering asm.js, using TypedArrays more, anything – when I stumbled upon another JavaScript library for writing animated gifs.

gif.js was leaner, could use several web workers to process the frames and had what I thought was a better looking API. After retrofitting this new library, tweaking the settings and halving the size, I was able to produce gifs, right in the web app at blazing speeds.

The one downfall was that what I had gained in speed, I had lost in compression. A mere 10 seconds of GIF would produce about 30 MB worth of data. After some more heavy tweaking, I was able to get that down to about 5 MB / 10s. Still a lot, but it is uncompressed and aggressive compression via online tools can bring that down to as little as 600KB.

The other cool thing about working with Blobs is that you can append them directly to FormData objects, which meant that doing a cross origin ajax call to imgur.com to upload the generated gif was a breeze, and a much welcomed addition to the web app.

What I’ve learned

  • URL.createObjectURL is a great api for client generated media, solving so many problems you’d have otherwise.
  • Using TypedArrays will boost your data intensive app’s performance a lot.
  • Dividing workload between multiple concurrent WebWorkers actually works and helps.
  • WebRTC is at a pretty stable point where you can use the media devices of about 40% of internet users.
  • It is easy to make an app that lets users generate content without involving your server.
  • People really like playing with their web cams. I think using them in a web app makes perfect sense.
  • It is easy to fill up 2MB, imgur’s file limit, with gif data.

thumbs up!

I would also like to thank Johan Nordberg and nobuoka for their hard work coming up with their JavaScript gif writing libraries.

You can take face to gif for a quick spin, or look at the source code on github and fork it, improve it and have lots of fun; Just like I did.

I cannot wait until WebRTC becomes really available on mobile devices too!

View full post on Mozilla Hacks – the Web developer blog

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

headtrackr for real-time face tracking, smartphone features you never thought of, HTML5 Forms support + more in Hacks Weekly

This week Mozilla’s Developer Engagement team suggest reading about headtrackr for real-time face tracking, smartphone features you never thought of using, Web browser support for HTML5 Forms and more!

Weekly links

If there is anything you think we should read or know about, don’t hesitate to post a comment, contact us on Twitter or through any other means.
The picks this week are:

The Developer Engagement team

Mozilla’s Developer Engagement team work with writing articles, documentation – such as MDN (Mozilla Developer Network) – public speaking and generally helping and informing about open technologies and Mozilla products. If you are interested in following our work, here are the team members:

View full post on Mozilla Hacks – the Web developer blog

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

ZK face to face

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)