/* Automatic, anti-aliased rounded corners. By Steven Wittens Based on http://pro.html.it/esempio/nifty/ Note: there is a bug in the pixel coverage calculation for the first pixel in a horizontal run. It is now set to 0, which isn't that noticable. */ function NiftyCheck() { if(!document.getElementById || !document.createElement) { return false; } var b = navigator.userAgent.toLowerCase(); if (b.indexOf("msie 5") > 0 && b.indexOf("opera") == -1) { return false; } return true; } function Rounded(selector, bk, color, sizex, sizey) { var i; var v = getElementsBySelector(selector); var l = v.length; for (i = 0; i < l; i++) { AddTop(v[i], bk, color, sizex, sizey); AddBottom(v[i], bk, color, sizex, sizey); } } Math.sqr = function (x) { return x*x; }; function Blend(a, b, alpha) { var ca = Array( parseInt('0x' + a.substring(1, 3)), parseInt('0x' + a.substring(3, 5)), parseInt('0x' + a.substring(5, 7)) ); var cb = Array( parseInt('0x' + b.substring(1, 3)), parseInt('0x' + b.substring(3, 5)), parseInt('0x' + b.substring(5, 7)) ); return '#' + Math.round(ca[0] + (cb[0] - ca[0])*alpha).toString(16) + Math.round(ca[1] + (cb[1] - ca[1])*alpha).toString(16) + Math.round(ca[2] + (cb[2] - ca[2])*alpha).toString(16); } function AddTop(el, bk, color, sizex, sizey) { var i, j; var d = document.createElement("div"); d.style.backgroundColor = bk; d.className = "rounded"; var lastarc = 0; for (i = 1; i <= sizey; i++) { var coverage, arc2, arc3; // Find intersection of arc with bottom of pixel row arc = Math.sqrt(1.0 - Math.sqr(1.0 - i / sizey)) * sizex; // Calculate how many pixels are bg, fg and blended. var n_bg = sizex - Math.ceil(arc); var n_fg = Math.floor(lastarc); var n_aa = sizex - n_bg - n_fg; // Create pixel row wrapper var x = document.createElement("div"); var y = d; x.style.margin = "0px " + n_bg +"px"; // Make a wrapper per anti-aliased pixel (at least one) for (j = 1; j <= n_aa; j++) { // Calculate coverage per pixel // (approximates circle by a line within the pixel) if (j == 1) { if (j == n_aa) { // Single pixel coverage = ((arc + lastarc) * .5) - n_fg; } else { // First in a run arc2 = Math.sqrt(1.0 - Math.sqr((sizex - n_bg - j + 1) / sizex)) * sizey; coverage = (arc2 - (sizey - i)) * (arc - n_fg - n_aa + 1) * .5; // Coverage is incorrect. Why? coverage = 0; } } else if (j == n_aa) { // Last in a run arc2 = Math.sqrt(1.0 - Math.sqr((sizex - n_bg - j + 1) / sizex)) * sizey; coverage = 1.0 - (1.0 - (arc2 - (sizey - i))) * (1.0 - (lastarc - n_fg)) * .5; } else { // Middle of a run arc3 = Math.sqrt(1.0 - Math.sqr((sizex - n_bg - j) / sizex)) * sizey; arc2 = Math.sqrt(1.0 - Math.sqr((sizex - n_bg - j + 1) / sizex)) * sizey; coverage = ((arc2 + arc3) * .5) - (sizey - i); } x.style.backgroundColor = Blend(bk, color, coverage); y.appendChild(x); y = x; var x = document.createElement("div"); x.style.margin = "0px 1px"; } x.style.backgroundColor = color; y.appendChild(x); lastarc = arc; } el.insertBefore(d, el.firstChild); } function AddBottom(el, bk, color, sizex, sizey) { var i, j; var d = document.createElement("div"); d.className = "rounded"; d.style.backgroundColor = bk; var lastarc = 0; for (i = 1; i <= sizey; i++) { var coverage, arc2, arc3; // Find intersection of arc with bottom of pixel row arc = Math.sqrt(1.0 - Math.sqr(1.0 - i / sizey)) * sizex; // Calculate how many pixels are bg, fg and blended. var n_bg = sizex - Math.ceil(arc); var n_fg = Math.floor(lastarc); var n_aa = sizex - n_bg - n_fg; // Create pixel row wrapper var x = document.createElement("div"); var y = d; x.style.margin = "0px " + n_bg + "px"; // Make a wrapper per anti-aliased pixel (at least one) for (j = 1; j <= n_aa; j++) { // Calculate coverage per pixel // (approximates circle by a line within the pixel) if (j == 1) { if (j == n_aa) { // Single pixel coverage = ((arc + lastarc) * .5) - n_fg; } else { // First in a run arc2 = Math.sqrt(1.0 - Math.sqr((sizex - n_bg - j + 1) / sizex)) * sizey; coverage = (arc2 - (sizey - i)) * (arc - n_fg - n_aa + 1) * .5; // Coverage is incorrect. Why? coverage = 0; } } else if (j == n_aa) { // Last in a run arc2 = Math.sqrt(1.0 - Math.sqr((sizex - n_bg - j + 1) / sizex)) * sizey; coverage = 1.0 - (1.0 - (arc2 - (sizey - i))) * (1.0 - (lastarc - n_fg)) * .5; } else { // Middle of a run arc3 = Math.sqrt(1.0 - Math.sqr((sizex - n_bg - j) / sizex)) * sizey; arc2 = Math.sqrt(1.0 - Math.sqr((sizex - n_bg - j + 1) / sizex)) * sizey; coverage = ((arc2 + arc3) * .5) - (sizey - i); } x.style.backgroundColor = Blend(bk, color, coverage); y.insertBefore(x, y.firstChild); y = x; var x = document.createElement("div"); x.style.margin = "0px 1px"; } x.style.backgroundColor = color; y.insertBefore(x, y.firstChild); lastarc = arc; } el.appendChild(d); } function getElementsBySelector(selector) { var i; var s = []; var selid = ""; var selclass = ""; var tag = selector; var objlist = []; if (selector.indexOf(" ") > 0) { //descendant selector like "tag#id tag" s = selector.split(" "); var fs = s[0].split("#"); if (fs.length == 1) { return objlist; } return document.getElementById(fs[1]).getElementsByTagName(s[1]); } if (selector.indexOf("#") > 0) { //id selector like "tag#id" s = selector.split("#"); tag = s[0]; selid = s[1]; } if (selid != "") { objlist.push(document.getElementById(selid)); return objlist; } if (selector.indexOf(".") > 0) { //class selector like "tag.class" s = selector.split("."); tag = s[0]; selclass = s[1]; } var v = document.getElementsByTagName(tag); // tag selector like "tag" if (selclass == "") { return v; } for (i = 0; i < v.length; i++) { if (v[i].className == selclass) { objlist.push(v[i]); } } return objlist; }