Losing face with IE8

I’ve discovered a bug in IE8.

If you are using @font-face for your main site, and for your iframe, then you may find that the font-face is removed and replaced with arial or helvetica when the iframe is removed from the page. This is a common effect of modal iframe lightbox systems, like shadowbox or thickbox.

My assumption is that the iframe is ‘stealing’ the font-face EOT file, and killing references to it when the iframe is removed. This affects the main page.

In tests, I’ve found that this effect depends on both the cache and the element with focus when the iframe is removed. This dependance (especially on the cache) makes this effect quite hard to reliably reproduce.

Interestingly, the effect does not cause a repaint of the page. You need to scroll or move a window over the top to cause a repaint, revealing the unstyled text. Note also that it is the font rendering that has changed, but not the letter positioning – causing our ‘unstyled’ font to look even worse than plain text.

As promised, a demo:
You’ll need IE8. You want this page to be cached (try refresh, but not ctrl-refresh, with cache status as automatic). Note that the ‘kill frame’ link below does not return false.

This text is styled


Click this link to kill the iframe.
Now resize the window to try and trigger a repaint.
(This effect is quite unreliable, so you may need to refresh and kill a few times to see it happen. If you just can’t Click here for a screenshot)

My workaround solution is to reload the main page stylesheet after the box is closed.
Hardly pretty, but it should work. I’ll leave it to the hardcore CSS/JS fraternity to try and reload the font-face lines themselves.

Add an ID to your stylesheet tag:
[code]
<link id=”main-css” rel=”stylesheet” type=”text/css” href=”/css/styles.css” />
[/code]
Then, after your box closes, reload it:
[code]
document.getElementById(‘main-css’).href=document.getElementById(‘main-css’).href;
//or in jQuery
$(‘#main-css’)[0].href=$(‘#main-css’)[0].href;
[/code]

Additional:
Make sure your iframe doctype matches the container. It’s possible that if they don’t match, then only one will show the fonts.

Update:
This is an interesting thread:
http://stackoverflow.com/questions/7768029/ie8-web-font-iframe-bug-workarounds

Man walks down the street

Man walks down the street. Takes him ten minutes every morning.

One day, his watch breaks and starts running fast. It takes twice as long, according to the watch. Completing the same distance took twenty minutes. He buys a new watch.

The following week, some wanker at the council moves his tube station 400 yards further away. According to his new watch, the journey again takes twice as long as usual: twenty minutes. The man blames cheap foreign imports, and buys a new watch.

I have a grid in three dimensions. It’s held together with wires, will balls at the joints. Each wire is 10cm long.

The next day, I measure my grid with a ruler. Each wire is now 20cms long. But none of the balls look any further apart. I buy a new ruler.

I throw away my grid and buy a new one. It’s bigger.

A lot bigger.

My grid has balls one light-year apart. Each ball is held in a rigid cubic system as before. My grid extends to infinity in all six directions: up, down, to the left, to the right, in front, and behind. Infinitely.

I know what you’re thinking: “You must have huge balls”. But I don’t like to brag.

I measure the distance along the wires between the balls, not with a ruler, but with light and a stopwatch. A ball sends out light, and I time exactly one year before the light reaches the next ball. That’s one light-year.

All over the grid, it always takes one year for light to reach the next ball.

The next day, a fine summer’s day in 1665, Newton invents gravity. This does not go unnoticed.

Each one of my balls has a large mass, and so a strong gravitational pull. Each ball attracts every other ball around it, not just the nearest, but all of them. It’s quite a shock to my grid, but my grid still hangs together. I rush out and measure my wires again. To my relief, each wire, measured by pulses of light, is exactly one light-year long.

All is well and good, and my grid holds steady. Of course, it does not collapse in on itself, because it extends infinitely in every direction. As each ball pulls those around it, they are equally pulled away by those more distant. Each ball has an equal pull on its left and its right.

For 250-odd years, my grid hangs together, perfectly happily. Occasionally I step outside to admire my balls (steady), by the light of the moon.

In 1915, some bloke called Einstein completes his General Theory of Relativity. In it, he invents several fundamental principles. Mass-energy equivalence, for example, as shown by the famous equation e=mc^2. Woo.
Something else he does is change gravitational theory. Newton is now proved wrong, for gravity is not a force, it is a distortion of space and time caused by masses.

I have to admit, this funny-looking bloke has me scared. I rush out to check on my beautiful, infinite, gleaming grid and see whether it has been affected. And I find some disturbing results.

Near each of my massive balls (by which I mean, my balls with mass), there are some weird effects happening. Close to the surface of each mass, I find that time is running more slowly.

I dig out my trusty stopwatch and wait for the light. A ball emits light, and the light travels more slowly than usual near the ball. Further from the ball it picks up speed as it moves along the wire away from the ball, but then slows again as it gets near the other ball. In total, my stopwatch shows that two years have passed.

Shit. The bastard’s only gone and ruined my grid. I go back inside to sit down and have a calming cup of tea.

Edwin Hubble catches my attention in 1929. He’s spent ten years looking closely at my grid, and he’s found something more peculiar still. He watches as many balls as he can, from the one ball he’s sat on. He’s been looking at the light beams all over my grid and he’s worked out that my grid is expanding.

I’m incredulous. “Where would it expand to?” I ask, “It’s infinite, FFS.” But the arrogant fool is insistent. Look at the evidence, he says.

The distances, as measured by light, between each ball, are getting further apart. Ipso facto, the grid is getting bigger. I have a quick check, and he’s right. A beam of light now takes 3 years to get from one ball to another.

But if I’m honest, those balls look a bit smaller. They’ve taken some of the mass that was hanging between the balls, and they’ve pulled it in. They’ve squeezed themslves together. Effectively, they’ve become bigger and denser masses, I wasn’t expecting that. With tighter, more compact masses, the light travel time is more affected by the gravity, and so it takes longer to get between the balls.

But my grid is still the same size. Or is it?

Did my watch break, or did someone move the tube station?

Long polling Comet

I’ve been working on a long-polling comet client from Amix at Plurk, who uses it to monitor messages on the server. While he simply provides it as a ‘solution’, not detailing the hurdles he overcame to get there, it’s clear that there’s some thought gone into it.
http://amix.dk/blog/post/19489#Comet-long-polling-for-all-browsers-using-ScriptCommunicator

The script requires you to set a variable in your jsonp response. The script checks whether that variable is true after the jsonp loads. If true, your json has loaded. If not, something has gone wrong.

So, if your jsonp looks like this:
callback({blah:”blah”});
You’ll need to revise it to this:
callback({blah:”blah”});ScriptCommunicator.callback_called = true;

On the jQuery forums, John Resig said he isn’t enamoured with this approach since it means adapting the jsonp response, and if you’re using jsonp then you’re probably not in control of the feed. It’s a fair point, but you could simply add the callback_called variable into the callback function instead.

Plus, if you’re running Comet long-polling, it’s better to use a different domain for your comet feed, to prevent tying up threads in the browser. So jsonp is needed.

The “difficult” part of the process is knowing when to run the second script, that checks the callback_called value. Amix uses a variety of methods for different browsers to achieve this.

In Firefox (default case) -> create two script tags using document.createElement, and attach them to the body.

In IE -> use the onreadystatechange event to call onSuccess, and then detect errors there, based on the readyState (somewhat illogical).

In Safari/Chrome -> write two script tags out with document.writeln. Presumably, this is intended for use with an iframe, though that’s not clear. OOTB, no webkit browsers receive data.

Having tried to hack the script to make the Safari browsers use the same method as Firefox, I’ve found that Safari’s caching kicked in and failed to load new scripts from the server (though this could be my fault for not changing the script name each time).

Looking back at Plurk, the comet scripts are indeed in an iframe, so I think this script probably needs some more input before it’s going to work for anyone else. Hopefully, Amix (or someone) will put together a demo page and make any necessary fixes to the script when making that work.

It’s a very useful function/tool/script. Thanks Amix.