角の丸いボックスをつくるものをつくってみた.

こんなかんじになる.

コードを乗っけてみる.

var mylib = {};

// general purpose style accesser
// if you want to set style or get style,
// you must use this function to access all styles
mylib.style = function (obj, prop, val) {
    // arguments
    // * obj : object
    // * prop : property ["string"]
    // * val : property ["string"]
    if (val) {
	switch (prop) {
	case "opacity":
	    mylib.style.opacity (obj, val);
	    break;
	case "float" :
	    obj.style.cssFloat = val;
	    obj.style.float = val;
	    break;
	default :
	    obj.style[prop] = val;
	    break;
	}
    } else {
	switch (prop) {
	case "opacity":
	    return mylib.style.opacity (obj);
	    break;
	case "float" :
	    return mylib.style.get (obj, "cssFloat") ?
		mylib.style.get (obj, "cssFloat") :
		mylib.style.get (obj, "float");
	    break;	    
	default :
	    return mylib.style.get (obj, prop);
	    break;
	}
    }
};

mylib.style.applyStyles = function (element, styles) {
    // arguments
    // * element : HTML object
    // * styles : array of array
    //   i.e. [["color", "#f00"], ["float", "left"], ...]
    if (!element || !styles)
	throw new Error (this.toString () + " : arguments are null");

    styles.forEach (function (style) {
	mylib.style (element, style[0], style[1]);
    });
};    

////////////////////////////////////////
// helper function for mylib.style () //
////////////////////////////////////////

// get computed style
mylib.style.get = function (obj, prop) {
    // argument
    // * obj : target object
    // * prop : property (js notation)
    
    if (obj.currentStyle) {
	// for IE, Opera
	return obj.currentStyle[prop];
    } else if (window.getComputedStyle) {
	// for FF
	var computedStyle = document.defaultView.getComputedStyle (obj, null);
	return computedStyle.getPropertyValue (prop.replace (/[A-Z]/g,
							     function (param) {
								 return "-" + param.toLowerCase ();
							     }));
    } else {
	// or i should throw exception .... ?
	return null;
    }
};

mylib.util = {};
mylib.util.splitOffPx = function (str) {
    return Number (str.match (/([0-9.]*)px/)[1] ?
		   str.match (/([0-9.]*)px/)[1] :
		   null) ;
};

mylib.structure = {};
mylib.structure.RoundBox = function (element, roundWidth) {
    
    //////////////////////
    // helper functions //
    //////////////////////
    
    var coloredDiv = function (size) {
	var div = document.createElement ("div");
	mylib.style.applyStyles (div,
				 [["height", "1px"],
				  ["backgroundColor", backgroundColor],
				  ["width", String (size + "px")],
				  ["float", "left"],
				  ["padding", "0px"],
				  ["margin", "0px"],
				  ["border", "0px"]]);
	return div;
    };
    
    var transDiv = function (size) {
	var div = document.createElement ("div");
	mylib.style.applyStyles (div,
				 [["height", "1px"],
				  ["backgroundColor", "transparent"],
				  ["width", String (size + "px")],
				  ["float", "left"],
				  ["padding", "0px"],
				  ["margin", "0px"],
				  ["border", "0px"]]);
	return div;
    };

    var spacerDiv = function (size) {
	var div = document.createElement ("div");
	mylib.style.applyStyles (div,
				 [["height", "1px"],
				  ["backgroundColor", backgroundColor],
				  ["width", size],
				  ["float", "left"]]);
	return div;
    };

    //////////
    // main //
    //////////

    // structure
    //   element
    //   corners
    //   tmpContens
    //   corners
    
    // backup target's old styles
    var backgroundColor = mylib.style (element, "backgroundColor");
    var color = mylib.style (element, "color");
    var float = mylib.style (element, "float");
    var margin = mylib.style (element, "margin");
    
//    var paddingLeft = Number (mylib.style (element, "paddingLeft").match (/([0-9]*)px/)[1]);
    var paddingLeft = mylib.util.splitOffPx (mylib.style (element, "paddingLeft"));
    var paddingRight = mylib.util.splitOffPx (mylib.style (element, "paddingRight"));
    var paddingTop = mylib.util.splitOffPx (mylib.style (element, "paddingTop"));
    var paddingBottom = mylib.util.splitOffPx (mylib.style (element, "paddingBottom"));
//    var width = mylib.util.splitOffPx (mylib.style (element, "width"));
    var width = element.offsetWidth;

    // force initialize
    mylib.style.applyStyles (element,
			     [["backgroundColor", "transparent"],
			      ["width", width + "px"],
			      ["border", "none"],
			      ["float", float != "none" ? float : "none"],
			      ["overflow", "hidden"],
			      ["padding", "0px"]]);
    
    var tmpContents = document.createElement ("div");
    tmpContents.innerHTML = element.innerHTML;
    mylib.style.applyStyles (tmpContents,
			     [["width", width -
			       (paddingLeft + paddingRight) + "px"],
			      ["cssFloat", "left"],
			      ["margin", "0px"],
			      ["backgroundColor", backgroundColor],
			      ["color", color],
			      ["overflow", "hidden"],
			      ["paddingLeft", paddingLeft + "px"],
			      ["paddingRight", paddingRight + "px"],
			      ["paddingTop", paddingTop + "px"],
			      ["paddingBottom", paddingBottom + "px"]
			     ]);
    
    element.innerHTML = "";
    
    for (var i = roundWidth - 1; i >= 0 ; i--) {
	var transWidth = roundWidth - Math.round (Math.sqrt (roundWidth * roundWidth - i * i));
	var coloredWidth = Math.round (Math.sqrt (roundWidth * roundWidth - i * i));

	var transDivR = (transWidth != 0) ? transDiv (transWidth) : null;
	var transDivL = (transWidth != 0) ? transDiv (transWidth) : null;
	
	var coloredDivR = coloredDiv (coloredWidth), coloredDivL = coloredDiv (coloredWidth);
	
	var spacer = spacerDiv (width - (roundWidth * 2) + "px");	

	if (transDivL != null)
	    element.appendChild (transDivL);
	element.appendChild (coloredDivL);
	element.appendChild (spacer);
	element.appendChild (coloredDivR);
	if (transDivR != null)
	    element.appendChild (transDivR);
    }

    element.appendChild (tmpContents);
    
    for (var i = 0; i < roundWidth; i++) {
	var transWidth = roundWidth - Math.round (Math.sqrt (roundWidth * roundWidth - i * i));
	var coloredWidth = Math.round (Math.sqrt (roundWidth * roundWidth - i * i));
	
	var transDivR = (transWidth != 0) ? transDiv (transWidth) : null;
	var transDivL = (transWidth != 0) ? transDiv (transWidth) : null;
	
	var coloredDivR = coloredDiv (coloredWidth), coloredDivL = coloredDiv (coloredWidth);
	
	var spacer = spacerDiv (width - (roundWidth * 2) + "px");

	if (transDivL != null)
	    element.appendChild (transDivL);
	element.appendChild (coloredDivL);
	element.appendChild (spacer);
	element.appendChild (coloredDivR);
	if (transDivR != null)
	    element.appendChild (transDivR);
    }
};

mylib.structure.RoundBoxWithBorder = function (argTarget, argRoundWidth) {
    // check arguments
    var target = argTarget && typeof argTarget == "object" ? argTarget : null;
    var roundWidth = argRoundWidth ? argRoundWidth : null;

    ////////////
    // setter //
    ////////////
    
    this.setTarget = function (argTarget) {
	target = argTarget && typeof argTarget == "object" ? argTarget : null;
	return;
    };
    
    this.setRoundWidth = function (argRoundWidth) {
	roundWidth = argRoundWidth ? argRoundWidth : null;
	return;
    };

    ///////////////
    // controler //
    ///////////////

    // apply round box with border line
    this.apply = function () {
	// restore old style
	targetStyle = {};
	targetStyle.width = target.offsetWidth;
	targetStyle.height = target.offsetHeight;
	targetStyle.borderWidth = mylib.util.splitOffPx (mylib.style.get (target, "border-left-width"))
	targetStyle.borderColor = mylib.style.get (target, "borderLeftColor");
	targetStyle.padding = {};
	targetStyle.padding.left = mylib.util.splitOffPx (mylib.style.get (target, "padding-left"));
	targetStyle.padding.right = mylib.util.splitOffPx (mylib.style.get (target, "padding-right"));
	targetStyle.padding.bottom = mylib.util.splitOffPx (mylib.style.get (target, "padding-bottom"));
	targetStyle.padding.top = mylib.util.splitOffPx (mylib.style.get (target, "padding-top"));
	targetStyle.backgroundColor = mylib.style.get (target, "backgroundColor");

	var newTargetStyle = {};
	newTargetStyle.width = targetStyle.width;
	// まるまった分だけ高さが増す
	newTargetStyle.height = targetStyle.height + (roundWidth * 2);

	// initialize of target
	targetInnerHTML = target.innerHTML;
	target.innerHTML = null;

	// reference of outerBox that shows a border line
	var outerBox = target.appendChild (document.createElement ("div"));
	(function (outerBoxDammy) {
	    mylib.style.applyStyles (outerBoxDammy,
				     [["width", newTargetStyle.width + "px"],
				      ["height", Number (newTargetStyle.height - (roundWidth * 2)) + "px"],
				      ["padding", "0px"],
				      ["border", "0px"],
				      ["backgroundColor", targetStyle.borderColor]]);
	} (outerBox.appendChild (document.createElement ("div"))));

	// reference of innerBox that shows a inner element
	var innerBox = target.appendChild (document.createElement ("div"));
	(function (innerBoxDammy) {
	    mylib.style.applyStyles (innerBoxDammy,
				     [["width", newTargetStyle.width + "px"],
				      ["height", Number (newTargetStyle.height - (roundWidth * 2)) + "px"],
				      ["padding", "0px"],
				      ["border", "0px"],
				      ["backgroundColor", targetStyle.backgroundColor]]);
	} (innerBox.appendChild (document.createElement ("div"))));
	innerBox.firstChild.innerHTML = targetInnerHTML;
	
	mylib.style.applyStyles (target,
				 [["width", newTargetStyle.width + "px"],
				  ["height", newTargetStyle.height + "px"],
				  ["padding", "0px"],
				  ["border", "0px"],
				  ["position", "relative"],
				  ["top", "0px"],
				  ["left", "0px"],
				  ["backgroundColor", "transparent"]]);
	
	mylib.style.applyStyles (outerBox,
				 [["width", newTargetStyle.width + "px"],
				  ["height", newTargetStyle.height + "px"],
				  ["padding", "0px"],
				  ["border", "0px"],
				  ["position", "relative"],
				  ["top", "0px"],
				  ["left", "0px"],
				  ["backgroundColor", targetStyle.borderColor],
				 ]);
	
	mylib.style.applyStyles (innerBox,
				 [["width", Number (newTargetStyle.width - (targetStyle.borderWidth * 2)) + "px"],
				  ["height", Number (newTargetStyle.height - (targetStyle.borderWidth * 2))+ "px"],
				  ["padding", "0px"],
				  ["border", "0px"],
				  ["position", "absolute"],
				  ["top", targetStyle.borderWidth + "px"],
				  ["left", targetStyle.borderWidth + "px"],
				  ["backgroundColor", targetStyle.backgroundColor],
				 ]);
	
	var obj1 = new mylib.structure.RoundBox (outerBox, roundWidth);
	var obj2 = new mylib.structure.RoundBox (innerBox, argRoundWidth - targetStyle.borderWidth);
	return;
	
    };
};

実行はこう.

#target {                                                                                                                                                                 
  background-color : #f99;                                                                                                                                                
  width : 400px;                                                                                                                                                          
  padding-left : 10px;                                                                                                                                                    
  padding-right : 10px;                                                                                                                                                   
  padding-top : 0px;                                                                                                                                                      
  padding-bottom : 0px;                                                                                                                                                   
  margin : 10px;                                                                                                                                                          
  font-size : 20px;                                                                                                                                                       
  border : 3px #333 solid;                                                                                                                                                
}                                                                                                                                                                         
                                                                                                                                                                          
.inner {                                                                                                                                                                  
  padding-left : 10px;                                                                                                                                                    
  padding-right : 10px;                                                                                                                                                   
}                                                                                                                                                                         
<div id="target">
  <div class="inner">
    lskd<span style="color:#00f">jfl;a</span>ksdf<br/>asdf
    alskd<span style="color:#00f">jfl;a</span>ksdf<br/>asdf
  </div>
</div>
window.onload = function () {
    var obj = new RoundBoxWithBorder ($ ("target"), 20);
    obj.apply ();
};

問題点は,パディングを使うのにはターゲットの内側にもう1つボックスを作る必要があること,
displayをblock以外にすると,どうなるかわからんこと,
アンチエイリアスがかかっていないのでかっこわるいこと.
なんだ問題ばっかだな.