続・丸角

この前作った丸角ライブラリには大きな欠点がありました。なんとpaddingを0px以外に設定すると、角の表示がおかしくなってしまうのです。それからborderも丸くなりません。

困ったのでRico.jsとか見たんですけど、いちいち背景色を指定しないといけなかったり、やっぱりpaddingを指定するとおかしくなったりで、どれも足りない。っていうことで改良しました。borderもpaddingもOKです。

/**
 * brownie-round-corner.js
 * 
 * require prototype.js (1.4.0 - )
 * 
 * @author T.Akima
 * @copyright T.Akima
 * 
 * see also:  http://pro.html.it/esempio/nifty/
 */
RoundCorner = Class.create();
Object.extend( RoundCorner, {
    apply: function() { this.applyElements( arguments, {} ); },
    applySmall: function() { this.applyElements( arguments, {size:"small"} ); },
    applyLarge: function() { this.applyElements( arguments, {size:"large"} ); },
    
    applyElements: function( elements, options ) {
        if (elements.constructor == String)
            elements = [elements];
        for(var i = 0; i < elements.length; i++)
            this._apply( elements[i], options );
    },
    
    _apply: function( className, options ) {
        var elements = document.getElementsByClassName(className);
        for(var i = 0; i < elements.length; i++) {
            var element = elements[i];
            options.innerColor = Element.getStyle(element, "background-color");
            options.outerColor = this.getParentColor( element );
            new RoundCorner( element, options );
        }
    },
    
    getParentColor: function( element ) {
        var elementBg = Element.getStyle(element, "background-color");
        for(var current = element.parentNode; current != document; current = current.parentNode) {
            var currentBg = Element.getStyle(current, "background-color");
            if (elementBg != currentBg)
                return currentBg;
        }
        return elementBg;
    }
} );

RoundCorner.prototype = {
    initialize: function( element, options ) {
        this.element = element;
        this.innerColor = options.innerColor;
        this.outerColor = options.outerColor;
        this.xclass = (options.size == "large") ? "rl" : (options.size == "small") ? "rs" : "r";
        this.xcount = (options.size == "large") ? 8 : (options.size == "small") ? 2 : 4;
        this.borders = Border.getBorderObj( this.element );
        this.paddings = PaddingMargin.getPaddings( this.element );
        this.insertInnerDiv();
        this.addTopPart();
        this.addToBottom();
    },
    
    insertInnerDiv: function() {
        var d = document.createElement("div");
        d.style.backgroundColor = this.innerColor;
        for(;this.element.childNodes.length > 0;) {
            var child = this.element.childNodes[0];
            this.element.removeChild(child);
            d.appendChild(child);
        }
        d.style.borderLeft = this.borders.left.format();
        d.style.borderRight = this.borders.right.format();
        d.style.paddingTop = this.paddings.top;
        d.style.paddingRight = this.paddings.right;
        d.style.paddingBottom = this.paddings.bottom;
        d.style.paddingLeft = this.paddings.left;
        //
        d.style.textAlign = this.element.style.textAlign;
        this.element.style.borderWidth = "0px"
        this.element.style.padding = "0px";
        this.element.appendChild(d);
    },
    
    addTopPart: function() {
        var d = document.createElement("b");
        d.className="rtop";
        d.style.backgroundColor = this.outerColor;
        var topBorderWidth = Border.pxToNum( this.borders.top.width );
        for(var i = 0; i < this.xcount; i++){
            var x = document.createElement("b");
            x.className = this.xclass + (i + 1);
            x.style.backgroundColor = (i < topBorderWidth) ? this.borders.top.color : this.innerColor;
            x.style.borderLeft = this.borders.left.format();
            x.style.borderRight = this.borders.right.format();
            d.appendChild(x);
        }
        this.element.insertBefore(d, this.element.firstChild);
    },
    
    addToBottom: function() {
        var d = document.createElement("b");
        d.className = "rbottom";
        d.style.backgroundColor = this.outerColor;
        var bottomBorderWidth = Border.pxToNum( this.borders.bottom.width );
        for(var i = this.xcount - 1; i > -1; i--){
            var x = document.createElement("b");
            x.className = this.xclass + (i + 1);
            x.style.backgroundColor = (i < bottomBorderWidth) ? this.borders.bottom.color : this.innerColor;
            x.style.borderLeft = this.borders.left.format();
            x.style.borderRight = this.borders.right.format();
            d.appendChild(x);
        }
        this.element.appendChild(d, this.element.firstChild);
    }
}

Border = {
    
    _border_format: function() {
        var s = (this.width || "0px") + " " + (this.style || "solid") + " " + (this.color || "black" );
        return s;
    },
    
    
    positions: ["top", "right", "bottom", "left"],
    properties: ["width","style","color"],
    
    pxToNum: function( pxStr ) {
        if (pxStr.indexOf("px") == pxStr.length -2) {
            return pxStr.substring(0, pxStr.length -2) * 1;
        }
        return 0;
    },
    
    _getProperty: function( element, position, prop ) {
        var styleName = "border" + ((position) ? "-"+position : "") + ((prop) ? "-"+prop : "");
        return Element.getStyle( element, styleName );
    },
    
    parseToObj: function( borderString ) {
        if (!borderString)
            return null;
        var parts = borderString.split(" ");
        return {
            width: parts[0],
            style: parts[1],
            color: parts[2],
            format: this._border_format
        }
    },
    
    buildObj: function( width, style, color ) {
        return {
            width: width || "0px",
            style: style,
            color: color,
            format: this._border_format
        }
    },
    
    getProperty: function( element, position, prop ) {
        if ((position) && (prop)) {
            var result = this._getProperty(element, position, prop);
            if (result)
                return result;
        }
        if (prop) {
            var result = this._getProperty(element, null, prop);
            if (result)
                return result;
        }
        if (position) {
            var result = this.parseToObj(this._getProperty(element, position, null));
            if ((result) && (prop))
                return result[prop];
        }
        var result = this.parseToObj(this._getProperty(element, null, null));
        if ((result) && (prop))
            return result[prop];
        return null;
    },
    
    _getProperties: function( element, position ) {
        var b1 = this.parseToObj(this._getProperty(element, position));
        if (b1)
            return b1;
        var available = false;
        var v = [];
        for(var i = 0; i < this.properties.length; i++) {
            v[i] = this._getProperty(element, position, this.properties[i]);
            if (v[i])
                available = true;
        }
        if (available) {
            return this.buildObj.apply(this, v);
        }
        return {};
    },
    
    getProperties: function( element, position ) {
        if (position) {
            var r = this._getProperties(element, position);
            if (r)
                return r;
        }
        return this._getProperties(element, null);
    },
    
    getBorderObj: function( element ) {
        var result = {};
        for(var i = 0; i < this.positions.length; i++) {
            var pos = this.positions[i];
            result[pos] = this.getProperties( element, pos );
        }
        return result;
    }
}

PaddingMargin = {
    positions: ["top", "right", "bottom", "left"],
    
    getMargins: function( element ) {
        return this.getObject(element, "margin");
    },
    
    getPaddings: function( element ) {
        return this.getObject(element, "padding");
    },
    
    getObject: function(element, name ) {
        var value = Element.getStyle( element, name );
        if (value) {
            var parts = value.split(' ');
            var result = {};
            switch (parts.length) {
                case 1:
                    result.top = parts[0];
                    result.right = parts[0];
                    result.bottom = parts[0];
                    result.left = parts[0];
                    break;
                case 2:
                    result.top = parts[0];
                    result.right = parts[1];
                    result.bottom = parts[0];
                    result.left = parts[1];
                    break;
                case 3:
                    result.top = parts[0];
                    result.right = parts[1];
                    result.bottom = parts[2];
                    result.left = parts[1];
                    break;
                case 3:
                    result.top = parts[0];
                    result.right = parts[1];
                    result.bottom = parts[2];
                    result.left = parts[3];
                    break;
            }
            return result;
        }
        var result = {};
        for(var i = 0; i < this.positions.length; i++) {
            var pos = this.positions[i];
            result[pos] = Element.getStyle( element, name + "-" + pos );
        }
        return result;
    }
}