pashanoid has asked for the wisdom of the Perl Monks concerning the following question:

Hello everyone, how do I hack the cgi.pm in order to make it put "conditional comments" between <head>and</head>? Read the doc, no problem with js or any other parameters, but this one seems to be tricky... This is the output I need:

<link rel="stylesheet" type="text/css" href="/styles/invertor.css"> <link rel="stylesheet" type="text/css" href="/styles/ie1.css"> <!--[if lte IE 6]> <link rel="stylesheet" media="all" type="text/css" href="/styles/ie2.c +ss" /> <![endif]-->

I do the first two lines with:

print $q->start_html(-title=>'searc http://invertor.ru', -author=>'@pashanoid', -base=>'true', -meta=>{'keywords'=>'invertor ups search solar wind alternativ +e energy', 'copyright'=>'MicroART'}, -style => [{'src'=>'/styles/invertor.css'}, {'src'=>'/styles/i +e1.css',}], -lang => 'ru-RU', -encoding=>'windows-1251', );

How on Earth do I get CGI.pm to put the

<!--[if lte IE 6]> <link rel="stylesheet" type="text/css" href="/styles/ie2.css" /> <![endif]-->

stuff in the header? I absolutely need this for the dreadfull IE abomination to render my css correctly... Best regards, thank you!

Replies are listed 'Best First'.
Re: IE specific conditional comments in header of CGI.pm
by marto (Cardinal) on Apr 06, 2012 at 07:53 UTC

    I use templates (see HTML::Template, Template::Toolkit) to separate my perl code from my html/CSS/JavaScript, which among other advantages makes it easier to control things such as this.

      well, you're saying that there is no way, right?

        well, you're saying that there is no way, right?

        I think he's saying you have to write it, but its better to switch to templates as early as possible, because the alternative is this

        monkeypatching one of CGI.pm's very complicated html generation subroutines, no test written for test suite

        I suppose it might be more genetic to accept

        { 'src' => '/styles/ie1.css', -wrapp => [ '<!--[if lte IE 6]>', '<![endif]-->' ], },
        but whatever :)
Re: IE specific conditional comments in header of CGI.pm
by dasgar (Priest) on Apr 06, 2012 at 16:10 UTC

    I think that you can probably just use print to create your own customer header section rather than using the header and start_html methods from CGI. For example, something like the following untested code:

    print '<header>'; print '<link rel="stylesheet" type="text/css" href="/styles/invertor.c +ss">'; print '<link rel="stylesheet" type="text/css" href="/styles/ie1.css">. +; print '<!--[if lte IE 6]>'; print '<link rel="stylesheet" media="all" type="text/css"href="/styles +/ie2.css" />'; print '<![endif]-->' print '</header>';

    From a technical standpoint, I believe this will work. From a code writing viewpoint, I can definitely understand why some may not want to do this. In any case, I do believe that this a work around.

    Also, you could take this concept a step further to create a subroutine that takes the parameters (similar to the header and start_html methods of CGI) and returns HTML code that you could print.

Re: IE specific conditional comments in header of CGI.pm
by Don Coyote (Hermit) on Apr 09, 2012 at 13:01 UTC

    pashanoid, importing the :html2 paramater after use CGI: will enable the comment and Link methods to be utilised. Using these you can construct your conditional comments and use the start_html method, for example:

    • Set up your code, Importing the html2 methods. I'm in html4 so I include the no_xhtml flag too.
    use strict; use warnings; use CGI qw/:html2 -noxhtml/;
    • Before the start_html method set up a sub which reproduces the Link method
    sub linkstyle(){ Link { -rel => 'stylesheet', -type => 'text/css', -src => $arebelong.'script/ie2.css', -media => 'all' } };
    • Now within the start_html call the head method with a reference to an array that includes the comment method which includes the call to the relevant sub for the conditional
    print $q->start_html( -head=>[ comment('[if lte IE 6]>'."\n".&linkstyle.'<![endif]') ] );
    • Put them all together and add a few methods so that the ref to an array is a ref to an array (and not a ref to an array holding one item which could be held by a scalar (this is for a conditional after all)) and you can compare a comment and link to a stylesheet with a forged conditional comment
    #! /usr/bin/perl use strict; use warnings; use CGI qw/:html2 -noxhtml/; use CGI::Pretty; my $allyour = "http://localhost/"; my $arebelong = "http://localhost/"; my $normalstyle = "http://localhost/"; my $normalscript = "http://localhost/"; my $q = CGI->new(); print $q->header(-type=>'text/html'); sub linkstyle(){ Link({-rel => 'stylesheet', -type => 'text/css', -src => $arebelong.'to/us/script/ie2.css', -media => 'all' }) }; print $q->start_html( -lang=>'en-GB', -title=>'conditionalcomments or hot css buns', -head=>[ Link({-rel => 'stylesheet', -type => 'text/css', -src => $allyour.'buns/script/ie8.css', -media => 'all' }), comment('exists (conditional comment method) ? find : next'), comment('[if lte IE 6]>'."\n".&linkstyle."\n".'<![endif]'), ], -style=>{-src=> $normalstyle.'style/w3m.css', -media=>'all'}, -script=>{-type=>'text/javascript', -src=> $normalscript.'script/nom/nom.js'} ); print $q->h1('HelloWorld!!'), $q->end_html; exit 0;

    This returns the various link elements to stylesheets as required.

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="en-GB"><head><title>conditionalcomments or hot css buns</t +itle> <link type="text/css" media="all" src="http://localhost/buns/script/ie +8.css" rel="stylesheet"> <!-- exists (conditional comment method) ? find : next --> <!-- [if lte IE 6]> <link type="text/css" media="all" src="http://localhost/to/us/script/i +e2.css" rel="stylesheet"> <![endif] --> <link rel="stylesheet" type="text/css" href="http://localhost/style/w3 +m.css"media="all"> <script src="http://localhost/script/nomnom.js" type="text/javascript" +></script> </head> <body> <h1> HelloWorld!! </h1> </body> </html>

    One thing I am not too sure about is whether the 'rel' attribute not being first in order within the link element will make a difference, I have a niggle that it is supposed to be first from somewhere but not sure. However this occurs when the link method is called both straightforwardly within the head method and when called as a return from a sub so probably is ok.

    I would question why you are trying to produce conditional comments from a server cgi script though. As I would expect these are mostly used in shtml. Unless of course you are producing static shtml for future usage. Then though, wouldn't there now be a need to ensure the correct DTD is in use? Would be interesting to know.

    Coyote