Developer of location based application, a frontend specialist for Google Maps API and page optimization.

// Google Reader

// Introducing Yeti: The YUI Easy Testing Interface

Welcome to Yeti

Testing JavaScript is an important but often overlooked part of web development. One reason is because developing for the web means targeting more than one browser. YUI currently classifies 11 different environments that enjoy our highest support level. In addition, we also test YUI on emerging X-grade environments like mobile devices. When you have so many different environments to support, it’s tempting to just pick a couple important ones to develop with locally and hope for the best.

At YUI, we use Selenium and Hudson for running YUI Test-based unit tests on various browser and operating system configurations as part of our continuous integration strategy. This is great for catching problems that result from integrating your work with the rest of a complex software stack. It comes with a price: CI tools like these are complicated to setup and maintain. In any case, they don’t help you while you’re developing code and testing before you commit.

Today, I’m excited to release Yeti 0.1.0, an experimental command-line tool designed to make cross-browser testing easier before you commit a line of code.

Yeti automatically launches JavaScript unit tests in a browser and reports the results without leaving your terminal. It’s very simple to use: Just run yeti test.html to get the results of the YUI Test-based test in test.html. You can pass multiple HTML documents to test multiple components at once.

$ yeti dom/tests/dom.html attribute/tests/attribute.html json/tests/json.html ✔ DOM Tests from Safari (Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-us) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16) 20 passed 0 failed ✔ Y.JSON (JavaScript implementation) from Safari (Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-us) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16) 68 passed 0 failed ✔ Attribute Unit Tests from Safari (Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-us) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16) 106 passed 0 failed 194 tests passed! (3217ms)

The real power of Yeti is running tests in multiple browsers simultaneously. Although Yeti can open your tests one-by-one on your computer, Yeti allows you to run tests on any browser on any device—all at the same time.

If you run Yeti without arguments, it will start a web server that you can access at http://localhost:8000. You can then point browsers or devices on your network to that URL and every test you run from that point will be executed on all browsers visiting the test page.

Multiple browsers with Yeti

When combined with the excellent localtunnel, firewalls between you and other computers are less painful. If you’re not working with sensitive information, it’s a simple way to make your Yeti available to the internet:

$ localtunnel 8000 Port 8000 is now publicly accessible from http://example.localtunnel.com

You can then visit that URL to access Yeti and start running tests:

Yeti on iOS 4 Safari

This is especially useful for cellular devices: You can use your carrier’s internet connection without needing to get your device on the same network as your development computer.

Yeti aims to make JavaScript testing easier; however, it’s far from being complete. (Don’t take the 0.1.0 version number lightly.) Yeti assumes you’re using YUI Test, has only been tested on Mac OS X, and may not work with some kinds of testing scenarios. Despite these shortcomings, Yeti has been so useful internally that we didn’t want to wait any longer to share it with the YUI community.

Getting the code

Yeti is available on GitHub and offered under YUI’s BSD license.

Installing

Yeti is written entirely in JavaScript and runs on top of NodeJS. If you’re already a NodeJS and npm user, installing is very simple:

$ npm install yeti@stable

If you haven’t installed NodeJS and npm and you’re on a recent Mac, you can still install Yeti with a convenient installer.

Yeti Icon Download the Yeti 0.1.0 Installer 2.7 MB
Requires Mac OS X 10.6 and a Intel Core 2 processor or better

If your computer doesn’t meet the installer’s requirements, you can still use Yeti if you’re able to install npm. More installation and usage instructions are available in Yeti’s README.

Your participation is welcome

Yeti is the first project we’ve launched in YUI Labs, an umbrella category where our new ideas and initiatives will take shape. As such, Yeti is offered without the same level of support as our other projects. We still encourage you to ask questions and give feedback in Yeti’s forums and hope Yeti makes testing easy and fun. If it doesn’t, please tell us, file a bug or consider contributing to Yeti.

Happy testing!

About the Author: Reid Burke (@reid) is the newest member of the YUI team. He loves abominable snow monsters and JavaScript.

Kategorien: Google Reader

// Best New Mashups: Point A to Point B

We have mashups to help us figure out where we want to go, the best way to get there, and then what’s the coolest stuff to do when we get there. One thing that’s often overlooked is how much it’ll cost us to get from point A to point B.

Go Gas
Go Gas is a Google Maps and TinyLink mashup that determines how much a trip will cost you in gas. You simply enter your start point (HTML5-capable browsers have the option of using geolocation to get the start point) and your course is plotted. Go Gas shows you how many miles your trip is and what you can expect to pay in gas costs.

Go Gas

More at our Go Gas profile

Guia Postos (trans. “Guide Posts”)
If you happen to be traveling Brazil, you have Guia Postos. Guia Postos is a mashup that combines Facebook, Google AJAX, and Google Maps to give you a local map, showing gas prices and fuel quality.

Guia Postos

More at our Guia Postos profile


Sponsored by

Nokia Developer Summit 2010

Kategorien: Google Reader

// Dive into the ocean with Google Earth for Android

(Cross-posted from Google LatLong)
Especially during the summer months, staring out into the ocean leads to daydreams of sailing the open water, freedom and exploration. Now you can take three-quarters of this vast planet - the ocean - with you on your mobile device by downloading the new Google Earth 1.1 for Android.

With the release of this feature, escape the hustle and bustle of life on land and discover the marine world using Google Earth on your mobile device. Now, you can check out the landscape and terrain in Monterery Bay Canyon, which is larger than the Grand Canyon, by zooming in on Google Earth below the ocean surface just off the coast. Once underwater, we can use the “look around” button to tilt the view and see the extent of this great undersea canyon.

The latest version of Google Earth for Android also introduces the “Explore the Ocean” layer, which features hundreds of photos and videos from more than 100 contributors who are excited to share their stories of sea. Plan your next vacation during your daily commute by clicking on any of the little blue icons. The gold highlighted icons represent content from the Mission Blue Hope Spot initiative.


For those of you running Android 2.2, there are some more treats in store. Google Earth now supports Flash in balloons, so if you have the Flash player installed on your mobile device, you can watch videos right in the balloon. We’ve also made the program easier to navigate; for most devices, you can now use two fingers to “look around” and change your viewpoint, as an alternate to using the on-screen button. This makes it even easier to tilt your view to see mountainous landscapes or underwater canyons. Rotating your view with a simple twist of your fingers is now available on more devices as well.

Google Earth for Android 1.1 is available in Android Market today for most Android devices running version 2.1 or later. Explore the ocean anywhere.
qrcode
Posted by Jenifer Austin Foulkes, Product Manager
Kategorien: Google Reader

// Want to pack JS and CSS really well? Convert it to a PNG and unpack it via Canvas

Jacob Seidelin of nihilogic fame (remember his Super Mario in JavaScript solution) is one of my unsung heroes of JavaScript. His solutions have that Dean Edwards "genius bordering on the bat-sh*t-crazy" touch that make you shake your head in disbelief when they come out but later on become very interesting.

One of his posts from 2008 entitled "Compression using Canvas and PNG-embedded data" had a good idea: if you want to compress JavaScript and CSS you could reverse engineer a packing algorithm in JavaScript or you could use a lossless packing system that is already in use and supported in browsers. In this case the packed format is PNG and the way to unpack it is by using the canvas API's getImageData() method:

PLAIN TEXT JAVASCRIPT: var x = function(z, m, ix ) { // image, callback, chunk index
  var o = new Image();
  o.onload = function() {
    var s = "",
        c = d.createElement("canvas"),
        t = c.getContext("2d"),
        w = o.width,
        h = o.height;
    c.width = c.style.width = w;
    c.height = c.style.height = h;
    t.drawImage(o, 0, 0);
    var b = t.getImageData( 0, 0, w, h ).data; //b : bucket of data
    for(var i= 0; i <b.length; i += 4) {
      if( b[i]> 0 )
        s += String.fromCharCode(b[i]);
    }
    m(s, ix);
  }
  o.src = z;
}

As there are quite some interesting competitions going on that need really small JavaScript solutions Alex Le took up Jacob's work and wrapped it in a build script that concatenates, packs and converts to a PNG and unpacks it for the 10K competition with a JavaScript. In the process Alex also found some bug in Internet Explorer 9's canvas implementation as it only reads the first 8192 bytes of a PNG and returns 0 for the others :(.

It is pretty amazing how efficient this way of packing is. What we need to test now is when and if it is worth while to have the unpacking done on the client. Imagine adding your JS and CSS to the end of an image and cropping it in CSS to have all the info you need in an app in a single HTTP request. Let the games begin.

Kategorien: Google Reader

// Will Native Mobile Applications Wither Away?


James Pearce has started a fascinating series, called WhitherApps.com, trying to rewrite the BBC iPhone application and other native mobile apps using HTML5. From the kickoff blog post:

WhitherApps is a bandwagon-busting experiment. I believe there are far too many native client apps which could have been far better written as mobile web apps. What we’re going to try and do is take a few examples, apply a little reverse-engineering, and rewrite them, warts and all, with web technologies.

James has already produced three blog posts rewriting the BBC iPhone app but with HTML5 (Part I, Part II, Part III). I encourage you to read them. He's already gotten impressively far; here is a screenshot of the HTML5 app so far:

[via kenguish]

Kategorien: Google Reader

// Apps vs. the Web

There's an app for that, and you're the folks who are creating it. But should you design a web-based application, or an iPhone app? Each approach has pluses and minuses—not to mention legions of religiously rabid supporters. Apple promotes both approaches (they even gave the web a year-long head start before beginning to sell apps in the store), and the iPhone's Safari browser supports HTML5 and CSS3 and brags a fast JavaScript engine. Yet many companies and individuals with deep web expertise choose to create iPhone apps instead of web apps that can do the same thing. Explore both approaches and learn just about everything you'll need to know if you choose to create an iPhone app—from the lingo, to the development process, to the tricks that can smooth the path of doing business with Apple.contact.us@alistapart.com (Craig Hockenberry)171950337276650572771783531540108469243707033830592011208735060980017056701895051773338608210570182616842222664160054718181681573423188967511736528485931647586211762090165046421182028852983123196160280476611736287053283018385338218504819643025237776564496453001632191690810581796003386268540498594594062937683479819466541606838311038306985816069252667413438386172310396753262678771563148001297753176801266613426536334404155726133765976708371263596504213267338000328150887782938865078946610042609084550601243235038329046506545191465402380258052217905025516583160577366516820122573207401360114416646153021065591207255902850239894926146454738511584670807194096043
Kategorien: Google Reader

// It&#39;s time for the baked-in Android UI to die - Computerworld Blogs

It's time for the baked-in Android UI to die 23 comments

Android User InterfaceListen up, Android manufacturers: The time has come for your built-in Android user interface to go away. Call it Motoblur, call it Sense, call it whatever you want -- as long as it's coming preinstalled on Android phones, it's officially overstayed its welcome.

These days, practically every Android phone-maker is including its own custom UI -- or "skin," as it's often called -- on top of Google's basic Android software. The motivation is understandable: With modern Android devices having increasingly similar hardware power, the skins give companies a way to set their phones apart. And that's fine. It's the implementation that's a problem.

The manufacturers, you see, insist on integrating their UIs into the phone's operating system, replacing the stock Android OS with their own tweaked-out editions. It's pretty much the standard M.O. these days; it's what we see with Motorola's Motoblur, HTC's Sense, Samsung's TouchWiz, and Dell's and Sony's custom Android skins. And it's a practice that needs to end.

[This story is from the new Android Power blog at Computerworld. Follow @AndroidPower on Twitter or subscribe via RSS to make sure you don't miss a beat.]

The Trouble with the Integrated Android UI

The idea of the integrated Android interface presents a couple of serious issues. First, rolling out new versions of Android becomes a painfully involved and delayed process: Even with Google's updated software out in the wild, manufacturers have to make their own modifications and bake their custom skins back in before users can get the goods. We're seeing that happen right now with the Android 2.2 upgrade. (Yes, I know that HTC and Sprint were first out of the carrier gate with Froyo for the EVO -- and major props to them for making that happen -- but as most Android owners know, that's more the exception than the rule.)

Even worse is the situation playing out with brand new Android devices. Just this month, both the Dell Streak and Sony Ericsson Xperia X10 debuted running Android 1.6 under custom skins. I'll be blunt: There's absolutely no excuse for a brand new Android device to be shipping with a year-old version of the operating system. Froyo aside, Android 2.0 has been out since last October, and Android 2.1 has been around since January. Despite the two manufacturers' vague promises of upgrades -- Dell has said its Streak will receive the current version of Android sometime this year, while Sony has promised to bring the Xperia X10 up to version 2.1 before New Year's -- it's simply embarrassing and unacceptable for new hardware to be launching with such outdated software. 

Shifting the Android Skinning Strategy

Android Custom SkinsSo what's the answer? I would make the argument that Android doesn't even need these manufacturer-made skins anymore: The stock interface has made leaps and bounds in the last few releases, and word is Google's next major update will add on yet another layer of UI-oriented polish. I know I'm not the only original Droid owner who was disappointed to see the new Droid 2 arrive with Motorola's Motoblur instead of the vanilla Android its predecessor possessed; having the stock OS presents plenty of desirable advantages, and most of the skin-provided features are things you can easily implement on your own with third-party utilities.

That said, I can accept the fact that phone-makers want to put their own distinguishing touches on devices -- and realistically, I know that isn't going to change anytime soon. Both Motorola and HTC have already hinted about plans to continue developing their skins into the future, despite Google's advances with the Android OS.

My proposal, then, is for the manufacturers to meet us halfway and stop baking their modifications into the system. If you want to include custom widgets, make them standalone apps. If you think your added home screens and special navigation systems are super-duper, turn them into separate launcher/home screen replacement programs. Preinstall this stuff on the phones if you must, but stop integrating it into the damn OS.

Aside from simplifying the Android upgrade process -- new versions of the stock OS could be rolled out far more efficiently, with the widgets and launchers requiring only basic compatibility updates like any other normal Android apps -- this switch would embrace the choice-oriented nature of Android so many users value. If customers want your software modifications, they'll have them. But if they prefer starting with the base OS and building their own experiences, they can uninstall your additions and get back to square one without any complex procedures.

Manufacturers, you've worked hard to create custom skins for your Android devices. Now it's time to work harder to turn those skins into assets rather than liabilities for your users. It'll make the Android ecosystem -- and yes, your products -- far stronger in the end.

JR Raphael writes about smartphones and other tasty technology. You can find him on Facebook, Twitter, or at eSarcasm, his geek-humor getaway.

Kategorien: Google Reader

// Add-ons, and Opting out of Google Analytics Without Them

Recently, Google made available the “Google Analytics Opt-out Browser Add-on.” This add-on enables consumers to “indicate that information about the website visit should not be sent to Google Analytics.” We agree that making it easy for consumers to protect their privacy is good, and Internet Explorer offers a variety of features to help keep you in control of your information when visiting websites. In this post, we describe how to use some of these built in features to accomplish the same outcome without installing a Browser Helper Object and the Google Update Service.

Users of Internet Explorer 7 and 8 (and soon 9) who wish to prevent Google Analytics’ script from running can follow these steps:

  1. In Internet Explorer, open the Tools tool icon menu and click Internet Options.
  2. Click the Security tab and then click the Restricted Sites icon.
  3. Click the Sites button.
  4. In the box at the top, add *.google-analytics.com and push the Add button.
  5. Click the Close button, and then the OK button to dismiss Internet Options.

After this configuration change, script from the Google Analytics website will not run on any webpage, and cookies will never be sent to the Google Analytics server.

Internet Options Restricted Sites dialog

How does this simple procedure work?  In IE7, we made a minor change to the Restricted Sites zone. IE will not run scripts that originate from sites the user places in the Restricted zone.

To protect your privacy further, IE will not send cookies to sites in the Restricted Sites zone.  In general, you can block script from any other domains by also adding those domains to the Restricted Sites zone.

Add-ons are useful and important. They are also a key cause of performance, stability, and security issues for all browsers. A more trustworthy approach involves building more functionality into the core browser and relying more on data (in the form of declarative descriptions, like XML) than code to extend the browser. For example, Accelerators in IE are XML descriptions of how to get a map, rather than arbitrary script that can get a map and possibly do more (like slow down the browser, or share more information than you’d like). Webslices are XML descriptions of parts of a webpage to show on IE’s Favorites Bar, rather than arbitrary script that can modify IE’s user interface and possibly do more than that under the hood.

In this situation, rather than install and run a lot of additional software on the machine, people can just add a web site to the Restricted Sites zone. Similarly, InPrivate Filtering in IE8 (and IE9) supports Importing and Exporting lists of sites that the user doesn’t want to exchange information with. That’s a simpler, safer, faster and more reliable approach than running more code.

Eric Lawrence
Program Manager

ieblog098532500928217618030577915952271422150715527456364425823699098610103789995369850837480554912741669513681716810479778380028406141261185418841487810999573394249610638179830014493517075538201677623897870010994694584133800711967577028120371827036968632801106509621544974119525149519713915563439091112164034320267217128576820422035628948529633001476917668200178031
Kategorien: Google Reader

// The jQuery Project is Proud to Announce the jQuery Mobile Project

Mobile web development is an emerging hot topic in the web development community. As such, the jQuery Team has been hard at work on determining the strategy and direction that the jQuery Project will take. Today, we are proud to announce the jQuery Mobile Project. We’ve launched a new site at jquerymobile.com that publicly outlines our strategy, research and UI designs.

As always, we want to hear from you.  We’ve created a new Mobile jQuery forum to collect feedback from the community.  Please feel free to join in on the discussion and read more in the announcement.

Kategorien: Google Reader

// Controlling custom fonts with the Google WebFonts API

One thing Google released at the last I/O conference was hosting for custom fonts to use in web sites for browsers that support that feature. So instead of streaming the fonts from your own server you can just point to Google’s farm and be done with it.

Fonts hosted by Google

Google hosts a few fonts for you and all you need to do is embed them.

Google font directory

They also released a font preview tool that allows you to tailor the font you want to your needs:

Google Font previewer tool

Hand-written blockquotes

One of the fonts is a scribbly little handwriting font called Reenie Beanie (I’ve used it for the sticky notes in my collection of hacks). Using this font you can create for example some sweet looking blockquotes:

blockquotes in hand written font

All you need to do is to include the font as a CSS link:

<link href="http://fonts.googleapis.com/css?family=Reenie+Beanie:regular" rel="stylesheet" type="text/css">

And then you style your blockquote. As the font is rather small you need to bump up its size a bit:

blockquote{ font-family: 'Reenie Beanie', sans-serif; font-size:160%; background:#eee; color:#666; margin:1em 0; padding:.5em; }

And this is where it gets problematic. If for any reason the font cannot be loaded or the browser doesn’t support custom fonts, the experience is less pretty:

When the font doesn't load you have huge blockquotes

Which is a big problem of any pure CSS solutions – you hope things work but you can’t test for it (media queries being the exception here). However, there is another way to use the Google fonts.

Test, don’t hope

Instead of using the direct CSS links you can use the JavaScript Webfont loader which creates the style links with JavaScript and gives you a handle on what was loaded and not (Bonus: the loader is on GitHub).

Instead of the CSS link simply add the following script:

<script src="http://www.google.com/jsapi"></script> <script> google.load("webfont", "1"); google.setOnLoadCallback(function() { WebFont.load({ google: { families: [ 'Reenie Beanie' ] }}); }); </script>

The loader now adds classes to the HTML element of the document to tell you when the font is loaded and when it is available. You can load Google fonts, those hosted by TypeKit and really any other on the web. For all the fonts you specify in the loaded these classes are .wf-inactive and .wf-active respectively. You can also test for a certain font with its name and weight. So to check for Reenie Beanie, the class is .wf-reeniebeanie-n4-active when it is available.

You can use this to define the whole style as relying on the font:

.wf-reeniebeanie-n4-active blockquote{ font-family: 'Reenie Beanie', sans-serif; font-size:160%; background:#eee; color:#666; margin:1em 0; padding:.5em; }

Even better, the webfont loader also provides you with events to subscribe to:

WebFontConfig = { google: { families: [ 'Tangerine', 'Cantarell' ] }, typekit: { id: 'myKitId' }, loading: function() { // do something }, fontloading: function(fontFamily, fontDescription) { // do something }, fontactive: function(fontFamily, fontDescription) { // do something }, fontinactive: function(fontFamily, fontDescription) { // do something }, active: function() { // do something }, inactive: function() { // do something } };

You can use that to display loading messages during font retrieval and all kind of other tricks.

Kategorien: Google Reader

// Business Card Design Starter Kit: Showcase, Tutorials, Templates

 Showcase, Tutorials, Templates Showcase, Tutorials, Templates
 Showcase, Tutorials, Templates  Showcase, Tutorials, Templates  Showcase, Tutorials, Templates

Professionals in any field should always keep business cards on them because you never know when you’ll meet a potential client, partner or like-minded person. Despite their small size, business cards are one of the most powerful and handiest marketing tools. Not only do they create a link between you and your new contact, they’re also a quick way to give a great first impression. Business cards promote your skills and achievements and serve as a little container for big ideas.

Don’t underestimate the process of designing business cards; a well-made card does not just share your contact details: it generates further sharing and buzz. Like any self-promotion tool, designing a business card requires solid brainstorming and careful implementation to get the best effect.

This post targets a diverse audience. It features a collection of remarkable business card designs that could help you in your search for creative ideas. The round-up of fresh tutorials and business card templates further down might come in handy for those who don’t have the skills or experience to design their own.

[Offtopic: by the way, did you know that we are publishing a Smashing eBook Series? The brand new eBook #3 is Mastering Photoshop For Web Design, written by our Photoshop-expert Thomas Giannattasio.]

Showcase Of Original And Memorable Business CardsLetterpress Cards

Letterpress printing has actually been the only form of printing text and images since it was invented by Johannes Gutenberg in the 15th century. Because of its distinctive qualities, such as crisp and tangible impression onto paper, letterpress work is now widely used for branding and identity development. Letterpress gives stronger visual definition to type and artwork and has a special touch, which is why it’s a popular technique for business card printing. Below you can see some beautiful examples of letterpress business cards.

John Henry Donovan
On this business card, the fine design created by Irish designer and developer John Henry Donovan is complemented by the printer’s excellent choice of paper and inking.

 Showcase, Tutorials, Templates

Greg Anderson
This card works because of the stylish dirty texture, good use of color and, of course, letterpress. Designed by Thomas Guy.

 Showcase, Tutorials, Templates

Chris Piascik
The funky typography of freelance graphic designer Chris Piascik is set off well by the letterpress work on his business card.

 Showcase, Tutorials, Templates

Space 150
This stylish letterpress business card was designed for the creative agency Space150 by designer Evan Nagan. The card is part of the agency’s periodic general redesign, which it conducts every 150 days. The elegant constellation theme and high-quality letterpress printing make for an excellent card.

 Showcase, Tutorials, Templates

White Rabbit
This card promotes the portfolio of the German photographer Florian Muller (aka the White Rabbit). The use of the negatives pattern incorporates the card owner’s occupation well, and the surface is enhanced by an embossed rabbit.

 Showcase, Tutorials, Templates

One in Zero
The business card of Hong Kong-based idea firm OneinZero is minimalist: the focus is on the letterpress type and paper texture.

 Showcase, Tutorials, Templates

Christian Garibaldi
The effective combination of blind and ink debossing, along with the subtle coloring along the edge, makes for a clean and exquisite business card that perfectly conveys the aesthetic of the photographer’s online portfolio.

 Showcase, Tutorials, Templates

Montage
Dallas Graham of Montage Creative has a simple and strong business card.

 Showcase, Tutorials, Templates

Paper Monkey Press
Some filigree letterpressing is evident on the card of Paper Monkey Press.

 Showcase, Tutorials, Templates

Second World Design
The guys over at Second World took their branding very seriously, resulting in the clean beautiful letterpress card you see below.

 Showcase, Tutorials, Templates

Kinetic Lens
This card was designed by photographer Riley Maclean for his company Kinetic Lens. Combining various letterpress techniques and a great set of red tones, this business card has a multi-dimensional feel. It’s printed on thick 220-pound-bond cotton paper.

 Showcase, Tutorials, Templates

Laura Moretz
A good use of letterpress on the front and back of this card and the labels make this card memorable. It’s printed on French Speckletone #140 stock.

 Showcase, Tutorials, Templates

23rd And 5th
Here is a beautiful business card showing fine typography and two-color letterpress. It was designed for the staff of the 23rd & 5th branding agency. This business card for the Director of Development features a QR code that drives contacts to a dedicated mobile website optimized for the iPhone, Blackberry and Android.

 Showcase, Tutorials, Templates

Die-Cut Business Cards

Something else that determines a business card’s memorability and appeal is shape. Today many individuals, businesses and organizations die-cut their cards, going beyond traditional dimensions. Die-cutting is an effective way to make a business card eye-catching, unique and even interactive. But remember that a die-cut card should still be compact enough to fit in a standard wallet or card holder. Alternatively, you could suggest some other way to carry or hold your card. Some noteworthy die-cut business cards are showcased below.

Derrick Mitchell
Derrick Mitchell, a designer from Kalispell, Montana, creates his business cards by hand with chip board, screen printing, labels and stamps.

 Showcase, Tutorials, Templates

Popupology
This cute die-cut business card is done entirely in-house by designer Elod Beregszaszi.

 Showcase, Tutorials, Templates

Dyalect
The chic design of this business card is accentuated by the custom shape and 16-point silk matte finish card stock.

 Showcase, Tutorials, Templates

Kaman
This concept-based business card was designed by Mehdi Tuchak for the Iranian multimedia company Kaman.

 Showcase, Tutorials, Templates

Sean Gerety
This lovely business card mimics a Moleskine notebook. While the front is glossy, the back is matted and can be used as a note card.

 Showcase, Tutorials, Templates

Amundson Films
Cheap card stock and moderate-quality print wonderfully fit the aesthetic of this vintage movie ticket business card. Great job, Alice Cho!

 Showcase, Tutorials, Templates

Alteroy
This die-cut masterpiece belongs to the Israel-based designer Alteroy. The cardboard icons can be separated. Much effort was put into this business card, and the result is absolutely worth it.

 Showcase, Tutorials, Templates

Carlos Vazquez
This super-cute business card might be the shortest route to any Mac fan’s heart.

 Showcase, Tutorials, Templates

Herbert Martin
Besides containing the contact info of German dentist Herbert Martin, this business card has another cool function: it helps you check your bite by way of a die-cut stencil. Designed by Petra Penz.

 Showcase, Tutorials, Templates

Truf
The business card is square and “combines a hand-crafted feel with the style of Russian propaganda posters.”

 Showcase, Tutorials, Templates

Classic, With a Twist

Most of the business cards below have a classic rectangular shape and standard dimensions… but that is where their classic-ness ends. Creative ideas and skillful implementation make these cards look anything but ordinary.

Coco
The amazing identity concept for COCO was created by Polish designer “Wallstreet Different Creature.” This business card, as part of the overall branding, is pure style and beauty.

 Showcase, Tutorials, Templates

Erich Hartmann
Erich Hartmann designed his business card to spell out a bunch of his skills, along with his main occupation. This clever idea is nicely visualized by way of a two-sided card, with an offset logo on the front and letterpress on the back.

 Showcase, Tutorials, Templates

Fran Rosa
Motion and graphics designer Fran Rosa takes different angles on both his website and business cards… literally.

 Showcase, Tutorials, Templates

Grill Me
To see the info on this business card, grill it against a fire, because the card is stamped with lemon juice for ink. Quite an original idea, but using this effect for non-essential information or for an image, rather than contact info, might be more reasonable.

 Showcase, Tutorials, Templates

Luciano Ferreira
A lovely typographic business card made by Brazilian graphic designer Luciano Ferreira for promotional purposes.

 Showcase, Tutorials, Templates

Sandra Boils
This elegant business card was made for Spanish jazz vocalist Sandra Boils by graphic design studio Estudio Menta.

 Showcase, Tutorials, Templates

Stepan Prokop
A beautiful artistic business card by graphic designer Stepan Prokop.

 Showcase, Tutorials, Templates

Synchromatik
The rich grass texture makes the card of designer Marko Manojlovic look fresh and beautiful.

 Showcase, Tutorials, Templates

Van Der Buzz
This transparent business card, mimicking an X-ray, belongs to Ukrainian advertising agency Van Der Buzz.

 Showcase, Tutorials, Templates

What What
These cool playful business cards were created by twin brothers, designers John and Edward Harrison, also known as What What.

 Showcase, Tutorials, Templates

Combining Techniques

When it comes to developing promotional material for a brand today, the variety of choice is impressive. With all the different printing techniques, the loads of diverse paper and material available and relatively cheap digital technology, the process of designing a business card is limited only by the designer’s imagination. The following business cards rely on both paper quality and printing methods to create a memorable experience.

TAM Cargo
Traditional at first glance, this business card can be transformed into a little cargo transport box. The card was design by Brazilian advertising agency Y&R for TAM Airlines.

 Showcase, Tutorials, Templates

Cinch Creative
Design company Cinch Creative printed its business cards on 60-point Blotter paper with a fine natural texture. Thanks to this and the debossed logo and text, the card is a pleasure for both the eyes and hands.

 Showcase, Tutorials, Templates

Feelme Crew
This creative business card in the shape of a clapper board was designed by Ralev.com for Bulgarian multimedia agency Feelme Crew.

 Showcase, Tutorials, Templates

Fiverr
Here’s a green approach to business card design. The cards for Fiverr CEO Micha Kaufman are made from recycled paper and cardboard. Moreover, the cards are completely hand-made. See details on Kaufman’s Facebook page.

 Showcase, Tutorials, Templates

Groundflights
This card, inspired by a boarding pass stub, was created by creative agency R3M1X3D for transportation company Groundflights. It is a successful mix of letterpress printing and die-cutting.

 Showcase, Tutorials, Templates

Herofilm
A beautiful business card stylized as a film frame. It was designed by Jimmituanart for Herofilm Productions.

 Showcase, Tutorials, Templates

Philosophy Communications
With a squeezable circle built in, the business card of PR company Philosophy Communications is a two-in-one solution. Brilliant work, wouldn’t you agree?

 Showcase, Tutorials, Templates

Rhino Studio
Premium paper, imitation rhino skin and a stylized typographic logo make this card chic indeed. Designed by Contreforme.

 Showcase, Tutorials, Templates

Paper Fortress
This vintage-looking business card, which features die-cutting, embossing and high-quality paper, was designed by the studio Second World for the film production company Paper Fortress.

 Showcase, Tutorials, Templates

Hear
This fancy silk-laminated card, featuring a spot UV coating, was designed by social media and design company Hear.

 Showcase, Tutorials, Templates

Gita Ayu
The cool illusion on this business card was achieved with a thin transparent plate that makes it look as though this faux-3D brick is broken. The amazing card was created by Saatchi & Saatchi, Indonesia, for a karate club.

 Showcase, Tutorials, Templates

Something Completely Different

The cards showcased below considerably expand the parameters of the business card format. It seems that business cards can be grown, played with and even eaten! Look at the craziest business card concepts around.

MODhair
Not only can you comb your hair with this business card, you can also play a classic rock song on it with your fingernail. The card was designed by Fabio Milito for a Rome-based hair salon.

 Showcase, Tutorials, Templates

Gitam BBDO Spicy
The Gitam BBDO agency uses spice sachets as business cards, associating each of its departments with a particular condiment.

 Showcase, Tutorials, Templates

BC Adventure Survival Training
The cards of BC Adventure remain extremely useful even in situations where a business card is useless. They are made of organic beef jerky and are good to eat for up to a year.

 Showcase, Tutorials, Templates

RDA
To promote one of his projects (an interactive chopping board), designer Sam Gough created 20 wooden business cards, carving his project’s title and contact info neatly into each.

 Showcase, Tutorials, Templates

Dept of Energy
With its business “cords,” Dept of Energy shows a skillful play on its identity and style.

 Showcase, Tutorials, Templates

Lush
This business card is a thin envelope stuffed with grass seed. The clean design, clever copy and sneaky seed surprise make for an adorable card. Designed by Brandon Knowlden.

 Showcase, Tutorials, Templates

Taberu Me
For the most desperate self-promoters, peanut business cards are not a bad idea. Taberu Me uses innovative CO2 laser engraving technology to print on the peanuts. But before you hands yours out, make sure no squirrels or chipmunks are around.

 Showcase, Tutorials, Templates

Wes Thomas
This business card design is an ongoing project of Philadelphia-based industrial designer Wes Thomas. The laser-cut card can be quickly transformed in a cute desktop toy. This is no ordinary concept and is pretty labor-intensive, but who would refuse such a business toy for their desk?

 Showcase, Tutorials, Templates

Business Card Galleries

Only the truly unique are remembered. When designing anything for yourself, it’s always useful to look around for fresh ideas. Here are permanent showcase galleries where you can find trends and best practices for business card design.

Tutorials

To get you started on your own business card, we’ve selected some fresh and useful tutorials and guides that cover various issues you might deal with in this area.

Create a Print-Ready Business Card in Illustrator
In this tutorial, well-known designer and blogger Chris Spooner walks you through the process of creating a fun business card with a sketched illustration.

 Showcase, Tutorials, Templates

How to Create a Stylish Business Card Template in Adobe Photoshop
In this tutorial, you learn how to create an elegant minimalist business card design in Photoshop. The source files are available for free downloading.

 Showcase, Tutorials, Templates

Create a Grunge Print-Ready Business Card
Use this tutorial to create a business card with nifty faded brush strokes in Photoshop.

 Showcase, Tutorials, Templates

How to Create a Nebula Background in Photoshop
Learn how to design a business card with an astral background.

 Showcase, Tutorials, Templates

Print-Ready Business Card Tutorial
This tutorial explains how to create a print-ready business card with a clean dark design in Photoshop.

 Showcase, Tutorials, Templates

How to Make a Print-Ready Business Card in Photoshop
In this tutorial, you will learn how to create a two-sided business card with crop marks and bleed.

 Showcase, Tutorials, Templates

How to Design Your Business Card
This article discusses the basics of business card design and covers some best practices.

 Showcase, Tutorials, Templates

Business Card Design Walkthrough
Along with other step-by-step tutorials, a detailed case study like this one might be useful to you.

 Showcase, Tutorials, Templates

PSD Tutorial: Design a Dirty Business Card
Learn how to create a simple business card, complete with grungy texture.

 Showcase, Tutorials, Templates

Business Card Tutorial in Inkscape
Here is a detailed guide on how to design a business card in Inkscape. While the result shown does not look that great, the principles of working in Inkscape are described quite well, so you can get a better result using this open-source graphics editor.

Business Card
If you like the business card shown below, learn how to create it in Photoshop in this tutorial.

 Showcase, Tutorials, Templates

Making Creative Business Card
This tutorial shows how to make a nice business card in a matter of minutes.

 Showcase, Tutorials, Templates

How to Design a Print-Ready Business Card Design in Photoshop
This business card tutorial includes a couple of bonus templates, which you can download in PSD format and use for free.

 Showcase, Tutorials, Templates

How to Design Business Card
Learn how to create the unconventional and attractive business card below.

 Showcase, Tutorials, Templates

Grungy Business Card
Another variation of the grunge design is explained in this guide. The image preview and PSD file are free to download.

 Showcase, Tutorials, Templates

How to Make your Own Photographic Negative Business Cards
Now, here’s a completely different take on business card design. Photographer Steph Goralnik shares his technique for crafting a unique photographic negative business card.

 Showcase, Tutorials, Templates

How to Choose Business Card Paper
Paper is an important consideration when printing business cards. The right paper can make your card shine, while poor-quality stock can spoil even a top-notch design. Read this article to learn the key points and differences between various types of paper.

How to Choose the Right Paper
Although quite old, this article contains some useful tips on choosing the right paper for your business card. A solidly written article.

Templates

A template is definitely a great option for those who don’t have the skill to create a business card on their own. But even if you’re a professional designer, you may need the job done very fast or simply want to save time making customizations. This is when a template comes in handy. Below you’ll find a selection of well-designed free and commercial business card templates that you can take advantage of in your own projects.

Free Templates

Most of the templates in this category are free for personal and commercial use, but please be sure to read all accompanying legal usage notes before downloading the files.

I love dA Business Card

This nifty business card design was created by graphic designer depart on the occasion of deviantArt’s birthday. The template is available for free download in both PSD and Ai formats.

 Showcase, Tutorials, Templates

FreelanceSwitch Business Card Template
This Adobe Illustrator template can be customized for any freelance profession. The pack comes with templates for writers, coders and designers.

 Showcase, Tutorials, Templates

Bokeh Business Card | More
The PSD template for this business card is available in high resolution and is ready to print.

 Showcase, Tutorials, Templates

Free Business Card Template for Photoshop (PSD) | More
This minimalist grayscale business card template is available as a free download at DeviantArt.

 Showcase, Tutorials, Templates

Free Business Card Design Pumpkin
This “Pumpkin” business card template features 300 DPI resolution and CMYK color mode for professional printing, front and back sides and four color schemes: pumpkin, cream, Indian pink and brown.

 Showcase, Tutorials, Templates

Construction Hazard Stripes Theme | More
This print-ready business card template is in Photoshop format.

 Showcase, Tutorials, Templates

Free Abstract Blue Business Card Template
This double-sided PSD card template includes well-organized layers and is in CMYK color mode for easy editing.

 Showcase, Tutorials, Templates

Die Gallery
In this gallery, you’ll find some unusual card shapes, all for free. All files are in EPS format.

Business Card Template
Here is a blank template for a standard US business card. Both JPEG and PSD versions of the template are available for free downloading.

 Showcase, Tutorials, Templates

Noise Modern Card | More
This download pack includes two full-layered PSD files for the front and back. The dimensions are 3.5 x 2 inches, and the resolution is 300 DPI.

 Showcase, Tutorials, Templates

Minimax Positivo Business Card Template
The template has six color variations and features a letterpress effect. The template package includes a PSD file, PDF help file and preview image.

 Showcase, Tutorials, Templates

Business Card Template (Vector) | More
A free Adobe Illustrator business card template in 3.5 x 2 inch format.

 Showcase, Tutorials, Templates

Vertical Business Card Vectors | More
An EPS file containing 18 vertical business card templates with JPG preview.

 Showcase, Tutorials, Templates

Free business card templates
10 free business card designs in PSD and TIFF formats.

 Showcase, Tutorials, Templates

Seextwood Business Card | More
A minimalist template in CMYK mode and 300 DPI resolution. The dimensions are 3.5 x 2.5 inches.

 Showcase, Tutorials, Templates

4 Blue Personal Business Card Templates | More
A set of four PSD business card templates in blue. The dimensions are 3 x 2 inches, and the resolution 300 DPI.

 Showcase, Tutorials, Templates

Premium Templates

Pure Style Business Card Template | More
A minimalist two-sided business card design (3.5 x 2 inches) that can fit practically any profession or brand. The template comes in high resolution and requires Adobe Photoshop 8 or higher for editing. Price: $7

 Showcase, Tutorials, Templates

Blue Monster Business Card Template | More
This funny template is ready to print and can be easily customized in a vector graphics editor. Price: $4

 Showcase, Tutorials, Templates

Business card (set 17) | More business card templates
These cheerful business cards might appeal to people in creative fields. Three license types are available; the basic one gives you this set for $5.

 Showcase, Tutorials, Templates

Typography Mini Business Card | More
These bright typographic mini-cards come in two styles, grungy and clean, and include a black and white version for low-cost printing. The templates are print-ready and can be edited in Photoshop. Price: $6

 Showcase, Tutorials, Templates

Tender Flowers Business Card | More
An original floral design that would work well for wedding photographers. It is print-ready and can be customized in Photoshop. Price: $7

 Showcase, Tutorials, Templates

Blue Bubble business card | More
This clean and airy design will appeal to fans of minimalism. It is in print-ready CMYK, 300 DPI, and includes two PSD files and two high-quality JPG images. Price: $5

 Showcase, Tutorials, Templates

Black Business Card Template | More
This business card has a rather universal design and would serve a personal brand, company or other project equally well. It is print ready; all you need to do is change the default text. Price: $7

 Showcase, Tutorials, Templates

The Black Family business Card Pack | More
These super-original and cute business cards might be good for showing off members of a creative team. They are two-sided, in CMYK and 300 DPI, easy to edit and print-ready. Price: $6

 Showcase, Tutorials, Templates

Related Posts

You may be interested in the following related posts:

(al)

© Julia May for Smashing Magazine, 2010. | Permalink | Post a comment | Add to del.icio.us | Digg this | Stumble on StumbleUpon! | Tweet it! | Submit to Reddit | Forum Smashing Magazine
Post tags: , ,

Kategorien: Google Reader

// New Job Titles Show APIs Moving Mainstream

Just about every web developer must now be comfortable at least consuming APIs, if not creating them. This trend now shows itself in job titles including “API” and “mashup,” and more often in the requirements and experience section of job listings.

Consider growth in the number of mashup jobs listed on job search site Indeed. Then compare it to the trends we noted in early 2007.

Some recent examples:

At a time when marketers are discovering APIs, it’s safe to say the interest in moving beyond developers. But it’s still a highly technical requirement, which means those with the skills are in demand. Just look at the glut of job listings for Amazon Web Services.

Kategorien: Google Reader

// Commonly Confused Bits Of jQuery

Smashing-magazine-advertisement in Commonly Confused Bits Of jQuerySpacer in Commonly Confused Bits Of jQuery
 in Commonly Confused Bits Of jQuery  in Commonly Confused Bits Of jQuery  in Commonly Confused Bits Of jQuery

The explosion of JavaScript libraries and frameworks such as jQuery onto the front-end development scene has opened up the power of JavaScript to a far wider audience than ever before. It was born of the need — expressed by a crescendo of screaming by front-end developers who were fast running out of hair to pull out — to improve JavaScript’s somewhat primitive API, to make up for the lack of unified implementation across browsers and to make it more compact in its syntax.

All of which means that, unless you have some odd grudge against jQuery, those days are gone — you can actually get stuff done now. A script to find all links of a certain CSS class in a document and bind an event to them now requires one line of code, not 10. To power this, jQuery brings to the party its own API, featuring a host of functions, methods and syntactical peculiarities. Some are confused or appear similar to each other but actually differ in some way. This article clears up some of these confusions.

[Offtopic: by the way, did you know that there is a Smashing eBook Series? Book #2 is Successful Freelancing for Web Designers, 260 pages for just $9,90.]

1. .parent() vs. .parents() vs. .closest()

All three of these methods are concerned with navigating upwards through the DOM, above the element(s) returned by the selector, and matching certain parents or, beyond them, ancestors. But they differ from each other in ways that make them each uniquely useful.

parent(selector)

This simply matches the one immediate parent of the element(s). It can take a selector, which can be useful for matching the parent only in certain situations. For example:

$('span#mySpan').parent().css('background', '#f90'); $('p').parent('div.large').css('background', '#f90');

The first line gives the parent of #mySpan. The second does the same for parents of all <p> tags, provided that the parent is a div and has the class large.

Tip: the ability to limit the reach of methods like the one in the second line is a common feature of jQuery. The majority of DOM manipulation methods allow you to specify a selector in this way, so it’s not unique to parent().

parents(selector)

This acts in much the same way as parent(), except that it is not restricted to just one level above the matched element(s). That is, it can return multiple ancestors. So, for example:

$('li.nav').parents('li'); //for each LI that has the class nav, go find all its parents/ancestors that are also LIs

This says that for each <li> that has the class nav, return all its parents/ancestors that are also <li>s. This could be useful in a multi-level navigation tree, like the following:

<ul id='nav'> <li>Link 1 <ul> <li>Sub link 1.1</li> <li>Sub link 1.2</li> <li>Sub link 1.3</li> </ul> <li>Link 2 <ul> <li>Sub link 2.1 <li>Sub link 2.2 </ul> </li> </ul>

Imagine we wanted to color every third-generation <li> in that tree orange. Simple:

$('#nav li').each(function() { if ($(this).parents('#nav li').length == 2) $(this).css('color', '#f90'); });

This translates like so: for every <li> found in #nav (hence our each() loop), whether it’s a direct child or not, see how many <li> parents/ancestors are above it within #nav. If the number is two, then this <li> must be on level three, in which case color.

closest(selector)

This is a bit of a well-kept secret, but very useful. It works like parents(), except that it returns only one parent/ancestor. In my experience, you’ll normally want to check for the existence of one particular element in an element’s ancestry, not a whole bunch of them, so I tend to use this more than parent(). Say we wanted to know whether an element was a descendent of another, however deep in the family tree:

if ($('#element1').closest('#element2').length == 1) alert("yes - #element1 is a descendent of #element2!"); else alert("No - #element1 is not a descendent of #element2");

Tip: you can simulate closest() by using parents() and limiting it to one returned element.

$($('#element1').parents('#element2').get(0)).css('background', '#f90');

One quirk about closest() is that traversal starts from the element(s) matched by the selector, not from its parent. This means that if the selector that passed inside closest() matches the element(s) it is running on, it will return itself. For example:

$('div#div2').closest('div').css('background', '#f90');

This will turn #div2 itself orange, because closest() is looking for a <div>, and the nearest <div> to #div2 is itself.

2. .position() vs. .offset()

These two are both concerned with reading the position of an element — namely the first element returned by the selector. They both return an object containing two properties, left and top, but they differ in what the returned position is relative to.

position() calculates positioning relative to the offset parent — or, in more understandable terms, the nearest parent or ancestor of this element that has position: relative. If no such parent or ancestor is found, the position is calculated relative to the document (i.e. the top-left corner of the viewport).

offset(), in contrast, always calculates positioning relative to the document, regardless of the position attribute of the element’s parents and ancestors.

Consider the following two <div>s:

Hello – I’m outerDiv. I have position: relative and left: 100px

Hi – I’m #innerDiv. I have position absolute, left: 50px and top: 80px.

Querying (no pun intended) the offset() and position() of #innerDiv will return different results.

var position = $('#innerDiv').position(); var offset = $('#innerDiv').offset(); alert("Position: left = "+position.left+", top = "+position.top+"\n"+ "Offset: left = "+offset.left+" and top = "+offset.top )

Try it yourself to see the results: click here.

3. .css(‘width’) and .css(‘height’) vs. .width() and .height()

These three, you won’t be shocked to learn, are concerned with calculating the dimensions of an element in pixels. They both return the offset dimensions, which are the genuine dimensions of the element no matter how stretched it is by its inner content.

They differ in the data types they return: css('width') and css('height') return dimensions as strings, with px appended to the end, while width() and height() return dimensions as integers.

There’s actually another little-known difference that concerns IE (quelle surprise!), and it’s why you should avoid the css('width') and css('height') route. It has to do with the fact that IE, when asked to read “computed” (i.e. not implicitly set) dimensions, unhelpfully returns auto. In jQuery core, width() and height() are based on the .offsetWidth and .offsetHeight properties resident in every element, which IE does read correctly.

But if you’re working on elements with dimensions implicitly set, you don’t need to worry about that. So, if you wanted to read the width of one element and set it on another element, you’d opt for css('width'), because setting dimensions, just like in CSS, requires specifying a unit of measurement.

But if you wanted to read an element’s width() with a view to performing a calculation on it, you’d be interested only in the figure; hence width() is better.

Note that each of these can simulate the other with the help of an extra line of JavaScript, like so:

var width = $('#someElement').width(); //returns integer width = width+'px'; //now it's a string like css('width') returns var width = $('#someElement').css('width'); //returns string width = parseInt(width); //now it's an integer like width() returns

Lastly, width() and height() actually have another trick up their sleeves: they can return the dimensions of the window and document. If you try this using the css() method, you’ll get an error.

4. .click() (etc) vs. .bind() vs. .live() vs. .delegate

These are all concerned with binding events to elements. The differences lie in what elements they bind to and how much we can influence the event handler (or “callback”). If this sounds confusing, don’t worry. I’ll explain.

click() (etc)

It’s important to understand that bind() is the daddy of jQuery’s event-handling API. Most tutorials deal with events with simple-looking methods, such as click() and mouseover(), but behind the scenes these are just the lieutenants who report back to bind().

These lieutenants, or aliases, give you quick access to bind certain event types to the elements returned by the selector. They all take one argument: a callback function to be executed when the event fires. For example:

$('#table td ').click(function() { alert("The TD you clicked contains '"+$(this).text()+"'"); });

This simply says that whenever a <div> inside #table is clicked, alert its text content.

bind()

We can do the same thing with bind, like so:

$('#table td ').bind('click', function() { alert("The TD you clicked contains '"+$(this).text()+"'"); });

Note that this time, the event type is passed as the first argument to bind(), with the callback as the second argument. Why would you use bind() over the simpler alias functions?

Very often you wouldn’t. But bind() gives you more control over what happens in the event handler. It also allows you to bind more than one event at a time, by space-separating them as the first argument, like so:

$('#table td').bind('click contextmenu', function() { alert("The TD you clicked contains '"+$(this).text()+"'"); });

Now, our event fires whether we’ve clicked the <td> with the left or right button. I also mentioned that bind() gives you more control over the event handler. How does that work? It does it by passing three arguments rather than two, with argument two being a data object containing properties readable to the callback, like so:

$('#table td').bind('click contextmenu', {message: 'hello!'}, function(e) { alert(e.data.message); });

As you can see, we’re passing into our callback a set of variables for it to have access to, in our case the variable message.

You might wonder why we would do this. Why not just specify any variables we want outside the callback and have our callback read those? The answer has to do with scope and closures. When asked to read a variable, JavaScript starts in the immediate scope and works outwards (this is a fundamentally different behavior to languages such as PHP). Consider the following:

var message = 'you left clicked a TD'; $('#table td').bind('click', function(e) { alert(message); }); var message = 'you right clicked a TD'; $('#table td').bind('contextmenu', function(e) { alert(message); });

No matter whether we click the <td> with the left or right mouse button, we will be told it was the right one. This is because the variable message is read by the alert() at the time of the event firing, not at the time the event was bound.

If we give each event its own “version” of message at the time of binding the events, we solve this problem.

$('#table td').bind('click', {message: 'You left clicked a TD'}, function(e) { alert(e.data.message); }); $('#table td').bind('contextmenu', {message: 'You right clicked a TD'}, function(e) { alert(e.data.message); });

Events bound with bind() and with the alias methods (.mouseover(), etc) are unbound with the unbind() method.

live()

This works almost exactly the same as bind() but with one crucial difference: events are bound both to current and future elements — that is, any elements that do not currently exist but which may be DOM-scripted after the document is loaded.

Side note: DOM-scripting entails creating and manipulating elements in JavaScript. Ever notice in your Facebook profile that when you “add another employer” a field magically appears? That’s DOM-scripting, and while I won’t get into it here, it looks broadly like this:

var newDiv = document.createElement('div'); newDiv.appendChild(document.createTextNode('hello, world!')); $(newDiv).css({width: 100, height: 100, background: '#f90'}); document.body.appendChild(newDiv); delegate()

Another shortfall of live() is that, unlike the vast majority of jQuery methods, it cannot be used in chaining. That is, it must be used directly on a selector, like so:

$('#myDiv a').live('mouseover', function() { alert('hello'); });

But not…

$('#myDiv').children('a').live('mouseover', function() { alert('hello'); });

… which will fail, as it will if you pass direct DOM elements, such as $(document.body).

delegate(), which was developed as part of jQuery 1.4.2, goes some way to solving this problem by accepting as its first argument a context within the selector. For example:

$('#myDiv').delegate('a', 'mouseover', function() { alert('hello'); });

Like live(), delegate() binds events both to current and future elements. Handlers are unbound via the undelegate() method.

Real-Life Example

For a real-life example, I want to stick with DOM-scripting, because this is an important part of any RIA (rich Internet application) built in JavaScript.

Let’s imagine a flight-booking application. The user is asked to supply the names of all passengers travelling. Entered passengers appear as new rows in a table, #passengersTable, with two columns: “Name” (containing a text field for the passenger) and “Delete” (containing a button to remove the passenger’s row).

To add a new passenger (i.e. row), the user clicks a button, #addPassenger:

$('#addPassenger').click(function() { var tr = document.createElement('tr'); var td1 = document.createElement('td'); var input = document.createElement('input'); input.type = 'text'; $(td1).append(input); var td2 = document.createElement('td'); var button = document.createElement('button'); button.type = 'button'; $(button).text('delete'); $(td2).append(button); $(tr).append(td1); $(tr).append(td2); $('#passengersTable tbody').append(tr); });

Notice that the event is applied to #addPassenger with click(), not live('click'), because we know this button will exist from the beginning.

What about the event code for the “Delete” buttons to delete a passenger?

$('#passengersTable td button').live('click', function() { if (confirm("Are you sure you want to delete this passenger?")) $(this).closest('tr').remove(); });

Here, we apply the event with live() because the element to which it is being bound (i.e. the button) did not exist at runtime; it was DOM-scripted later in the code to add a passenger.

Handlers bound with live() are unbound with the die() method.

The convenience of live() comes at a price: one of its drawbacks is that you cannot pass an object of multiple event handlers to it. Only one handler.

5. .children() vs. .find()

Remember how the differences between parent(), parents() and closest() really boiled down to a question of reach? So it is here.

children()

This returns the immediate children of an element or elements returned by a selector. As with most jQuery DOM-traversal methods, it is optionally filtered with a selector. So, if we wanted to turn all <td>s in a table that contained the word “dog” orange, we could use this:

$('#table tr').children('td:contains(dog)').css('background', '#f90'); find()

This works very similar to children(), only it looks at both children and more distant descendants. It is also often a safer bet than children().

Say it’s your last day on a project. You need to write some code to hide all <tr>s that have the class hideMe. But some developers omit <tbody> from their table mark-up, so we need to cover all bases for the future. It would be risky to target the <tr>s like this…

$('#table tbody tr.hideMe').hide();

… because that would fail if there’s no <tbody>. Instead, we use find():

$('#table').find('tr.hideMe').hide();

This says that wherever you find a <tr> in #table with .hideMe, of whatever descendancy, hide it.

6. .not() vs. !.is() vs. :not()

As you’d expect from functions named “not” and “is,” these are opposites. But there’s more to it than that, and these two are not really equivalents.

.not()

not() returns elements that do not match its selector. For example:

$('p').not('.someclass').css('color', '#f90');

That turns all paragraphs that do not have the class someclass orange.

.is()

If, on the other hand, you want to target paragraphs that do have the class someclass, you could be forgiven for thinking that this would do it:

$('p').is('.someclass').css('color', '#f90');

In fact, this would cause an error, because is() does not return elements: it returns a boolean. It’s a testing function to see whether any of the chain elements match the selector.

So when is is useful? Well, it’s useful for querying elements about their properties. See the real-life example below.

:not()

:not() is the pseudo-selector equivalent of the method .not() It performs the same job; the only difference, as with all pseudo-selectors, is that you can use it in the middle of a selector string, and jQuery’s string parser will pick it up and act on it. The following example is equivalent to our .not() example above:

$('p:not(.someclass)').css('color', '#f90'); Real-Life Example

As we’ve seen, .is() is used to test, not filter, elements. Imagine we had the following sign-up form. Required fields have the class required.

<form id='myform' method='post' action='somewhere.htm'> <label>Forename * <input type='text' class='required' /> <br /> <label>Surname * <input type='text' class='required' /> <br /> <label>Phone number <input type='text' /> <br /> <label>Desired username * <input type='text' class='required' /> <br /> <input type='submit' value='GO' /> </form>

When submitted, our script should check that no required fields were left blank. If they were, the user should be notified and the submission halted.

$('#myform').submit(function() { if ($(this).find('input').is('.required[value=]')) { alert('Required fields were left blank! Please correct.'); return false; //cancel submit event } });

Here we’re not interested in returning elements to manipulate them, but rather just in querying their existence. Our is() part of the chain merely checks for the existence of fields within #myform that match its selector. It returns true if it finds any, which means required fields were left blank.

7. .filter() vs. .each()

These two are concerned with iteratively visiting each element returned by a selector and doing something to it.

.each()

each() loops over the elements, but it can be used in two ways. The first and most common involves passing a callback function as its only argument, which is also used to act on each element in succession. For example:

$('p').each(function() { alert($(this).text()); });

This visits every <p> in our document and alerts out its contents.

But each() is more than just a method for running on selectors: it can also be used to handle arrays and array-like objects. If you know PHP, think foreach(). It can do this either as a method or as a core function of jQuery. For example…

var myarray = ['one', 'two']; $.each(myarray, function(key, val) { alert('The value at key '+key+' is '+val); });

… is the same as:

var myarray = ['one', 'two']; $(myarray).each(function(key, val) { alert('The value at key '+key+' is '+val); });

That is, for each element in myarray, in our callback function its key and value will be available to read via the key and val variables, respectively.

One of the great things about this is that you can also iterate over objects — but only in the first way (i.e. $.each).

jQuery is known as a DOM-manipulation and effects framework, quite different in focus from other frameworks such as MooTools, but each() is an example of its occasional foray into extending JavaScript’s native API.

.filter()

filter(), like each(), visits each element in the chain, but this time to remove it from the chain if it doesn’t pass a certain test.

The most common application of filter() is to pass it a selector string, just like you would specify at the start of a chain. So, the following are equivalents:

$('p.someClass').css('color', '#f90'); $('p').filter('.someclass').css('color', '#f90');

In which case, why would you use the second example? The answer is, sometimes you want to affect element sets that you cannot (or don’t want to) change. For example:

var elements = $('#someElement div ul li a'); //hundreds of lines later... elements.filter('.someclass').css('color', '#f90');

elements was set long ago, so we cannot — indeed may not wish to — change the elements that return, but we might later want to filter them.

filter() really comes into its own, though, when you pass it a filter function to which each element in the chain in turn is passed. Whether the function returns true or false determines whether the element stays in the chain. For example:

$('p').filter(function() { return $(this).text().indexOf('hello') != -1; }).css('color', '#f90')

Here, for each <p> found in the document, if it contains the string hello, turn it orange. Otherwise, don’t affect it.

We saw above how is(), despite its name, was not the equivalent of not(), as you might expect. Rather, use filter() as the positive equivalent of not().

Note also that unlike each(), filter() cannot be used on arrays and objects.

Real-Life Example

You might be looking at the example above, where we turned <p>s starting with hello orange, and thinking, “But we could do that more simply.” You’d be right:

$('p:contains(hello)').css('color', '#f90')

For such a simple condition (i.e. contains hello), that’s fine. But filter() is all about letting us perform more complex or long-winded evaluations before deciding whether an element can stay in our chain.

Imagine we had a table of CD products with four columns: artist, title, genre and price. Using some controls at the top of the page, the user stipulates that they do not want to see products for which the genre is “Country” or the price is above $10. These are two filter conditions, so we need a filter function:

$('#productsTable tbody tr').filter(function() { var genre = $(this).children('td:nth-child(3)').text(); var price = $(this).children('td:last').text().replace(/[^\d\.]+/g, ''); return genre.toLowerCase() == 'country' || parseInt(price) >= 10; }).hide();

So, for each <tr> inside the table, we evaluate columns 3 and 4 (genre and price), respectively. We know the table has four columns, so we can target column 4 with the :last pseudo-selector. For each product looked at, we assign the genre and price to their own variables, just to keep things tidy.

For the price, we replace any characters that might prevent us from using the value for mathematical calculation. If the column contained the value $14.99 and we tried to compute that by seeing whether it matched our condition of being below $10, we would be told that it’s not a number, because it contains the $ sign. Hence we strip away everything that is not number or dot.

Lastly, we return true (meaning the row will be hidden) if either of our conditions are met (i.e. the genre is country or the price is $10 or more).

filter()

8. .merge() vs. .extend()

Let’s finish with a foray into more advanced JavaScript and jQuery. We’ve looked at positioning, DOM manipulation and other common issues, but jQuery also provides some utilities for dealing with the native parts of JavaScript. This is not its main focus, mind you; libraries such as MooTools exist for this purpose.

.merge()

merge() allows you to merge the contents of two arrays into the first array. This entails permanent change for the first array. It does not make a new array; values from the second array are appended to the first:

var arr1 = ['one', 'two']; var arr2 = ['three', 'four']; $.merge(arr1, arr2);

After this code runs, the arr1 will contain four elements, namely one, two, three, four. arr2 is unchanged. (If you’re familiar with PHP, this function is equivalent to array_merge().)

.extend()

extend() does a similar thing, but for objects:

var obj1 = {one: 'un', two: 'deux'} var obj2 = {three: 'trois', four: 'quatre'} $.extend(obj1, obj2);

extend() has a little more power to it. For one thing, you can merge more than two objects — you can pass as many as you like. For another, it can merge recursively. That is, if properties of objects are themselves objects, you can ensure that they are merged, too. To do this, pass true as the first argument:

var obj1 = {one: 'un', two: 'deux'} var obj2 = {three: 'trois', four: 'quatre'} $.extend(true, obj1, obj2);

Covering everything about the behaviour of JavaScript objects (and how merge interacts with them) is beyond the scope of this article, but you can read more here.

The difference between merge() and extend() in jQuery is not the same as it is in MooTools. One is used to amend an existing object, the other creates a new copy.

There You Have It

We’ve seen some similarities, but more often than not intricate (and occasionally major) differences. jQuery is not a language, but it deserves to be learned as one, and by learning it you will make better decisions about what methods to use in what situation.

While there are strict rules these days for writing semantic and SEO-compliant mark-up, JavaScript is still very much the playground of the developer. No one will demand that you use click() instead of bind(), but that’s not to say one isn’t a better choice than the other. It’s all about the situation.

Related Posts

You may be interested in the following related posts:

We appreciate the feedback of our Twitter followers who reviewed the article before it was published.

(al)

© Andy Croxall for Smashing Magazine, 2010. | Permalink | Post a comment | Add to del.icio.us | Digg this | Stumble on StumbleUpon! | Tweet it! | Submit to Reddit | Forum Smashing Magazine
Post tags: , , ,

Kategorien: Google Reader

// Kick Ass Kickoff Meetings

Too many kickoff meetings squander the busiest, most expensive people's time reiterating what everyone already knows. If every meeting is an opportunity, why waste your first one? By asking stakeholders tough questions before the kick-off, and using the meeting itself to explore ideas and build relationships, you can turn a room of mutually suspicious turf battlers into an energetic team with shared ownership of the end-product and the kind of bond that can sustain the group through the challenges ahead.contact.us@alistapart.com (Kevin M. Hoffman)0751378682283124802616842222664160054718047661173628705328300816066675552957724709552507979975981384044375306313066172691531749482756492499412338410067542425880102659191065487226471266994542052149937302095882669455426217059045546266446307391139278710371453443409228660293930066575
Kategorien: Google Reader

// Fun With Fast JavaScript

This post is by Vladimir Vukićević and is a re-post from his personal weblog.

Fast JavaScript is a cornerstone of the modern web. In the past, application authors had to wait for browser developers to implement any complex functionality in the browser itself, so that they could access it from script code. Today, many of those functions can move straight into JavaScript itself. This has many advantages for application authors: there’s no need to wait for a new version of a browser before you can develop or ship your app, you can tailor the functionality to exactly what you need, and you can improve it directly (make it faster, higher quality, more precise, etc.).

Here are two examples that show off what can be done with the improved JS engine and capabilities that will be present in Firefox 4. The first example shows a simple web-based Darkroom that allows you to perform color correction on an image. The HTML+JS is around 700 lines of code, not counting jQuery. This is based on a demo that’s included with Google’s Native Client (NaCl) SDK; in that demo, the color correction work is done inside native code going through NaCl. That demo (originally presented as “too slow to run in JavaScript”) is a few thousand lines of code, and involves downloading and installing platform-specific compilers, multiple steps to test/deploy code, and installing a plugin on the browser side.

I get about 15-16 frames per second with the default zoomed out image (around 5 million pixels per second — that number won’t be affected by image size) on my MacBook Pro, which is definitely fast enough for live manipulation. The algorithm could be tightened up to make this faster still. Further optimizations to the JS engine could help here as well; for example, I noticed that we spend a lot of time doing floating point to integer conversions for writing the computed pixels back to the display canvas, due to how the canvas API specifies image data handling.

The Web Darkroom tool also supports drag & drop, so you can take any image from your computer and drop it onto the canvas to load it. A long (long!) time ago, back in 2006, I wrote an addon called “Croppr!”. It was intended to be used with Flickr, allowing users to play around with custom crops of any image, and then leave crop suggestions in comments to be viewed using Croppr. It almost certainly doesn’t work any more, but it would be neat to update it: this time with both cropping and color correction. Someone with the addon (perhaps a Jetpack now!) could then visit a Flickr photo and experiment, and leave suggestions for the photographer.

The second example is based on some work that Dave Humphrey and others have been doing to bring audio manipulation to the web platform. Originally, their spec included a pre-computed FFT with each audio frame delivered to the web app. I suggested that there’s no need for this — while a FFT is useful for some applications, for others it would be wasted work. Those apps that want a FFT could implement one in JS. Some benchmark numbers backed this up — using the typed arrays originally created for WebGL, computing an FFT in JS was approaching the speed of native code. Again, both could be sped up (perhaps using SSE2 or something like Mono.Simd on the JS side), but it’s fast enough to be useful already.

The demo shows this in action. A numeric benchmark isn’t really all that interesting, so instead I take a video clip, and as it’s playing, I extract a portion of the green channel of each frame and compute its 2D FFT, which is then displayed. The original clip plays at 24 frames per second, so that’s the upper bound of this demo. Using Float32 typed arrays, the computation and playback proceeds at around 22-24fps for me.

You can grab the video controls and scrub to a specific frame. (The frame rate calculation is only correct while the video is playing normally, not while you’re scrubbing.) The video source uses Theora, so you’ll need a browser that can play Theora content. (I didn’t have a similar clip that uses WebM, or I could have used that.)

These examples are demonstrating the strength of the trace-based JIT technique that Firefox has used for accelerating JavaScript since Firefox 3.5. However, not all code can see such dramatic speedups from that type of acceleration. Because of that, we’ll be including a full method-based JIT for Firefox 4 (for more details, see David Anderson’s blog, as well as David Mandelin’s blog). This will provide significantly faster baseline JS performance, with the trace JIT becoming a turbocharger for code that it would naturally apply to.

Combining fast JavaScript performance alongside new web platform technologies such as WebGL and Audio will make for some pretty exciting web apps, and I’m looking forward to seeing what developers do with them!

Edit: Made some last-minute changes to the demos, which ended up pulling in a slightly broken version of jQuery UI that wasn’t all that happy with Safari. Should be fixed now!

Kategorien: Google Reader

// DOM Traversal

The latest Platform Preview Build includes two great interoperable features for working with the DOM – DOM Traversal and Element Traversal. These features provide web developers with simple, flexible, and fast ways of traversing through a document using the same markup across browsers. These features come in the form of flat enumeration, simplifying the DOM tree to an iterative list, and filtering which enables you to tailor the set of nodes you traverse. These features work with the same markup across browsers – you can try out any of the code here in the IE9 platform preview and other browsers.

Without these features, finding an element of interest on a page requires you to do one or more depth-first traversals of the document using firstChild and nextSibling. This is usually accomplished with complex code that runs slowly. With the DOM and Element Traversal features, there are new and better ways of solving the problem. This blog post is a primer and provides a few best practices to get you on your way.

I’ll start with Element Traversal, since it’s the simplest of the interfaces and follows familiar patterns for enumerating elements in the DOM. Element Traversal is essentially a version of DOM Core optimized for Elements . Instead of calling firstChild and nextSibling, you call firstElementChild and nextElementSibling. For example:

if (elm.firstElementChild)
{
elm = elm.firstElementChild;

while (elm.nextElementSibling)
{
// Do work...
}
}

This is faster and more convenient, saving you the trouble of having to check for text and comment nodes when you’re really only interested in elements.

DOM Traversal is designed for much broader use cases. First, you create a NodeIterator or a TreeWalker. Then you can use one of the iteration methods to traverse the tree:

var iter = document.createNodeIterator(elm, NodeFilter.SHOW_ELEMENT, null, false); // This would work fine with createTreeWalker, as well

var node = iter.nextNode();
while (node = iter.nextNode())
{
node.style.display = "none";
}

The codepath above iterates through a flat list of all nodes in the tree. This can be incredibly useful since in many cases you don’t care whether something is a child or sibling of something else, just whether it occurs before or after your current position in the document.

A big benefit of DOM Traversal is that it introduces the idea of filtering, so that you only traverse the nodes you care about. While nodeIterator only performs flat iterations, TreeWalker has some additional methods, like firstChild(), that let you see as much or as little of the tree structure as you want.

The SHOW_* family of constants provides a way to include broad classes of nodes, such as text or elements (like SHOW_ELEMENT in the earlier example). In many cases, this will be enough. But when you need the most precise control, you can write your own filter via the NodeFilter interface. The NodeFilter interface uses a callback function to filter each node, as in the following example:

 

var iter = document.createNodeIterator(elm, NodeFilter.SHOW_ALL, keywordFilter, false);

function keywordFilter(node)
{
var altStr = node.getAttribute('alt').toLowerCase();

if (altStr.indexOf("flight") != -1 || altStr.indexOf("space") != -1)
return NodeFilter.FILTER_ACCEPT;
else
return NodeFilter.FILTER_REJECT;
}

For a live example, check out my demo for DOM Traversal -- I used NodeFilter extensively there. Complex filtering operations on the list of media elements were as simple as using a NodeFilter callback like the one above.

In this post, I showed that you have options in how to traverse a document. Here are suggested best practices for when you should use the various interfaces:

  • If the structure of the document is important – and you’re only interested in elements – consider Element Traversal. It’s fast and won’t leave a big footprint in your code.
  • If you don’t care about document structure, use NodeIterator instead of TreeWalker. That way, it’s obvious in your code that you’re only going to be using a flat list. NodeIterator also tends to be faster, which becomes important when traversing large sets of nodes.
  • If the SHOW_* constants do what you need for filtering, use them. Using constants makes your code simpler, as well as having slightly better performance. However, if you need fine-grained filtering, NodeFilter callbacks become indispensable.

I’ve already found these features to be a great help in my own coding, so I’m really excited to see what you do with them. Download the latest Platform Preview, try out the APIs, and let us know what you think.

Thanks!
Jonathan Seitel
Program Manager

ieblog024387318668354780130615750198106986196316289822634129174992024800448994943962400755382016776238978712351670300482372876130058154698051444570045836691136043254113585538727088907822
Kategorien: Google Reader

// How to use Selenium 2 with Maven

There are several ways to use Selenium 2:

  1. If you don’t have Selenium 1.x legacy code, you might want to directly use on of the new WebDriver implemenations like ChromeDriver, HtmlUnitDriver, FirefoxDriver, or InternetExplorerDriver which provide a nice, small and easy to learn API.
  2. If you have Selenium 1.x legacy code, you can still use the well known DefaultSelenium class or the new WebDriverBackedSelenium, which extends DefaultSelenium but uses one of the WebDriver implementations internally.

Whichever option you prefer, if you have want to use Maven, all you need to do is add the following dependency to your pom.xml:

<dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium</artifactId> <version>2.0a5</version> </dependency>

If you know, that you will only use a certain WebDriver implementation, e.g. the FirefoxDriver, you don’t need to depend on the selenium artifact (which has dependencies to all WebDriver implementations as well as the support classes). Instead you can add the dependency to just the artifact you need, e.g.

<dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-firefox-driver</artifactId> <version>2.0a5</version> </dependency>

When using a WebDriver implementation, there is no need to start a Selenium server – the browser will be directly started and remote controlled.

But if you are using DefaultSelenium (or the RemoteWebDriver implementation), you still need to start a Selenium server.

The best way is to download the standalone Selenium server jar and just use it.

Furthermore you can also embed the Selenium server into your own project, if you add the following dependency to your pom.xml:

<dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-server</artifactId> <version>2.0a5</version> </dependency>

Now you can create a SeleniumServer instance yourself and start it.

Be aware, that the selenium-server artifact has a dependency to the servlet-api-2.5 artifact, which you need to exclude, if your project will be run in a web application container.

Well, I hope that covers everything you need to know on how to use Selenium 2 with Maven.

Michael


Kategorien: Google Reader

// Building a custom HTML5 video player with CSS3 and jQuery - Opera Developer Community

Introduction

The HTML5 <video> element is already supported by most modern browsers, and even IE has support announced for version 9. There are many advantages of having video embedded natively in the browser (covered in the article Introduction to HTML5 video by Bruce Lawson), so many developers are trying to use it as soon as possible. There are a couple of barriers to this that remain, most notably the problem of which codecs are supported in each browser, with a disagreement between Opera/Firefox and IE/Safari. That might not be a problem for much longer though, with Google recently releasing the VP8 codec, and the WebM project coming into existence. Opera, Firefox, Chrome and IE9 all have support in final builds, developer builds, or at least support announced for this format, and Flash will be able to play VP8. This means that we will soon be able to create a single version of the video that will play in the <video> element in most browsers, and the Flash Player in those that don't support WebM natively.

The other major barrier to consider is building up a custom HTML5 <video> player — this is where a Flash-only solution currently has an advantage, with the powerful Flash IDE providing an easy interface with which to create a customized video player component. IF we want to write a customised player for the HTML5 <video> element we need to handcode all the HTML5, CSS3, JavaScript, and any other open standards we want to use to build a player!

And this is where this article comes in. This is the first of a series in which we will look at building up an easily customizable HTML5 <video> player, including packaging it as a simple jQuery plugin, choosing control types and outputting custom CSS for your own situation. In this article we will look at:

  1. Video controls
  2. Basic markup for controls
  3. Packaging the player as a jQuery plugin
  4. Look and Feel
  5. Themeing the player

We'll use jQuery for easier DOM manipulation, and jQuery UI for the slider controls used for seeking and changing the volume level. To build a scalable solution, we'll wrap everything up in a jQuery plugin.

Video controls

As professional web designers, we want to create a video player that looks consistent across browsers. Each browser however provides its own different look and feel for the player, from the minimal approach of Firefox and Chrome, to the more shiny controls of Opera and Safari (see Figure 1 for the controls in each browser). If we want our controls to look the same across all browsers, and integrate with our own design, we'll have to create our own controls from scratch. This is not as hard as it seems.

Native browser video controls

Figure 1: Native browser video controls across different browsers

All media elements in HTML5 support the media elements API, which we can access using JavaScript and use to easily wire up functions such as play, pause, etc. to any buttons we create. Because the native video player plays nicely with other open web technologies, we can create our controls using HTML, CSS, SVG or whatever else we like.

Basic markup for controls

First, we'll need to create the actual markup for the video controls. We'll need a Play/Pause button, a seek bar, a timer and a volume button and slider. We'll insert the markup for the controls after the <video> element, and wrap them up in another element.

<div class="ghinda-video-controls"> <a class="ghinda-video-play" title="Play/Pause"></a> <div class="ghinda-video-seek"></div> <div class="ghinda-video-timer">00:00</div> <div class="ghinda-volume-box"> <div class="ghinda-volume-slider"></div> <a class="ghinda-volume-button" title="Mute/Unmute"></a> </div> </div>

We've used classes instead of IDs for all elements, to be able to use the same code for multiple video players on the same page.

Packaging the player as a jQuery plugin

After creating the markup we'll have to tie our elements to the media elements API, in order to control the video's behavior. As noted before, we'll package the player as a jQuery plugin, which will also aid reuse on multiple elements.

AUTHOR'S NOTE: I'm going to assume you are familiar with the basic anatomy of a jQuery plugin, and JavaScript, so I'm only briefly going to explain the script. If you need more information on these subjects, consult Craig Buckler's How to develop a jQuery plugin tutorial, and the JavaScript section of the Opera web standards curriculum.

$.fn.gVideo = function(options) { // build main options before element iteration var defaults = { theme: 'simpledark', childtheme: '' }; var options = $.extend(defaults, options); // iterate and reformat each matched element return this.each(function() { var $gVideo = $(this); //create html structure //main wrapper var $video_wrap = $('<div></div>').addClass('ghinda-video-player').addClass(options.theme).addClass(options.childtheme); //controls wraper var $video_controls = $('<div class="ghinda-video-controls"><a class="ghinda-video-play" title="Play/Pause"></a><div class="ghinda-video-seek"></div><div class="ghinda-video-timer">00:00</div><div class="ghinda-volume-box"><div class="ghinda-volume-slider"></div><a class="ghinda-volume-button" title="Mute/Unmute"></a></div></div>'); $gVideo.wrap($video_wrap); $gVideo.after($video_controls);

Here we are using jQuery to create the video player markup dynamically (but not the video player itself), and removing the controls attribute once the script loads. That's because in cases where the user has JavaScript disabled, these controls will be useless, and he/she won't even get the native browser controls to the video element. It makes a lot more sense to start with the controls attribute present in case the script fails to load, and then removing it so the player will use our custom controls only after the script successfully loads.

Next, we'll have to target each of the elements in the controls, in order to be able to add listeners.

//get newly created elements var $video_container = $gVideo.parent('.ghinda-video-player'); var $video_controls = $('.ghinda-video-controls', $video_container); var $ghinda_play_btn = $('.ghinda-video-play', $video_container); var $ghinda_video_seek = $('.ghinda-video-seek', $video_container); var $ghinda_video_timer = $('.ghinda-video-timer', $video_container); var $ghinda_volume = $('.ghinda-volume-slider', $video_container); var $ghinda_volume_btn = $('.ghinda-volume-button', $video_container); $video_controls.hide(); // keep the controls hidden

We're targeting each control by its class; we'll keep the controls hidden until everything is ready.

Now for the Play/Pause controls:

var gPlay = function() { if($gVideo.attr('paused') == false) { $gVideo[0].pause(); } else { $gVideo[0].play(); } }; $ghinda_play_btn.click(gPlay); $gVideo.click(gPlay); $gVideo.bind('play', function() { $ghinda_play_btn.addClass('ghinda-paused-button'); }); $gVideo.bind('pause', function() { $ghinda_play_btn.removeClass('ghinda-paused-button'); }); $gVideo.bind('ended', function() { $ghinda_play_btn.removeClass('ghinda-paused-button'); });

Most browsers provide a secondary set of controls for the video in the right-click (ctrl-click on a Mac) context menu. Because of the way we are putting this together, if a user activated these alternative controls it would break our custom controls. In order to avoid this we're attaching events to the Play/Pause button itself, and the "Play", "Pause" and "Ended" listeners of the video player.

We're also adding and removing classes from our button to change the look of it, depending on the state of the video (Playing or Paused).

For creating the seek slider we'll use the jQuery UI Slider component.

var createSeek = function() { if($gVideo.attr('readyState')) { var video_duration = $gVideo.attr('duration'); $ghinda_video_seek.slider({ value: 0, step: 0.01, orientation: "horizontal", range: "min", max: video_duration, animate: true, slide: function(){ seeksliding = true; }, stop:function(e,ui){ seeksliding = false; $gVideo.attr("currentTime",ui.value); } }); $video_controls.show(); } else { setTimeout(createSeek, 150); } }; createSeek();

As you can see, we're using a recursive function, while reading the readyState of the video. We have to keep polling the video until it is ready, otherwise we can't determine the duration, and can't create the slider. Once the video is ready, we initialize the slider, and also show the controls.

Next we'll create the timer, and attach it to the timeupdate listener of the video element.

var gTimeFormat=function(seconds){ var m=Math.floor(seconds/60)<10?"0"+Math.floor(seconds/60):Math.floor(seconds/60); var s=Math.floor(seconds-(m*60))<10?"0"+Math.floor(seconds-(m*60)):Math.floor(seconds-(m*60)); return m+":"+s; }; var seekUpdate = function() { var currenttime = $gVideo.attr('currentTime'); if(!seeksliding) $ghinda_video_seek.slider('value', currenttime); $ghinda_video_timer.text(gTimeFormat(currenttime)); }; $gVideo.bind('timeupdate', seekUpdate);

Here we're using the seekUpdate function to get the currentTime attribute of the video, and the gTimeFormat function to format the actual value received.

For the volume controls, we'll also use the jQuery UI slider and a custom function on the volume button for muting and un-muting the video.

$ghinda_volume.slider({ value: 1, orientation: "vertical", range: "min", max: 1, step: 0.05, animate: true, slide:function(e,ui){ $gVideo.attr('muted',false); video_volume = ui.value; $gVideo.attr('volume',ui.value); } }); var muteVolume = function() { if($gVideo.attr('muted')==true) { $gVideo.attr('muted', false); $ghinda_volume.slider('value', video_volume); $ghinda_volume_btn.removeClass('ghinda-volume-mute'); } else { $gVideo.attr('muted', true); $ghinda_volume.slider('value', '0'); $ghinda_volume_btn.addClass('ghinda-volume-mute'); }; }; $ghinda_volume_btn.click(muteVolume);

Finally we're going the remove the controls attribute from the <video>, because by this point our own custom controls are set up and we want to use those instead of the browser defaults.

$gVideo.removeAttr('controls');

Now that we have our plugin all done, we can call it on any video element we want, like so.

$('video').gVideo();

This will call the plugin on all the video elements on the page.

Look and Feel

And now for the fun part, the look and feel of the video player. Once the plugin is ready, customizing the controls is really easy with a little bit of CSS. As you've notice we haven't added any styling to the controls. We'll use CSS3 for all the customizations regarding the player.

First, we'll add some style to the main video player container. We'll use this as the main chrome for the player.

.ghinda-video-player { float: left; padding: 10px; border: 5px solid #61625d; -moz-border-radius: 5px; /* FF1+ */ -ms-border-radius: 5px; /* IE future proofing */ -webkit-border-radius: 5px; /* Saf3+, Chrome */ border-radius: 5px; /* Opera 10.5, IE 9 */ background: #000000; background-image: -moz-linear-gradient(top, #313131, #000000); /* FF3.6 */ background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #313131),color-stop(1, #000000)); /* Saf4+, Chrome */ box-shadow: inset 0 15px 35px #535353; }

We've floated it left, to prevent it from expanding to the full width of the player, instead keeping it restrained to the width of the actual video element. We're using gradients and border radius to add polish, plus an inset box shadow to emulate the gradient effect in Opera, as it does not yet support gradients (as of 10.60, the latest version at the time of writing).

Next we'll float all the controls to the left, to align them horizontally. We'll use opacity and transitions on the Play/Pause and Volume Mute/Unmute buttons to create a nice hover effect.

.ghinda-video-play { display: block; width: 22px; height: 22px; margin-right: 15px; background: url(../images/play-icon.png) no-repeat; opacity: 0.7; -moz-transition: all 0.2s ease-in-out; /* Firefox */ -ms-transition: all 0.2s ease-in-out; /* IE future proofing */ -o-transition: all 0.2s ease-in-out; /* Opera */ -webkit-transition: all 0.2s ease-in-out; /* Safari and Chrome */ transition: all 0.2s ease-in-out; } .ghinda-paused-button { background: url(../images/pause-icon.png) no-repeat; } .ghinda-video-play:hover { opacity: 1; }

I'm sure you followed the JavaScript part carefully, and saw that we're adding and removing classes on the Play/Pause button depending on the state of the video(Playing/Paused). That's why the ghida-paused-button class overwrites the background property of the ghinda-video-play class.

Now for the sliders. As you saw before, we're using the jQuery UI slider control for both the seek bar and the volume level. This component has its own styles defined in jQuery UI's stylesheet, but we'll completely overwrite these to make the look of the slider more in keeping with the rest of the player.

.ghinda-video-seek .ui-slider-handle { width: 15px; height: 15px; border: 1px solid #333; top: -4px; -moz-border-radius:10px; -ms-border-radius:10px; -webkit-border-radius:10px; border-radius:10px; background: #e6e6e6; background-image: -moz-linear-gradient(top, #e6e6e6, #d5d5d5); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #e6e6e6),color-stop(1, #d5d5d5)); box-shadow: inset 0 -3px 3px #d5d5d5; } .ghinda-video-seek .ui-slider-handle.ui-state-hover { background: #fff; } .ghinda-video-seek .ui-slider-range { -moz-border-radius:15px; -ms-border-radius:15px; -webkit-border-radius:15px; border-radius:15px; background: #4cbae8; background-image: -moz-linear-gradient(top, #4cbae8, #39a2ce); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #4cbae8),color-stop(1, #39a2ce)); box-shadow: inset 0 -3px 3px #39a2ce; }

Currently the volume slider is also visible at all times, positioned next to the volume button. We'll change this so the slider is hidden by default, and shows up only when we're hovering the Mute/Unmute button, to make it look a bit more dynamic and neater. Again, transitions are our answer here:

.ghinda-volume-box { height: 30px; -moz-transition: all 0.1s ease-in-out; /* Firefox */ -ms-transition: all 0.1s ease-in-out; /* IE future proofing */ -o-transition: all 0.2s ease-in-out; /* Opera */ -webkit-transition: all 0.1s ease-in-out; /* Safari and Chrome */ transition: all 0.1s ease-in-out; } .ghinda-volume-box:hover { height: 135px; padding-top: 5px; } .ghinda-volume-slider { visibility: hidden; opacity: 0; -moz-transition: all 0.1s ease-in-out; /* Firefox */ -ms-transition: all 0.1s ease-in-out; /* IE future proofing */ -o-transition: all 0.1s ease-in-out; /* Opera */ -webkit-transition: all 0.1s ease-in-out; /* Safari and Chrome */ transition: all 0.1s ease-in-out; } .ghinda-volume-box:hover .ghinda-volume-slider { position: relative; visibility: visible; opacity: 1; }

We're hiding the volume slider by default, and giving the volume container a small fixed height that just fits the width of the volume button. We're also assigning transitions to both.

When the volume button is hovered, its height increases via the specified transition; we then use the .ghinda-volume-box:hover .ghinda-volume-slider descendant selector to transition the volume slider into view.

With basic CSS knowledge and some new CSS3 properties, we've already created a nice interface for our player, it looks like Figure 2:

Video player screenshot

Figure 2: Our finished video player.

Themeing the player

As you probably noticed, when creating the jQuery plugin, we've defined a set of default options. These options are theme and childtheme, and can be changed when calling the plugin, allowing us to easily apply custom themes as desired.

A theme represents a completely new set of CSS rules for every single control. A child theme on the other hand is a set of CSS rules that builds upon the rules of an existing theme, adding or overwriting the "parent" theme's style.

We can specify both of there options or only one, when calling the jQuery plugin.

$('video').gVideo({ childtheme:'smalldark' });

In the above example code we are calling the plugin with the smalldark child theme specified. This will apply our default parent theme, and then apply our child theme over the top of it, overwriting a small portion of the rules set by the parent theme. See Figure 3 for the Smalldark theme in action.

Smalldark child theme

Figure 3: the Smalldark child theme in action.

You can check out the final video player example live to see both themes in action, or download the source code (8.5mb, ZIP file) and experiment with it further.

Summary

Building our own custom video player with HTML5 video, JavaScript and CSS3 is fairly easy. By using JavaScript only for the actual functionality of the controls, and CSS3 for everything that involves the look and feel of the player, we get a powerful, easily customizable solution.

Kategorien: Google Reader

// Canto.js: An Improved Canvas API

Javascript author extraordinaire David Flanagan released Canto.js recently, a lightweight wrapper API for canvas, introduced here and documented at the top of the source code. Example:

PLAIN TEXT JAVASCRIPT: canto("canvas_id").moveTo(100,100).lineTo(200,200,100,200).closePath().stroke();
 

Notice three things:

  • canto() returns an abstraction of the canvas - a "Canto" object.
  • As with jQuery and similar libraries, there's method chaining; each method called on a Canto also returns the Canto.
  • lineTo() has been extended to support multiple lines being drawn in a single call.

Instead of setting the ink properties and then painting it, you can do it all in one step:

PLAIN TEXT JAVASCRIPT: canto("canvas_id").moveTo(100,100).lineTo(200,200,100,200).closePath().stroke({lineWidth: 15, strokeStyle: "red"});
 

And plenty more syntactic sugar - check out the API in the source code comments. Sweet!

Thanks @pkeane.

Kategorien: Google Reader

// Do You Know How Slow Your Web Page Is?

The Web Timing draft specification presents a standard set of metrics for measuring web page load time across browsers. We’re happy to announce that in Chrome 6, web developers can now access these new metrics under window.webkitPerformance.
Measuring web page load time is a notoriously tricky but important endeavor. One of the most common challenges is simply getting a true start time. Historically, the earliest a web page could reliably begin measurement is when the browser begins to parse an HTML document (by marking a start time in a <script> block at the top of the document).
Unfortunately, that is too late to include a significant portion of the time web surfers spend waiting for the page: much of the time is spent fetching the page from the web server. To address this shortcoming, some clever web developers work around the problem by storing the navigation start time in a cookie during the previous page’s onbeforeunload handler. However, this doesn’t work for the critical first page load which likely has a cold cache.
Web Timing now gives developers the ability to measure the true page load time by including the time to request, generate, and receive the HTML document. The timeline below illustrates the metrics it provides. The vertical line labeled "Legacy navigation started" is the earliest time a web page can reliably measure without Web Timing. In this case, instead of a misleading 80ms load time, it is now possible to see that the user actually experienced a 274ms time. Including this missing phase will make your measurements appear to increase. It’s not because pages are getting slower – we’re just getting a better view on where the time is actually being spent.

Across other browsers: Web Timing metrics are under window.msPerformance in the third platform preview of Internet Explorer 9 and work is underway to add window.mozPerformance to Firefox. The specification is still being finalized, so expect slight changes before the browser prefixes are dropped. If you’re running a supported browser, please try the Web Timing demonstration and send us feedback.
Posted by Tony Gentilcore, Software Engineer
Kategorien: Google Reader
Inhalt abgleichen

// My tweets

  • I like atmosphere here in the Sticky Wicket Pub, but we are sitting in the kids corner.

    vor 16 Stunden 27 Minuten
  • For now, the last day in beautiful Vancouver. Now, we heading to Victoria. http://twitpic.com/2mhxnz

    vor 1 Tag 57 Minuten
  • The fish & chips was delicious at the Lamplighter Pub, better than the original. (@ The Lamplighter Public House w/ 3 others)

    vor 1 Tag 18 Stunden
  • We are sitting in a nice cafe in Downtown Vancouver. This city is really impressive. But the weather could be better. #vancinsep

    vor 2 Tage 22 Stunden