Dave Rolsky - Effect.RoundedCorners-0.12

Documentation | Source

NAME

Effect.RoundedCorners - Rounds an elements' corners using CSS and the DOM

SYNOPSIS

  Effect.RoundedCorners.roundCorners( "some_block_element" );

  Effect.RoundedCorners.roundCorners( { "elementId": "some_block_element",
                                        "top":       true,
                                        "bottom":    false } );

DESCRIPTION

This library uses DOM manipulation and CSS to round the corners of elements without the need for images.

It is based on the "Nifty Corners" implementation by Alessandro Fulciniti described at http://pro.html.it/esempio/nifty/, but the code has been rewritten for clarity, and the API has been altered and simplified.

FUNCTIONS

This library provides one function, roundCorners(). In its simplest form, you can simply pass it the name of an element.

If you want more control, you can pass an object with the following properties:

  • elementId
  • This key indicates which element should be rounded.

  • top
  • bottom
  • Each of these properties should be a boolean, indicating whether or not the specified side of the element should be rounded.

DOM CHANGES AND CSS

The rounded corners effect is achieved by inserting a number of new, non-semnatic elements into the DOM inside the specified element. This implementation uses <b> elements since they are inherently non-semantic anyway. For each side that is being rounded, a set of five <b> elements is inserted, one parent element containing four others.

The effect is achieved through the use of a set of very short (in height) elements, each with a different left and right border size, something like this:

   -----*
   ---***
   --****
   -*****
   -*****

The dashes in the diagram represent the outside of the corner, and the asterisks the inside, so the above diagram is of the upper left corner. The border is styled so that it is the same color as the element outside the specified element. The rest of the element is styled so that the background is transparent.

Adding the rounding increases the height of each element by 6px on the side that is rounded, so an element that is rounded on both top and bottom will end up 12px bigger.

Rounding corners also requires the code to insert a new <style> element to define the rules needed to achieve the rounded corner effect. This style element will be added to the end of the document's <head> element.

Caveats

If the element you are rounding is padded, the end result looks very funny, so don't do that.

Also, because of the way the rounded corner effect is achieved, you can only round the corners of elements that can contain <b> elements. So, for example, you cannot use it to round the corners of a form input.

This library is less flexible (and efficient) than using the "-moz-border-radius" attribute in Firefox, but is more cross-platform (in theory).

AUTHOR

Dave Rolsky, <autarch@urth.org>.

COPYRIGHT

Copyright (c) 2006 Dave Rolsky. All rights reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as the Perl programming language (your choice of GPL or the Perl Artistic license).

JSAN.use("DOM.Ready");

if ( typeof Effect == "undefined" ) Effect = {};

Effect.RoundedCorners = {};

Effect.RoundedCorners.VERSION = "0.12";

Effect.RoundedCorners.roundCorners = function (params) {
    if ( typeof params == "string" ) {
        params = { "elementId": params };
    }

    if ( ! params["elementId"] ) {
        throw new Error("Effect.RoundedCorners requires an elementId parameter");
    }

    Effect.RoundedCorners._addStyles();

    if ( ! params.hasOwnProperty("top") ) {
        params["top"] = true;
    }

    if ( ! params.hasOwnProperty("bottom") ) {
        params["bottom"] = true;
    }

    var callback = function () {
        var elt = document.getElementById( params.elementId );
        if ( ! elt ) { return }
        Effect.RoundedCorners._roundCorners( elt, params );
    };
    DOM.Ready.onDOMDone(callback);
}

Effect.RoundedCorners._roundCorners = function (elt, params) {
    var color = params["color"];
    if ( ! color ) {
        var current_elt = elt.parentNode;
        while ( current_elt && ( ! color || color == "transparent" ) ) {
            try {
                color = window.getComputedStyle( current_elt, null ).backgroundColor;
            }
            /* at least on Firefox calling getComputedStyle on the
             * root HTML node seems to produce an error */
            catch (e) {}
            current_elt = current_elt.parentNode;
        }

        if ( color == undefined || color == "transparent" ) {
            color = "white";
        }
    }

    if ( params["top"] ) {
        Effect.RoundedCorners._roundUpperCorners( elt, color );
    }

    if ( params["bottom"] ) {
        Effect.RoundedCorners._roundBottomCorners( elt, color );
    }

}

Effect.RoundedCorners._roundUpperCorners = function (elt, color) {
    var container =
       Effect.RoundedCorners._makeElements( color, [ "1", "2", "3", "4" ] );

    elt.insertBefore( container, elt.firstChild );
}

Effect.RoundedCorners._roundBottomCorners = function (elt, color) {
    var container =
       Effect.RoundedCorners._makeElements( color, [ "4", "3", "2", "1" ] );

    elt.appendChild(container);
}

var foo = 1;
Effect.RoundedCorners._makeElements = function (color, order) {
    var container = document.createElement("b");
    container.className = "rounded-corners-container";

    while ( order.length ) {
        var b_tag = document.createElement("b");
        b_tag.className = "rounded-corners-" + order.shift();
        b_tag.style.backgroundColor = "transparent";
        b_tag.style.borderColor = color;

        container.appendChild(b_tag);
    }

    return container;
}

Effect.RoundedCorners._Styles = [
    [ ".rounded-corners-container",
      "display: block",
      "background-color: transparent" ],

    [ ".rounded-corners-container *",
      "display: block",
      "height: 1px",
      "overflow: hidden",
      "font-size: 1px",
      "border-style: solid",
      "border-width: 0px 1px"
    ],

    [ ".rounded-corners-1",
      "border-left-width: 5px",
      "border-right-width: 5px"
    ],

    [ ".rounded-corners-2",
      "border-left-width: 3px",
      "border-right-width: 3px"
    ],

    [ ".rounded-corners-3",
      "border-left-width: 2px",
      "border-right-width: 2px"
    ],

    [ ".rounded-corners-4",
      "height: 2px"
    ]
];

Effect.RoundedCorners._StylesAdded = 0;
Effect.RoundedCorners._addStyles = function () {
    if (Effect.RoundedCorners._StylesAdded) {
        return;
    }

    var styles = Effect.RoundedCorners._Styles;
    var style_string = "";

    for ( var i = 0; i < styles.length; i++ ) {
        var style = styles[i];

        style_string =
            style_string
            + style.shift()
            + " {\n  "
            + style.join(";\n  ")
            + ";\n}\n\n";
    }

    var style_elt = document.createElement("style");
    style_elt.setAttribute("type", "text/css");

    if ( style_elt.styleSheet ) { /* IE */
        style_elt.styleSheet.cssText = style_string;
    }
    else { /* w3c */
        var style_text = document.createTextNode(style_string);
        style_elt.appendChild(style_text);
    }

    var head = document.getElementsByTagName("head")[0];
    head.appendChild(style_elt);
    
    Effect.RoundedCorners._StylesAdded = 1;
}

/*

*/