Monday 7 February 2011

Joomla! 1.6: An Attack of Biggerism

I was quite relieved to try out Joomla! 1.6. So it's not just me who releases software before it is ready. In fact the link to download its more stable predecessor, version 1.5, is about 1/10th of the size. So the users are being recruited to do the testing. The danger of this strategy is that they might just move off somewhere else, say Drupal.

On my Linux laptop running Firefox the default installation gave me a 20mm white border at the top of the page. Heaven only knows what for. Below that a cavernous banner that consumes another 40 mm, leaving a thin strip for content at the bottom. In the administrator pages gratuitous icons the size of surfboards float around in the limited space, dwarfing the innumerable input controls, which seem more bewildering than ever before.

Gone is the list of components. Instead you have a melange of components, plugins and modules, which you have to manually filter to get what you want. The old way of doing this, while not ideal, was better and required fewer clicks on the part of the user. What if after filtering I want to just see the modules I installed? More mouse-clicks which destroy my previous configuration. I think they need to take a hard look at how to design a usable interface not go wild on artwork.

Gone, too, are the polished templates of 1.5. Joni Mitchell was right: 'You don't know what you got till it's gone'. In its place a collection of ugly and nearly useless ones. On the banner we read: 'We are volunteers', which sounds more like an apology than as a boast. They are at serious risk of losing their market dominance. My rating so far: 2/10

Saturday 5 February 2011

Pixel-perfect positioning of elements in HTML

The web is full of advice, most of it bad, on how to find out the precise position of any element on an HTML page in any browser. Well the answer is simpler than I thought.

The Box Model

Each element on a HTML page is surrounded first by its padding, then by its border finally by its margin. Or put it another way, the margin is on the outside of the border and the padding is on the inside. Padding is usually included in an element's height and width calculation, border may be and margin almost never is.

Computing the offset of an element from the top of its window

First you need to determine the top and left offset of an element. I believe this works in all browsers.

function getTopOffset( elem )
{
 var offset = 0;
 while ( elem != null )
 {
  offset += elem.offsetTop;
  elem = elem.offsetParent;
 }
 return offset;
}

This works because the use of a fixed point on each element insures that all other margins, padding and border values add up correctly. As for the margin of the body element, although different browsers use different values, the offsetTop property is measured to the outer edge of the border, just like the value stored in offsetHeight, so includes the margin. So if, as in IE, the margin-top value of body is 15 then the offsetTop property of the first element inside body will be 15. A similar routine will work for the left offset.

Measuring the height of an element

The height of an element (or its width) is more complex because we usually don't include the border width. The cross-browser property clientHeight is only cross browser in name because in IE it is only set for formatted elements. For unformatted elements like div and p its value is 0. You can force it to have a clientHeight property by giving it a css property "display: inline-block" as recommended on many websites. This is a hack that changes the way the element is displayed, which could play havoc with your display. A cleaner way is to use the offsetHeight property. It's always set even in IE. The only problem is subtracting the border-top-width and border-bottom-width. But these can be reliably computed from the css style:

function getHeight( elem, inclBorder )
{
    var borderHeight = getStyleValue(elem,"border-top-width")
        +getStyle(elem,"border-bottom-width");
    if ( elem.clientHeight )
        return (inclBorder)?borderHeight+elem.clientHeight
            :elem.clientHeight;
    else
        return (inclBorder)?elem.offsetHeight
            :elem.offsetHeight-borderHeight;
}
function getStyleValue( elem, prop )
{
    var value = getStyle( elem, prop );
    if ( value )
        return parseInt( value );
    else
        return 0;
}
function getStyle( elem, prop )
{
    // test if in IE
    if ( elem.currentStyle )
        var y = elem.currentStyle[cssToIE(prop)];
    else if ( window.getComputedStyle )
        var y = window.getComputedStyle(elem,null)
            .getPropertyValue(prop);
    return y;
}
function cssToIE( prop )
{
 var parts = prop.split("-");
 if ( parts.length > 0 )
 {
  var ccProp = parts[0];
  for ( var i=1;i 0 )
   {
    ccProp += parts[i].substr(0,1).toUpperCase()
     +parts[i].substr(1,parts[i].length-1);
   }
  }
  return ccProp;
 }
 else
  return prop;
}

Again, width is computed similarly. The css properties are always set even if you add them via a style= attribute on the element. getComputedStyle (Mozilla) and the element's currentStyle property (IE) both give you the computed css styles of an element. Only problem is that IE uses camelCase names for the hyphenated property names. That's easily fixed.

Getting Window height

The Firefox way to get window height is just window.innerHeight. But this doesn't work on IE of course. You have to use document.body.offsetHeight or document.documentElement.offsetHeight. (Everyone says to use the clientHeight property but that doesn't include the borders and you can thus get the wrong answer on IE):

function getWindowHeight()
{
 var myHeight = 0;
   if ( typeof(window.innerWidth) == 'number' )
     myHeight = window.innerHeight;
 else if ( document.documentElement
  && document.documentElement.offsetHeight )
     //IE 6+ in 'standards compliant mode'
  myHeight = document.documentElement.offsetHeight;
 else if ( document.body && document.body.offsetHeight )
    //IE 4+ non-compliant mode
  myHeight = document.body.offsetHeight;
 return myHeight;
}

Using these properties my tests indicate that any browser will give you pixel-perfect readouts of the position of elements on the page.

Wednesday 2 February 2011

Joomla! 1.6 released

Joomla! 1.6 is finally out for real. The installer script I wrote won't actually work in that version because the table names have been changed. I'll fix it as soon as possible. Also, I'll need to iron out any failures of the MVD-GUI in the new system, though I don't expect anything major.