Archive for the ‘mobile’ Category

Dealing with device orientation (Mobile web part 6)

Tuesday, August 24th, 2010

Introduction

If you read part 4 of this series, you’ll know that because of the variety of screen sizes, the best way to develop for mobile is to develop fluid layouts that take 100% of the available space on the screen.

What you probably didn’t think of is that there’s different screen widths even on the same device! This is due to screen orientation. And when the user changes the screen orientation, stuff may break (hey, it’s not a perfect world). In my experience this has meant needing to tweak percentage widths on elements, but I imagine there’s even more needs. Imagine an image carousel that can only fit three images across in portrait mode but can possibly fit four images in landscape mode. It might be nice to re-initialize the carousel to accommodate a forth image when the phone is in landscape mode (then again, that might create a lot of unnecessary overhead…).

In any case, I hope you can agree that it would sometimes be useful to know the screen orientation.

window.orientation and the orientationchange event

Luckily on the latest smartphones you have some goodies available to you that you don’t have on the desktop (since desktop users aren’t in the habit of constantly turning their screens sideways!).

window.orientation: this property gives the current screen orientation: 0 in portrait mode, 90 when rotated left, -90 when rotated right (no special value when the screen is upside-down)

orientationchange event: this window event fires after every 90 degrees of rotation and, like other events, can be applied in various ways:

// DOM Level 0 (avoid)
window.onorientationchange = function(){};

// DOM Level 2
window.addEventListener('orientationchange', function(){}, false);

Some websites recommend using orientationchange to dynamically add an orient attribute on the body element and target the orientation with CSS selectors (body[orient=landscape]), but this is in error. As it turns out, orientationchange is only fired AFTER the screen has been rotated (which also triggers a CSS reflow), which means this attribute is updated later (after the reflow). And unfortunately editing this orient attribute doesn’t trigger another CSS reflow. The result? When you rotate the device, these new CSS styles don’t get applied!

The fix is to add the orientation as a CSS class, which does trigger a CSS reflow. So our code at this point will look something like this:

(function(){
var init = function() {
  var updateOrientation = function() {
    var orientation = window.orientation;

    switch(orientation) {
      case 90: case -90:
        orientation = 'landscape';
      break;
      default:
        orientation = 'portrait';
    }

    // set the class on the HTML element (i.e. )
    document.body.parentNode.setAttribute('class', orientation);
  };

  // event triggered every 90 degrees of rotation
  window.addEventListener('orientationchange', updateOrientation, false);

  // initialize the orientation
  updateOrientation();
}

window.addEventListener('DOMContentLoaded', init, false);

})();

Now we can target elements like this in CSS:

.portrait body div { width: 10%; }
.landscape body div { width: 15%; }

With a little help from media queries

You may have heard of media queries being used to target mobile devices (based on screen pixel width) or to target the iPhone 4′s Retina display, but you may not have known that you can also target screen orientation!

@media all and (orientation: portrait) {
  body div { width: 10%; }
}

@media all and (orientation: landscape) {
  body div { width: 15%; }
}

The orientation media query is available on iOS 3.2+, Android 2.0+, and some other browsers.

This is a lot cleaner than the above JavaScript example in the sense that it’s pure CSS, and it’s part of the CSS that gets reflowed when the screen is rotated.

(Minor note: iOS 4 on the iPhone Simulator running 4.0.0 looks like it’s stuck in landscape orientation, but the media queries work correctly on my 3GS with 4.0.1)

Fallback: when window.orientation and media queries aren’t available…

If window.orientation isn’t available on a device, chances are the orientationchange event and media queries (for orientation) will also not be available. Oh no, what do we do now?

Even though this isn’t an entirely foolproof method, we can dynamically measure the window width and height and guess orientation based on that:

(function(){
var HTMLNode = document.body.parentNode;
var updateOrientation = function() {
  // landscape when width is biggest, otherwise portrait
  var orientation = (window.innerWidth > window.innerHeight) ? 'landscape': 'portrait';

  // set the class on the HTML element (i.e. )
  HTMLNode.setAttribute('class', orientation);
}
var init = function() {
  // initialize the orientation
  updateOrientation();

  // update every 5 seconds
  setInterval(updateOrientation, 5000);
}
window.addEventListener('DOMContentLoaded', init, false);
})();

Ok, so it’s not pretty, but it seems to work. The overhead in this fallback example is the fact that we have to use a polling technique (in this case every 5 seconds [5000 milliseconds]) to check for changes in orientation.

Note: there’s also the strong possibility that these browsers will not support the DOMContentLoaded event, but we’ll ignore that for the purposes of this article. (if you have problems, change DOMContentLoaded to load)

Putting it all together

Ok, so if you want the fallback example to work in addition to newer methods, unless you want to duplicate your CSS, then avoid using media queries to target orientation. Instead we’ll rely on adding a class to the html tag (or the body tag if you prefer).

Once we put everything together, we get something that looks like this:

(function(){
var supportsOrientation = (typeof window.orientation == 'number' && typeof window.onorientationchange == 'object');
var HTMLNode = document.body.parentNode;
var updateOrientation = function() {
  // rewrite the function depending on what's supported
  if(supportsOrientation) {
    updateOrientation = function() {
      var orientation = window.orientation;

      switch(orientation) {
        case 90: case -90:
          orientation = 'landscape';
        break;
        default:
          orientation = 'portrait';
      }

      // set the class on the HTML element (i.e. )
      HTMLNode.setAttribute('class', orientation);
    }
  } else {
    updateOrientation = function() {
      // landscape when width is biggest, otherwise portrait
      var orientation = (window.innerWidth > window.innerHeight) ? 'landscape': 'portrait';

      // set the class on the HTML element (i.e. )
      HTMLNode.setAttribute('class', orientation);
    }
  }

  updateOrientation();
}
var init = function() {
  // initialize the orientation
  updateOrientation();

  if(supportsOrientation) {
    window.addEventListener('orientationchange', updateOrientation, false);
  } else {
    // fallback: update every 5 seconds
    setInterval(updateOrientation, 5000);
  }

}
window.addEventListener('DOMContentLoaded', init, false);
})();

Minified (540 bytes):

(function(){var e=typeof window.orientation=="number"&&typeof window.onorientationchange=="object",f=document.body.parentNode;function c(){c=e?function(){var d=window.orientation;switch(d){case 90:case -90:d="landscape";break;default:d="portrait"}f.setAttribute("class",d)}:function(){f.setAttribute("class",window.innerWidth>window.innerHeight?"landscape":"portrait")};c()}window.addEventListener("DOMContentLoaded",function(){c();e?window.addEventListener("orientationchange",c,false):setInterval(c,5E3)},false)})();

Conclusion

And that’s it! Now we can reliably target different screen orientations with some straightforward CSS:

.portrait body div { width: 10%; }
.landscape body div { width: 15%; }

Again, in my experience I’ve used this to fix bugs. But I’m sure you can find more creative uses for it!

In this series

Part 1: The viewport metatag
Part 2: The mobile developer’s toolkit
Part 3: Designing buttons that don’t suck
Part 4: On designing a mobile webpage
Part 5: Using mobile-specific HTML, CSS, and JavaScript

Related

iPad web development tips (Nicholas C. Zakas)
iPhone window.onorientationchange Code (Ajaxian)
The orientation media query (Quirksmode)

Using mobile-specific HTML, CSS, and JavaScript (Mobile web part 5)

Tuesday, June 29th, 2010

Mobile-specific HTML

Use the viewport tag to properly fit the content to the screen:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>

Use the tel scheme for telephone numbers, allowing users to initiate calls by clicking:

<a href="tel:18005555555">Call us at 1-800-555-5555</a>

Or use the sms scheme to initiate an SMS message:

<a href="sms:18005555555">
<a href="sms:18005555555,18005555556">          <!-- multiple recipients -->
<a href="sms:18005555555?body=Text+goes+here">  <!-- predefined message body -->

You also have access to several Apple-specific tags to use in your web application (iPhone and iPod Touch):

// iOS 1.1.3+: this is the icon that's used when the user adds your app to the home screen
<link rel="apple-touch-icon" href="/custom_icon.png"/>

// iOS 3+: full-screen startup splash screen image
<link rel="apple-touch-startup-image" href="/startup.png">

// enable full-screen mode
<meta name="apple-mobile-web-app-capable" content="yes" />

// controls the appearance of the status bar in full-screen mode
<meta name="apple-mobile-web-app-status-bar-style" content="black" />

And also some handy attributes to turn off annoying autocorrect features (works on iPhone, but anything else?):

<input autocorrect="off" autocomplete="off" autocapitalize="off">

Mobile-specific CSS

Media queries enable you to target specific features (screen width, orientation, resolution) within CSS itself. You can use them two ways: 1) inline in a CSS stylesheet or 2) as the “media” attribute in the link tag, which targets an external stylesheet. The following is an example of inline CSS that’s applied only when the device is in portrait mode:

@media all and (orientation: portrait) {
	body { }
	div { }
}

Here’s the same media query using the other method, which points to an external stylesheet (not recommended, as it creates another network request):

<link rel="stylesheet" media="all and (orientation: portrait)" href="portrait.css" />

Here’s a few examples:

// target mobile devices
@media only screen and (max-device-width: 480px) {
	body { max-width: 100%; }
}

// recent Webkit-specific media query to target the iPhone 4's high-resolution Retina display
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
	// CSS goes here
}

// should technically achieve a similar result to the above query,
// targeting based on screen resolution (the iPhone 4 has 326 ppi/dpi)
@media only screen and (min-resolution: 300dpi) {
	// CSS goes here
}

Read more: Media queries (Mozilla Developer Center)

(edit: removed section on body[orient='portrait'], which requires JavaScript and is in error. See Part 6: Dealing with device orientation for more details.)

Mobile-specific JavaScript

window.devicePixelRatio: determine screen resolution (analogue to the media query). (iPhone 4 has the value 2, while Nexus One has the value 1.5).

window.navigator.onLine (boolean): not strictly mobile, but helpful for apps to determine if they’re being run offline

window.navigator.standalone (boolean, iOS 2.1+): determine if it’s running in full-screen mode (Apple only?)

touch events (iOS, Android 2.2+): touchstart, touchmove, touchend, touchcancel

gesture events (Apple only, iOS 2+): gesturestart, gesturechange, gesturend give access to predefined gestures (rotation, scale, position)

window.orientation and orientationchange event: triggered every 90 degrees of rotation (portrait and landscape modes)

MozOrientation (Fennec/Firefox Mobile, Firefox 3.5+): also not strictly mobile. Gives access to the device’s accelerometer (x-y-z orientation data), updated periodically. Works on Android phones (I tested on the Nexus One), Windows Mobile, etc. On the desktop this works with laptops such as Thinkpads and MacBooks.

-near future: camera/microphone access in Android 2.3 (announced at Google I/O 2010) through the Capture API

If you’re developing for a BlackBerry Widget, you have access to proprietary information through the blackberry object (which gives access to useful information such as blackberry.network [returns values such as CDMA and Wi-Fi] and blackberry.system).

You also have the option to use PhoneGap, which augments JavaScript and gives you access to more phone features that native apps would have access to.

Use a mobile-optimized JavaScript library

Because smartphone browsers are standards-based, the aim of a JavaScript library on mobile is less towards API normalization and more towards providing an actual UI framework, usually to emulate the feel of native apps (and to provide easier workarounds to lack of access to position:fixed). We’ve seen a few libraries released that emulate the iPhone UI, and in the future we might see libraries emulating the Android UI, as well as entirely new UIs.

There’s also a bit to be said about simply loading full desktop JavaScript libraries into mobile clients. In my opinion this doesn’t particularly make sense, especially in a world where latency and bandwidth are so much more of a concern. It doesn’t make sense to force the user wait longer and download code that’s ultimately useless to them (hacks for desktop browsers such as IE 6, etc).

Here’s a few of the mobile libraries now available:
-Sencha Touch
-baseJS
-XUI
-jQTouch: jQuery-style mobile library that emulates the look of the iPhone UI
-iUI: the first JavaScript library to be released, emulates the look of the iPhone UI. Originally coded by Joe Hewitt.
-PastryKit: Apple proprietary non-public JavaScript library with no available documentation

Take advantage of new stuff!

While not specific to mobile, there’s a lot of new stuff in general that you can use. If you limit yourself to the top smartphones (iPhone, Android, and maybe webOS), compared to the desktop you immediately have access to an even wider array of new stuff, especially many Webkit proprietary features, since most of these top smartphones have browsers based on Webkit.

-HTML: new tags (HTML5 (I’m sure you’ve heard of it by now…))
-CSS: 2d transforms, 3d transforms, animation, border radius, custom fonts with @font-face, etc.
-JavaScript: strict mode, constants, block scope, Date.now(), etc.

Related posts

This post is part of a series on the mobile web. You can read the other parts of the series here:
Part 1: The viewport metatag
Part 2: The mobile developer’s toolkit
Part 3: Designing buttons that don’t suck
Part 4: On designing a mobile webpage

iPhone 4 SunSpider test results (22% faster than iPhone 3GS)

Friday, June 25th, 2010
============================================
RESULTS (means and 95% confidence intervals)
--------------------------------------------
Total:                 10669.4ms +/- 1.0%
--------------------------------------------

  3d:                   1471.5ms +/- 2.1%
    cube:                428.7ms +/- 2.6%
    morph:               584.3ms +/- 4.7%
    raytrace:            458.5ms +/- 0.6%

  access:               1476.7ms +/- 1.3%
    binary-trees:        151.6ms +/- 1.3%
    fannkuch:            664.0ms +/- 0.1%
    nbody:               397.9ms +/- 2.1%
    nsieve:              263.2ms +/- 6.3%

  bitops:                947.2ms +/- 2.1%
    3bit-bits-in-byte:   195.7ms +/- 2.0%
    bits-in-byte:        206.1ms +/- 1.0%
    bitwise-and:         179.7ms +/- 1.1%
    nsieve-bits:         365.7ms +/- 3.9%

  controlflow:           169.5ms +/- 8.0%
    recursive:           169.5ms +/- 8.0%

  crypto:                668.7ms +/- 1.0%
    aes:                 307.0ms +/- 1.4%
    md5:                 181.1ms +/- 3.1%
    sha1:                180.6ms +/- 1.0%

  date:                  838.4ms +/- 4.6%
    format-tofte:        420.9ms +/- 7.4%
    format-xparb:        417.5ms +/- 2.8%

  math:                 1161.9ms +/- 1.0%
    cordic:              424.9ms +/- 0.5%
    partial-sums:        385.1ms +/- 0.3%
    spectral-norm:       351.9ms +/- 2.9%

  regexp:               1479.3ms +/- 0.1%
    dna:                1479.3ms +/- 0.1%

  string:               2456.2ms +/- 0.9%
    base64:              347.6ms +/- 3.1%
    fasta:               408.1ms +/- 6.7%
    tagcloud:            447.7ms +/- 0.6%
    unpack-code:         797.8ms +/- 0.4%
    validate-input:      455.0ms +/- 0.4%

Summary

Thanks to my coworker for lending me his phone for a few minutes (he waited in line for 9 hours yesterday when it first went on sale!).

This is quite an improvement over the iPhone 3GS running iOS4, which ran the SunSpider test in 13787ms. The iPhone 4 ran the same test in 10669ms, which makes it ~22% faster head-to-head.

Processors

The iPhone 3GS has a Samsung S5PC100 ARM Cortex-A8[5] 833 MHz (underclocked to 600 MHz), while the iPhone 4 has an Apple A4 1GHz (likely underclocked to an unknown speed).

How to install obsolete Android Virtual Devices (AVDs)

Wednesday, June 9th, 2010

Apparently it’s no longer possible to easily download Android versions 2.0 and 2.0.1 from the AVD Manager. I noticed this problem when I got a new machine and had to install everything from scratch. In the future I suspect even more AVDs will be made obsolete, so this solution also applies to them.

Why would you want to install obsolete AVDs? In my case it’s a matter of research: I simply want to see the progress of features being added to its browser, and track those changes over time.

Step 1: Manually download and inspect repository.xml

When updating from “Available Packages” there’s a little one-line error saying “Some packages were found but are not compatible updates.”

Ok, so let’s check out the XML for ourselves to see if we can find anything. So point your browser to https://dl-ssl.google.com/android/repository/repository.xml (to see the XML, right click to view the page source if you’re using a Webkit-based browser).

Search for the AVD version you want. In this case we want 2.0 and 2.0.1, so a simple search find the relevant blocks of code. And we also find the XML tag that’s the cause of our troubles, which prevents us from easily getting the AVDs:

<sdk:obsolete />

Step 2: Get the AVDs!

At this point you could do two things, either save repository.xml to your computer and remove these “obsolete” tags (then add the XML to your AVD Manager by clicking “Add Add-on Site…”), or simply find the path to the AVD and download it manually.

The second option is to simply manually download the paths, which are easy to find in the XML and are listed here for your convenience:
Android 2.0 AVD (Linux)
Android 2.0 AVD (Mac OSX)
Android 2.0 AVD (Windows)

Android 2.0.1 AVD (Linux)
Android 2.0.1 AVD (Mac OSX)
Android 2.0.1 AVD (Windows)

Step 3: Install!

Create directories under your Android SDK installation’s “platforms” folder. In this case we have 2.0 (API level 5) and 2.0.1 (API level 6), so I created these folders: android-5 and android-6. Now just unzip the contents into these folders.

Start up the AVD Manager and click on “Installed Packages”. If you don’t see your new (obsolete) packages you just installed, hit the Refresh button and you should see them.

Now you can create new AVDs with these obsolete packages!

Mobile First: Luke Wroblewski on mobile design

Saturday, June 5th, 2010

Click to play Luke Wroblewski: Mobile First

In episode 6 of The Big Web Show, Luke Wroblewski gives his “Mobile First” talk, explaining his philosophy for designing for mobile, the challenges, and a look at the road ahead. Luke explains that because of the limitations on mobile, developers are forced to really optimize the user experience for mobile. Often times this mobile experience turns out much better than on the desktop, where the “gluttony of resources” results in distracting and excessive webpages.

On designing a mobile webpage (Mobile web part 4)

Wednesday, May 26th, 2010

The frontend engineer lives at the intersection between design and engineering, and this is perhaps nowhere more true than in the world of mobile. In order to make a usable desktop website, an engineer must have at least some sense of design, and fortunately a lot of this has been standardized over the years. But the world of mobile is full of more unknowns, and the field is changing rapidly, especially lately from the shift away from older feature phones to the focus on smartphones. As such, the mobile engineer has to be on their toes in the sense of both design and engineering.

The focus of this article is on mobile design in general. I’m by no means an expert, but these are some things I’ve found to be essential and basic topics. Hopefully you will find this useful!

Only one column?

Mobile websites should only have one column of main content. This point is stressed again and again in mobile design, and for good reason: the paradigm of multi-column layouts is fairly well-entrenched in desktop design, but it’s simply not an option for a well-designed mobile site.

To illustrate this point, the following two images are both 320 pixels wide, which is a common smartphone width in portrait mode. The image on the left is the Yahoo! front page (yahoo.com) in its three-column fixed width desktop size, and the image on the right is Yahoo! mobile’s front page (m.yahoo.com):

This might not be a fair comparison, as the desktop version isn’t optimized for mobile, so you can’t even read the text without zooming in. However, even if the size of the text was increased, it’s apparent that three columns is just too much, both because of screen width concerns as well as concerns about too much content. There’s simply too much information being crammed down the user’s throat. Chances are the user only wants to check a few things and then put the phone back in their pocket, and this three-column version of the site is preventing them from doing that.

Modules, modules, modules

It’s helpful to think of a webpage as being composed of modules. If you’re converting a desktop website into a mobile site then you must essentially think of the website as bits of rearrangeable components:

What you’re doing is essentially grabbing your most important components and making sure they appear at the top, then stacking each module on top of each other. And don’t forget we do have variable screen widths on mobile (even on phones themselves, since they can be either in portrait or landscape mode), so we should be sure that each module is taking up 100% of the available screen space. In more technical terms, yes, this means we have to make a fluid layout.

Clarity and concision

It’s important to be both clear and concise in presentation. On the desktop we can get away with a certain amount of screen bloat, but users always appreciate simple sites when they come across them. This is a huge part of what made Google so successful: users came to the site for one thing, search, and the site was kept simple to facilitate that interaction.

As it turns out, it’s quite hard to be clear and concise. I like to compare this to writing papers for school. Often we were given assignments that needed to be a minimum of X amount of words or pages, and it was sometimes challenging to find information to meet this minimum. Fortunately (or unfortunately) many students developed a highly refined skill of BSing to fill the word limit. But were you ever given an assignment where there was a word/page MAXIMUM? This turns out to be much harder to write for, mostly because you can’t BS it. You have to identify the fluff, the nonessential bits, and surgically remove them from your paper. (As a side note, in the area of computer science, notice how many HUGE tomes there are out there compared to smaller books. I would venture to guess that engineers have a hard time being concise.)

This is just the problem we now face with mobile. We know how to fill up webpages with fluff: add an RSS feed here, add a module that ties into Facebook there, add another feed here, stick a relatively unimportant module there, add an excessive amount of social sharing buttons, and presto, we have a website that looks pretty active. But how does that translate to mobile? The questions you’re forced to ask yourself are: “do I really need this data feed displayed here?”, “do I need this huge Facebook module here taking up space?”. Or more positive questions like “what are the things users will come to my site to check, and how do I make it easier for them to find those things?”.

In the case of the last question, it’s easy to see from the above screenshots what Yahoo mobile thought was most important: Mail, Search, and News, all of which are visible at the top of the page. Think about your website’s main two or three features and try to make those just as visible.

Useful links

W3C Mobile Web Best Practices 1.0
Tips and Tricks for developing Mobile Widgets

In this series

Part 1: The viewport metatag
Part 2: The mobile developer’s toolkit
Part 3: Designing buttons that don’t suck

Designing buttons that don’t suck (Mobile web part 3)

Wednesday, May 19th, 2010

A button is something that seems to be made just for mobile: it’s designed to be big and easy to activate, as opposed to small and harder to activate, like normal text links. This seems ideal for a mobile devices, which have a small display area and whose form of input is a person’s (relatively) fat finger interacting with the screen. Contrast this with the desktop, where the display area is much larger and the input device, the mouse, is a much more highly refined and sensitive pointing device.

But you probably don’t want to make everything into a button. After all, there’s still a place for good old fashioned anchor tags. So what do you make into a button? Simple: areas of your website that get frequent usage. For instance, mobile.twitter.com has buttons for Search, Refresh results, and More (display more tweets), but leaves other things as anchors/hyperlinks, such as usernames and links in tweets. Basically, use common sense. You should have a mixture of both buttons and hyperlinks.

There’s a distinction to be made between form input buttons and other things that look like buttons. The former occurs within a Form tag and can be used to submit a form of data when clicked (and you can style it up all you want!). The latter is simply an Anchor tag disguised as a big clickable button, which is the focus of this article.

A button can be a very useful thing, and can make the user experience much much better. Yet it’s surprisingly easy to fail to create a proper button.

How to fail at creating a button

See if you can tell the difference between these two buttons:

If the difference isn’t immediately apparent, try mousing over the following buttons:

What’s the problem? The button on the top is only clickable when hovering over the text. In other words, it looks like a button but it acts just like a regular hyperlink. This is a common problem that I’ve seen a LOT, and I’ve even seen it on major websites (in fact, the faulty button is inspired by the live code on mobile.twitter.com).

How does this happen?

My theory is that when a design is passed down to a developer, the developer may think their job ends when their code produces output that looks like the original design documents. But they fail to take into consideration the actual usability of the website.

This is a simple mistake, but it definitely causes frustration when I find it on websites. And I find myself even more annoyed when I see this while browsing websites with my iPhone. It basically tells me that the developers don’t use their own website. That’s not a good impression to leave with your visitors.

Summary

In summary, buttons are an important part of your mobile website. They are designed to be easy to activate, so make sure that frequently used functions on your website are buttons. Also, don’t be lazy: TEST your code for usability and don’t assume that the product is done when it looks identical to the design specs.

The mobile developer’s toolkit (Mobile web part 2)

Tuesday, May 11th, 2010

Tools of the trade

You’re no mobile developer unless you have the tools to develop on mobile! And while it’s good to own at least one of the smartphones you’re developing on, it’s probably unrealistic to think that you’re going to go out of your way to buy several other unlocked smartphones just to test with. So you should have the next best thing: an SDK!

But an SDK is just one of the tools of the trade. Here’s links to more things to get you started!

SDKs, Emulators and Simulators

Short of having access to a real phone, the next best thing is to have an emulator/simulator. And good news: all the major smartphones have SDKs available for you!

iPhone SDK (Mac OS X only) – the quintessential SDK for the quintessential smartphone. Includes iPhone simulator.
Android SDK (Mac OS X, Windows, and Linux)
Palm webOS SDK (Mac OS X, Windows, and Linux) – emulator for Palm Pre, Pixi, etc. Also check out Ares, the browser-based tool for creating web apps.
Firefox Mobile emulator (aka Fennec) – mobile version of Firefox being developed for new Nokias and soon Androids
Opera Mobile emulator – this is the fastest emulator of the bunch, in terms of downloading and launching the program. Painless installation.
Opera Mini Simulator (Browser-based Java applet) – In-browser simulator. Note that Opera Mini is different than Opera Mobile.
Windows Phone 7 Series emulator

Keynote MITE (Mobile Interactive Testing Environment) (Windows only) – a glorified user agent switcher. Doesn’t have testing of real devices.

DeviceAnywhere (Java-based software that runs on Windows and Mac OSX) – a service that lets you test on actual mobile devices sitting in labs around the world. It has a tendency to be a bit clunky, but there’s no real alternatives on the market. Only subscribe to this if you intend on supporting more than just smartphones.

There’s also a much fuller list of feature phone emulators here at Mobiforge.com.

Mobile JavaScript libraries

baseJS
XUI
jQTouch – jQuery plugin for mobile development
iUI – iPhone user interface library
PastryKit – Apple-exclusive with no available documentation

Web App Wrappers

The concept is simple: use what you know to create an app with HTML/CSS/JS and turn it into a marketable native app with one of these “wrapper” services.

PhoneGap
appcelerator’s Titanium Mobile
QuickConnectFamily
Rhomobile (HTML-based)

User agent switchers

Many websites sniff a browser’s user agent to detect if it’s a mobile device. As a developer this presents a challenge, because a lot of development is done on a desktop browser. With a user agent switcher, a developer can masquerade their desktop browser as a mobile browser.

Firefox addon: User Agent Switcher

Safari: Enable the Develop toolbar (click on Safari -> Preferences -> Advanced) and click on Develop -> User Agent. Select a predefined user agent or enter a custom agent by selecting “Other…”

Chrome: There is no easy way to do this (note that the one user agent switcher extension for Chrome doesn’t work). Currently the only way is to set command line flags:

To change the user agent of Chrome in Windows:

  1. Make a copy of the shortcut to Chrome.
  2. Right click the copy and select Properties.
  3. In the Target field append ––user-agent=”myagent”

Example Target: “C:\Documents and Settings\Username\Local Settings\Application Data\Google\Chrome\Application\chrome.exe” ––user-agent=”Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)”

To change the user agent of Chrome in Mac OSX:

  1. Open Terminal
  2. Enter the following into terminal: /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome ––user-agent=”myagent”

Example command: /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome ––user-agent=”Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)”

Mobile detection

On the server side, mobile detection is mostly done by user agent sniffing (thus the need for the user agent switchers above), but there are a few other methods.

“Lite” user agent detection: these methods implement a simple server-side function (commonly in PHP) to detect common mobile user agents. There’s a few versions, mostly based on code by Andy Moore. There’s one implemented in the WordPress Mobile Pack and a similar one described on the Nokia developer forums.

WURFL (Wireless Universal Resource File) – a 10+ year old project that is still being used and gaining momentum. It’s beneficial because it’s open source and it offers a lot of valuable information about devices.

DeviceAtlas – essentially a commercial version of WURFL

Reporting bugs

Everybody’s human. All this new cutting-edge stuff isn’t exactly bug-free. Help squash bugs by reporting them on the project’s website. For best results, show a simplified example of the bug in action (try not to post big hunks of code!).

WebKit Bugzilla
Android: Report bugs

Blogs

Keep up to date! There’s new stuff happening all the time on the mobile web.

QuirksBlog – blog of Peter-Paul Koch (PPK), who is known for documenting and researching cross-browser inconsistencies. As of the last several years he’s been focusing on documenting mobile browser bugs.

Daring Fireball – John Gruber’s blog with a cultlike following. Frequently reports on mobile happenings, especially stuff relating to Apple.

Surfin’ Safari – The WebKit Blog
Android Developers blog
IE for Windows Phone Team Weblog
Opera Mobile Blog
Inside BlackBerry – The Official BlackBerry Blog

Yahoo! Mobile Blog
Google Mobile Blog

Miscellaneous

Yahoo! Blueprint – framework for normalizing cross-browser issues across thousands of devices

(this post is part of an ongoing series on the mobile web. Read the first part here)

The viewport metatag (Mobile web part 1)

Thursday, May 6th, 2010

The skinny

Use this:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>

Introduction

This series of posts is intended to introduce web developers to basic techniques for designing for the mobile web. It assumes at least a basic knowledge of creating desktop websites.

The problem

Ok, so you’ve settled down to learn how to write a website for a mobile device using your current knowledge of building desktop websites. So you start off with some pretty basic HTML:

<!doctype html>
<html>
<head>
    <title>Hello world!</title>
</head>

<body>

<p>Hello world!</p>

</body>
</html>

Ok! You can’t get much simpler than that. You check it out and it looks good on all the desktop browsers, since there’s really no opportunity yet for any cross-browser inconsistencies. And then you check it out on your mobile device:

Hello World on the iPhone

Doh! Where’d we go wrong? The text is obviously way too small to read without zooming in.

This is the first lesson in making mobile websites: width is your enemy. This is the first of many countless problems with device width you will encounter. Fair warning.

If you think about it logically, it seems to make sense: mobile Safari took a look at the page and assumed it was a document designed for the desktop, which is true of the vast majority of websites. So it gave the website a width of 980 pixels and presented it zoomed out. Which is why we can’t read anything until we zoom into the page.

Viewport

But this is no good! What we need to do is tell the browser that this webpage is optimized for mobile. And this is where the viewport metatag comes into the picture.

Now we tweak our Hello World just a bit…

<!doctype html>
<html>
<head>
    <title>Hello world!</title>

    <meta name="viewport" content="width=device-width"/>
</head>

<body>

<p>Hello world!</p>

</body>
</html>

And we get this…

Hello World with the Viewport tag

Much better! By setting the viewport width equal to “device-width”, we’re essentially telling it that the device width is 320px, not the default value of 980px that it guessed. If we set width=320 it would achieve the same result on the iPhone and a few other smartphones, but not all phones have this exact width, so it’s best to simply set device-width and let the mobile browser figure it out.

This viewport metatag is supported on many smartphones, from iPhone to Android to webOS (Palm) to even Internet Explorer Mobile, Opera Mini and Opera Mobile.

At the end of the day here’s what the standard viewport looks like, as grabbed from m.yahoo.com:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>

More fun with the viewport tag

In addition to solving our biggest concern with the width of the content, the viewport tag has more options to play with:

Property Description
width Width of the viewport in pixels (or device-width). If width isn’t set, it defaults to a desktop size (980px on mobile Safari).
height Height of the viewport in pixels (or device-height). Generally you don’t need to worry about setting this property.
initial-scale (0 to 10.0) Multiplier that sets the scale of the page after its initial display. Safe bet: if you need to set it, set it to 1.0. Larger values = zoomed in, smaller values = zoomed out
minimum-scale (0 to 10.0) The minimum multiplier the user can “zoom out” to. Defaults to 0.25 on mobile Safari.
maximum-scale (0 to 10.0) The minimum multiplier the user can “zoom in” to. Defaults to 1.6 on mobile Safari.
user-scalable (yes/no) Whether to allow a user from scaling in/out (zooming in/out). Default to “yes” on mobile Safari.

Feature phones: when viewport isn’t available…

Unfortunately the viewport tag is relatively new and as such isn’t universally supported, especially if you’re working on older feature phones. But there are some older methods at your disposal for identifying your website as optimized for mobile:

<meta name="HandheldFriendly" content="true"/>

This tag was originally used to identify mobile content in AvantGo browsers, but has now been made the general standard for identifying mobile websites. However, it’s unknown what range of browsers support this meta tag.

Another tag at your disposal is a Windows-proprietary meta tag that also took root and eventually became used as another means of identifying mobile content. The drawback with this tag is that a specific width must be given, which doesn’t make it as flexible as the viewport tag (see above). Again, it’s unknown what the support for this tag is:

<meta name="MobileOptimized" content="320"/>

Lastly, your website will be identified as a mobile optimized site if your doctype is either XHTML-MP or WML. However, this is becoming less and less the case these days, as browsers begin to support good old HTML4.01 and HTML5+.

(info for this section comes from Beginning Smartphone Web Development)

Reference

Safari HTML Reference: Supported Meta Tags
Mobile META Tags

PastryKit: digging into an Apple Pie

Wednesday, December 16th, 2009

Yesterday John Gruber wrote about Apple’s PastryKit, iPhone’s JavaScript framework that’s been discovered “in the wild” on the iPhone user guide at http://help.apple.com/iphone/3/mobile/. There’s a few ways to access the page:

  • with an actual iPhone or iTouch
  • by browsing with an iPhone/iTouch user agent. If you’re using Safari, enable the Developer menu in Safari>Preferences>Advanced and switching user agents by clicking on Develope>User Agent

What’s all the big fuss?

John was particularly interested in the responsiveness and native-like interaction of flinging through long lists, the fact the address bar is completely hidden, and the possibility of having a toolbar fixed to the top of the page. PastryKit makes all of these things possible and implements them better than anything else. And the result is nearly indistinguishable from a native app. Here’s a video I made of the iPhone user guide in action, powered by PastryKit. This is running on Safari – it’s not a native app!

PastryKit has been here for a while

As John Gruber points out, the code for PastryKit has been there for quite a while now. Stack Overflow has a question about it that was asked way back in July, and there are several more recent references to it by jQTouch developer David Kaneda on Twitter. Of course, since John’s post there’s been an explosion of interest in the form of even more tweets!

Hopefully with all of this increased attention, we’ll see Apple take notice and address it. Here’s hoping, anyway.

Some interesting features

There’s even more interesting takeaways from the PastryKit code, and I’m sure I’ve just barely scratched the surface:

  • implements its own form of Object-Oriented programming (obj.inherits and obj.synthetizes properties). When modules are declared, they’re registered as a PK Class (i.e. PKClass(PKBarButtonItem) registers PKBarButtonItem as a PK Class)
  • CSS3 wrapper functions (PKUtils.t() is a wrapper for translate3d, etc.)
  • no single library namespace (surprisingly) – which means there are many many global variables. This however is somewhat acceptable, as all variables are prefixed with “PK” and are declared to be constant (const PKStartEvent, const PKEndEvent) and cannot be overwritten.

There’s also some interesting takeaways not from PastryKit itself, but from the way the iPhone user guide is implemented. Most of the data on the page – including each menu icon (base64 encoded) – is located in a single 650kb JSON-encoded file called content.json. This means the initial loading of the page is quite slower than the user would normally expect, but once the initial payload has been delivered, it’s a relatively smooth browsing experience thereafter.

And as John Gruber already pointed out, this data is stored locally with the help of HTML5, allowing the user to continue reading even while offline!

iPhone user guide in Safari

iPhone user guide in Safari

PastryKit unminified and explained (sorta)

What I’m excited to show you now is a result of a bit of effort to make PastryKit more intelligible. Though there’s a minified version of the code on Apple’s website, it’s not obfuscated (and rendered unintelligible), so not all hope is lost! With the help of jsbeautifier.org we can now see the slightly unminified version of the code: PastryKit.js unminified.

The next thing I did was separate each module into its own file. I was able to separate the code into 27 numbered files, with the original ordering preserved (to prevent issues with dependencies). Viewing the code in this way definitely helps make sense of it all. You can download these separate files as part of a little unofficial SDK I made, which also includes a copy of the iPhone user guide with the JS iPhone-only redirect removed: PastryKit unofficial SDK.

PastryKit modules

The following is an explanation of each module I found. The descriptions are definitely incomplete and possibly inaccurate, so any comments or help is appreciated. But this should hopefully shed some light on the matter!

  • PKUtils – general helper functions (PKUtils.t() is a wrapper for CSS translate3d, PKUtils.degreesToRadians(), etc, etc.)
  • PKEventTriage – general event handler
  • PKPropertyTriage – handlePropertyChange() method – ?
  • Element – helper functions added to HTML Element prototype
  • Node – adds getNearestView() method to HTML Node prototype
  • PKClass – custom-rolled class with with “inherits” and “synthetizes” properties
  • PKObject – custom-rolled object with observer pattern. Most modules extend from this.
  • PKPoint – wrapper for WebKitPoint – used for touch events?
  • PKSize – wrapper for width/height properties
  • PKImage (inherits PKObject) – helper for creating Image elements and knowing when it’s finished loading (but doesn’t add the image to the DOM)
  • PKAnimator – basic animation tweens
  • PKTransition – helper for proprietary Webkit CSS transitions
  • PKTransaction – interacts with PKTransition – ?
  • PKView (extends PKObject) – manages a view, such as handling events that occur within that view – ?
  • PKContentView (extends PKView) – ?
  • PKRootView (extends PKContentView) – ?
  • PKScrollIndicator (extends PKView) – custom scrollbar
  • PKScrollView (extends PKView) – handles dynamically positioning the page when it’s scrolled
  • PKTableView (extends PKScrollView) – handles more touch/scroll events?
  • PKCellPath – ?
  • PKTableViewCell (extends PKView) – ?
  • PKToolbar (extends PKView) – manages the top toolbar
  • PKNavigationView (extends PKView) – manages bottom navigation bar
  • PKNavigationItem (extends PKObject) – manages bottom navigation buttons
  • PKControl (extends PKView) – manages generic controls
  • PKBarButtonItem (extends PKControl) – manages button controls
  • PKSearchBar.js (extends PKView) – manages the search bar

Conclusion after a first glance

As far as I can tell, this is no full-fledged JavaScript library. At least not for now.

On first glance PastryKit seems to be at most a nice development framework for making web apps with the same look-and-feel of native iPhone apps. And this framework in many ways does this better than anything out there (at the moment).

I echo the sentiments of Gruber – I do hope we hear more about this from Apple!