Detecting Retina Displays From JavaScript And CSS

I was looking at how to target Apple’s retina display for high resolution web pages earlier.

My first attempt was to look at the user agent string, but an up to date iPhone 4 sends the same string as an up to date iPhone 3GS.

A quick look around the internet reveals the solution for JavaScript is to actually use the window.devicePixelRatio property.

For a standard browser, this will be 1. However, on a retina display it will 2 – meaning twice the pixels.

For example…

if (window.devicePixelRatio >= 2) {
// retina display
} else {
// standard display
}

You can check your current devicePixelRatio using the following…

<script type="text/javascript">
document.write("Your browser has a devicePixelRatio of " + window.devicePixelRatio + "");
</script>

Apple aren’t the only ones using this in their webkit based browsers, you can read how to target device pixel density on Android. Android defines a density of 1 to be medium density, anything 1.5 or above as high density and anything under 0.75 to be low density.

On the client side we can use this to decide if we want to bring in retina quality imags, or standard ones. There is a jQuery plugin called Retina that does this.

If want to to pass display information back to the server to decide what images to render, this is a bit more complicated.

The best way to approach this would be to have a JavaScript set a cookie containing the devicePixelRadio and have the server read this back. A quick Google reveals that Ben Doran is doing just this, Detecting the iPhone4 and Resolution with Javascript or PHP.

Here’s Ben’s example code (slightly tweaked)…

<?php
if( isset($_COOKIE["pixel_ratio"]) ){
$pixel_ratio = $_COOKIE["pixel_ratio"];
if( $pixel_ratio >= 2 ){
echo "Is HiRes Device";
}else{
echo "Is NormalRes Device";
}
}else{
?>
<script type="text/javascript">
writeCookie();
function writeCookie()
{
the_cookie = document.cookie;
if( the_cookie ){
if( window.devicePixelRatio >= 2 ){
the_cookie = "pixel_ratio="+window.devicePixelRatio+";"+the_cookie;
document.cookie = the_cookie;
location = '<?=$_SERVER['PHP_SELF']?>';
}
}
}
</script>
<?php

A different approach could be to use CSS and media types. Webkit browsers like Safari on an iPhone have -webkit-min-device-pixel-ratio, Gecko browsers like Firefox have -moz-device-pixel-ratio.

An example using this approach on webkit could be

<link
rel="stylesheet"
type="text/css"
href="/css/retina.css"
media="only screen and (-webkit-min-device-pixel-ratio: 2)"
/>

Writing A Daytime Server In Node.js

I’ve previously written about using node.js as a simple UDP listener, now I thought I’d expand on this and give an example of a node.js application that works as both a UDP and TCP server.

A simple service that offers both UDP and TCP connections would be the Daytime Protocol, as defined in RFC 867. It listens to port 13 for both TCP and UDP connections, and returns the current date and time. Your local computer may well have this function enabled, to test the TCP version, you can simply telnet to port 13 and see what is returned.

telnet localhost 13

If you find you don’t have a local Daytime service running, try calling the one at time.ien.it, you should see something like this…

$ telnet time.ien.it 13
Trying 193.204.114.105...
Connected to ntp.ien.it.
Escape character is '^]'.
12 APR 2011 18:51:11 CEST
Connection closed by foreign host.

As you can see it simply returns the date and time before closing the connection.

We could write something like this very easily in node.js. In this case we’ll return the date in JavaScript’s UTC string format instead to keep it simple.

var net = require('net');
var port = 1300;
var now = function() {
  var date = new Date();
  return new Buffer(date.toUTCString() + "rn");
};
var tcpserver = net.createServer(function(c) {
  c.write(now());
  c.end();
});
tcpserver.listen(port);

We can test this by telneting to localhost on port 13

$ telnet localhost 1300
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Tue, 12 Apr 2011 17:17:55 GMT
Connection closed by foreign host.

Let’s take a quick detour into what the code is doing if you’ve not used node.js for any network programming before.

We require('net') so we can use node.js’s network socket support.

The now() function simply returns a Buffer with the current UTC date and time string in. A Buffer in node.js refers to the raw memory used behind the data, in this case our string with the date and time in.

Finally, we create the server, and add a callback function that is called when something connects to the socket. In this case we’re just writing out the contents of the now() function and ending the connection. Last but not least, we tell the socket which port to listen on.

We can see that this code works, but the Daytime protocol also offers a UDP service on the same port that can return the date and time string to a client.

Let’s add in some code to support this. We’ll assume our now() function and port variable are available already.

var dgram = require('dgram');
var udpserver = dgram.createSocket("udp4", function(msg, rinfo) {
  var daytime = now();
  udpserver.send(daytime, 0, daytime.length, rinfo.port, rinfo.address);
});
udpserver.bind(port);

So what is going on here? Well like the TCP code, we have to require('dgram'); to have access to node.js’s UDP support.

Next we create the socket and create a callback function that returns the date and time string back to the IP address and port of the calling computer. Finally we bind this to the port so we start listening for messages.

It’s harder to test a UDP server as we can’t telnet in, we will have to write a simple UDP client to send a blank message to the server and print out any replies to the console.

var dgram = require('dgram');
var message = new Buffer(" ");
var server_ip = '127.0.0.1';
var server_port = 43278;
var client = dgram.createSocket("udp4");
client.on('message', function (msg) {
  console.log(msg.toString());
  client.close();
});
client.send(message, 0, message.length, server_port, server_ip);

When you run this client on the same machine as your server you should get back the current date and time.

Here’s the final code for our Daytime server.

var net = require('net');
var dgram = require('dgram');
var port = 1300;
var now = function() {
  var date = new Date();
  return new Buffer(date.toUTCString() + "rn");
}
var tcpserver = net.createServer(function(c) {
  c.write(now());
  c.end();
});
tcpserver.listen(port);
var udpserver = dgram.createSocket("udp4", function(msg, rinfo) {
  var daytime = now();
  udpserver.send(daytime, 0, daytime.length, rinfo.port, rinfo.address);
});
udpserver.bind(port);

Using PHP To Send A UDP Message

Previously I’ve written about sending UDP datagrams using Perl and JavaScript with node.js.

As I’ve been using a lot of PHP recently, I thought I’d show how to send data over UDP using PHP.

If you’ve not come across UDP before, it’s a simple protocol for sending messages over the internet that aren’t guaranteed to arrive. You just fire them off and hope they arrive.

The previous examples showed sending a simple heartbeat message, a string simply saying “PyHB”, to a server listening on port 43278. I’ll do the same in this example.

Firstly we’ll setup a few variables saying where we’ll be sending the the message to, along with how often we want to send the message and what it should say.

$server_ip = '127.0.0.1';
$server_port = 43278;
$beat_period = 5;
$message = 'PyHB';

Now we have to create the socket, using the socket_create function. We need the domain to be of type AF_INET as we are using an IP4 address for our server, the type needs to be SOCK_DGRAM and the protocol needs to be SOL_UDPas we’re sending a UDP datagram.

$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP))

It’s time to send the message now, and to do this we can use PHP’s socket_sendto function. This function takes the parameters of the socket to send the message over, the message itself, the length of the message, some flags, the destination address of the message and the port to send it to. We’re not setting any flags so we can just set this field to 0. The following code will do the trick.

socket_sendto($socket, $message, strlen($message), 0, $server_ip, $server_port);

Let’s wrap this up in a loop that sends the message every $beat_period seconds.

<php
$server_ip   = '127.0.0.1';
$server_port = 43278;
$beat_period = 5;
$message     = 'PyHB';
print "Sending heartbeat to IP $server_ip, port $server_portn";
print "press Ctrl-C to stopn";
if ($socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) {
  while (1) {
    socket_sendto($socket, $message, strlen($message), 0, $server_ip, $server_port);
    print "Time: " . date("%r") . "n";
    sleep($beat_period);
  }
} else {
  print("can't create socketn");
}
?>

This code is run on the command line, and not via a web server.

Writing A UDP Server Using Node.js

Previously, I’ve written about using node.js to send a heartbeat to a python server using a UDP datagram.

Of course you may not want to run Python if you using node.js so I thought I’d give you a quick run through on writing a UDP server using node.js.

The earlier heartbeat example sent a small message saying “PyHB” to a server listening on port 43278. This example will listen out for that message and show it on the console to prove it’s working.

The first thing we need to do is to require("dgram") to allow us access to the dgram library.

var dgram = require("dgram");

We now need to create a datagram socket to listen on, as we’re going to listen out for an IP4 datagram we create this of type udp4.

var server = dgram.createSocket("udp4");

Node.js lets us bind to events, and dgram gives us three, message, listening and close.

To listen for an event, we need to use the listening event. As with other JavaScript events, we can pass in a callback function to actually do something when the event is fired. In this case, we’ll just use display the incoming message on the console, along with some details of the server that sent it.

server.on("message", function (msg, rinfo) {
  console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port);
});

It’s also useful to know we’ve actually setup our socket correctly, so we can use the listening event to return a message to console that everything has been setup OK and is working.

server.on("listening", function () {
  var address = server.address();
  console.log("server listening " + address.address + ":" + address.port);
});

Finally we need to actually bind our socket to a port so it can start listening for messages. For this we have to use the bind method.

server.bind(43278);

Putting this all together we have the following code that can listen for UDP datagrams and show them on the console.

var dgram = require("dgram");
var server = dgram.createSocket("udp4");
server.on("message", function (msg, rinfo) {
  console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port);
});
server.on("listening", function () {
  var address = server.address();
  console.log("server listening " + address.address + ":" + address.port);
});
server.bind(43278);

I hope this has been a useful quick introduction to writing a UDP server in node.js.

Using Node.js To Send A Heartbeat To A Python Server

I’ve been looking back at some old code and I found an old piece on using Perl to send a heartbeat to a Python server.

Recently I’ve been using the excellent node.js to do some cool JavaScript on the server side instead of in a client on a web broswer. I thought it would be fun to covert this simple script over to JavaScript.

This example is based on recipe 13.11 in the Python Cookbook.

The script needs to send a UDP datagram to a server listening on port 43278. In this example the server will be listening on localhost, 127.0.0.1.

As with the Perl script, we’ll set a few “constants” to let us change things easily if we want to. As JavaScript doesn’t have constants in this example we’ll just use variables. Firstly we nee to require “dgram” so we can use UDP datagrams. We’ll set the server ip address, the port to use, the time in seconds to send the heartbeat, a debug flag if we want to see a message on the console everytime we send a message, and the message itself “PyHB”.

var dgram = require('dgram');
var message = new Buffer("PyHB");
var server_ip = '127.0.0.1';
var server_port = 43278;
var beat_period = 5;
var debug = 1;

We’ll need to send out our heartbeat every beat_period seconds. To do this we can use JavaScript’s setInterval function to execute code every X milliseconds. As we’ve defined our beat_period in seconds, we’ll need to mulitply this value by 1000 to get the time in milliseconds.

setInterval(function() {
// datagram code goes here.
}, beat_period * 1000);

The code to send the datagram is really simple, 3 lines infact. We create a client socket, send the message then close the client socket.

var client = dgram.createSocket("udp4");
client.send(message, 0, message.length, server_port, server_ip);
client.close();

Putting this together, along with a bit of debugging information, we get the following code.

var dgram = require('dgram');
var message = new Buffer("PyHB");
var server_ip = '127.0.0.1';
var server_port = 43278;
var beat_period = 5;
var debug = 1;
console.log("Sending heartbeat to IP " + server_ip + " , port " + server_port);
console.log("press Ctrl-C to stop");
setInterval(function() {
var client = dgram.createSocket("udp4");
client.send(message, 0, message.length, server_port, server_ip);
client.close();
if (debug)
console.log("Time: " + new Date());
}, beat_period * 1000);

I hope that was a useful introduction to sending messages using UDP in Node.js.

Faking A Fixed Background In An iOS Web App

If the lack of a fixed background image position has been bugging you when your building your HTML / CSS based iOS apps, then I thought I’d share a work around I’ve been using.

If you are creating a native app from this in XCode then you would almost certainly be embedding the web page in a UIWebView. This is where the magic works.

Create a UIImageView with your background image on, then place your UIWebView directly over this image.

In your Objective-C you need to set the UIWebView‘s background colour to clearColor and make the UIWebView opaque. If your UIWebView is called webView the following two lines of Objective-C will do this.

[webView setBackgroundColor:[UIColor clearColor]];
[webView setOpaque:NO];

Your background image should now show through the webpage and be visible as the background.

iPhone Time Bug

I seem to have fallen victim of the iPhone daylight saving time bug that has affected owners in the southern hemisphere.

Today, my recurring alarms woke me an hour early.

The time at the top of the phone is an hour ahead of the time shown in the clock app.

It would seem the iPhone has forgotten the UK is still in British Summer Time for a few more days.

Very annoying!

MooTools 1.2 Beginners Guide Book Review

MooTools 1.2 Beginners Guide from Packt Publishing
After a year of using jQuery, I have an upcoming project that requires me to go back to MooTools. A lot of my MooTools knowledge was rather rusty, but a couple of weeks ago the nice people at Packt published a new book called MooTools 1.2 Beginner’s Guide and I managed to get my hands on a copy.

MooTools 1.2 Beginner’s Guide by Jacob Gube and Garrick Cheung promises readers they will “learn how to create dynamic, interactive, and responsive cross-browser web application using one of the most popular JavaScript frameworks”, and it certainly does that.

The book is very clearly written, with plenty of step by step examples. You’ll need a basic understanding of HTML, CSS and JavaScript but not much more.

The book starts out explaining what MooTools is, how to go about downloading it and then using it on a web page. It clearly explains the difference in using normal JavaScript code and MooTools code, before moving on to DOM selectors and other key utilities in the MooTools library. In addition to this, there are chapters on events, AJAX, animations and plugins.

When the book arrived I expected a very simple book, and I have to admit to having been pleasantly surprised. As well as being an excellent tutorial for beginners, there is actually quite a lot for the more experienced developer and I found myself picking up quite a few new tricks, and clarifying my knowledge in a few places. One area that MooTools has always been weak in comparison to rival frameworks like jQuery has been the quality of the documentation and tutorials for beginners, this book really addresses that area and should be a welcome addition to the library of any MooTools developer.

MooTools 1.2 Beginners Guide Official Website.

Maintaining The Scroll Position On An ASP.NET Page After Postback

I had a requirement today for an ASP.NET page to jump to the same part of the page once a form was submitted via a postback.

Qudos to my fellow developer Andy Howell for leaping in and pointing out that functionality was already in ASP.NET 2.0 and above, so there would be no need for me to write any funky JavaScript.

You need to set MaintainScrollPositionOnPostback to true. I did this in the Page tag on the ASP.NET page.

<%@ Page MaintainScrollPositionOnPostback="true" %>

Although I’ve not tested it yet, you should also be able to set it globally in the web.config file in the pages section.

<pages maintainScrollPositionOnPostBack="true" />

Or programmatically in the code behind.

System.Web.UI.Page.MaintainScrollPositionOnPostBack = true;

For more information on this, see the MSDN page for System.Web.UI.Page.MaintainScrollPositionOnPostBack.