Monday, October 21, 2013

More Drupal trickery

CMSes are not rocket science but they are complex systems, and learning your way around a new one can be a bit tiresome. So I decided to record a few fixes that took me hours to get right in case anyone else has the same problems. Also I can go back to this page if I forget.

Getting rid of those pesky node titles

If, like me, you like a simplistic home page that is mostly graphical, you don't want a title taking up vertical space and spoiling your carefully crafted design. Urgh! Although some themes seem to allow you to turn off titles, if you don't have that luxury you can still turn them off by setting the link inside the h1 or h2 element to "display: none" in your theme's .css file. I noticed that the exact element enclosing the node titles changes even within the space of a few weeks, so be careful. On my localhost installation the following worked:

.title { display:none }

But on the server a slightly different Drupal version or configuration forced me to change this to:

h2 a { display:none }

And even that is a bit dodgy, since it hides all links inside h2 elements. But refine it if you will. I used the 'Inspector' in Firefox Dev tools to find out what display properties the element in question had, then I looked for those properties in the theme's .css files, and if they weren't there I wrote a new rule. Easy stuff, but it's satisfying to get it working.

Just the story title appearing, not the content

This trivial problem had me going for a couple of hours. All it was was the 'teaser only' setting in Structure->Content Types->Appearance->ManageDisplay->Custom Display Setttings. Wow, they really bury this stuff in the bowels. I just set it to "Full content" and I got my content back on the home page. Whew!

Drupal on Postgres

I decided to use Postgres because someone else was already using Mysql on the server and I didn't want to be accused of screwing up their database. Also, I didn't know the Mysql password :-). Half the advice on this topic is just rubbish. People suggest tinkering with things that Drupal does for you automatically. Like adding a $db_url line to settings.php. What utter rubbish -- the installer does that for you. All you have to do is ensure that you have pdo_pgsql and pgsql installed. (You can check this by putting a file containing just "<?php phpinfo();" and then accessing it over the Web, to get the server configuration. You should have two sections with exactly those titles). Once everything is installed correctly Postgres comes up as a database option when you install. Easy-peasy.

Tooltips that are not painfully slow

If you use image-maps and areas to highlight portions of an image it is nice to tell the users what's in store if they click on that link. You can add a tooltip using the title attribute on <area> but all the browsers display it only after about 3 dreary seconds, by which time the user's mouse has moved on. No doubt that prevents irritating little popups as the mouse skims over the page looking for something, but in this case it is just plain annoying. So a custom tooltip is called for. I found plenty of advice and implementations on the Web but only a few that worked with <area>s. In the end, not wanting to download a monstrous library that didn't work the way I wanted I just concocted my own. (I should have done that in the first place).

You start with a simple definition of a tooltip. If you feel interested you can add a pointy arrow or whatever, but I was feeling a bit lazy:

div.tooltip
{
    background-color: #FFFFCC;
    width: auto;
    height: 18px;
    position: absolute;
    padding: 5px;
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;
    font: 15px times,serif;
    box-shadow: 4px 4px 4px #202020;
}

That gives you a boring tooltip-like box with a drop-shadow and flexible content. The text of the tooltip can then be specified in the area's alt attribute. The real trick was placing it on the screen in just the right place: centred under the area in question. The problem is that image-maps don't belong to the browser's 'box-model'. Areas can be regions and are placed within the image-map as only imagemaps know how. So browsers ignore them. If you ask for the position of an image-map jQuery will give you the bottom-right corner of the image, and the size of the map as 0, 0. The same goes for the areas themselves. Luckily you can parse the coords attribute of the areas and work out their x and y offsets and their height and width pretty easily. Then all you need is to find the offset (top, left) of the grandparent of the area to find out where to place the tooltip. The meat of it is:

function doNothing()
{
var text = $('.tooltip').text();
}
function initTooltips()
{
$('area').each(function()
{
    $(this).mouseenter(function() 
    {
        var desc = $(this).attr("alt");
        $(this).parent().parent().append( 
            "<div class=\"tooltip\">"+desc+"</div>" );
        var tooltip = $('.tooltip');
        if ( tooltip.size()>1 )
            tooltip.first().remove();
        /* allow new element to get a size */
        setTimeout(doNothing,0);
        var tooltip = $('.tooltip').last();
        var coords = $(this).attr("coords");
        var values = coords.split(",");
        var bot = 0;
        var left = 10000;
        var right = 0;
        for ( var i=0;i<values.length;i+=2 )
        {
            var x = parseInt(values[i]);
            var y = parseInt(values[i+1]);
            if ( bot < y )
                bot = y;
            if ( left > x )
                left = x;
            if ( x > right )
                right = x; 
        }
        var awidth = right-left;
        var offset = new Array();
        var ppoffset = tooltip.parent().offset();
        var ttwidth = tooltip.width();
        offset.top = ppoffset.top+bot+5;
        offset.left = (ppoffset.left + left + (awidth/2))-(ttwidth/2);  
        tooltip.offset( offset );
    });
    $(this).mouseout(function()
    {
        $('.tooltip').remove();
    });
});
}

You need to call the doNothing function to give the renderer a time-slice to calculate the dimensions of your new div. Otherwise it can end up returning a width of 0. Now just call the initTooltips function in your jQuery ready function and it will be awesome.

A different home page

If you want to have your home page use a different template from the rest of your site I'd say you're quite sane. After all, who would be mad enough to want it to be the same? The easiest way to do this is to create a page--front.tpl.php file inside the templates folder of your chosen theme. Then hack it until it looks right. That particular template file will then be used instead of the regular page.tpl.php file just for the home page. A victory for simplistic home pages everywhere.

Ugly "read more" link on home page

If you publish a page to the front page Drupal assumes that it is only a teaser. So it adds a "Read more" link, which takes you back to the home page. This is really a bug, but you can get around it by making that page the default home page in Configuration->System->Site Information. Just type in your node URL for the basic page on the home page and hey presto: no more annoying "Read more" link. (This also gives the node-titles the .title .class, which makes it easier to hide them). Sometimes I get the impression that the authors of Drupal have created something even they don't fully understand.

No comments:

Post a Comment