News Flash

Great article by @NeutronUK on how to create a print stylesheet using Firebug and the Web Developer Toolbar - http://cot.ag/bOQiVM

Tagged: PHP

1 May 2009

There have been a ton of helpful and interesting tips posted to Tipster recently, so I thought we’d pull a few out for you all (and give the submitters a bit of well-deserved publicity).

Topics that we’re covering are: MySQL, CSS, JavaScript, PHP, JQuery, life hacks and server admin.

MySQL Geo Search

Here’s a MySQL statement to search for nearest objects to you in a database, ‘lat’ & ‘lng’ are fields in the ‘items’ table with the location of object and $latitude & $longitude are the users location. The distance field will be the calculated distance in Km between the user and the object:

SELECT *,(((acos(sin((".$latitude."*pi()/180)) * sin((`lat`*pi()/180))+cos((".$latitude."*pi()/180)) * cos((`lat`*pi()/180)) * cos(((".$longitude."- `lng`)*pi()/180))))*180/pi())*60*1.1515*1.609344) as distance FROM `items` ORDER BY distance;

By: Sam Machin
Vote on this tip

Transparent background images – PNG fix for IE6 – a few reminders

When using the MS filter (via The AlphaImageLoader) to fix PNG transparency for IE6 — in your CSS, remember to:

  1. Set width and height for the element/s containing the transparent background image.
  2. First set background to none — then apply filter for background image.
  3. Apply ‘position: relative;’ to any contained links to ensure functionality

(Also, bear in mind that the background images can no longer be tiled or positioned via ‘background-position’).

By: Prisca
Vote on this tip

Address Longitude and Latitude in Google Maps

Google maps does not show the Longitude and Latitude of an address you search. To get this information, enter this piece of JavaScript into you browsers address bar and hit enter:

javascript:void(prompt('',gApplication.getMap().getCenter()));

A little window will then pop-up displaying the Longitude and Latitude for you. Bingo!

[Editor's note: If you add this to your bookmarks toolbar, it's even easier to use. Just click it whenever you're on Google Maps. Hat tip to Phil Balchin.]

By: Pete Roome
Vote on this tip

Custom Details in Code Hints – Zend Studio for Eclipse

Zend Studio is a brilliant platform for PHP development. In my view, well worth the cost. One of the best things about it now being built on Eclipse is the project-wide code hinting.

When you see the built-in code hints and highlight an option, you get loads of lovely details regarding the functions and classes that you are about to use… as you would expect from most modern IDEs. However, Zend Studio for Eclipse takes this further for your own classes and functions!

When you have written your classes and functions, start placing a multi-line comment just above the opening line, i.e. /**, hit Return and Studio will prompt you for data types and descriptions for your method variables.

This is invaluable in understanding those classes you wrote at 3:47am, 3.5 years ago and haven’t used since!

By: Simon Hamp
Vote on this tip

Use a Print Stylesheet

Print stylesheets allow you to change the style of your page when printing, without having to provide a separate “print version” of the markup.

You specify a print CSS by adding “media=’print’” as an attribute to the link tag.

<link rel="stylesheet" type="text/css" media="print" href="print.css"/>

In the print CSS you should remove unnecessary elements such as sidebars, menus, background colours, presentational images, etc so as not to waste ink and paper on parts which don’t need to be printed. You can also change the font and size to make sure the text is clear on the printed page.

You can even add some CSS to show the URLs of links on the page, which wouldn’t normally be seen when printing.

a[href]:after { content: " (" attr(href) ") "; }

By: Rich Adams
Vote on this tip

Make your links easier to read

Instead of using { text-decoration: underline; } on your links (as browsers do by default) use:

{ border-bottom: 1px solid; }.

This makes your links easier to read, as there will be more space between the text and the line underneath, so the line will no longer cross through your ‘y’s and ‘g’s.

You can also then style your underline with all the usual border stylings, much more exciting than a plain underline :)

By: Laura Kalbag
Vote on this tip

Manual filmstrips in jQuery

Really simple manual photo film-strip in jQuery. Used to swap a large image on a page with that of a thumbnail elsewhere on the page, such as different photos of a product in an e-commerce store.


$(document).ready(function(){
imageSwapper(".thumbnails a");
});


function imageSwapper(link) {
$(link).click(function(){
$(&#039;#largeimage&#039;).attr(&#039;src&#039;, this.href);
return false;
});
};

Just link the thumbnails to their larger versions and pop them in a div or paragraph of class thumbnails, and give the large image an ID of large image, and you are good to go!

By: Michael Peacock
Vote on this tip

Store user passwords as salted hashes

Just using a hash of the user password is not strong enough. If two users have the same password, they’ll have the same hash. Dictionary attacks are also still possible as the attacker can have a list of dictionary word hashes. Using a salted hash involves generating a random string of characters, which you then concatenate with the password before hashing. Two users with the same password will then have different hashes, and the stored hash will never just be a hash of a common word if the user chose a weak password. You then store the salt, and the hashed value in your database.

hash_to_store = sha1(salt + real_pass)

There are many different methods you could use too, such as concatenating the salt with a hash of the password and then hashing that, etc.

hash_to_store = sha1(sha1(real_pass) + ...

By: Rich Adams
Vote on this tip

CD/DVD stuck in Macbook

Having gotten a DVD stuck inside my Macbook the other day, i found the only way to force eject it was to hold down the trackpad button on reboot. DVD popped right out.

By: Pete Roome
Vote on this tip

Photo credit: flickr.com/photos/mance

Continue reading 28
Future of Web Design London May 17-19 2010

13 March 2009

A Microsoft browser plug-in might seem an odd target for the PHP developer, more used to working with open source platforms such as Linux, Apache and the MySQL database server. However there is much about Microsoft Silverlight that makes it a good match to such technologies. For a start, it is a free download and there are versions that run not only on Microsoft Windows XP and Vista but also on Intel-based Apple Macs running OS X 10. It is designed to work not only with Microsoft Internet Explorer but with all major Web browsers, and Microsoft is taking particular care to ensure compatibility with Firefox and Safari. There is even a version for Linux called Moonlight which is being developed as part of the open source Mono Project.

Silverlight is a powerful tool for creating Internet applications that go considerably beyond the capabilities of standard HTML and CSS. It supports a wide range of visual effects and has more than 30 user interface controls built-in, including not only buttons, list boxes and sliders but also a data grid and a calendar. It can display PNG and JPEG image files, and play back WMV, WMA and MP3 media with support for 720p HDTV display modes. Silverlight 1.0 was released in April 2007. The current version is Silverlight 2.0 (originally referred to as Silverlight 1.1) which is fully compatible with the original while offering many enhancements.

Inside a Silverlight application
You define the application that you want Silverlight to present using XAML (eXtensible Application Markup Language). This is based on the XML specification and was designed by Microsoft for initialising structured values and objects. The following XAML document declares a Canvas object containing a TextBlock, which is a lightweight element for displaying text:

Code example. Click link below to donwload actual text.

Download complete code example

The visual elements that make up a Silverlight application need to be placed within a container object, and this provides a reference in which they can be positioned. In our example we are using a Canvas object measuring 300 by 100 pixels as the container and we have set its Background property so that it displays in a light blue color. Into this we have placed a single TextBlock object which will display the traditional ‘Hello World!’ text string in a Verdana font 30 pixels in size and 10 pixels below and to the right of the top-left corner of the Canvas object. Note the dot syntax that we have employed to reference properties of the Canvas object.

Actually displaying a Silverlight application within an HTML page need involve little more than a standard Object tag. At its simplest, the following renders our example within a browser:

Code example. Click link below to donwload actual text.

Download complete code example

Here we have defined a space 300 pixels wide and 100 pixels wide in which to place the Silverlight plug-in, as defined by its MIME type. We have also defined a data attribute for the plug-in. In practice this is usually ignored but it can boost performance with some browsers (and note that the trailing comma is necessary as the attribute takes two parameters, the second having a ‘null’ value in this case). Finally, in the event that the client does not have Silverlight 2.0 installed, the anchor element displays a ‘Get Silverlight’ image from the Microsoft Web site which is linked to the page from which the user can download and install the plug-in.

The Silverlight plug-in takes a number of parameters but in this context the most important is ‘source’ which tells the plug-in where to find the application. In this case we are directing it to the file ‘silverlightapp.xml’. If this was to contain the XAML of our earlier example in simple text form, and both these files were uploaded to a directory on your Web server, then opening the HTML page would result in our ‘Hello World!’ application appearing to the top-left of your browser.

The XAML that defines the Silverlight application need not reside in a separate file. It can instead be defined within the page that instantiates the plug-in using a special script block. For example, we could insert the following immediately before the ‘pluginHost’ div block in our HTML page above, which also shows off some of the special effects supported by Silverlight:

Code example. Click link below to donwload actual text.

Download complete code example

We reference this XAML block by changing the ‘source’ parameter for the Silverlight1 object as follows:

Code example. Click link below to donwload actual text.

Download complete code example

The hash character indicates that what follows references a script block on the current page. The other principle difference between this and our earlier XAML example is that we have placed a Rectangle object on the Canvas. This is a Shape element, as is the Line, Ellipse, Polygon and Polyline, and as such supports a wider range of display options. The RadiusX and RadiusY attributes round the corners of the Rectangle, while the Fill property allows us to specify a Brush object. In this case we have used the LinearGradientBrush to shade the Rectangle in a graduated blend of yellow and light blue.

Most of the other parameters supported by the Silverlight plug-in can be ignored at this stage. However ‘minRuntimeVersion’ can be useful if you want to ensure, for example, that version 2.0 is installed rather than version 1.0. This can be accompanied by ‘autoUpgrade’ which means that an attempt should be made to upgrade automatically in the event of too early a version being found. There is also the ‘OnLoad’ parameter which can specify a JavaScript function that should be run once the plug-in is loaded (more on that later).

If you want to know more about the options available when instantiating Silverlight, then the article ‘Instantiating a Silverlight Plug-in’ from Microsoft’s MSDN Library is a good place to start.

Using PHP with Silverlight
For the PHP developer, the important point is that the source for the Silverlight object can be anything that returns XAML, and that includes a PHP script. This opens up many possibilities. For example, the following PHP page uses Silverlight to display data extracted from a MySQL database:

Code example. Click link below to donwload actual text.

Download complete code example

Assuming this is part of the page ‘customers.php’ on our PHP server, then calling it with the following URL would cause Silverlight to display the name, city and postcode of the 134th customer in the database:

http://myserver.com/customers.php?ID=134

Having extracted the ID value from the query string, the code opens a connection to the database and then runs a query which gets the data for the customer specified and places it in the object $result. The function mysqli_fetch_array() extracts the data from $result into the array $row, from where it can be read and inserted into the XAML using the echo command.
This is far from production code, with little in the way of error checking, but it does serve to demonstrate how PHP can be used to generate a Silverlight application. For the sake of simplicity our example embeds the XAML within the page that instantiates the Silverlight control, but you could equally specify a PHP page as the source for the Silverlight control itself, as in the following snippet:

Code example. Click link below to donwload actual text.

Download complete code example

All that is required here is that the page clients.php return valid XAML code that can be rendered by Silverlight.

Adding user interaction with JavaScript
The Silverlight plug-in exposes a JavaScript API that allows any XAML element can be manipulated by JavaScript, in much the same way that you would program against the HTML Document Object Model (DOM) exposed by the page. Furthermore, Silverlight boasts a wide range of programmable events which opens up many possibilities for user interaction.

For example, in the following we have added an ‘x:Name’ attribute to the TextBlock element. This allows JavaScript to access and manipulate the element using the findName function. We have also attached an event handler stating that the JavaScript function changeText should be executed if the user depresses the left mouse button while the pointer is over the Canvas element:

Code example. Click link below to donwload actual text.

Download complete code example

We can now define the changeText function by adding the following to the page that instantiates the Silverlight object:

Code example. Click link below to donwload actual text.

Download complete code example

This script locates the element we want to manipulate using the findName function, and then sets its Text attribute to change from ‘Hello World!’ to ‘Goodbye!’ when the Canvas is clicked. One important point to note here is that the JavaScript is interpreted by the browser and not by the Silverlight plug-in. The x:Name attribute provides a handle that allows the findName function to reach into Silverlight for objects declared within the XAML code.

You can use these techniques to respond to a wide range of events. The API allows you to respond to simple movements of the mouse, or when the mouse pointer enters or leaves an object. You can respond to the depression of the left mouse button, and when it is released. Most objects respond to key up and key down events as well, and there are facilities for determining the key combination. The TextBox control supports a TextChanged event, while the PasswordBox control supports a PasswordChanged event and the Button control supports a Click event

One of Silverlight’s great strengths is this ability to manipulate anything you declare in your XAML code through a coherent object model. Check out the Silverlight Developer Center in the MSDN Library for a comprehensive reference to the whole API.

Interacting with a PHP Web Service
Most of the techniques discussed so far work with both versions of Silverlight. However Silverlight 2.0 opens up new possibilities for client-side processing as it includes a version of the .NET Framework and the Common Language Runtime (CLR) which allows it to run client-side code written in C#, Visual Basic and many other languages. The code for such programs is compressed into a single ZIP file together with the XAML definition and a manifest (also written in XML). The result is given the file extension XAP and referenced through the plug-in’s source parameter in the same way as we referenced our XAML file in the example above. When the page containing the plug-in is opened by the client, the XAP file is downloaded and unpacked, and then the code is compiled and executed.

This opens up further opportunities for the PHP programmer as such applications can make calls to Web services, and those Web services can be defined in PHP. For such an application to work the service has to be SOAP 1.1 compliant, and you will need to define a clientaccesspolicy.xml file if the service comes from a different domain to the application. This is to prevent cross-site forgery (see the article Making a Service Available Across Domain Boundaries for more on this).

It is also worth noting that Silverlight 2.0 also includes the Dynamic Language Runtime (DLR) which supports IronPython, IronRuby and Managed JScript. These languages are being developed at Microsoft’s open source project hosting site Codeplex. For further details see Silverlight Dynamic Languages SDK.

Choosing the Right Tools
While not a requirement, Microsoft has released a number of tools that would be useful to the PHP developer looking to work with Silverlight. Microsoft Visual Web Developer 2008 Express Edition is a useful Web page designer with full support for CSS, JavaScript and AJAX. It can also be used with Silverlight Tools for Visual Studio 2008 to automate production of much of the infrastructure behind a Silverlight application. Both can be downloaded from the Microsoft Web site free of charge.

Microsoft Expression Blend 2 is a professional graphic design tool that outputs XAML, allowing designers to create attractive user interfaces and to automatically generate the code required by Silverlight for its display. Alternatively increased support from the community means there are a growing number of third party XAML editors out there as well.

Sitting alongside Blend 2 is Microsoft Expression Web 2. Aimed at the professional Web designer, this latest release introducing many features that have been designed specifically for the PHP developer. There are menu options for inserting common PHP snippets, including pre-defined form, URL and session variables, server side includes and other structures. Furthermore, Expression Web 2 will render the page in Design View as though all the code, including server side includes, were in a single file, allowing you to see your code in action without leaving the editor.

Expression Web 2 understands PHP which means it will colour code language constructs intelligently, and there is full support for auto-completion so that you can see what functions and parameters are available to you as you write the code. Expression Web 2 also includes the PHP 5.2.5 runtime which you can use locally as a development server.

So Silverlight has a great deal to offer the PHP developer – something that Microsoft is clearly recognising with its support for PHP in Expression Web 2. Trial versions of Microsoft’s Expression range are available for download.

[Main image by Pathfinder Linden]

Continue reading 49

19 June 2007

In part one we covered the basics of how to get your website internationalised. In this part we're going to take things a stage further and look at some of the real world problems you might encounter when working with other languages.

Plurals

Dealing with plurals is the first challenge when internationalising a website. Let's imagine you're building a blogging engine and want a simple label at the bottom of each post to say how many comments have been posted. You could begin by creating two entries in the PO file; one for 'comment' and one for 'comments', then choosing one based on how many comments there are. The problem with this approach is you are assuming there are only ever two types of plural (which there are in English). This is not always the case with other languages.

Eastern European languages for example quite often have three plural forms, some Asian languages such as Japanese don't even use plural forms. The plural forms section of the gettext manual has the following example of how they work in Polish when describing a number of files (plik):

1 plik
2,3,4 pliki
5-21 pliko'w
22-24 pliki
25-31 pliko'w

As you can see it has 3 different types of plurals (plik, pliki, pliko'w), other issues arise in languages, like Spanish, where other words change depending on plurality, for example:

the red car
el coche rojo

the red cars
los coches rojos

In this case just altering the Spanish word for car (coche) wouldn't be enough since the article and adjective need to be changed as well.

So how do we compensate for this? It turns out gettext already has a way of dealing with this using the function ngettext over gettext in places where we need to use plurals. It works the same as gettext but takes two extra parameters: the first is the sentence in it's plural form and the second is the number relating to the plural, so this might be the number of comments or in this case the number of cars.

Our PHP will look like this:


  //Old singular form
  echo gettext("the red car");

  //New plural form
  echo ngettext("the red car", "the red cars", $numberOfCars);

When we generate our PO file using xgettext it will see that we've used ngettext and generate a place for our translator to type in the singular and plural forms of the whole sentence, like so:


  msgid "the red car"
  msgid_plural "the red cars"
  msgstr[0] "el coche rojo"
  msgstr[1] "los coches rojos"

The number in square brackets indicates the type of plural, so for Polish we would have:


  msgid "file"
  msgid_plural "files"
  msgstr[0] "plik"
  msgstr[1] "pliki"
  msgstr[2] "pliko'w"

But if we wanted to print '42 files' how would gettext know which of the three plurals to pick? We have to tell it through a formula. Somewhere near the top of your PO file (you may need to open it in a plain text editor for this) you need to add something similar to the following to describe your language. In this example we'll just use English:


  "Plural-Forms: nplurals=2; plural=n != 1;n"

So what on earth does that mean? Well nplurals tells gettext how many plurals the language has (English has two), plural then defines the formula where n is the number passed to ngettext via the third parameter. In this case if n == 1 then plural will equal 0 (i.e. not a plural) otherwise it will equal 1 (i.e. use the plural). Thankfully we can reuse this for languages such as German, Spanish, Italian and Dutch. For other languages such as Polish and Czech the formula becomes a bit more complicated:


  Plural-Forms: nplurals=3;
                plural=n==1 ? 0 :
                n>=2 && n<=4 && (n0<10 || n0>=20) ? 1 : 2; //Polish

  Plural-Forms: nplurals=3;
		plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;  //Czech

Fortunately the plurals section of the gettext manual has a list (they start about half way down) of most of the formulas you're ever likely to need, so you can just copy and paste them into your PO file header. This saves much banging of your head against the wall whilst trying to work out terrifying formulas for languages like Russian:


  Plural-Forms: nplurals=3;
		plural=n==1 && n0!=11 ? 0 :
	        n>=2 && n<=4 && (n0<10 || n0>=20) ? 1 : 2;

Yikes!

Dynamic Data

One of the problems mentioned briefly in part one was dynamic data. For example: what if you want to place a user's name into a sentence: “John likes apples”. This could be approached like this:


  echo $name . " " . gettext("likes apples");

What happens when our new language needs to put something in front of the name? For example in Spanish this sentence would be:

A John le gustan las manzanas

An 'a' has been added to the start of the sentence. It's not optional and we need a way to allow our translator to add it. The simplest approach to this is to use something like sprintf e.g.


  echo gettext("%s likes apples");

Our translator can then provide the following translation in the PO file:


  msgid "%s likes apples"
  msgstr "A %s le gustan las manzanas"

Our PHP then becomes:


  echo sprintf(gettext("%s likes apples"), $name);

Sprintf also allows for numbered arguments which means the translator can swap their order if they need to, numbered arguments can look at bit confusing to non-techies so you could write your own version of sprintf that uses a simpler numbered syntax, on Diarised this is exactly what we did which means instead of seeing something like %2\$s, our translators see {2}.

While sprintf is good for situations like the one above it's not so great for links. At present you may need to stick something like this in your PO file:


  msgid 'www.example.com“>click here to visit our home page'

Just as we didn't want to give our translator PHP code we shouldn't be giving it HTML either. While we could break it down and add entries for both 'click here' and 'to go to our home page' this isn't a very good solution since your translator will almost certainly need to see the whole sentence in context in order to produce an accurate translation.

For Diarised we wrote a sprintf style function to look for square brackets and turn the text inside them into links e.g.:


  echo linkprintf("[click here] to visit our home page", "www.example.com“);

This means we can hide HTML from our translator and also keep the urls out of the translation file, so our translator sees:


  msgid '[click here] to visit our home page'
  msgstr '[haz clic aquí] para visitar nuestra página de inicio

Localising other content

As we've seen gettext is great for localising text but what about things like images, videos and audio? For Diarised we needed localised images for our Diary graphic on the home page as well as for some of the buttons. We approached this by writing a function that emulated gettext but would return localised files if available, dropping back to English by default.


  function get_localised_resource($localePath, $normalPath, $filename){
    $locale = $_SESSION[”locale”];    //get the current locale
    $localePath = “locale/$localePath/$filename”;    //path to localised resource
    if(file_exists($localePath)){    //if our localised version exists, return it
      return $localePath;
    }else{
      $normalPath = $normalPath.”/”.$filename;    //if not check for our fallback version
      if(file_exits($normalPath)){    //if it exists, return it
        return $normalPath;
      }else{
	return null;    //otherwise return null
      }
    }
  }

  function get_localised_image($filename){
    return get_localised_resource(”images“, “templates/_img”, $filename);
  }

Here we have a generic localised function that checks for a localised resource and an example of the kind of function you could write to use it. The first parameter we pass (”images”) tells our function which folder our localised content is in, so if our locale is Spanish our path will be locale/es_ES/images/.

Our second parameter is where to look if it can't find the localised version, we keep our regular images in a folder called templates but you'll obviously need to update this for your own projects. This means we can put something like this into our HTML:


  “>

From this point adding — for example — localised video is just a case of creating a new function get_localised_video that just passes different directory names to our main get_localised_resource function. For Diarised we even went as far doing this for our e-mails. Although, since these are text, we could have used gettext it's always neater to keep content like e-mails separate from code and this allowed us to do it.

Automatically setting the locale

A nice touch for a localised website is to try and work out what language the user might want the website to appear in. Although there's no way of knowing for certain we can make an educated guess that will probably get it right for most of your visitors. The way to do this is by checking the language header sent by the user's browser when it requests a page. For example mine looks like this:


  en-gb,en-us;q=0.7,en;q=0.3

This lists the three preferred languages, en-gb (British English), en-us (US English), en (English), the last two are followed by q= and a number indicating the quality value, the higher this value the more the user prefers it. If the figure is missed (such as with en-gb) it uses the default value of 1. Lets look at another example:


  es-es,de;q=0.7,en;q=0.3

This particular user is saying, send me Spanish if you've got it, if not German and if you haven't got that then English, so with this in mind how can we go about sending a page in the user's preferred language if it's available? In PHP you can check the user's preferred language by calling $_SERVER["HTTP_ACCEPT_LANGUAGE“]. From there you can write a function that uses regular expressions to work out the user's preferred language or if you're feeling lazy you can just use the one we wrote for Diarised:


  function get_accept_language(){
    $matches = preg_split("/,[ ]?/", $_SERVER["HTTP_ACCEPT_LANGUAGE“]);
    $results = array();
    foreach($matches as $match){
      if(preg_match(”/;q=(d[.d] )/”, $match, $scoreArr)){
        $score = $scoreArr[1];
      }else{
        $score = 1;
      }
      $results[$score] = str_replace($scoreArr[0], “”, $match);
    }
    krsort($results);
    return $results;
}

This will return the languages codes in an array sorted in the order the users wants, this allows you to search through the array until you find a language you support. It's worth remembering you should only do this as a last resort when you don't know for certain which language your user wants. So if they've chosen to see the website in French don't force it to appear in German just because their browser says is German their preferred language.

Conclusion

That's it. hopefully with the help of these articles you'll be able to start producing your own internationalised websites. We've covered a lot but actually this is just the tip of the iceberg. Other issues include formatting dates, times, numbers, names and telephone numbers. There are also region specific things even between countries that speak the same language for example the US has zip codes while in the UK we have post-codes. I'll leave you to figure out some of this for yourselves!

If you'd like to learn more about this the internationalisation section of the w3c website is a great start. They have lots of useful information on things such as date formats, forms and character sets as well as a nice list of tips that cover most of the issues you might run into. I'd also highly recommend reading The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) from Joel on Software, character encoding issues can be a complete nightmare so it's well worth trying to understand how they work so you can avoid them.

Continue reading 1

Sign Up to our Newsletter

Enter your e-mail address below to receive regular updates on web design, web development and web business. Subscribe today and receive a free 44 page PDF "Designing Web User Interfaces" by Ryan Singer of 37signals.

Subscribe to the Think Vitamin articles RSS feed

HTML5 Online Conference April 12 2010

News

Twitter

Follow us on Twitter

Subscribe

Article Subscribers

Feedburner blog subscriber indicator

News Subscribers

Feedburner blog subscriber indicator

Subscribe by Email

You can receive Think Vitamin updates via email. Just pop your email address in the box below and click the arrows.

Subscribe by RSS

You can also receive new Think Vitamin posts via your RSS feed reader

Subscribe RSS Think Vitamin is a proud member of the Smashing Network

Ads Via The Deck