An Analysis of Typography on the Web










Typography is one of the most—if not the most—important aspects of web design. Some would argue that it takes up to 95% of web design, so why do we often neglect its importance? The readers who come to your site will often decide whether or not to stay according to your typographic choices. After all, they came here to read in the first place. Think about it for a second: if content really is king, logically typography should be treated as the queen.

In fact, even some font names suggest that classification; Futura, Optima, Times New Roman (OK, that’s probably a dude), Verdana, Lucida, Georgia, Helvetica… There’s no question about it, Typography is the queen. Therefore, she also needs to be dressed up properly before going out: she should put on some kerning and tracking, maybe a different font-variant, and already she’s looking like a real lady.

Not sure what I’m talking about? Well, read on.


Knowing Your (sans) Serifs

Before proceeding with this article, and especially if you don’t have much contact with typography, I suggest you fill the gaps of your Typographic knowledge from Typedia, taking special note of Typeface classifications and the anatomy of a typeface, which will serve you well when making your own font-stacks and pairing fonts.

After you finish reading the two articles on Typedia, come back here so we can tighten your newly-founded Typographic knowledge and prepare it for the next few chapters of this article.

Tightening Wisdom #1: Typefaces Relate

Typefaces have dynamic relationships and can look good or bad together, depending on who they’re mixed with and their differences. If we’d like to get technical, there are in fact three ways in which typefaces can relate:

  1. Concord

    A concordant relationship is the one with no thrills, where two typefaces are very similar in characteristics. It can also be a single typeface in multiple styles and/or sizes.

  2. Contrast

    When typefaces are fairly different from each other, contrast appears. It’s usually good to aim for contrast, for instance, between a serif and sans-serif typeface.

  3. Conflict

    Two (or more) typefaces who have different characteristics that are still similar enough to create distress on a page are in conflict. You should usually avoid this type of relationship.

Contrasting, conflicting and concording relationship between fonts.

Tightening Wisdom #2: Typefaces Differ

Typefaces can vary. Whether it is weight, height, width, or anything else, every single typeface has some characteristic that makes it stand out. You should learn to spot these subtleties and adapt to their influence. And don’t think it doesn’t matter, since even various iterations of the same typefaces can be significantly unequal at times.

This specifically relates to the Web, where the art of creating and applying font stacks is very important. You do not have to pick exactly the same-looking typefaces for a fallback, but it’s only fair to say that an oldstyle font like Garamond should be backed up by another oldstyle typeface with sensibly similar characteristics (Caslon, Baskerville, Times, for instance).

Adobe Garamond Pro, Garamond Premier Pro and Georgia side-by-side

Although they’re all serifs, Georgia, Garamond and Adobe Garamond Pro (200 point size in example above) look very different.

Tightening Wisdom #3: Not Every Typeface is Suitable For All Situations

A modern font, such as Bodoni Condensed or Bodoni Bold is an excellent choice for headlines, whereas it would likely be a bad typeface for extensive lines of body copy, where it would only distract the reader from the content. An oldstyle like Garamond (I ♥ Garamond) is a much better choice for these situations.

Non-designers often make poor decisions when choosing typefaces for different occasions, and—although I’m going to skip the Comic Sans lecture—you should be aware of the fact that it’s not always suitable to use, say, Georgia for body copy. It’s also not always bad to use Arial as your preferred typeface; but do consider what message you are trying to convey, via your typography.


Learning From The Best

This article is not primarily a showcase, yet it’s always interesting to observe what other talented designers have done to make their (client’s) websites a delight to look at. We’re going to see what can be done with careful consideration for font decoration, as well as solid font-stacks and smart typographic choices.

(P.S. If you’d like to see other examples of nice Typography on line, browse through Typesites’ archives. There’s not too much content there, but they’ve covered some very good sites.)

Websafe Fonts: A List Apart

A List Apart, careful consideration to Webfonts
A List Apart shows how Websafe fonts can look good indeed when given enough thought.

Is Verdana the most boring typeface you can use? Not if you ask Jason Santa Maria. He was smart in using Verdana’s strength (X-height) to make body copy rather small in size for a dignified, elegant look that A List Apart deserves. The small size also makes it pleasant to read in the long run.

Georgia is mostly used for emphasis on certain page elements, and as a display typeface. From other noticeable design decisions, uppercase letters are small in size and positive letter-spaced for easier readability and better looks.

Font Stacks: Jon Tan

JonTangerine.com, typographic excellence
Jon Tan, attention to detail brings Typographic perfection.

Jon Tan, like Khoi Vin and Daniel Mall, also follows the cult of black & white minimalist design with carefully placed splashes of orange. Although there’s a lack of excitement in color choice, you could say that Jon makes up for it by taking extra care of his typographic choices. The CSS file of Jontangerine.com contains more than 250 different declarations for all micro-typography!

The main body copy is set in lovely Georgia, while centered headings appear in a Times-based font stack with Baskerville and Palatino:

font-family: baskerville, 'palatino linotype', 'times new roman', serif;

In other areas, typographic “color” is achieved using different font-variants, various shades of black and excellent font styling. Definitely one of the best typography-centered sites out there!

@font-face Embedding: Information Highwayman

Information Highwayman
Information Highwayman is embedding Justus, a free font.

You have probably heard a lot about @font-face embedding with CSS during the past few months. Although Internet Explorer has had a similar technique ever since its fourth iteration (we’re ashamed to admit this), only in 2009—when all of the five big browsers implemented @font-face (the right way)—did we start talking intensively about using non-core webfonts online.

There are, as you might know, a few considerable drawbacks to this technique (primarily copyright issues), but if you find a suitable font for your needs, you have every chance of improving the way readers experience your site. D. Bnonn Tennant (Information Highwayman) decided to use Justus for body copy, which contrasts quite well against the sans-serif background element (the “compelling magnum”) and helps in achieving the “worn-out” effect on the site.

Typekit: Elliot Jay Stocks

FF Tisa Web Pro on ElliotJayStocks.com
The slabby FF Tisa goes perfect with Elliot’s website.

Elliot likes to use Slab-Serif typefaces, which is exemplified in both his excellent 8 faces magazine on Typography (highly recommend it), with FF Unit Slab, and his own Website, where FF Tisa Web Pro is embedded using Typekit’s font embedding service.

There isn’t as much typographic styling on the site as, for instance, Jon Tan has; however, he’s done a great job with alignment and color, which also never should be overlooked and are important ingredients in good typography.

Image Replacement and sIFR: Squared Eye

Squared Eye, sIFR typography
Squared Eye uses sIFR Flash text replacement.

Although they’re rapidly becoming “old” replacement techniques, Flash and image-replaced text (both Cufón and manually inserted images) instead of ordinary text are important for cross-browser compatibility in sites whose visitors aren’t predominantly using modern browsers, as well as in cases where the particular font isn’t available due to one or the other reason (e.g., copyright issues).

Squared Eye places emphasis on different levels of headings with sIFR, as well as with manually inserted images. He’s using a beautiful slab-serif Archer in harmony with a Lucida-based font stack for a modern, yet still elegant look.


Putting Our Knowledge to Good Use

Although I’m going to provide a few font-stacks you can use in your designs, consider the following more as a “training” for making your own font stacks. There are already plenty of other sites out there which offer a lot of readymade solutions for both display and body copy text.

As the saying goes, “Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime.”

Gripping the Bases: Your Readers

Before beginning to build font stacks, you should become acquainted with your primary audience and determine what software and Operating Systems they use. That way, you can predict which fonts they might have installed, and how much typographic flexibility that provides you.

For instance; Matthew Smith (Squared Eye) probably (rightfully) predicted that most of his audience will not have a font like Archer installed on their computers and decided to embed it using Flash font replacement (comparing to Archer, ~97% of users have Flash installed).

Always design with core Webfonts first, and then gradually improve with font stacks)

For more information on fonts shipped with different software, browse through 24 Ways’ Font Matrix, Fluid Web Type and Apaddedcell. You might also find Microsoft’s extensive documentation on fonts that come with their products, as well as insight into their Typographic department, a useful read.

Notice The Small Things

When it comes to building font stacks, you’ll need to consider a few variables, when determining what make fonts different from one other (remember the Georgia-Garamond-Garamond comparison above?). This, again, comes down to your experience and familiarity with different font categories. You’ll need to learn to notice not only the way serifs are presented (are they slanted, or straight? Or do they not exist?), but also the small(er) differences between two similar typefaces.

Consider how they communicate with each other, their x-heights and readability on small sizes, as well as their form and direction. Even if this sounds, perhaps, intimidating right now, remember how practice makes perfect.

Example: Ibis Display and Archer, although both slab-serifs by category, probably wouldn’t make a good pair due to the significant difference in the way their serifs are presented and the noticeable thick/thin transitions on Ibis versus a monoweight Archer.

Writing a Sample Font Stack

I’ve already mentioned I like Garamond. So I’m going to base a font stack off of Times New Roman, which is the Web-safe font closest in appearance to the aforementioned oldstyle typeface.

I would like to mention that Garamond, due to its low X-height, likely isn’t the best choice when designing for excellent readability on screen (after all, it wasn’t made for screen presentation primarily), but it is fine if used on high enough font sizes (in my opinion, 16-17 pixel/1em Garamond is optimal).

In optical scaling, as it is called, smaller text sizes typically have larger x-heights, wider stem widths, and less typographic stem contrast and larger display sizes have smaller x-heights with more variation in stem widths.
MSDN Blogs

Font degrading in our font-stack
How our font family will degrade in case Garamond isn’t available (Garamond colored blue in examples).

According to 24 Ways’ Font Matrix, Garamond is shipped with Office Word 2007 for Windows, and Word 2004 for Mac, which means that it’s available to a huge percentage of visitors. For those who don’t have it installed, I’ve provided a backup in the form of Adobe’s Caslon, Garamond and Minion Pro typefaces which come shipped with the Creative Suite (notice, however, that all of these fonts are also available for individual download; I’m mentioning the programs they ship with because I suppose a lot of you bought them with Adobe’s software).

I’ve also decided to use Crimson text from Google’s Webfont repository to provide a decent fallback before Times. The final font stack looks like this:

font-family: Garamond, Adobe Garamond Pro, Minion Pro, Adobe Caslon Pro, Crimson Text, Times, serif;

This font stack should be used exclusively on higher font sizes, especially because Windows is notorious for poor font rendering.

Font rendering in Safari vs. Chrome

Chrome with default settings (left) and Safari with font smoothing set to Medium (right). May look subtle at first, but it makes a big impact on readability in smaller sizes.

If you were looking for extremely good on-screen readability, the high-x-height-blessed Georgia and Verdana (both fonts are from the nineties, made specifically for screen rendering) will provide more pleasing results in font-stacks.

For instance, we could take advantage of the similarity between the Lucida serifs (Fax and Bright, which also come with MS Word) and Droid serif from the Google Webfont repository to make a highly readable font-stack with a large x-height:

font-family: Lucida Bright, Lucida Fax, Droid serif, Georgia, Serif;

Once again Google’s webfonts come to action before a generic solution, mostly because Droid serif is much closer in appearance to Lucida than Georgia and Times, respectively.

A very similar Verdana-based stack would also contain the three almost equal Lucida sans-serifs (Grande – ships with Mac, Sans, Sans Unicode):

font-family: Lucida Sans, Lucida Sans Unicode, Lucida Grande, Verdana, Sans-serif;

Notice how the replacement fonts have similar characteristics, particularly how the g letter is virtually the same across typefaces, and how the o resembles a circle rather than an ellipse. As with most sans-serifs, they’re monoweight and don’t have any thick/thin transitions (Optima, for instance, isn’t monoweight —that’s what makes it more difficult to pair with other fonts).

Lucida-based Sans-serif font stack

Being Picky

While creating sensible font stacks is important, in order to provide excellent typography, you’re going to have to do the “extra ten percent” and provide typographical contrast using different font variants, weights, direction and nurturing care to all micro typographic methods.

Jon Tan, attention to micro typography

Jon Tan tackles micro typography with extra care.

Jon Tan, for instance, uses some CSS3 selectors to create great visual impact.

.entry-content p:first-line,
.entry-content img + p:first-line {
	font-variant: small-caps;
	font-weight: 900;
	text-indent: 0px;
}

He’s using centered and italicized headings within a blog post in a Times-based font stack. This, when combined with justified text and his minimalistic design, makes for a very pleasant reading experience. Remember: small things do matter.

Absolutely astonishing headings on jontangerine.com

Mixing things up with a bold typeface, uppercase titles and positive letter spacing for smaller headings will many times provide a far better experience and contrast, as well as clearer separation to the body copy, than just a different typeface. Samantha Warren has covered Typographic hierarchy very well, and I suggest you read her article for a broader understanding of the topic.

Lucida and Garamond, contrasting and conflicting
Contrast improves separation. Can you even notice the second heading?

A seventeen pixel Garamond for body copy and 15px Lucida Sans for subheading level 4 (h4) do look quite different in the upper two situations, only due to a few small changes in our CSS:

body {
	font: 17px/1.4 Garamond, Adobe Garamond Pro, /* ... (look at the Garamond-based stack above) */ serif;
	color: #333;
	text-align: justify;
} 

h4#uppercase {
	text-transform: uppercase;
	font: bold 14px/1 Lucida Grande, Lucida Sans, Verdana, sans-serif;
	margin-top: 15px; letter-spacing: 1px;
}

h4#normalcase {
	text-transform: none;
	font-weight: normal;
	letter-spacing:0;
}

The italicized ampersands are another one of those techniques that prove how “small things matter” (notice, however, that not all fonts have “special” ampersands):

.amp {
	font-family:Adobe Caslon Pro,Garamond, Palatino Linotype, Bell MT, Minion Pro, Garamond, Constantia, Goudy Old Style, High Tower text, serif;

	/* The font-stack above contains some font-families that
	have nice ampersands. You should pick a couple that suit your
	needs on a particular website, rather than use all.
	For instance, Caslon, Palatino and Baskerville do a nice job
		most of the time. */

	font-style: italic;
	line-height: 0;
}

If you would like to automate the use of fancy ampersands (enclosing them to proper classes, as well as having some advanced typographic help), I suggest looking up the WP-Typography plugin for WordPress.


Additional JavaScript Enhancement

We could further improve our user’s experience by enhancing the site with some simple JavaScript to test whether she has a particular font installed on her system. Then, it’s simply a matter of picking a suitable fallback font, if the font isn’t available (i.e., increase font size to make another font more readable, use image replacement, load additional fonts, etc.).

Note that you should still consider the fact that a small percentage of users browse the web with JavaScript turned off.

You could, perhaps, add a noscript class to the body if JavaScript is disabled and prepare some sensible typography for it, accordingly.

That said, there are a few, essentially equal, techniques for discovering if a particular font is installed on the user’s system. I’m going to use a slightly modified version of Lucas Smith’s code:

function testFont(name) {
    name = name.replace(/['"]/g,'');

    var	body  = document.body,
		test  = document.createElement('div'),
		installed = false,
		template =
			'<b style="display:inline !important; width:auto !important; font:normal 80px/1 \'X\',sans-serif !important">mmmmmwwwww</b>'+
			'<b style="display:inline !important; width:auto !important; font:normal 80px/1 \'X\',monospace !important">mmmmmwwwww</b>',
		ab;

    if (name) {
        test.innerHTML = template.replace(/X/g, name);

        test.style.cssText = 'position: absolute; visibility: hidden; display: block !important';

        body.insertBefore(test, body.firstChild);

        ab = test.getElementsByTagName('b');

        installed = ab[0].offsetWidth === ab[1].offsetWidth;

        body.removeChild(test);
    }

    return installed;
}

Upon pasting the code into your JavaScript file, you can simply test whether a particular font is installed on the users’ computer by using conditional statements:

if (testFont("FontName"))
	// Do stuff if the font is installed
else
	// Do stuff if the font isn't installed, i.e. load Cufón replacement

One of the more interesting uses of this technique would possibly be linking to a font-loading file (@font-face, Google Webfonts…), in the case our preferred fonts aren’t available on the user’s system. That way, we improve performance, and don’t force the user to download extra ~30kb for no reason:

if (!testFont("Lucida Fax") && !testFont("Lucida Bright") && !testFont("Droid serif")) {

  var head = document.getElementsByTagName("head")[0];
  var webfontLink = document.createElement('link');
  webfontLink.rel = 'stylesheet';
  webfontLink.href = 'http://fonts.googleapis.com/css?family=Droid+serif';
	// now we have <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Droid+serif">
  head.appendChild(webfontLink);

}

Further Reading and Resources

♣ ♠ ♣ ♠ ♣ ♣ ♠ ♣

I hope that you now have a better understanding of typography on the web. There’s definitely more to the matter, and I’ll enjoy hearing what you have to say about it in the comments!

Quick Tip: Getting Offline Access with HTML5 Application Cache










Just when you thought you’d seen all the cool features of HTML5, I’m here to bring you yet another one. The internet is no longer about just websites; it’s about web applications. Often, our users are on portable or mobile devices, and they won’t always have access to a network. With HTML5’s Application Cache, you can provide them with all or some of the functionality they would have online, no matter where they go.



Step 1: Make the Cache Manifest

The trick here is using a cache manifest file. In its most basic form, it’s incredibly simple:

CACHE MANIFEST

# version 0.1

index.html
style.css
script.js
preview.jpg

Step 2: Serve the Manifest Correctly

This file needs to be served with a content-type header of text/cache-manifest; it’s really simple to do this with a .htaccess file:

AddType text/cache-manifest manifest

This will serve all files with an extention of “manifest” with the appropriate content-type header.


Step 3: Hook the Manifest In

To use the cache manifest file, you simply add a property to the html element:

<!DOCTYPE html>
<html lang="en" manifest="site.manifest">
	<meta charset='utf-8'>

Now, the next time a user visits your site / app, their browser will cache the required files. It’s that easy. If they browse to your URL when they’re offline, they’ll get the cached content.


Caveat: Refreshing the Cache

It’s important to note that even when the user is online, the browser will only go to the server to get new content in three cases:

  1. The user clears their cache (obviously removing your content).
  2. The manifest file changes.
  3. The cache is updated via JavaScript

So, to force all your users to reload their cache, you can change something in the manifest file (not the files linked to, the actual content of the manifest file). Most of the time, you’ll probably just want to change a comment, and that will be enough.

If you want, build cache updating into your app via the JavaScript API; that’s beyond the scope of this quick tip, but if you want to learn more, check out this article at html5rocks.com.


Browser Support

Like a lot of other HTML5 features, the Application Cache is supported by all the modern browsers.


Chart from www.findmebyip.com

And that’s HTML5′s Application Cache; it’s pretty cool, and I’m sure it will be used by developers, of almost any site, to provide a gracefully degrading experience that keeps their users happy wherever they are. Thanks for reading!

How to Create a Web-Based Drawing Application Using Canvas: New Premium Tutorial










Combining HTML with the all new <canvas> feature, you can make some pretty awesome web apps! In this Premium exclusive tutorial, we will create a neat interactive drawing application using HTML and JavaScript. Along the way, we’ll also learn the basic concepts of the all new <canvas> feature. Become a Premium member to access this, as well as many other amazing tutorials and screencasts.

Preview
Preview
Preview
Preview

Creating a Web Poll with PHP










Polls are nearly ubiquitous on the web today, and there are plenty of services that will provide a drop-in poll for you. But what if you want to write one yourself? This tutorial will take you through the steps to create a simple PHP-based poll, including database setup, vote processing, and displaying the poll.


Step 1: Plan & Create the Database

In order to store poll results, we’re going to store three pieces of information:

  • A question identifier
  • An answer identifier
  • The number of votes a question/answer pair has gotten

For this tutorial, we’ll be using PDO and SQLite. If you’re working with SQLite3, you can create a new database via the command line tool; if you’re using an older version, a quick PHP script will do the trick. Here’s the one used for this tutorial:

<?php
echo "creating database\n";
try {
    $dbh = new PDO('sqlite:voting.db');
    $dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
    $dbh->exec('
        CREATE TABLE tally (
        QID varchar(32) NOT NULL,
        AID integer NOT NULL,
        votes integer NOT NULL,
        PRIMARY KEY (QID,AID))
    ');
}
catch(PDOException $e) {
    echo "ERROR!!: $e";
    exit;
}
echo "db created successfully.";
?>
Voting Database Structure

This simple script will create a SQLite database in the directory you run it. Unlike mySQL, the database here is a flat file. If you’re familiar with SQL, the create should make sense to you, although the last line may be new to some people:

PRIMARY KEY (QID,AID)

This creates a composite key for the database. Entries in either column do not have to be unique to that column, but the combination of the two must be unique.


Step 2: Design Your Poll’s HTML

Before you start writing any PHP, you need to decide how to create your poll in terms of markup. We’re going to try to keep the markup as semantic and simple as possible. Your poll will have two looks:

  • Question waiting to be answered
  • Current Results of the poll

In writing this HTML, some classes will be included to help with the CSS later.

Poll View

Because a poll is primarily a list of answers, we’re going to incorporate an unordered list to contain those answers. For the question itself, we’re going to use a heading tag.

<form class="webPoll" method="post" action="test.php">
    <h4>What question would you like to ask?</h4>
    <ul>
        <li>Answer Here</li>
        <li>Another Answer Here</li>
    </ul>
</form>

That’s pretty basic, but doesn’t include any form elements. Radio buttons are the most appropriate since we’re only allowing one answer per poll. Also, we’re going to use the label tag to associate answers with the proper radio button. Now our form HTML looks more like this:

<form class="webPoll" method="post" action="test.php">
    <h4>What question would you like to ask?</h4>
    <ul>
        <li>
            <label class='poll_active'>
            <input type='radio' name='AID' value='0'>
            First Answer Here
            </label>
        </li>
    </ul>
</form>

That’s a little more complex, but not too bad. Still a bit more to add. We’re going to include a fieldset tag to open up some styling options, and of course we need a submit button!

<form class="webPoll" method="post" action="/poll/test.php">
    <h4>What question would you like to ask?</h4>
    <fieldset>
    <ul>
        <li>
            <label class='poll_active'>
            <input type='radio' name='AID' value='0'>
            First Answer Here
            </label>
        </li>
    </ul>
    </fieldset>
    <p class="buttons">
        <button type="submit" class="vote">Vote!</button>
    </p>
</form>

For each answer, a new LI tag is added and the value of the radio button incremented. That will eventually be done by our PHP. The extra HTML is the fieldset tag, and the paragraph wrapped around the button – both of which will be used by our CSS.

Answer View

The HTML is going to be nearly identical for the answer view. The line-item tags won’t contain a form element and we’ll be adding a div which can be used to show the percentage of votes that answer received. Here’s how that will look:

<li>
    <div class='result' style='width:20px;'>&nbsp;</div>
    <label class='poll_results'>
        10%: First Answer Here
    </label>
</li>

Yes, that’s an inline style you see there. That style will be generated by our PHP based on the current percentage of each individual answer. Here’s what we have so far:

Unstyled Poll

Step 3: Style the Form

The HTML we created in the last step was not very attractive. Let’s see if we can fix that up a bit. We’re going to use the wonderful CSS3 PIE (progressive Internet Explorer) library so we can obtain a similar look across all browsers. To make this library work properly, there are numerous cases where you must apply a relative position to elements. You can read all the details on the library website.

Style the Form Tag

We’re going to use the form tag as our container. It’s going to have nice, rounded corners, and a bit of a drop shadow. The styles below also specify a width, and padding.

form.webPoll {
    background:#ededed;
    behavior:url(PIE.php);
    border:1px solid #bebebe;
    -moz-border-radius:8px;
    -webkit-border-radius:8px;
    border-radius:8px;
    -moz-box-shadow:#666 0 2px 3px;
    -webkit-box-shadow:#666 0 2px 3px;
    box-shadow:#666 0 2px 3px;
    margin:10px 0 10px 8px;
    padding:6px;
    position:relative;
    width:246px;
}

The key line here is the behavior attribute. This will be ignored by non-IE browsers and will add the CSS3 functionality to IE6-8.

Basic styling

Still ugly, but a noticeable improvement.

Box the Answers

Next, we’re going to create a nice box around the answers and use a bit of illusion to make the border look inset by a pixel. This is done by coloring the outer-most border (the fieldset) the same color as the interior, and then using the unordered-list tag as our real border. Here’s the CSS:

form.webPoll fieldset {
    background:#FCFAFC;
    behavior:url(PIE.php);
    border:1px solid #FCFAFC;
    -moz-border-radius:10px;
    -webkit-border-radius:10px;
    border-radius:10px;
    margin:0;
    padding:0;
    position:relative;
}
form.webPoll ul {
    behavior:url(PIE.php);
    border:2px #bebebe solid;
    -moz-border-radius:10px;
    -webkit-border-radius:10px;
    border-radius:10px;
    font-family:verdana;
    font-size:10px;
    list-style-type:none;
    margin:0;
    padding:10px 0;
    position:relative;
}
Basic styling

Style the Answers

Next we need to add a little CSS to make our options look better.

form.webPoll li {
    margin:0 16px;
    overflow:auto;
    padding:4px 0 6px;
    position: relative;
}
form.webPoll input {
    position: absolute;
    top: 4px;
    *top: 0;
    left: 0;
    margin: 0;
    padding:0;
}
label.poll_active {
    float:right;
    width:90%;
}

You might ask why we’re using absolute positioning on the inputs and floating the label. The reason is simple: multi-line answers. If an answer to your poll question is long, you want the radio button to look like a bullet on an unordered list – hanging. This will keep the text from wrapping around it if it’s multiple lines.

There’s also a style targeting IE specifically with the * hack to cause the buttons to line up properly in IE6-8.

We also need to style the bar used to show results. We’ll add that now:

form.webPoll .result {
    background: #d81b21;
    background: -webkit-gradient(linear, left top, left bottom, from(#ff8080), to(#aa1317));
    background: -moz-linear-gradient(top,  #ff8080,  #aa1317);
    -pie-background: linear-gradient(#ff8080, #aa1317);
    border:1px red solid;
    -moz-border-radius:3px;
    -webkit-border-radius:3px;
    border-radius:3px;
    clear:both;
    color:#EFEFEF;
    padding-left:2px;
    behavior: url('PIE.php');
}

There’s another new attribute here: -pie-background, which allows us to, in conjunction with the PIE library, use gradient backgrounds in IE. There’s still a few touches to add.

Question and Button

A default H4 may not be what you’re looking for, so let’s add some styling to that.

form.webPoll h4 {
    color:#444;
    font-family:Georgia, serif;
    font-size:19px;
    font-weight:400;
    line-height:1.4em;
    margin:6px 4px 12px;
    padding:0;
}

And I’m not a big fan of default buttons, so we’re going to use a CSS sprite to liven it up a bit.

.buttons {
    margin:8px 0 1px;
    padding:0;
    text-align:right;
    width:122px;
}
.vote {
    background:url(res/vote.png) repeat scroll 0 0 transparent;
    border:medium none;
    height:40px;
    text-indent:-9999em;
    width:122px;
}
.vote:hover {
    background-position:0 -41px;
    cursor:pointer;
}

What about IE6? It doesn’t support the hover psudo-class! We can either leave those users out in the cold (they’ll still see the button default state) or we can use another lovely little GPL licensed library, Whatever:hover.

Final Poll CSS

Last Bits

In order to accommodate some IE6 quirks, certain elements need to have something called “HasLayout” triggered. The easiest way to do this is to set a property of zoom for these elements. The property is ignored by non-IE browsers.

form.webPoll ul,li { /*// Make IE6 happy //*/
    zoom:1;
}

You’ll also notice there are borders between each question. This was done with an additional class on the LI tags specifying a border. The class will be assigned to all but the last item by the PHP script.

The completed CSS file is contained in the download.


Step 4: Create a PHP Class — Decide on the Interface

Now it’s time to create the PHP to generate polls, show results, and handle votes. I’d like to keep using the script as simple as possible, so I’m planning the usage ahead of time. To create a poll in a particular place in a page, you’ll just use the following PHP:

$a = new webPoll(array(
        'What subjects would you like to learn more about?',
        'HTML & CSS',
        'JavaScript',
        'JS Frameworks (jQuery, etc)',
        'Ruby/Ruby on Rails',
        'PHP',
        'mySQL'));

That’s it. You’ll pass an array to the constructor which contains the question followed by the answers. In order to track the questions in the database, we’ll create an MD5 hash of the question to use as an identifier.


Step 5: Decide on the Class Properties

There’s certain data that’s going to be needed by each poll; we’re going to store some of this in class properties. We’ll need to store the question and the answers, the basic HTML, the question identifier, and some information on how to draw the results bars. Here’s the start:

class webPoll {

    # makes some things more readable later
    const POLL = true;
    const VOTES = false;

    # number of pixels for 1% on display bars
    public $scale = 2;

    # the poll itself
    public $question = '';
    public $answers = array();

    # the HTML
    private $header = '<form class="webPoll" method="post" action="%src%">
                       <input type="hidden" name="QID" value="%qid%" />
                       <h4>%question%</h4>
                       <fieldset><ul>';
    private $center = '';
    private $footer = "\n</ul></fieldset>%button%\n</form>\n";
    private $button = '<p class="buttons"><button type="submit" class="vote">Vote!</button></p>';

    # question identifier
    private $md5 = '';

The initial constants will be used in one of the methods to make it more readable so it’s easier to know whats going on.

Take note of the hidden input that’s been added here. This is the question identifier used to store information in the database. All the values in the HTML surrounded by percent signs will be replaced.


Step 6: Create the HTML Poll or Answers

Since it’s already been decided the poll will be made by creating an object, let’s examine the __construct method.

public function __construct($params) {
    $this->question = array_shift($params);
    $this->answers = $params;
    $this->md5 = md5($this->question);  

    $this->header = str_replace('%src%', $_SERVER['SCRIPT_NAME'], $this->header);
    $this->header = str_replace('%qid%', $this->md5, $this->header);
    $this->header = str_replace('%question%', $this->question, $this->header);

    # has the user voted yet?
    isset($_COOKIE[$this->md5]) ? $this->poll(self::VOTES) : $this->poll(self::POLL);
}

In the first line, we peel the question off the array stack with array_shift, and store it in a property. We also store the questions, leaving them as an array. We also create the question identifier here, by making an md5 hash of the question itself.

The next three lines perform some replacements on the HTML. The first sets our form action to point at the page the poll is one. The second puts our question identifier in a hidden form field. The third puts our question into the HTML.

In the final line of the constructor we check if the user has voted on this particular poll, and if he has, we show the votes. If he hasn’t, we show the poll.


Step 7: Generate the Poll

Both generating the poll and generating the results are very similar operations. In order to keep our code DRY we break the creation into three methods. The main one is “poll”.

DRY: Don't Repeat Yourself
private function poll($show_poll) {
    $replace = $show_poll ? $this->button : '';
    $this->footer = str_replace('%button%', $replace, $this->footer);

    # static function doesn't have access to instance variable
    if(!$show_poll) {
        $results = webPoll::getData($this->md5);
        $votes = array_sum($results);
    }

    for( $x=0; $x<count($this->answers); $x++ ) {
        $this->center .= $show_poll ? $this->pollLine($x) : $this->voteLine($this->answers[$x],$results[$x],$votes);
    }

    echo $this->header, $this->center, $this->footer;
}

Here’s the breakdown of what’s going on in this function:

lines 2 & 3: We only need a vote button if the user hasn’t voted. Here we determine if we’re going to use the button HTML or not, and then either insert the HTML, or replace the %button% placeholder with an empty string.

lines 6 – 8: If we’re not showing the poll, we obviously need the results, so here we go fetch them. We also calculate the total votes cast for use later in determining percentages.

lines 11 – 12: This generates the LI tags in our HTML. Depending on if we’re showing the poll or the results, we generate different HTML. This HTML generation is handed off to two functions:

  • pollLine
  • voteLine

line 15: Simply dumps out the data to the page.


Step 8: The pollLine() Method

This is a very simple method, which takes the current index of the answer as an argument.

private function pollLine($x) {
    isset($this->answers[$x+1]) ? $class = 'bordered' : $class = '';
    return "
    <li class='$class'>
            <label class='poll_active'>
            <input type='radio' name='AID' value='$x' />
                {$this->answers[$x]}
            </label>
    </li>
";
}

It checks if there’s an answer after the current one on its first line, and if there is, applies a class of bordered to that LI tag. The very last answer won’t get this class, allowing us to achieve the visual effect intended.


Step 9: The voteLine() Method

This method is getting 3 parameters passed into it:

  • $answer : The question answer for this line
  • $result : The number of votes this option has gotten
  • $votes : The total number of votes cast in this poll

With that information, the LI tags for the voting results can be produced.

private function voteLine($answer,$result,$votes) {
    $result = isset($result) ? $result : 0;
    $percent = round(($result/$votes)*100);
    $width = $percent * $this->scale;
    return "
    <li>
            <div class='result' style='width:{$width}px;'>&nbsp;</div>{$percent}%
            <label class='poll_results'>
                $answer
            </label>
    </li>
";
}

Since it’s possible for there to be no votes for an option, it will effectively leave $result unset. If we detect this we’ll give it a default value of 0 votes.

Next, we determine what percent of the votes the option got and finally use the scale property to determine the width, in pixels, that the results bar should be. Then we finally return the HTML containing all that information.


Step 10: Write the getData() Method

If you look back up a bit, you’ll see we call the getData() method which is defined as a static method in the class. Why static? Because if we decide to enhance this poll later by making it AJAX based, we’ll want access to that method without object creation. Here’s the method:

static function getData($question_id) {
    try {
        $dbh = new PDO('sqlite:voting.db');
        $dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

        $STH = $dbh->prepare('SELECT AID, votes FROM tally WHERE QID = ?');
        $STH->execute(array($question_id));
    }
    catch(PDOException $e) {
        # Error getting data, just send empty data set
        return array(0);
    }

    while($row = $STH->fetch()) {
        $results[$row['AID']] = $row['votes'];
    }

    return $results;
}

The question ID is passed into the method and it will return an array containing the answer ID’s and the number of votes that answer has. If an answer has no votes, it won’t have an entry in the array, which we’ve already dealt with in the voteLine() method.

Since database errors in web polls are particularly tragic, we’re simply going to return an empty array if one occurs. The user will get 0 votes for each result. In a production environment you might want to log this error to a file, or send the admin an email.


Step 11: Handling a Vote

We’re going to add a second static method to the class, and this one will handle incoming votes. Votes will only be counted if the user hasn’t voted before (as determined by a cookie) and once the user has voted we’ll set a cookie indicating this.

In this type of web application, it’s nearly impossible to stop multiple votes without excluding some legitimate users. Setting a cookie is just a basic precaution.

This is one of the more complex methods in our webPoll class, and we’re going to look at it in three parts.

static function vote() {
    if(!isset($_POST['QID']) ||
       !isset($_POST['AID']) ||
       isset($_COOKIE[$_POST['QID']])) {
        return;
    }

A call to the vote() method will be at the top of our PHP page, so the first thing we want to do is decide if there’s a vote to process or not. The above statement is how we determine this. Here’s what it says:

  • If there’s no Question Identifier in our POST data (OR!!)
  • If there’s no Answer Identifier in our POST data (OR!!)
  • If a cookie has been set already matching the Question Identifier

If any of those are true, we don’t have to process a vote, and we leave the method.

$dbh = new PDO('sqlite:voting.db');
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

try {
    $sth = $dbh->prepare( "INSERT INTO tally (QID,AID,votes) values (:QID, :AID, 1)" );
    $sth->execute(array($_POST['QID'],$_POST['AID']));
}
catch(PDOException $e) {
    # 23000 error code means the key already exists, so UPDATE!
    if($e->getCode() == 23000) {
        try {
            $sth = $dbh->prepare( "UPDATE tally SET votes = votes+1 WHERE QID=:QID AND AID=:AID");
            $sth->execute(array($_POST['QID'],$_POST['AID']));
        }
        catch(PDOException $e) {
            $this->db_error($e->getMessage());
        }
    }
    else {
        $this->db_error($e->getMessage());
    }
}

This looks a lot more complicated then it really is. What happens here is we check if a particular answer has gotten a vote before. If it hasn’t we create a new record for that answer, and give it one vote. If it has, we update the existing record. So how’s it decide which to do?

PDO exception magic.

Remember at the very beginning we created our multi-column primary key? When we try to insert a record into the table which matches an existing QID/AID pair, an exception is thrown, and in particular the exception code is 23000 (duplicate key).

If the insert throws an exception, we’re going to check the exception code, and if it matches 23000, we’ll try to update the record instead. Of course if the insert fails for a different reason, or the update fails as well, we’re going to just issue a call to a method called db_error() which just echos a generic error message. Like before, a production environment would log this error and/or notify the admin.

Using PDO Exceptions

Finally, the end of the method:

    # entry in $_COOKIE to signify the user has voted, if he has
    if($sth->rowCount() == 1) {
        setcookie($_POST['QID'], 1, time()+60*60*24*365);
        $_COOKIE[$_POST['QID']] = 1;
    }
}

By using rowCount() we can verify that we’ve either updated or inserted a vote. If a vote has been successfully registered we set a cookie indicating as much, using the question identifier as the cookie name.

In addition to setting the cookie, we populate the super-global $_COOKIE, so when the poll displays, it shows answers rather then presenting the poll again.


Step 12: Put It All Into Action

We’ve written the PHP, set up the CSS and HTML, now it’s time to put it all into use. In this example, we’re just going to drop everything into a page that’s otherwise blank. At the very top of the page, insert the following:

<?php
    include('webPoll.class.php');
    webPoll::vote();
?>

It’s important that this be the very top of the page, before any HTML. Why? Because if there’s a vote to process, a cookie may be written, and you can’t write cookies after anything else has been sent. The call to the static method vote() returns if there’s not the proper POST data to process.

Next, we’ll include all the styles we wrote as a seperate stylesheet. Also, we’re going to include a particular style just for IE that was mentioned earlier to enable the :hover psudo-class.

<link rel="stylesheet" href="poll.css" type="text/css" />
<!--[if IE]>
<style> body { behavior: url("res/hover.htc"); } </style>
<![endif]-->

In the BODY of your HTML page, you’ll drop in the following PHP to insert the polls:

$a = new webPoll(array(
        'What subjects would you like to learn more about?',
        'HTML & CSS',
        'JavaScript',
        'JS Frameworks (jQuery, etc)',
        'Ruby/Ruby on Rails',
        'PHP',
        'mySQL'));

$b = new webPoll(array(
        'What is your question?',
        'Don\'t have one',
        'Why?',
        'When?',
        'Where?'));

That’s it! Thanks for reading. Any thoughts, questions, or suggestions?

Quick Tip: What you May Not Know About JavaScript’s Logical AND Operator










In today’s video quick tip, we’ll be reviewing JavaScript’ logical AND operator. Those of you who are just beginning to get into JavaScript, or even a library like jQuery, might not realize that they can even be used as micro if statements!


Example 1: General Usage

// EXAMPLE 1
var a = 5,
	b = 10;

if ( (a === 5) && (b === 10) ) {
	alert('yay');
}

The AND operator’s use in the code above is what the huge majority of us are most familiar with. If a equals 5, and b equals 10, then do something awesome, like display an alert box that says, “Yay!”

The right side of the && operator will only run if the left side is equal to true. With that in mind, we can use this to our advantage!


Example 2: Checking if an Element Exists

In most of my AJAX-based applications, there will be a point where I must first determine whether an element with a particular id exists within the DOM. If it does not, I’ll create it. Otherwise, I’ll work with the element that already exists. Generally, we can use an if statement for this sort of task.

if ( !document.getElementById('contents') ) {
  // then call a function that inserts the element into the DOM.
}

Alternatively, we can use the && operator to accomplish this task.

!document.getElementById('contents') && createElem('div', 'contents', 'hello world');

Remember, that fake createElem function will, again, only run if the left side is equal to true. Think of it this way: is it true that we could not find an element with an id of contents on the page? If so, then move on to the right side. Now if it’s equal to false, the right side will never run.


Example 3: Loading jQuery Locally

When reviewing the HTML5 Boilerplate, I noticed that Paul uses a clever one-liner that potentially loads a local version of jQuery, if, for some reason, there was an error downloading the file from your CDN of choice.

!window.jQuery && document.write('<script src="localjQuery.js"><\/script>');

Is it true that jQuery does not exist? If so, move on to the right side, and insert a script element, which references jQuery locally. Nifty, eh?


Conclusion

Before you go crazy with this technique, be careful. It certainly makes for slightly less readable code, and that should be an important factor in your decision — especially when return to six month old projects!

Apple loosens reigns, allows 3rd party iOS dev tools with caveat

Here’s a surprise we didn’t expect this morning — or ever, for that matter — Apple has changed its stance on iOS app development, now allowing all tools “…as long as the resulting apps do not download any code.” Theoretically, this would include Adobe Flash CS5 but certainly includes tools like Unity. [Note that while the Flash CS5 authoring environment may be kosher, this rule still excludes the Flash browser plugin due to the no-downloaded-code clause. -Ed.]

In addition, Apple has published the App Store Review Guidelines for the very first time. We’ll be anxious to hear what developers have to say after giving those guidelines a good read.

You’ll remember a recent change in Apple’s SDK language that prohibited iOS apps to be written with anything other than Apple-approved tools, including Flash. This led to a viciously bitter spat between Adobe and Apple (though it really seemed to be between Jobs and Adobe CEO Shantanu Narayen) with both sides setting up their tents and firing barbs. To say that this morning’s change is dramatic is an understatement.

Great, now I have to be on the lookout for 3 other horsemen for the rest of the day.

[Via Engadget]

TUAWApple loosens reigns, allows 3rd party iOS dev tools with caveat originally appeared on The Unofficial Apple Weblog (TUAW) on Thu, 09 Sep 2010 09:49:00 EST. Please see our terms for use of feeds.

Read | Permalink | Email this | Comments

VLC coming to the iPad

VLC, the play-anything video player for the Mac, may soon be available as an iPad app. App maker Applidium has spent months porting the open source player into an iPad app and has submitted it to the App Store. Now they’re just waiting for Apple to approve it; if approved, the app will be available next week, and like its big brother on the Mac, the app will be free.

Having VLC available on the iPad would be hugely beneficial. VLC plays far more video formats than QuickTime or the iPad’s built-in video support; on the Mac, I’ve often said that if VLC can’t play it, it can’t be played. We don’t know yet if VLC on the iPad will allow you to move (for instance) AVI files straight into the VLC program via iTunes or if you’ll be required to stream files from a Mac to view them on the iPad. In either case, VLC’s ability to play almost any video codec out there would vastly expand the iPad’s capabilities.

That said, there are multiple reasons why Apple might reject this app. “Duplicating functionality” is one possible reason; the iPad already has a built-in video player, though one that’s far more restrictive in the formats that it supports. There may be severe battery life issues to contend with as well. The iPad has the ability to decode H.264 video via its built-in hardware, but most other formats would have to be decoded via software, and depending on the format, it could tax the iPad’s A4 processor pretty heavily. Finally, it’s possible that media providers might squawk in protest at the iPad being able to easily and freely play video from any source — let’s just say that a lot of the AVI files and almost all of the VIDEO_TS folders out there aren’t exactly condoned by the media conglomerates and leave it at that.

I hope this app does get approved. I don’t own an iPad, but being able to play back virtually any type of video file on the device via VLC would be a huge selling point for me, and probably for many others, too.

TUAWVLC coming to the iPad originally appeared on The Unofficial Apple Weblog (TUAW) on Thu, 09 Sep 2010 09:30:00 EST. Please see our terms for use of feeds.

Read | Permalink | Email this | Comments

Work on iOS 4.1 jailbreak continues

With iOS 4.1 still warm from its journey through the tubes, the jailbreaking community is already working its way inside. Chronic Dev Team member pod2g has discovered yet another bootrom-based exploit that would supposedly work across all iOS devices running the latest firmware. That means that the iPhone 4 and the shiny, new iPod touch are on the list.

The jailbreak isn’t yet widely available, but with confirmations of initial success in less that 24 hours, it shouldn’t be long before this jailbreak is available to the masses. Redmond Pie notes that patching this exploit will require a revised hardware version with updated bootroms for iPhone 4, iPhone 3GS, iPad and the iPod touches from Apple. In other words, a firmware update won’t be adequate.

We’ll let you know when the jail has actually been broken.

[Via Engadget]

TUAWWork on iOS 4.1 jailbreak continues originally appeared on The Unofficial Apple Weblog (TUAW) on Thu, 09 Sep 2010 09:00:00 EST. Please see our terms for use of feeds.

Read | Permalink | Email this | Comments

The extra safe, extra cautious iOS 4.1 upgrade guide

In case you missed it, the highly anticipated iOS 4.1 software update was released yesterday. If you’ve already upgraded, or after reading that sentence you’re not already downloading it now, then you obviously like to play it cool and safe. Hey, there’s nothing wrong with that. Good for you! Either that, or you got seriously burnt last time.

Well, when you’re good and ready, Mac Observer has just the guide for you. It’s so extensive, it practically holds your hand when taking your first steps to the land of iOS 4.1. From considering whether you should upgrade or not, to making sure your ‘must have‘ apps are compatible and backed up for the new update, the walk through will guide you every step of the way, without making you run before you can walk!

Seriously though, if you can’t afford any mishaps, it’s well worth the read. The walk through will even guide you on resetting your iTunes warnings so that the ones you nonchalantly clicked through last time will trigger again. Just make sure you read them this time, OK?

Have you upgraded your iOS device to software version 4.1? Have you hit any snags along the way? Let us know how you’re doing in the comments.

TUAWThe extra safe, extra cautious iOS 4.1 upgrade guide originally appeared on The Unofficial Apple Weblog (TUAW) on Thu, 09 Sep 2010 08:30:00 EST. Please see our terms for use of feeds.

Read | Permalink | Email this | Comments

TUAW’s Daily App: Auditorium

Auditorium is that rare kind of game that’s a must-play no matter what kind of gamer you are. It’s a puzzle game, a music game, and a piece of art at various times. It’s out now on the iPhone courtesy of EA (and the main download is absolutely free), but even if you don’t want to take up space on your mobile device, just head over to the website and play the Flash demo for a little bit. My guess is that you’ll be taken by the beauty and originality, at least enough to pop over to the App Store and download the main game.

The idea is that there is a stream of music flowing through each level, and it’s your job to use the various widgets you’ve been given to shape and paint the music into certain spots on the board. As you move through the levels, you’ll get more and more adept at sending the flow where you need it to go. Fortunately, the puzzles get harder and harder as you play, creating a great curve of both learning and adjusting your mind enough to find the right solution.

The main game is free, and then you can purchase all of the levels in three different packs, at 99 cents each. But even for the whole three bucks, this is quite an experience; it’s more than worth the price. Again, if you’re doubtful, give the demo a try, and see if you’re not convinced to try the whole thing in order to see where it goes.

TUAWTUAW’s Daily App: Auditorium originally appeared on The Unofficial Apple Weblog (TUAW) on Thu, 09 Sep 2010 08:00:00 EST. Please see our terms for use of feeds.

Read | Permalink | Email this | Comments

HDR photo hands-on with iPhone 4 and iOS 4.1

I’ve never used one of the HDR apps, so I was eager to try out this new feature using iOS 4.1 on my iPhone 4.

Launching the camera now gives you an HDR option at the top of your screen. It’s automatically set to off. When you toggle the option on, it will automatically switch the camera flash to off.

Using HDR will provide you with two shots — one normal shot and one with HDR utilized. For my test subjects I used:

  • A shot of a window from a few feet away.
  • A shot of a window standing at the window.
  • A dark shot using the cat lounging next to the iMac as a model
  • A well-lit shot using one of the other cats, who happened to claim a kitchen cabinet as his own, as a model.

The most noticeable difference came from the window shot taken a few feet away. As seen above, the normal shot has the outside areas overexposed while you can clearly see the apartment building across from mine — including some detailed areas — in the HDR shot. This shot was taken about eight feet from the window.

TUAWHDR photo hands-on with iPhone 4 and iOS 4.1 originally appeared on The Unofficial Apple Weblog (TUAW) on Wed, 08 Sep 2010 19:30:00 EST. Please see our terms for use of feeds.

Permalink | Email this | Comments

Found Footage: Last week’s SteveFest in three minutes

We’re all busy people, and I’m sure that many of us missed the iPod/Apple TV SteveFest on the first. Once again, Neil Curtis, master of cutting to the chase, has created a three-minute version of the 75-minute presentation. Previously, Neil did a very short version of the adjective enhanced iPad rollout; he’s very good at this sort of thing.

This little video (making wonderful use of music) only mentions stores “with people” in them, the new iPods, the Game Center, Ping, and the underwhelming new Apple TV. I’ve been through the full video a number of times, and nowhere does Steve mention just what resolution he’s talking about when he says HD. In my opinion, this is a bag of hurt…but maybe that’s just me. There’s also some Lady Gaga in the video.

So, don’t expect anything about iOS 4.2 or anything iOS related. It’s worth a look and will probably give you a chuckle or two.

Keep up the good work, Neil.

TUAWFound Footage: Last week’s SteveFest in three minutes originally appeared on The Unofficial Apple Weblog (TUAW) on Wed, 08 Sep 2010 18:00:00 EST. Please see our terms for use of feeds.

Read | Permalink | Email this | Comments

TUAW TV Live: An Apple TV in pieces and a machine that goes Ping

The time has come, the walrus said, to talk of many things. Of Apple TVs and iOS 4.1, of new iPods and Pings. On today’s TUAW TV Live the discussion is sure to wander all over the metaphorical map. As promised earlier, I will have my old Apple TV torn apart and will point out some interesting design flaws that demonstrate why the darned things ran so hot.

We have lots of other cool stuff to talk about, and I’m seriously hoping that iOS 4.1 drops before the show so I can give you a hands-on demo of some of the new features. To join in from your Mac or PC, just go to the next page by clicking the link at the bottom of this post, and you’ll find a livestream viewer and a chat tool. The chat tool allows you to join in on the fun by asking questions or making comments.

If you’re driving somewhere and would like to watch TUAW TV Live while you’re stuck in traffic, please don’t — keep your eyes on the road! However, if someone else is doing the driving, you can watch the show on your iPhone by downloading the free Ustream Viewing Application.

iPad users haven’t been forgotten, either, as you can tune in to TUAW TV Live on your iPad! That link will send you to a non-Flash page, although you won’t have access to our chat tool. And one final note — if the show has started and you’re seeing a previously recorded show instead of the livestream, you can always pop on over to ustream.tv/tuaw to join the show in progress.

TUAWTUAW TV Live: An Apple TV in pieces and a machine that goes Ping originally appeared on The Unofficial Apple Weblog (TUAW) on Wed, 08 Sep 2010 16:55:00 EST. Please see our terms for use of feeds.

Read | Permalink | Email this | Comments

VersionTracker.com officially ‘absorbed’ by CNET

Have you been to VersionTracker.com lately? If you try today, you’ll be redirected to the CNET site, where you’ll get a brief explanation that the venerable VersionTracker site is now a branded part of the CNET empire.

VersionTracker Pro, a paid feature, will be discontinued after the current subscriptions run out. The VersionTracker newsletters will continue, but they will be rebranded as CNET products. CNET has put up a page explaining the changes.

This process actually began in 2007, when CNET acquired VersionTracker, MacFixIt, and iPhone Atlas. VersionTracker goes back to 1995, when it was a Mac only site. Over time, the content expanded to include Windows software. The familiar layout of VersionTracker has been changed, and it may startle a few users. I don’t think MacFixIt was improved any by the CNET takeover, and I don’t have high hopes for VersionTracker, either, but I’m going to keep an open mind.

CNET was acquired by CBS two years ago. Other than the irritating and frequent plugs for CBS TV, the site is still useful and continues to aggressively cover all things related to tech.

If you need an alternative to VersionTracker, MacUpdate is still around, and AppFresh (based on i use this) and Logiciel are worth a look. There is also a Dashboard Widget called App Update that will check for software updates.

[via Daring Fireball]

TUAWVersionTracker.com officially ‘absorbed’ by CNET originally appeared on The Unofficial Apple Weblog (TUAW) on Wed, 08 Sep 2010 16:00:00 EST. Please see our terms for use of feeds.

Permalink | Email this | Comments

iMovie updated to 1.1, requires iOS 4.1

Apple’s official iMovie app for iPhone has been updated to version 1.1. The new update requires iOS 4.1 and is compatible with the new iPod touch. It also adds the ability to split up video clips, automatically loop music for a longer videos and updated Photos browser. There are a few other upgrades to help performance and reliability, and a new tips and indicators to help you use the app. High Dynamic Range photography is new in iOS 4.1, but since HDR requires multiple exposures of a still picture, there’s nothing in the new iMovie app to similarly improve your videos.

Current users can upgrade right now via the App Store. iMovie for iOS can be purchased for US$4.99. Enjoy the update!

TUAWiMovie updated to 1.1, requires iOS 4.1 originally appeared on The Unofficial Apple Weblog (TUAW) on Wed, 08 Sep 2010 15:47:00 EST. Please see our terms for use of feeds.

Read | Permalink | Email this | Comments