/**
* Cornerz 0.6 - Bullet Proof Corners
* Jonah Fox (jo...@parkerfox.co.uk) 2008
*
* Usage: $('.myclass').curve(options)
* options is a hash with the following parameters. Bracketed is thedefault
*   radius (10)
*   borderWidth (read from BorderTopWidth or 0)
*   background ("white"). Note that this is not calculated from theHTML as it is expensive
*   borderColor (read from BorderTopColor)
*   corners ("tl br tr bl"). Specify which borders
*   fixIE ("padding") - attmepts to fix IE by incrementing theproperty by 1 if the outer width/height is odd.

CHANGELIST from  v0.4

0.5 - Now attempts to fix the odd dimension problem in IE
0.6 - Added semicolons for packing and fixed a problem with odd borderwidth's in IE

4/3/09 -- S Swett changed to fix a rendering problem in IE -- TT 4620.  Made it so IE doesn't blow away element
attributes that were set with Javascript elsewhere.  When IE used "innerHTML = h" it was blowing up.  Changed to
use $$.append, which also required touching up XML -- see function vmlCurve.

4/8/09 -- S Swett changed to fix a problem in IE where thin 1 pixel
vertical or horizontal lines would appear in corners if height or width was odd.

*/

;(function($){

  if($.browser.msie && document.namespaces["v"] == null) {
    document.namespaces.add("v", "urn:schemas-microsoft-com:vml");
    var ss = document.createStyleSheet().owningElement;
    ss.styleSheet.cssText = "v\\:*{behavior:url(#default#VML);}"
  }

  $.fn.cornerz = function(options){

    function canvasCorner(t,l, r,bw,bc,bg){
            var sa,ea,cw,sx,sy,x,y, p = 1.57, css="position:absolute;";
            if(t)
                    {sa=-p; sy=r; y=0; css+="top:-"+bw+"px;";  }
            else
                    {sa=p; sy=0; y=r; css+="bottom:-"+bw+"px;"; }
            if(l)
                    {ea=p*2; sx=r; x=0; css+="left:-"+bw+"px;"}
            else
                    {ea=0; sx=0; x=r; css+="right:-"+bw+"px;";      }

            var canvas=$("<canvas width="+r+"px height="+ r +"px style='" +css+"' ></canvas>");
            var ctx=canvas[0].getContext('2d');
            ctx.beginPath();
            ctx.lineWidth=bw*2;
            ctx.arc(sx,sy,r,sa,ea,!(t^l));
            ctx.strokeStyle=bc;
            ctx.stroke();
            ctx.lineWidth = 0;
            ctx.lineTo(x,y);
            ctx.fillStyle=bg;
            ctx.fill();
            return canvas;
    };

    function canvasCorners(corners, r, bw,bc,bg) {
            var hh = $("<div style='display: inherit' />"); // trying out style='float:left'
            $.each(corners.split(" "), function() {
              hh.append(canvasCorner(this[0]=="t",this[1]=="l", r,bw,bc,bg));
            });
            return hh;
    };

    function vmlCurve(r,b,c,m,ml,mt, right_fix) {
        var l = m-ml-right_fix;
        var t = m-mt;
        // S Swett replaced following line (different ending tag format)
        // return "<v:arc filled='False' strokeweight='"+b+"px' strokecolor='"+c+"' startangle='0' endangle='361' style=' top:" + t +"px;left: "+ l + ";width:" + r+ "px; height:" + r+ "px' />";
        return "<v:arc filled='False' strokeweight='"+b+"px' strokecolor='"+c+"' startangle='0' endangle='361' style=' top:" + t +"px;left: "+ l + ";width:" + r+ "px; height:" + r+ "px' ></v:arc>";
    }

    function vmlCorners(corners, r, bw, bc, bg, w, ieOddWidth, ieOddHeight, targetDivId) {   // S Swett added last 3 parms
      var h ="<div id='"+targetDivId+"_cornerz' style='text-align:left; '>";   // S Swett added "targetDivId_cornerz"
      $.each($.trim(corners).split(" "), function() {
        var css,ml=1,mt=1,right_fix=0;
        if(this.charAt(0)=="t") {
          css="top:-"+bw+"px;";
        }
        else {
          // css= "bottom:-"+bw+"px;";   // S Swett commented out
          var bottomValue = (ieOddHeight) ? -1 - bw : 0 - bw;   // S Swett added
          css= "bottom:"+bottomValue+"px;";   // S Swett added
          mt=r+1;
        }
        if(this.charAt(1)=="l")
          css+="left:-"+bw+"px;";
        else {
          // css +="right:-"+(bw)+"px; "; // odd width gives wrong margin? 
  // S Swett commented out
            var rightValue = (ieOddWidth) ? -1 - bw : 0 - bw;   // SSwett added
            css +="right:"+rightValue+"px; "; // odd width gives wrong margin?  
 // S Swett added
           ml=r;
           right_fix = 1;
        }

        var cornerDivId = targetDivId + "_" + this;   // S Swett added
        h+="<div id='"+cornerDivId+"' style='"+css+"; position: absolute; overflow:hidden; width:"+ r +"px; height: " + r + "px;'>";   // S Swett added "cornerDivId"
        h+= "<v:group  style='width:1000px;height:1000px;position:absolute;' coordsize='1000,1000' >";
        h+= vmlCurve(r*3,r+bw,bg, -r/2,ml,mt,right_fix);
        if(bw>0)
          h+= vmlCurve(r*2-bw,bw,bc, Math.floor(bw/2+0.5),ml,mt,right_fix);
        h+="</v:group>";
        h+= "</div>";
      });
      h += "</div>";

      return h;
    };

    var settings = {
      corners : "tl tr bl br",
      radius : 10,
      background: "white",
      borderWidth: 0,
      fixIE: true };
    $.extend(settings, options || {});

    var incrementProperty = function(elem, prop, x) {
      var y = parseInt(elem.css(prop)) || 0 ;
      elem.css(prop, x+y);
    }

    return this.each(function() {

      var $$ = $(this);
      var r = settings.radius*1.0;
      var bw = (settings.borderWidth || parseInt($$.css("borderTopWidth")) || 0)*1.0;
      var bg = settings.background;
      var bc = settings.borderColor;
      bc = bc || ( bw > 0 ? $$.css("borderTopColor") : bg);

      var cs = settings.corners;

      if($.browser.msie) {//need to use innerHTML rather than jQuery

        // begin section added by S Swett
        var thisId = $$.attr("id");
        if (thisId == undefined || thisId == null || thisId == "")
        {
            var myDate = new Date();
            thisId = "x_" + myDate.valueOf();
        }

        $('#' + thisId + '_cornerz').remove();   // remove first, in case a div is requested to be rounded multiple times
        var ieOddWidth = ($$.outerWidth() % 2 == 1);
        var ieOddHeight = (this.offsetHeight % 2 == 1);
        // end section added by S Swett

        h = vmlCorners(cs,r,bw,bc,bg, $(this).width(), ieOddWidth,ieOddHeight, thisId );   // S Swett added last 3 parameters
        // this.innerHTML += h;   // S Swett commented out
        $$.append(h);   // S Swett added

        // begin section added by S Swett
        var ieOddWidthAfterAppend = ($$.outerWidth() % 2 == 1);
        var ieOddHeightAfterAppend = (this.offsetHeight % 2 == 1);

        if (!ieOddWidth && ieOddWidthAfterAppend)
        {
            var trCornerDivSelector = "#" + thisId + "_tr";
            var rightPixelsStr = $(trCornerDivSelector).css("right");
            var newRightPixels = parseInt(rightPixelsStr) - 1;
            $(trCornerDivSelector).css("right", "" + newRightPixels + "px");

            var brCornerDivSelector = "#" + thisId + "_br";
            rightPixelsStr = $(brCornerDivSelector).css("right");
            newRightPixels = parseInt(rightPixelsStr) - 1;
            $(brCornerDivSelector).css("right", "" + newRightPixels +"px");
        }

        if (!ieOddHeight && ieOddHeightAfterAppend)
        {
            var blCornerDivSelector = "#" + thisId + "_bl";
            var bottomPixelsStr = $(blCornerDivSelector).css("bottom");
            var newBottomPixels = parseInt(bottomPixelsStr) - 1;
            $(blCornerDivSelector).css("bottom", "" + newBottomPixels+ "px");

            var brCornerDivSelector = "#" + thisId + "_br";
            bottomPixelsStr = $(brCornerDivSelector).css("bottom");
            newBottomPixels = parseInt(bottomPixelsStr) - 1;
            $(brCornerDivSelector).css("bottom", "" + newBottomPixels+ "px");
        }
        // end section added by S Swett

      }
      else  //canvasCorners returns a DOM element
        $$.append(canvasCorners(cs,r,bw,bc,bg));

      if(this.style.position != "absolute")
        this.style.position = "relative";

       this.style.zoom = 1; // give it a layout in IE

       if($.browser.msie && settings.fixIE) {
          var ow = $$.outerWidth();
          var oh = $$.outerHeight();

          if(ow%2 == 1) {
            incrementProperty($$, "padding-right", 1);
            incrementProperty($$, "margin-right", 1);
          }

          if(oh%2 == 1) {
            incrementProperty($$, "padding-bottom", 1);
            incrementProperty($$, "margin-bottom", 1);
          }
        }

      }

    );

  }
})(jQuery); 
