// Constants

var DefaultRadiusSize = 5;

// Calculates the corner and defines the indent line sizes
function calculateCornerIndent() {
   function point(xCoord, yCoord) {
      this.x = xCoord;
      this.y = yCoord;
   }
   this.radius--;
   // Plot the points for the 45 degree section of the curve
   var y = this.radius;
   var d = -this.radius;
   var x2m1 = -1;
   var Plot = new Array();
   Plot[0] = new point(1, this.radius);
   for (x=1;x<(this.radius/Math.SQRT2);x++) {
      x2m1 += 2;
      d += x2m1;
      if (d >= 0) {
         y--;
         d -= (y<<1);
      }
      Plot[Plot.length] = new point(x+1, y);
   }
   // Mirror the coordinates for the other 45 degrees
   var PlotMirror = Plot.reverse().slice(1);
   Plot.reverse();
   for (var n=0;n<PlotMirror.length;n++) Plot[Plot.length] = new point(PlotMirror[n].y, PlotMirror[n].x);
   // Determine the padding line size
   this.margin = new Array();
   this.margin[0] = ++this.radius;
   var LastY = -1;
   for (j=0;j<Plot.length;j++) {
      (Plot[j].y == LastY) ? this.margin[this.margin.length-1]-- : this.margin[this.margin.length] = this.radius - Plot[j].x;
      LastY = Plot[j].y;
   }
}

// Apply the BG color to the element, either by setting the class or the style directly
function applyContentBackground(PlainElement, ElementStyle) {
   if (this.original.className != '') PlainElement.className = this.original.className;
   else if (this.bgColor != '') ElementStyle += 'background-color:' + this.bgColor;
   PlainElement.style.cssText = ElementStyle;
}

// Draws the corner lines above and below the content area
function buildBoxCorner(MarginIndent) {
   for (var j=0;j<MarginIndent.length;j++) {
      var CornerLine = document.createElement('div');
      var CornerStyle = 'height:1px;font-size:1px;line-height:1px;padding:0;width:' + (this.width-(MarginIndent[j]*2)).toString()  + 'px;margin:0 ' + MarginIndent[j] + 'px;';
      this.applyBgColor(CornerLine, CornerStyle);
      CornerLine.appendChild(document.createTextNode('\u00a0')); // &nbsp;
      this.container.appendChild(CornerLine);
   }
}

// Adds the original box content to the new, rounded element
function addBoxContent() {
   // Clone the original element to use inside of the rounded area
   var InnerContent = this.original.cloneNode(true);
   InnerContent.removeAttribute('rounded'); // To make sure that this cloned node doesn't get another set of rounded corners applied to it
   InnerContent.removeAttribute('radius'); // No longer needed by the inner content element
   InnerContent.style.padding = '0';
   InnerContent.style.margin = '0';
   // Make another element to hold the cloned element
   var ContentContainer = document.createElement('div');
   var ContainerStyle = 'margin:0;padding:0 ' + this.radius + 'px;';
   this.applyBgColor(ContentContainer, ContainerStyle);
   ContentContainer.appendChild(InnerContent);
   // Add this to the container element, between the rounded lines
   this.container.appendChild(ContentContainer);
}

// Replaces the square element with the new, rounded one
function morphRoundedBox() {
   this.container = document.createElement('div');
   this.container.style.width = this.width + 'px';
   this.calculateCorner();
   this.buildCorner(this.margin);
   this.addContent();
   this.buildCorner(this.margin.reverse());
   this.original.parentNode.replaceChild(this.container, this.original);
}

// Object to transform the square element
function roundedBox(OriginalElement) {
   // Properties
   this.original = OriginalElement;
   this.bgColor = this.original.style.backgroundColor;
   // Look for the radius attribute, otherwise use the default of 5 pixels
   var RadiusAttribute = this.original.getAttribute('radius');
   this.radius = ((RadiusAttribute != null) && (/\d+/.test(RadiusAttribute))) ? parseInt(RadiusAttribute) : DefaultRadiusSize;
   // Set the width of the new, rounded box
   this.width = this.original.clientWidth + (this.radius*2);
   // Methods
   this.applyBgColor = applyContentBackground;
   this.calculateCorner = calculateCornerIndent;
   this.buildCorner = buildBoxCorner;
   this.addContent = addBoxContent;
   this.morph = morphRoundedBox;
}

// Turns square elements into ones with rounded corners
function roundCorners() {

	var TagName = (arguments.length == 1) ? arguments[0].toLowerCase() : 'div';
   var TagList = document.getElementsByTagName(TagName);

	for (var j=0;j<TagList.length;j++) {
      if (TagList[j].getAttribute('rounded') != null) {
         RoundBox = new roundedBox(TagList[j]);
         RoundBox.morph();
      }
   }

}