fside
03-29-2008, 10:38 PM
The following is a standalone module that reads "radius-border" and others in IE 6 stylesheets and attempts to place a radius around the object, using shims, both top and bottom. There are simple methods which use fixed size corner graphics. But they must always stay the same size. There are far more elaborate shim methods than this, below, from "nifty corners" and "ruzee", both of which use many, many more shims to produce effects like a border, blur, and anti-aliasing. They can have up to nine segments/shim. This uses just one. The idea was to keep down the number of shims.
That also makes it less flexible. Nifty and ruzee can also grow or shrink with the object. Here - the width gets fixed. They use what here is called, sandwich. Shims are attached to the object, above, and then below. And they use more than one segment/shim to produce the 'sliding door' effect, allowing width expansion/contraction (and even more segments for anti-aliasing, etc). But if one wanted all that, both nifty are ruzee are pretty tight code, and one could just use those.
The default method, here, is to float the object over a rounded background, getting the text right up on the 'ears' if you like. As with nifty and ruzee, there are some limitations. There are more with this, than those. That is, some elements will work fine - others won't (it'll throw off the layout, or just look odd). The 'sandwich' method, as termed here, the one that they use, tends to better preserve the layout. But even there, depending on the object, or the positioning, some elements just won't work at all. Trial and error. Once you render, you might have to adjust padding and margin to get the text or object to 'sit' where you want, for the final effect.
Even for all the limitations of this, it might be interesting to some to see basically how it's done. This is intended only for IE6, and uses IE 'hacks' which won't work elsewhere. Just IE 6. Borders can't be specified (or read from existing styles). That starts getting into complications. And this is a kludgy method, as it is. This really should be done at the application level. It should be built-in.
And this probably shouldn't be the 'hack-around', either. IE6 supports VML, and Opera SVG. For simple corners, Flash and java scripts might work as suggest in Flanagan's javascript book. I don't know. But these kind of things ought to be possible via that route. And that's where I intend to look next. So for the shim method, this was as far as I wanted to go. It basically shows how it can be done. This code minifies to about 7K. But then nifty and ruzee are both very compact, as well - they just really clutter the page with divs, hundreds of 'em. But you get the effect.
But some simple round or oval corners, by a couple of methods, with no border, if that's all one needs, and if the particular element is amenable, then here goes:
(function(){
var cright = "MIT license rules (www.opensource.org/licenses/mit-license.php), copyright 2008 scenic-route.com";
/* IE 6 ONLY!! ********************************* IE 6 ONLY!!
*
* Trailing edge corner rounding.
* Simple, but expensive, alternative to VML/SVG/canvas, etc.
*
* One method creates a 'shadow' object and floats the original object over it. Original can be right up on the corners, that is.
* The other method, called 'sandwich', is like that of "nifty corners" or "ruzee", but here using just the one shim.
* Both of those are much more elaborate and tile up to nine blocks/segments /line, for anti-aliasing, borders, and 'sliding doors'.
*
* Load script: as external script just before closing body tag in the html:
* <!--[if IE 6]><script language="Javascript1.2" src="<script loc and name here>" type="text/javascript"></script><![endif]-->
* Obviously use the directory and filename where you saved this as a .js script.
*
* Notes: for example, an image would need a div around, and that would be set with the radius.
* While the element need not have a "width" property, the effective width will be fixed as the width for the shims.
* So might as well use a fixed width. Padding may also have to be adjusted.
* And for that, some elements, depending on element or position, just won't work.
* The sandwich option tends to preserve the float so that the image can move, but the width will still be fixed, regardless.
* With the non-sandwich default, the background color must not be set. The radius color will be used.
*
* Features: all that said, each argument is optional and can be placed in any order.
* Values are specified as, "px", "em", or "%".
* A second radius can be used, to produce an ellipse/oval corner. The letter, "w", is suffixed.
* Colors can be either the three, #xxx, or six #xxxxxx, but must be in that 'hash' form.
* Left or right corners may be specified, but not both on the same 'row' - right corner will take precedence.
* If set anywhere, sandwich is applied to entire object.
* Scallop produces a concave radius, or sorts.
*
* Styles in stylesheet: as styles for whatever class rule you prefer:
* border-radius: radius (px,em,%) | second radius (px,em,%)"w" | #xxxxxx | sandwich b | scallop b | rightonly b | leftonly b
* border-color: #xxxxxx (overrides any color set in border-radius)
* border-color-mid: #xxxxxx (non-sandwiched default, color of middle section, overrides border-radius, and border-color)
* border-top: (same args as for border-radius, overrides border-radius and border-color)
* border-bottom: (same as for top, overrides border-radius and border-color)
*
* example:
* .block3 {
* margin-left: 200px;
* padding: 1em;
* padding-right: o;
* width: 400px;
* background: #ddf;
* border-radius: 30px left #ddf scallop sandwich;
*/
/* Stnd object-by-class collector */
function getTagsByClassName(clasName, node, tag){
var arRtnElmts = [ ];
node = node || document.documentElement;
tag = tag || "*";
var arViewElmts = node.getElementsByTagName(tag);
var regex = new RegExp('(^| )'+clasName+'($| )');
for ( var i=0; i < arViewElmts.length; i +=1) {
if ( regex.test( arViewElmts[i].className ) ) {
arRtnElmts.push(arViewElmts[i]);
}
}
return arRtnElmts;
}
var radian = Math.PI/180;
/** More calculation intensive, but generally more flexible than Bresenham plotter algorithms.
*
* p = { limit: max angle, angle: start angle, x: 0, y: 0, done: false, rad: radius, radw: 2nd radius (ellipse), incr: step value };
* Step value can be integer or real, neg or positive.
*/
function bruteCalc(p){
p.x = Math.round(p.rad *Math.cos(p.angle*radian +p.fact));
p.y = Math.floor( ( (p.radw !=="none") ? p.radw : p.rad) *Math.sin(p.angle*radian));
p.angle +=p.incr;
p.done = (p.incr <0) ? p.angle <p.limit : p.angle >p.limit;
}
/* Tack on the lines to create a top or bottom radius.
* [Note warning, just above, about changes made by reference to elements of arT, since it is an object, an array. ]
*/
function addSpans(arT, pNode, bkClr, sandwich){
var childNode, arY;
sandwich = !!sandwich;
while (arT.length >0){
arY = ["<span class='shims' style='display:block;background:",bkClr,";font-size:1px;margin-left:",arT.pop(),"px;width:",arT.pop(),"px;'></span>"];
/* IE broken DOM, as it were, allows such a string as argument to createElement. */
childNode = document.createElement(arY.join(""));
if (sandwich){
pNode.insertBefore(childNode,pNode.lastChild);
} else {
pNode.appendChild(childNode);
}
}
}
/* valu is a string ending in "px", "em", or % (% of ht) - return value in pixels */
function getPxVal(valu, ht){
valu = valu.toLowerCase();
if (valu.indexOf("px") !== -1){ return parseInt(valu,10); }
if (valu.indexOf("%") !== -1){ return Math.round(parseInt(valu,10)/100 *ht); }
if (valu.indexOf("em") !== -1){ return Math.round(parseFloat(valu) *document.getElementById("measEM").offsetWidth/10); }
}
function getArgs(strArgs){
var arTB = strArgs.split(" "), thisTB, thisR;
this.rad ="none"; this.radw ="none"; this.left =false; this.right =false; this.color ="none"; this.sandwich =false; this.scallop =false;
while (arTB.length>0){
thisTB = arTB.pop().toLowerCase();
if (thisTB.indexOf("%")!==-1 || thisTB.indexOf("em")!==-1 || thisTB.indexOf("px")!==-1 ){
thisR =getPxVal(thisTB);
if ( thisTB.indexOf("w") !==-1 ){
this.radw =thisR;
} else {
this.rad =thisR;
}
}
if (thisTB==="left"){ this.left =true; }
if (thisTB==="right"){ this.right =true; }
if (thisTB==="sandwich"){ this.sandwich =true; }
if (thisTB==="scallop"){ this.scallop =true; }
if (thisTB.indexOf("#") !== -1){ this.color =thisTB; }
}
return this;
}
var arPosStyles = ["position","top","left","right","bottom"];
/* Place element in new div, tack on the top lines, put in the middle block, tack on the bottom lines. */
function stackBlocks(oEl, oArgs){
var initWd, origWd, origHt, nodeTop, p, i, apsi, arT =[ ], sandwich, arY, thisRtn, adjRad, isRadw;
var topRad, btmRad, topRad2, btmRad2, leftonlyTop, leftonlyBtm, rightonlyTop, rightonlyBtm;
var midHt, node2, btmClr, midClr, topClr, topScal, btmScal;
/* Set defaults, then get the styles */
topRad = btmRad = 0;
topRad2 = btmRad2 = "none";
btmClr = topClr = midClr = "none";
leftonlyTop = leftonlyBtm = rightonlyTop = rightonlyBtm = false;
topScal = btmScal = sandwich = false;
if (oArgs["border-radius"]){
thisRtn = getArgs(oArgs["border-radius"]);
if ( thisRtn.rad !=="none" ){ topRad = btmRad = thisRtn.rad; }
if ( thisRtn.radw !=="none" ){ topRad2 = btmRad2 = thisRtn.radw; }
if ( thisRtn.color !=="none" ){ btmClr = topClr = midClr = thisRtn.color; }
leftonlyTop = leftonlyBtm = thisRtn.left;
rightonlyTop = rightonlyBtm = thisRtn.right;
sandwich = thisRtn.sandwich;
btmScal = topScal = thisRtn.scallop;
}
if (oArgs["border-radius-color"]){ btmClr = topClr = midClr = oArgs["border-radius-color"]; }
if (oArgs["border-radius-color-mid"]){ midClr = oArgs["border-radius-color-mid"]; }
if (oArgs["border-radius-top"]){
thisRtn = getArgs(oArgs["border-radius-top"]);
if ( thisRtn.rad !=="none" ){ topRad = thisRtn.rad; }
if ( thisRtn.radw !=="none" ){ topRad2 = thisRtn.radw; }
if ( thisRtn.color !=="none" ){ topClr = thisRtn.color; }
if ( thisRtn.sandwich ===true){ sandwich = thisRtn.sandwich; }
if ( thisRtn.scallop ===true){ topScal = thisRtn.scallop; }
if ( thisRtn.left ===true){ leftonlyTop = thisRtn.left; }
if ( thisRtn.right ===true){ rightonlyTop = thisRtn.right; }
}
if (oArgs["border-radius-bottom"]){
thisRtn = getArgs(oArgs["border-radius-bottom"]);
if ( thisRtn.rad !=="none" ){ btmRad = thisRtn.rad; }
if ( thisRtn.radw !=="none" ){ btmRad2 = thisRtn.radw; }
if ( thisRtn.color !=="none" ){ btmClr = thisRtn.color; }
if ( thisRtn.sandwich ===true){ sandwich = thisRtn.sandwich; }
if ( thisRtn.scallop ===true){ btmScal = thisRtn.scallop; }
if ( thisRtn.left ===true){ leftonlyBtm = thisRtn.left; }
if ( thisRtn.right ===true){ rightonlyBtm = thisRtn.right; }
}
if (rightonlyBtm){ leftonlyBtm =false; }
if (rightonlyTop){ leftonlyTop =false; }
if (topRad===0 && btmRad===0){ return; }
nodeTop = document.createElement("div");
origWd = oEl.offsetWidth;
origHt = oEl.offsetHeight;
nodeTop.style.width = origWd +"px";
if (sandwich){
nodeTop = oEl.parentNode.insertBefore(nodeTop,oEl);
/*^ oEl goes inside new div, the new div effectively taking its place in the order */
oEl = nodeTop.appendChild(oEl);
} else {
/* Fix the new div to occupy the same dimensions and left margin as the original element. */
nodeTop.style.marginLeft = oEl.offsetLeft +"px";
/* IE slides the latter sibling over previous, so insert before */
nodeTop = oEl.parentNode.insertBefore(nodeTop,oEl);
for (i=0; i <arPosStyles.length; i +=1){
apsi = arPosStyles[i];
if (oArgs[apsi]){ nodeTop.style[apsi] = oArgs[apsi]; }
}
}
arT = [ ];
isRadw = (topRad2 !=="none");
adjRad = isRadw? topRad2 : topRad;
initWd = origWd -adjRad*2;
/* Object members are handled by reference in javascript, so the calling function will modify them. */
p = { limit: 0, angle: 90, x: 0, prevx: -1, y: 0, done: false, rad: topRad, radw: topRad2, incr: -0.5, fact: (topScal?1.97:0) };
while (!p.done){
bruteCalc(p);
if (p.prevx !==p.x){
arT.push(initWd +p.y +(leftonlyTop? adjRad: p.y) +(rightonlyTop? p.y+adjRad: 0));
arT.push( (rightonlyTop? 0-p.y: adjRad) -p.y);
}
p.prevx = p.x;
}
addSpans(arT, nodeTop, topClr, (sandwich?"up":""));
if (!sandwich){
/* Slide the original element up and over the radiused background */
if (!oArgs.top){ oEl.style.marginTop = 0- origHt +"px"; }
/* Put in the middle rectangular part of the background before the bottom section. */
arY = ["<span class='shims' style='display:block;background:",midClr,";'></span>"];
node2 = document.createElement(arY.join(""));
var midNode = nodeTop.appendChild(node2);
midHt = origHt -topRad -btmRad;
if(midHt>0){ midNode.style.height = midHt +"px"; }
}
arT = [ ];
isRadw = (btmRad2 !=="none");
adjRad = isRadw? btmRad2 : btmRad;
initWd = origWd -adjRad*2;
p = { limit: 90, angle: 0, x: 0, prevx: -1, y: 0, done: false, rad: btmRad, radw: btmRad2, incr: 0.5, fact: (btmScal?1.97:0) };
while (!p.done){
bruteCalc(p);
if (p.prevx !==p.x){
arT.push(initWd +p.y +(leftonlyBtm? adjRad: p.y) +(rightonlyBtm? p.y+adjRad: 0));
arT.push( (rightonlyBtm? 0-p.y: adjRad) -p.y);
}
p.prevx = p.x;
}
addSpans(arT, nodeTop, btmClr);
}
var buildingSep = "**__separator__**";
/* Examine the active style sheets for any radius styles. Return of a list of all radius styles per rule. */
function findClasses(){
/* Find active style sheets. */
var arCss = [ ], arBuilding = [ ], prevlen, cnt=0;
var Css = document.styleSheets, zClass;
var arRadiusStyles = [
"border-radius",
"border-radius-color",
"border-radius-color-mid",
"border-radius-top",
"border-radius-bottom"
], arsm, apsm;
for (var i=0; i<Css.length; i +=1) {
if (Css[i].disabled === false){ arCss.push(i); }
}
for (var j=0; j < arCss.length; j +=1){
for (var k=0; k < Css[arCss[j]].rules.length; k +=1){
zClass = Css[arCss[j]].rules[k];
if (zClass.selectorText.indexOf(".") !== -1 ){
prevlen = arBuilding.length;
for (var m=0; m <arRadiusStyles.length; m +=1){
arsm = arRadiusStyles[m];
if (typeof zClass.style[arsm] !=="undefined"){ arBuilding.push(arsm+":"+zClass.style[arsm]); }
}
if (prevlen < arBuilding.length){
for (m=0; m <arPosStyles.length; m +=1){
apsm = arPosStyles[m];
if (typeof zClass.style[apsm] !=="undefined"){ arBuilding.push(apsm+":"+zClass.style[apsm]); }
}
arBuilding.push(zClass.selectorText.substr(1));
arBuilding.push(buildingSep);
cnt +=1;
}
}
}
}
arBuilding.push(cnt);
return arBuilding;
}
function roundCorners(){
var arBuilt = findClasses();
var cnt = arBuilt.pop();
if (cnt ===0){ return; }
/* Loop below assumes previous separator has been discarded. */
arBuilt.pop();
/* Set up division to measure em */
var node = document.createElement("<div id='measEM' style='display:none;height:10em;width:10em;'></div>");
document.documentElement.lastChild.appendChild(node);
var arElmts = [ ], nextStyle;
for (var j=0; j<cnt; j +=1){
var oArgs = { };
arElmts = getTagsByClassName(arBuilt.pop());
while (arBuilt.length >0){
nextStyle = arBuilt.pop();
if (nextStyle ===buildingSep){ break; }
oArgs[nextStyle.split(":")[0] ] =nextStyle.split(":")[1];
}
for (var i=0; i <arElmts.length; i +=1){
stackBlocks(arElmts[i], oArgs);
}
}
}
window.onload = function(){ setTimeout(roundCorners,10); }
})();
That also makes it less flexible. Nifty and ruzee can also grow or shrink with the object. Here - the width gets fixed. They use what here is called, sandwich. Shims are attached to the object, above, and then below. And they use more than one segment/shim to produce the 'sliding door' effect, allowing width expansion/contraction (and even more segments for anti-aliasing, etc). But if one wanted all that, both nifty are ruzee are pretty tight code, and one could just use those.
The default method, here, is to float the object over a rounded background, getting the text right up on the 'ears' if you like. As with nifty and ruzee, there are some limitations. There are more with this, than those. That is, some elements will work fine - others won't (it'll throw off the layout, or just look odd). The 'sandwich' method, as termed here, the one that they use, tends to better preserve the layout. But even there, depending on the object, or the positioning, some elements just won't work at all. Trial and error. Once you render, you might have to adjust padding and margin to get the text or object to 'sit' where you want, for the final effect.
Even for all the limitations of this, it might be interesting to some to see basically how it's done. This is intended only for IE6, and uses IE 'hacks' which won't work elsewhere. Just IE 6. Borders can't be specified (or read from existing styles). That starts getting into complications. And this is a kludgy method, as it is. This really should be done at the application level. It should be built-in.
And this probably shouldn't be the 'hack-around', either. IE6 supports VML, and Opera SVG. For simple corners, Flash and java scripts might work as suggest in Flanagan's javascript book. I don't know. But these kind of things ought to be possible via that route. And that's where I intend to look next. So for the shim method, this was as far as I wanted to go. It basically shows how it can be done. This code minifies to about 7K. But then nifty and ruzee are both very compact, as well - they just really clutter the page with divs, hundreds of 'em. But you get the effect.
But some simple round or oval corners, by a couple of methods, with no border, if that's all one needs, and if the particular element is amenable, then here goes:
(function(){
var cright = "MIT license rules (www.opensource.org/licenses/mit-license.php), copyright 2008 scenic-route.com";
/* IE 6 ONLY!! ********************************* IE 6 ONLY!!
*
* Trailing edge corner rounding.
* Simple, but expensive, alternative to VML/SVG/canvas, etc.
*
* One method creates a 'shadow' object and floats the original object over it. Original can be right up on the corners, that is.
* The other method, called 'sandwich', is like that of "nifty corners" or "ruzee", but here using just the one shim.
* Both of those are much more elaborate and tile up to nine blocks/segments /line, for anti-aliasing, borders, and 'sliding doors'.
*
* Load script: as external script just before closing body tag in the html:
* <!--[if IE 6]><script language="Javascript1.2" src="<script loc and name here>" type="text/javascript"></script><![endif]-->
* Obviously use the directory and filename where you saved this as a .js script.
*
* Notes: for example, an image would need a div around, and that would be set with the radius.
* While the element need not have a "width" property, the effective width will be fixed as the width for the shims.
* So might as well use a fixed width. Padding may also have to be adjusted.
* And for that, some elements, depending on element or position, just won't work.
* The sandwich option tends to preserve the float so that the image can move, but the width will still be fixed, regardless.
* With the non-sandwich default, the background color must not be set. The radius color will be used.
*
* Features: all that said, each argument is optional and can be placed in any order.
* Values are specified as, "px", "em", or "%".
* A second radius can be used, to produce an ellipse/oval corner. The letter, "w", is suffixed.
* Colors can be either the three, #xxx, or six #xxxxxx, but must be in that 'hash' form.
* Left or right corners may be specified, but not both on the same 'row' - right corner will take precedence.
* If set anywhere, sandwich is applied to entire object.
* Scallop produces a concave radius, or sorts.
*
* Styles in stylesheet: as styles for whatever class rule you prefer:
* border-radius: radius (px,em,%) | second radius (px,em,%)"w" | #xxxxxx | sandwich b | scallop b | rightonly b | leftonly b
* border-color: #xxxxxx (overrides any color set in border-radius)
* border-color-mid: #xxxxxx (non-sandwiched default, color of middle section, overrides border-radius, and border-color)
* border-top: (same args as for border-radius, overrides border-radius and border-color)
* border-bottom: (same as for top, overrides border-radius and border-color)
*
* example:
* .block3 {
* margin-left: 200px;
* padding: 1em;
* padding-right: o;
* width: 400px;
* background: #ddf;
* border-radius: 30px left #ddf scallop sandwich;
*/
/* Stnd object-by-class collector */
function getTagsByClassName(clasName, node, tag){
var arRtnElmts = [ ];
node = node || document.documentElement;
tag = tag || "*";
var arViewElmts = node.getElementsByTagName(tag);
var regex = new RegExp('(^| )'+clasName+'($| )');
for ( var i=0; i < arViewElmts.length; i +=1) {
if ( regex.test( arViewElmts[i].className ) ) {
arRtnElmts.push(arViewElmts[i]);
}
}
return arRtnElmts;
}
var radian = Math.PI/180;
/** More calculation intensive, but generally more flexible than Bresenham plotter algorithms.
*
* p = { limit: max angle, angle: start angle, x: 0, y: 0, done: false, rad: radius, radw: 2nd radius (ellipse), incr: step value };
* Step value can be integer or real, neg or positive.
*/
function bruteCalc(p){
p.x = Math.round(p.rad *Math.cos(p.angle*radian +p.fact));
p.y = Math.floor( ( (p.radw !=="none") ? p.radw : p.rad) *Math.sin(p.angle*radian));
p.angle +=p.incr;
p.done = (p.incr <0) ? p.angle <p.limit : p.angle >p.limit;
}
/* Tack on the lines to create a top or bottom radius.
* [Note warning, just above, about changes made by reference to elements of arT, since it is an object, an array. ]
*/
function addSpans(arT, pNode, bkClr, sandwich){
var childNode, arY;
sandwich = !!sandwich;
while (arT.length >0){
arY = ["<span class='shims' style='display:block;background:",bkClr,";font-size:1px;margin-left:",arT.pop(),"px;width:",arT.pop(),"px;'></span>"];
/* IE broken DOM, as it were, allows such a string as argument to createElement. */
childNode = document.createElement(arY.join(""));
if (sandwich){
pNode.insertBefore(childNode,pNode.lastChild);
} else {
pNode.appendChild(childNode);
}
}
}
/* valu is a string ending in "px", "em", or % (% of ht) - return value in pixels */
function getPxVal(valu, ht){
valu = valu.toLowerCase();
if (valu.indexOf("px") !== -1){ return parseInt(valu,10); }
if (valu.indexOf("%") !== -1){ return Math.round(parseInt(valu,10)/100 *ht); }
if (valu.indexOf("em") !== -1){ return Math.round(parseFloat(valu) *document.getElementById("measEM").offsetWidth/10); }
}
function getArgs(strArgs){
var arTB = strArgs.split(" "), thisTB, thisR;
this.rad ="none"; this.radw ="none"; this.left =false; this.right =false; this.color ="none"; this.sandwich =false; this.scallop =false;
while (arTB.length>0){
thisTB = arTB.pop().toLowerCase();
if (thisTB.indexOf("%")!==-1 || thisTB.indexOf("em")!==-1 || thisTB.indexOf("px")!==-1 ){
thisR =getPxVal(thisTB);
if ( thisTB.indexOf("w") !==-1 ){
this.radw =thisR;
} else {
this.rad =thisR;
}
}
if (thisTB==="left"){ this.left =true; }
if (thisTB==="right"){ this.right =true; }
if (thisTB==="sandwich"){ this.sandwich =true; }
if (thisTB==="scallop"){ this.scallop =true; }
if (thisTB.indexOf("#") !== -1){ this.color =thisTB; }
}
return this;
}
var arPosStyles = ["position","top","left","right","bottom"];
/* Place element in new div, tack on the top lines, put in the middle block, tack on the bottom lines. */
function stackBlocks(oEl, oArgs){
var initWd, origWd, origHt, nodeTop, p, i, apsi, arT =[ ], sandwich, arY, thisRtn, adjRad, isRadw;
var topRad, btmRad, topRad2, btmRad2, leftonlyTop, leftonlyBtm, rightonlyTop, rightonlyBtm;
var midHt, node2, btmClr, midClr, topClr, topScal, btmScal;
/* Set defaults, then get the styles */
topRad = btmRad = 0;
topRad2 = btmRad2 = "none";
btmClr = topClr = midClr = "none";
leftonlyTop = leftonlyBtm = rightonlyTop = rightonlyBtm = false;
topScal = btmScal = sandwich = false;
if (oArgs["border-radius"]){
thisRtn = getArgs(oArgs["border-radius"]);
if ( thisRtn.rad !=="none" ){ topRad = btmRad = thisRtn.rad; }
if ( thisRtn.radw !=="none" ){ topRad2 = btmRad2 = thisRtn.radw; }
if ( thisRtn.color !=="none" ){ btmClr = topClr = midClr = thisRtn.color; }
leftonlyTop = leftonlyBtm = thisRtn.left;
rightonlyTop = rightonlyBtm = thisRtn.right;
sandwich = thisRtn.sandwich;
btmScal = topScal = thisRtn.scallop;
}
if (oArgs["border-radius-color"]){ btmClr = topClr = midClr = oArgs["border-radius-color"]; }
if (oArgs["border-radius-color-mid"]){ midClr = oArgs["border-radius-color-mid"]; }
if (oArgs["border-radius-top"]){
thisRtn = getArgs(oArgs["border-radius-top"]);
if ( thisRtn.rad !=="none" ){ topRad = thisRtn.rad; }
if ( thisRtn.radw !=="none" ){ topRad2 = thisRtn.radw; }
if ( thisRtn.color !=="none" ){ topClr = thisRtn.color; }
if ( thisRtn.sandwich ===true){ sandwich = thisRtn.sandwich; }
if ( thisRtn.scallop ===true){ topScal = thisRtn.scallop; }
if ( thisRtn.left ===true){ leftonlyTop = thisRtn.left; }
if ( thisRtn.right ===true){ rightonlyTop = thisRtn.right; }
}
if (oArgs["border-radius-bottom"]){
thisRtn = getArgs(oArgs["border-radius-bottom"]);
if ( thisRtn.rad !=="none" ){ btmRad = thisRtn.rad; }
if ( thisRtn.radw !=="none" ){ btmRad2 = thisRtn.radw; }
if ( thisRtn.color !=="none" ){ btmClr = thisRtn.color; }
if ( thisRtn.sandwich ===true){ sandwich = thisRtn.sandwich; }
if ( thisRtn.scallop ===true){ btmScal = thisRtn.scallop; }
if ( thisRtn.left ===true){ leftonlyBtm = thisRtn.left; }
if ( thisRtn.right ===true){ rightonlyBtm = thisRtn.right; }
}
if (rightonlyBtm){ leftonlyBtm =false; }
if (rightonlyTop){ leftonlyTop =false; }
if (topRad===0 && btmRad===0){ return; }
nodeTop = document.createElement("div");
origWd = oEl.offsetWidth;
origHt = oEl.offsetHeight;
nodeTop.style.width = origWd +"px";
if (sandwich){
nodeTop = oEl.parentNode.insertBefore(nodeTop,oEl);
/*^ oEl goes inside new div, the new div effectively taking its place in the order */
oEl = nodeTop.appendChild(oEl);
} else {
/* Fix the new div to occupy the same dimensions and left margin as the original element. */
nodeTop.style.marginLeft = oEl.offsetLeft +"px";
/* IE slides the latter sibling over previous, so insert before */
nodeTop = oEl.parentNode.insertBefore(nodeTop,oEl);
for (i=0; i <arPosStyles.length; i +=1){
apsi = arPosStyles[i];
if (oArgs[apsi]){ nodeTop.style[apsi] = oArgs[apsi]; }
}
}
arT = [ ];
isRadw = (topRad2 !=="none");
adjRad = isRadw? topRad2 : topRad;
initWd = origWd -adjRad*2;
/* Object members are handled by reference in javascript, so the calling function will modify them. */
p = { limit: 0, angle: 90, x: 0, prevx: -1, y: 0, done: false, rad: topRad, radw: topRad2, incr: -0.5, fact: (topScal?1.97:0) };
while (!p.done){
bruteCalc(p);
if (p.prevx !==p.x){
arT.push(initWd +p.y +(leftonlyTop? adjRad: p.y) +(rightonlyTop? p.y+adjRad: 0));
arT.push( (rightonlyTop? 0-p.y: adjRad) -p.y);
}
p.prevx = p.x;
}
addSpans(arT, nodeTop, topClr, (sandwich?"up":""));
if (!sandwich){
/* Slide the original element up and over the radiused background */
if (!oArgs.top){ oEl.style.marginTop = 0- origHt +"px"; }
/* Put in the middle rectangular part of the background before the bottom section. */
arY = ["<span class='shims' style='display:block;background:",midClr,";'></span>"];
node2 = document.createElement(arY.join(""));
var midNode = nodeTop.appendChild(node2);
midHt = origHt -topRad -btmRad;
if(midHt>0){ midNode.style.height = midHt +"px"; }
}
arT = [ ];
isRadw = (btmRad2 !=="none");
adjRad = isRadw? btmRad2 : btmRad;
initWd = origWd -adjRad*2;
p = { limit: 90, angle: 0, x: 0, prevx: -1, y: 0, done: false, rad: btmRad, radw: btmRad2, incr: 0.5, fact: (btmScal?1.97:0) };
while (!p.done){
bruteCalc(p);
if (p.prevx !==p.x){
arT.push(initWd +p.y +(leftonlyBtm? adjRad: p.y) +(rightonlyBtm? p.y+adjRad: 0));
arT.push( (rightonlyBtm? 0-p.y: adjRad) -p.y);
}
p.prevx = p.x;
}
addSpans(arT, nodeTop, btmClr);
}
var buildingSep = "**__separator__**";
/* Examine the active style sheets for any radius styles. Return of a list of all radius styles per rule. */
function findClasses(){
/* Find active style sheets. */
var arCss = [ ], arBuilding = [ ], prevlen, cnt=0;
var Css = document.styleSheets, zClass;
var arRadiusStyles = [
"border-radius",
"border-radius-color",
"border-radius-color-mid",
"border-radius-top",
"border-radius-bottom"
], arsm, apsm;
for (var i=0; i<Css.length; i +=1) {
if (Css[i].disabled === false){ arCss.push(i); }
}
for (var j=0; j < arCss.length; j +=1){
for (var k=0; k < Css[arCss[j]].rules.length; k +=1){
zClass = Css[arCss[j]].rules[k];
if (zClass.selectorText.indexOf(".") !== -1 ){
prevlen = arBuilding.length;
for (var m=0; m <arRadiusStyles.length; m +=1){
arsm = arRadiusStyles[m];
if (typeof zClass.style[arsm] !=="undefined"){ arBuilding.push(arsm+":"+zClass.style[arsm]); }
}
if (prevlen < arBuilding.length){
for (m=0; m <arPosStyles.length; m +=1){
apsm = arPosStyles[m];
if (typeof zClass.style[apsm] !=="undefined"){ arBuilding.push(apsm+":"+zClass.style[apsm]); }
}
arBuilding.push(zClass.selectorText.substr(1));
arBuilding.push(buildingSep);
cnt +=1;
}
}
}
}
arBuilding.push(cnt);
return arBuilding;
}
function roundCorners(){
var arBuilt = findClasses();
var cnt = arBuilt.pop();
if (cnt ===0){ return; }
/* Loop below assumes previous separator has been discarded. */
arBuilt.pop();
/* Set up division to measure em */
var node = document.createElement("<div id='measEM' style='display:none;height:10em;width:10em;'></div>");
document.documentElement.lastChild.appendChild(node);
var arElmts = [ ], nextStyle;
for (var j=0; j<cnt; j +=1){
var oArgs = { };
arElmts = getTagsByClassName(arBuilt.pop());
while (arBuilt.length >0){
nextStyle = arBuilt.pop();
if (nextStyle ===buildingSep){ break; }
oArgs[nextStyle.split(":")[0] ] =nextStyle.split(":")[1];
}
for (var i=0; i <arElmts.length; i +=1){
stackBlocks(arElmts[i], oArgs);
}
}
}
window.onload = function(){ setTimeout(roundCorners,10); }
})();