Lazy-loading print stylesheets - part II

By crisp on Friday 22 April 2011 03:25 - Comments (5)
Categories: Browsers, Tweakers.net, Views: 11.786

Even though some browsers now defer downloading print stylesheets I thought this still wasn't enough. I was more thinking in line of: why not download the print stylesheet *only* when the user has actually requested a print-out?

Fact is and remains that the likelihood that someone is going to print your page is very slim, so why bother including a print stylesheet up-front? Wouldn't it be better to include the print stylesheet *only* when a user requests a print-out?

Then I started thinking about the options to detect just that, and I recalled the onbeforeprint event that IE issues right before a page gets printed. Now this event seems very usefull for the purpose of loading a print-stylesheet right before printing, so I started experimenting with that.

Basically I needed 2 things: a means to detect wether the browser supports the 'onbeforeprint' event, and secondly a means to load the print stylesheet synchronously during that event.

Now the first was easy; a simple if('onbeforeprint' in window) is sufficient. The second one was also quite easy: Ajax supports synchronous calls as well (even though it is not recommended, but we do already use it in some places).

So, reducing the need to download the print stylesheet up-front boils down to something like this:

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
function loadPrintStyle(cssFile)
{
    if ('onbeforeprint' in window)
    {
        window.onbeforeprint = function()
        {
            loadCSS(cssFile, 'print', true);
        }
    }
    else
    {
        loadCSS(cssFile, 'print');
    }
}

function loadCSS(fileName, media, sync)
{
    if (!loadCSS.loaded)
        loadCSS.loaded = {};

    if (!(fileName in loadCSS.loaded))
    {
        loadCSS.loaded[fileName] = true;

        // check if not already loaded fixed in head
        var links = document.getElementsByTagName('link'), i = links.length, style;
        while (i--)
        {
            if (links[i].href.indexOf(fileName) > -1)
                return false;
        }

        if (sync)
        {
            style = Ajax().sendRequest(
                getXmlHttpUrl('frontpage', 'stylesheet') + '&file=' + encodeURIComponent(fileName),
                {
                    method: 'GET',
                    type: 'text',
                    async: false
                }
            );

            return style && createStylesheet(fileName, style, media);
        }

        style = document.createElement('link');
        style.type = 'text/css';
        style.rel = 'stylesheet';
        style.media = media || 'screen,handheld,projection';
        style.href = fileName.indexOf('http://') != 0 ? ImgURL + 'x/' + (window.debug ? '' : 'min/') + fileName : fileName;
        getHead().appendChild(style);

        return style;
    }

    return false;
}

function createStylesheet(label, style, media, overwrite)
{
    var el, txt;

    if (!createStylesheet.elements)
        createStylesheet.elements = {};

    if ((el = createStylesheet.elements[label]))
    {
        if (!overwrite)
            return el;
    }
    else
    {
        el = document.createElement('style');
        el.type = 'text/css';
        el.media = media || 'screen,handheld,projection';
        getHead().appendChild(el);
        createStylesheet.elements[label] = el;
    }

    if (el.styleSheet)
    {
        el.styleSheet.cssText = style;
    }
    else
    {
        txt = document.createTextNode(style);
        if (el.firstChild)
            el.replaceChild(txt, el.firstChild);
        else
            el.appendChild(txt);
    }

    return el;
}



Now that seems to be a lot of code, but a lot of it we already had and is re-used in other places.

Basically this means that browsers supporting 'onbeforeprint' won't get the print stylesheet untll requested. At the moment I think that's only Internet Explorer, but hopefully this usecase will make other browsers add support for 'onbeforeprint' as well.

Do note that for non-JS supporting clients you may want to include the link to your print CSS in the <head> wrapped in <noscript>-tags.

Happy lazy-printing :)

Volgende: Adoptie, daar kies je toch zelf voor? 05-'11 Adoptie, daar kies je toch zelf voor?
Volgende: Code Groen! 03-'11 Code Groen!

Comments


By Tweakers user Herko_ter_Horst, Friday 22 April 2011 09:20

I'd rather wait to see more browsers adopt the lazy-loading approach. In the mean time, I wouldn't bother with a MS- and JS-only "solution". Just doesn't seem worth it to me...

By Tweakers user crisp, Friday 22 April 2011 09:39

Herko_ter_Horst wrote on Friday 22 April 2011 @ 09:20:
I'd rather wait to see more browsers adopt the lazy-loading approach. In the mean time, I wouldn't bother with a MS- and JS-only "solution". Just doesn't seem worth it to me...
Lazy-loading still means a useless request in 99,9% of all cases. Think of the trees! ;)

By Tweakers user sebastius, Sunday 24 April 2011 21:07

Would it be possible to see how many printouts are actually made from T.net?

By Tweakers user crisp, Sunday 24 April 2011 21:40

sebastius wrote on Sunday 24 April 2011 @ 21:07:
Would it be possible to see how many printouts are actually made from T.net?
No, not accurately. We could do some logging using the onbeforeprint event in IE, but other browsers don't fire any event when a user wants to print a page from the browser UI. We do log clicks on the print buttons in articles; those are used around 20-30 times per day.

[Comment edited on Sunday 24 April 2011 21:40]


By Tweakers user Jasper Janssen, Saturday 19 November 2011 11:14

Per article, or at all? Either way, it's... not very much.

Could you run an extrapolation from the percentage of IE users, using the assumption that (non-mobile/tablet) browsers have similar numbers of printers? I think that'd lead to an overestimate because there may well be a correlation between using IE and being likely to print stuff out, but I imagine that effect'd be relatively small.

Comments are closed