jQuery To Scroll To A Specific Element

I thought I’d share a useful snippit of jQuery code for scrolling to a specific element on a page.

$('html, body').animate({
    scrollTop: ($('#element').offset().top)
},500);

We use the .animate() method to scroll to the top of #element, over a period of 500 milliseconds.

jQuery To Scroll To The First Element With A Specific Class

A practical use of this could be in validating a form and you want to scroll to the first error for the user to correct. Assuming all elements with problems have been given the class of error, we can scroll to the first one using jQuery’s .first() method before chaining on .offset() and the property top as before.

$('html, body').animate({
    scrollTop: ($('.error').first().offset().top)
},500);

Now, go get scrolling!

Using SQL Server ntext Columns In PHP

I had to connect to a SQL Server database from a PHP script earlier, and I came across an error I wasn’t expecting.

My SQL was working fine, until I tried to select one particular column, it would then give me a 4004 error. Other columns in this table worked fine, so I investigated more.

The error string returned with the 4004 error code was “Unicode data in a Unicode-only collation or ntext data cannot be sent to clients using DB-Library (such as ISQL) or ODBC version 3.7 or earlier.”

Looking at the table definition, the column I was trying to SELECT was of type ntext. This is used to hold UTF-8 data.

By default the driver I had installed for PHP on Ubuntu Linux using

apt-get install php5-sybase

couldn’t understand this UTF-8 data. The solution is to edit the conf file used by freetds, which is the code used to talk to the SQL Server database by the PDO DBLib library.

So, in /etc/freedts/freetds.conf I added these settings

[global]
tds version = 8.0
client charset = UTF-8

After adding those settings, I was successfully able to SELECT the ntext column from the SQL Server database.

Adding A Trailing Slash To A Zend Framework URL

“We need all our URL’s to have a trailing slash”, was a request I had in recently.

This sounds easy enough, a quick rewrite rule will do the trick, and that is what I added.

RewriteRule ^(.*[^/])$ /$1/ [R=301,L]

I look at the start of the URL, grab every character to the end of the URL, making sure the last one isn’t a slash already, then rewrite that with slashes around it, issuing a 301 redirect and informing Apache not to process any more rules.

This works great for pages already on the server, for example /guestbook becomes /guestbook/. However, what if we wanted to load /logo.gif, this would rewrite to /logo.gif/ and cause a error.

OK, so we need not to match every character in the URL, but only if it doesn’t have a dot in there. The site in question was a Zend Framework application, and this caused it’s own problems.

Zend Framework applications have their own rewriting rules…

RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]

This checks if the requested resource is actually a real object Apache can serve, if not it passes it over to the Zend Framework to handle internally via the index.php script.

So what happens if /guestbook is actually a Zend Framework application?

Well, the URL would be rewritten to /index.php/.

Why? Well the first rewrite we added a slash, this caused the page to re-requested, this then passed to the Zend Framework rewrites, this saw it needed to rewrite to index.php, this caused the page to be re-requested again internally, which added a slash to the end, and redirected again. Finally this request was /index.php/ which doesn’t exist and failed.

Wow, that was a mouthful, let’s look at that as a sequence diagram.

sequence diagram showing apache rewrites and Zend Framework working incorrectly

What we need is to only rewrite the requested URL if it doesn’t have a trailing slash and if it doesn’t have a dot in the request and if it isn’t an internal Apache redirect. We also only want to rewrite if the request is a GET, POSTs (DELETE’s and PUT’s too) don’t support rewriting in the browser.

This indicates a series a conditions that need to be met, so tells me we should be using Apache’s RewriteCond directive.

Let’s check for a GET request first…

RewriteCond %{REQUEST_METHOD} GET [NC]

The %{REQUEST_METHOD} variable in a rewrite rule tells us the HTTP method used to make the request, so we just need to check if that is GET. The [NC] makes the check case insensitive so matches GET, get, Get, etc…

Next we need to see if the request already has a trailing slash.

RewriteCond %{REQUEST_URI} !/$

This checks the requested URI and sees if the last character isn’t a slash.

Now we need to check if there are any dots in the request.

RewriteCond %{REQUEST_URI} !.

This just checks that there isn’t a dot in the requested URI. As dot normally matches any character, we need to escape this with a clash first.

If all these conditions match, we can issue our RewriteRule.

RewriteRule ^.*$ %{REQUEST_URI}/ [R=301,L]

This takes the requested URI, adds a slash and issues a 301 status code to force the browser to re-request the page and change the URL shown in the address bar. We add the L to tell Apache not to process any more rules.

Let’s put this all together, and insert it above the normal Zend Framework rewrites, but after RewriteEngine On.

RewriteCond %{REQUEST_METHOD} GET [NC]
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{REQUEST_URI} !.
RewriteRule ^.*$ %{REQUEST_URI}/ [R=301,L]

Let’s request /guestbook again, and see what happens.

sequence diagram showing apache rewrites and Zend Framework

Handling HTTP And HTTPS Ads With JavaScript

A few days ago I wrote about a problem I had with some javascript ad code defering execution. Well another problem arose today with the code, and I thought I’d share the solution.

Some pages on the site I’m developing on are served over https, others are served over http. They share a common template so the same ad code is served across all pages. At the moment they serve purely over http, and this is great most of the time, however when the page is served over https a security alert is shown asking the user if they want to show unsecure content. Most users would say no in this situation so our ads won’t be shown.

What we need is a way for ads to be shown if a user is on a secure or normal connection.

Thankfully our ad provider allows us to request the same ad in either http or https by just changing the protocol, e.g. http://ad... or https://ad... .

The ad is written out using a document.write statement and is meant to be executed as the page is rendering.

We need to detect how the current page is being served, so we know what protocol to request the ad in.

This is easy in JavaScript, we can just query the value document.location.protocol. This returns either ‘http:’ or ‘https:’. Note the trailing colon…

We can use the value document.location.protocol directly, but just incase another protocol has been used, we can default everything to http if https hasn’t been used. The following code will help here…


var protocol = 'https:' == document.location.protocol ? 'https' : 'http';

Here we are seeing if document.location.protocol is the value ‘https:’, if it is set the value of protocol to ‘https’, else set it to ‘http’.

Let’s look at the original ad code…


<script type="text/javascript">
<!--
if (window.adgroupid == undefined) {
window.adgroupid = Math.round(Math.random() * 1000);
}
document.write('>scr'+'ipt language="javascript1.1" src="http://adserver.adtech.de/addyn|3.0|311.0|3328078|0|225|ADTECH;cookie=info;alias=FindClassicCars+Maserati+7+leaderboard;loc=100;target=_blank;key=key1+key2+key3+key4;grp='+window.adgroupid+';misc='+new Date().getTime()+'"></scri'+'pt>');
//-->
</script>

We can take our earlier ternary expression to embed the protocol directly into the ad code like this.


<script type="text/javascript">
<!--
if (window.adgroupid == undefined) {
window.adgroupid = Math.round(Math.random() * 1000);
}
document.write('>scr'+'ipt language="javascript1.1" src="'+( 'https:'==document.location.protocol?'https':'http') +'://adserver.adtech.de/addyn|3.0|311.0|3328078|0|225|ADTECH;cookie=info;alias=FindClassicCars+Maserati+7+leaderboard;loc=100;target=_blank;key=key1+key2+key3+key4;grp='+window.adgroupid+';misc='+new Date().getTime()+'"></scri'+'pt>');
//-->
</script>

The ad code will now serve ads to our customers if they are on either a normal or secure page, and our ad team is happy again.

Defering Inline JavaScript Problems

I came across an interesting problem trying to debug a website that had issues with some ad code earlier. The site was working fine until ad code had been added, then in Internet Explorer it was only showing the ad instead of the page. Firefox, Safari and Chrome were fine, so it suggested a problem with the ad code.

The ad code in question was pretty common, the sort that inserts a script tag via a document.write.

<script language="javascript" defer="defer" async >
<!--
if (window.adgroupid == undefined) {
window.adgroupid = Math.round(Math.random() * 1000);
}
document.write('>scr'+'ipt language="javascript1.1" src="http://adserver.adtech.de/addyn|3.0|311.0|3328078|0|225|ADTECH;cookie=info;alias=FindClassicCars+Maserati+7+leaderboard;loc=100;target=_blank;key=key1+key2+key3+key4;grp='+window.adgroupid+';misc='+new Date().getTime()+'"></scri'+'pt>');
//-->
</script>

The problem turned out to be with the attribute defer in the script tag.

Defer gives the browser a clue that a piece of JavaScript can be run later, rather than as soon as the browser sees it. This can be used to speed up the rendering of a site. However, Internet Explorer runs differently to other browsers. As the script in question was inline, all the other browsers ran it immediately, whereas Internet Explorer didn’t. On Internet Explorer the code was run once the page DOM had been created, so writing out the fresh tags after the document was closed. This caused the ads to show on what looked like a new page on IE’s below version 9, and on IE 9 the ads appeared at the bottom of the page.

The fix is to simply remove the defer attribute and change the the opening script tag to the following, leaving the rest of the ad tag in place.

<script type="text/javascript">

You may have noticed I’ve ignored the async attribute that was in the original script tag. That’s an interesting new attribute in HTML5, but alas a topic for another time.

Using CSS3 On Internet Explorer With PIE

Until a few hours ago some parts of this website used boring old images as buttons, however I’ve now started to bring this website into 2011 and swap them out for something far cooler and semantically better. These are now links styled up with CSS3.

The buttons had rounded corners and a drop shadow, easy to create using tools like Adobe’s Photoshop, but a pain to do before CSS3. With CSS3, we can use the following to add the curved border and drop shadow.

-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
-webkit-box-shadow: rgba(0,0,0, .5) 3px 3px 6px;
-moz-box-shadow: rgba(0,0,0, .5) 3px 3px 6px;
box-shadow: rgba(0,0,0, .5) 3px 3px 6px;

OK, we’ve had to use a few custom extensions for Mozilla and Webkit based browsers, but it works. However, as always, Microsoft’s Internet Explorer doesn’t want to play nicely and isn’t able to support these features. There are a few work arounds, but at present the best seems to be PIE – Progressive Internet Explorer.

PIE makes Internet Explorer 6-8 capable of rendering several of the most useful CSS3 decoration features. At present it has full or partial support for border-radius, box-shadow, border-image, multiple background images and linear gradient background images.

It’s easy to add PIE as an HTML Component (HTC), you just need to reference it in your CSS.

behaviour: url(PIE.htc);

As if by magic, those CSS3 features will start working in Internet Explorer.

You will need to download PIE and host it somewhere. You will also need to make sure that your web server is setup to serve HTC files with the content-type header of “text/x-component”. If you use Apache, you can use the following line in your config, or in a .htaccess file.

AddType text/x-component .htc

Access The Bootstrap From A Zend Framework Action Controller

When working with the Zend Framework you often need access to the Bootstrap to fetch resources. The classic way to get the bootstrap in most of the examples for the Zend Framework is like this…

$bootstrap = $this->getBootstrap();

However, this method is not globally available, so from an action controller for example, that method would fail. There is an alternative way to get access to the Bootstrap.

$bootstrap = $this->getInvokeArg('bootstrap');

This works because Zend_Application_Bootstrap_Bootstrap registers itself as the front controller parameter bootstrap, which lets us access it from the router, dispatcher, plugins and action controllers.

So, if I had a twig resource I wanted to access from an action controller, I could use the following code…

$bootstrap = $this->getInvokeArg('bootstrap');
$twig = $bootstrap->getResource('twig');

or by chaining accessors, I could reduce this to one line…

$twig = $this->getInvokeArg('bootstrap')->getResource('twig');

For more information, read Zend Framework’s Theory of Operation.

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.