Internet Explorer / IE ignoring certain CSS when printing

Is Internet Explorer 7 or 8 ignoring (some) CSS rules when printing or generating a print preview (but the page displays fine in the browser)? Are you using HTML5 by any chance? Are the rules being ignored those that use the new HTML5 tags in their selectors? Congratulations, you've found another bug in IE 7 & 8 (it looks to of been fixed in IE 9).

Yes, even if you've used the document.createElement('tagname'); JS fix to allow you to apply styles to the new HTML5 tags in IE, this is a different issue - which specifically affects printing or generating a print preview.

So, to fixes. There is the IE Print Protector for printing HTML5 pages in Internet Explorer (pre v9). This JS library replaces the new HTML5 tags with existing tags (such as divs) when the page is printed and applies the same styles to them.

This isn't the only solution however. The new HTML5 tags do not have to be replaced with other tags - they just have to have the CSS rules (re)applied directly to them through JS. You could hard-code these into a JS file - or you could write some JS which reads the CSS rules and (if their selectors use the new HTML5 tags) applies the same rules directly to the relevant elements.

Here is an example (that uses the Prototype 1.7 JS library) which handles the header, nav and footer tags (but could easily be expanded for other tags):

document.observe('dom:loaded', function() {
if (Prototype.Browser.IE && // oh how I loathe thee..
(navigator.userAgent.match(/MSIE 7/) || navigator.userAgent.match(/MSIE 8/))) {
/* this compensates for IE 7 & 8 not applying the styles of CSS selectors
which use the new HTML5 tags - but only when printing a page! */
var cssSelectorsAndRules = new Array();
for (var i = 0; i < document.styleSheets.length; i++) {
/* this is the IE 'processed' version of the original content (no comments, individually
separated-out selectors (and duplicated 'shared' rules), all rules on a single line for
a selector, etc.) */
var lines = document.styleSheets[i].cssText.split("\n");
var html5TagSelector = '';
var rulesStr = '';
for (var lineNum = 0; lineNum < lines.length; lineNum++) {
if (lines[lineNum].match(/\{/) &&
lines[lineNum].match(/(?:(?:header)|(?:nav)|(?:footer))/)) {
// HTML5 tag selector line
html5TagSelector = lines[lineNum].sub(/\{/, '').strip().toLowerCase();
} else if (!html5TagSelector.empty()) {
if (!lines[lineNum].match(/\}/)) rulesStr = lines[lineNum].strip().toLowerCase();
else { // end of rules for a HTML5 tag selector
cssSelectorsAndRules.push(new Array(html5TagSelector, rulesStr));
html5TagSelector = '';
}
}
}
}
/* because of a bug in Prototype 1.7 in IE 7 we can't rely on CSS selectors which
use the new HTML5 tags, so we add an id attribute to the tags of the same name */
if (navigator.userAgent.match(/MSIE 7/)) {
$$('body')[0].descendants().each(function(element) {
if (element.tagName == 'header') element.writeAttribute('id', 'header');
else if (element.tagName == 'nav') element.writeAttribute('id', 'nav');
else if (element.tagName == 'footer') element.writeAttribute('id', 'footer');
});
}
cssSelectorsAndRules.each(function(cssSelectorAndRules) {
var selector = cssSelectorAndRules[0];
// change to id instead of tag selector to match the altered markup
if (navigator.userAgent.match(/MSIE 7/)) {
selector = selector.replace(/((?:header)|(?:nav)|(?:footer))/, '#$1');
}
$$(selector).each(function(element) {
var styles = {};
var rulesArray = cssSelectorAndRules[1].split(';'); // index 1 is the rules
rulesArray.each(function(ruleStr) {
var ruleParts = ruleStr.split(':');
styles[ruleParts[0].strip().camelize()] = ruleParts[1].strip();
});
element.setStyle(styles);
});
});
}
});

Unfortunately, due to a bug in Prototype 1.7 in IE 7 (due to be fixed in v1.7.0.1 apparently), we have to employ an additional measure for IE 7 - adding an id to the HTML5 tags, that we then use to apply the CSS rules. In this example, it adds an id of "header" to the header tag, an id of "nav" to the nav tag, and so forth. Obviously this is not ideal and may potentially conflict - so this may need to be tweaked, depending on your setup. Prototype 1.7.0.1 doesn't seem to have an official release date has yet ("soon-ish" was mention back in July). Alternatively, if you're using a locally hosted copy of the Prototype 1.7 library, you can try patching your local version with this proposed fix.

Tagged , , and .

Using cURL to retrieve multiple URLs from a text file

curl -K params.txt

params.txt contents:

url = http://tomholland.me.uk/about
url = http://tomholland.me.uk/publications
output = file1.html
output = file2.html

Will create files named:

file1.html
file2.html

curl -K params.txt

params.txt contents:

url = http://tomholland.me.uk/{about}
url = http://tomholland.me.uk/{publications}
output = #1.html
output = #1.html

Will create files named:

about.html
publications.html

Update:

An alternative to the second method:

xargs -n1 curl -o "#1.html" < urls.txt

urls.txt contents:

http://tomholland.me.uk/{about}
http://tomholland.me.uk/{publications}

Will create files named:

about.html
publications.html

If you're running Tiger (Mac OS 10.4) or Leopard (Mac OS 10.5) then curl and xargs are there by default (I'm unsure about Jaguar or Panther).

Tagged , and .

Codebase updates

Ben has recently published some code for routing requests to the correct controllers and views in a PHP MVC framework, so I've spent some of my weekend integrating it into my codebase (yep, this is the sort of thing I do on weekends).

Mapping URLs to site functionality has always seemed quite clumsy in my projects to date; Ben's solution has quite a Rails feel to it and is definitely the most elegant method I have encountered to date.

Tagged , , and .

Dropping support for IE 6

Regarding phasing out support for IE 6 across all 37signals products.

When I made the latest set of cosmetic changes to the blog, I decided I would no longer test in IE 6. If you are using Windows then you really should be using Firefox (or if you're one of those people who don't like v3, perhaps Opera). If using Internet Explorer is "using the Internet" to you, then you should accept the default choices you are offered when accessing Windows Update (which will include IE 7).

When I first started working as a Web Developer I was still testing in Netscape Navigator 4 and Internet Explorer 4. IE 5 was painful to support and IE 6 followed in the footsteps of its parent. IE 7 isn't perfect, but at least there are less bugs for developers to deal with.

Now if only the rest of the world would follow suit, then I could stop supporting it when developing sites for others.

Tagged , , and .

How not to build an unsubscribe system

Apparently the concept of a 1-click unsubscribe mechanism is completely lost on those responsible for the Tesco website. Here are the unsubscribe steps required to stop e-mails from the Tesco online store:

Once you have logged in to www.tesco.ie follow these 4 steps to unsubscribe.

  1. Select the "log out/my details" tab from the top menu.
  2. Go to the "Update My Details" section and click on "click here to update your details.
  3. Scroll down to the "Data Protection" section and click on the link "click here to receive information about Tesco products and services".
  4. Check the box after the sentence "I do NOT want to receive offers and information about Tesco products and/or services." Press Submit.

It may take up to five working days to unsubscribe.

Sometimes I worry that I'm pretty thick and that one day I won't be able to find employment. Then I realise that some company is still paying the people who build these systems a wage, despite the utter complete mess they make of it - and I feel a bit more confident that I won't be jobless. I mean someone who built this system must have looked at the above and thought "yea - this is terrible".

Tagged , and .

Uploading files with ActionScript 2.0 & PHP

If you have to write some server side code (such as PHP) to receive a file being uploaded through HTTP POST from ActionScript 2.0 (such as in Flash 8 - here is a good tutorial) - the $_FILES['Filedata'] variable which PHP can access is something defined in the Flash internals - not something a Flash developer sets.

Hopefully this will save some PHP and Flash developers a few hours of headache.

Tagged , , and .

Subversion and Collaboa

Thanks to Geffy, I've been able to start using Subversion to manage my source code - this little blog may not seem like much, but with its MVC structure, is composed of over 50 PHP and JavaScript files.

As part of this, you can now access the source code using the Collaboa tool. Obviously, things such as usernames and passwords have been removed; but the potential for finding logic flaws still remains. I won't pretend I understood everything in the book (Ok - probably about 5%), but a paragraph from Bruce Schneier's Applied Cryptography sticks in my mind:

"If I take a letter, lock it in a safe, hide the safe somewhere in New York, and then tell you to read the letter, that's not security. That's obscurity. On the other hand, if I take a letter and lock it in a safe, and then give you the safe along with the design specifications of the safe and a hundred identical safes with their combinations so that you and the world's best safecrackers can study the locking mechanism--and you still can't open the safe and read the letter, that's security."

Tagged , , , and .

Location tagging blog entries

As some of you may have already noticed, I've added the ability to tag each blog post with a latitude and longitude; on the user front-end you will see a "Blogged from" link, which, when clicked, shows the location of the blog entry in a popup using Google Maps (if you're reading this via a feed, then you'll need to view blog entries on the site to see this). You can also view the location of all blog entries I've made; when clicked, the red markers will tell you the latitude and longitude, the nickname I gave that location (if it's a location I regularly blog from) and the number of posts made from that location.

The coolest bit is actually on the admin front-end, where you use Google Maps and a drag-and-drop marker to select the location you're blogging from. I hope to add location tagging to blog comments too, so you guys will get to use this functionality when you're leaving a comment on a blog entry (and then I'll be able to map a blog entry and where the comments on it came from).

I'm after some feedback on improvments that could be made, ideas on other ways to map the location data, etc. Matt and Geffy have already mentioned a few things (such as making the the "x blog posts made from here" on the "All blog posts" tab link to a page listing all the blog posts from that location). I'm also planning to add the ability to upload a photo for each location, which would appear in the map marker balloon.

Drop me an e-mail, let me know what you think.

Tagged and .

Tim Berners-Lee BCS Lovelace lecture

Tim Berners-Lee gave the British Computer Society's 2007 Lovelace Lecture last night at the Congress Centre, on Great Russell Street in London.

It was free to attend (you just had to book in advance) and it was only about 15 minutes walk from where I work. The lecture content was similar to some of his other lectures I've seen webcasts of, but it was worthwhile going to a lecture in person, even if the majority of the audience weren't quite the young Web coding types I'd expected.

Update:
Lecture slides (Thanks Jean-Gui!)
Lecture on Google Video

Tagged and .

Gravatar vs Pavatar

I'm looking to implement an avatar solution for comments; something more than each user just uploading an image.

A while back Geffy mentioned Gravatar, but there have been some reports of outages and closure to new signups. Pavatar looks like an interesting idea - but I'm not sure if caching the avatars (as per the Pavatar Candidate Recommendaton) limits the flexibility of the idea.

What do you guys think - Gravatars or Pavatars?

Tagged , , , and .

Firefox 1.5 and Atom 1.0 issue

I've found an odd issue when using the "Live Bookmark" feature in Firefox 1.5 to subscribe to Atom 1.0 feeds.

Below are extracts from 2 example feeds (both of which validate against RFC 4287 using feedvalidator); one uses type="html" for each entry title, the other type="xhtml" (and a child div element with xmlns attribute, as required by the RFC):

<entry>
...
<title type="html">entry one</title>
...
</entry>

<entry>
...
<title type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">entry one</div>
</title>
...
</entry>

The latter example (using type="xhtml") is valid and works in Safari - but Firefox 1.5 does not display the entry titles in its "Live Bookmarks" feature. If you remove the child div element, the titles then appear in Firefox - but it invalidates the feed.

Upgrading to Firefox 2 fixes this issue; if you're stuck with 1.5 then RSS 2.0 would be the better feed choice.

Tagged , , , and .

Can you see the difference?

Ok, you might not be able to tell, but I've rewritten most of the core blog code to use OO under PHP 5 - if everything is working correctly, it should appear almost exactly the same client side, with one or two additions.

It might seem kind of fruitless right now, but it makes the site much easier to maintain and more flexible when it comes to adding new features (yes - including the ever delayed comments).

Both the Atom and RSS blog feeds have moved, in preperation for new feeds which the new features will bring, so please update your feed subscriptions (I'll keep the old feed URLs functioning for some time, whilst everyone updates).

Drop me an e-mail if you spot any issues!

I don't want to promise too much, but I'm currently developing more location based features, including some Google maps integration.

Tagged and .

Fixed the missing blogs issue!

I noticed at the weekend that some of my archive blog posts have been going missing - they were still in the database, but the site was reporting them as post not found.

It turns out that becuase the server time was set to UTC, when using PHP's strtotime function to create a timestamp that crossed a BST boundary, it would not take the hour difference into account (meaning the timestamp was exactly 3600 seconds out). I've managed to rectify this by using the date_default_timezone_set function, passing it the string 'Europe/London' and everything seems to be retrieved fine now.

Tagged and .

Playing SSL on Mac OS X

Having had to setup SSL on a Linux hosting server, I decided it would be a good idea to have SSL using a self-signed certificate set up on my Mac for testing purposes.

If you find yourself with the same inkling, take a look at Using mod_ssl on Mac OS X.

Tagged , , and .

RSS 2.0

After much whinging from the likes of Geffy, Matt & Luke, I have added an RSS 2.0 feed to the site. This represents about 75% of my readship. Aren't I a considerate ranter.

Tagged , and .

Most used blog post tags

Blog entries by month

  1. January 2012 (1)
  2. August 2011 (2)
  3. March 2011 (1)
  4. February 2011 (1)
  5. November 2010 (1)
  6. October 2010 (1)
  7. August 2010 (2)
  8. January 2009 (1)
  9. December 2008 (1)
  10. November 2008 (1)
  11. October 2008 (2)
  12. September 2008 (3)