/**

 * RUZEE.Borders 0.16.1

 * (c) 2006 Steffen Rusitschka <steffen@rusitschka.de>

 *

 * RUZEE.Borders is freely distributable under the terms of an MIT-style license.

 * For details, see http://www.ruzee.com/

 */



/**

 * RUZEE.Borders for jQuery

 *

 * modified by Maeda Daisuke

 * 2007/10/09

 * maeda@ini.co.jp

 */



var RUZEE=window.RUZEE||{};

RUZEE.userAgent=navigator.userAgent.toLowerCase();

RUZEE.isIE=typeof window.RUZEE.isIE != 'undefined'

  ?window.RUZEE.isIE

  :RUZEE.userAgent.indexOf('msie')>=0

    && RUZEE.userAgent.indexOf('opera')==-1;



RUZEE.Borders={



  /**

   * Set to false to not draw the borders automatically on

   * domload when RUZEE.Events are available.

   */

  autoRender:true,



  /** Add mapping rules to be executed on render(). */

  add:function(mappings){

    for(rule in mappings){

      var rules=rule.split(',');

      for(var i=0; i<rules.length; ++i){

        var r=rules[i].replace(/^\s+|\s+$/,'');

        var ms=RUZEE.Borders.mappings[r]||{};

        for (m in mappings[rule]) ms[m]=mappings[rule][m];

        RUZEE.Borders.mappings[r]=ms;

      }

    }

  },



  /**

   * Render all added mapping rules into the DOM

   * If RUZEE.Events is not available, this method MUST be called in the

   * window.onload method (or with a similar technique)!

   * Note: Since v0.12, this method is asynchronous! If you need to do

   * stuff AFTER the rendering finished, do it inside the function you passed

   * in via the onfinished parameter.

   */

  render:function(onfinished){

    if(onfinished) RUZEE.Borders.onfinished=onfinished;

    var start=new Date().getTime();

    for(rule in RUZEE.Borders.mappings){

      

      //modified for jQuery START

			var rules = rule.split('|');

			var jQObj;

			if(rules[1]){

				jQObj = $(rules[0]).not(rules[1]);//jQueryで対象要素取得

			}else{

				jQObj = $(rule);//jQueryで対象要素取得

			}

				

      var e = new Array();

      for(i=0;i<jQObj.length;i++){//jQueryオブジェクトを通常オブジェクトとして取り出し

        e.push(jQObj[i]);

      }

      //modified for jQuery END

      

      var b=new RUZEE.Borders.Border(RUZEE.Borders.mappings[rule]);

      delete RUZEE.Borders.mappings[rule];

      b.calc(e);

      // if we are rendering for more than 3 seconds, give Firefox some time to get

      // rid of the "unresponsive script" message.

      if(new Date().getTime()-start>3000){

        setTimeout('RUZEE.Borders.render()',0);

        return;

      }

    }

    RUZEE.Borders.renderCalcs();

    if(RUZEE.Borders.onfinished) RUZEE.Borders.onfinished();

  },



  // ---- internal fields and methods ----



  /** the mappings: 'CSS rule' -> Border */

  mappings:{},



  /** The corner cache */

  cache:{},



  /** The completed calulations to render */

  calcs:[],



  /** if Dean Edward's cssQuery is available, use it */

  cssQuery:function(s){

    var c=s.charAt(0);

    if(c=='#'&&!(/\s/.test(s))) return [ document.getElementById(s.substr(1)) ];

    if(window.cssQuery) return window.cssQuery(s);



    alert("Don't know what to do with '"+s+"' Did you forget to include cssquery?");

    return [];

  },



  /** Add a completed calculation */

  addCalc:function(calc){

    RUZEE.Borders.calcs.push(calc);

  },



  renderCalcs:function(){

    for(var i=0; i<RUZEE.Borders.calcs.length; ++i){

      RUZEE.Borders.calcs[i]();

    }

    RUZEE.Borders.calcs=[];

  }

};



/** The Border class */

RUZEE.Borders.Border=function(d){

  var t=this;



  var _cornerRadius,_shadowRadius,_shadowPadding,_shadowShift,_coShadowS,

      _coBgIn,_coBorder,_coBgOut,

      _imgBgInURL,_imgBgInRepeat,_isL,_isR,_isT,_isB,_imgBgInURL,

      _cacheID,_psT,_psB,_wBorder,_height;



  /** Set the background image for element e to position x,y */

  var setBgImg=function(e,x,y){

    if(!_imgBgInURL) return;

    e.style.backgroundImage=_imgBgInURL;

    x=-x;y=-y;

    e.style.backgroundPosition=x+'px '+y+'px';

    if(_imgBgInRepeat) e.style.backgroundRepeat=_imgBgInRepeat;

  };



  /** Create a DIV with width w, height h, background color bg, overflow o */

  var crDiv=function(w,h,bg,o){

    var d=RUZEE.isXHTML

      ?document.createElementNS('http://www.w3.org/1999/xhtml','div')

      :document.createElement('div');

    d.style.padding=d.style.margin='0px';

    d.style.border='none';

    d.style.width=w?w:'auto';

    if(h) { d.style.height=h; d.style.fontSize="0"; d.style.lineHeight="0px"; }

    if(!bg) bg='transparent';

    d.style.background=bg;

    if(o) d.style.overflow=o;

    return d;

  };



  /** Create wrapper DIV around element c */

  var addLR=function(c,co,w,h,bgx,bgy){

    var e=crDiv(null,h,co);

    if(typeof bgx!='undefined') setBgImg(e,bgx,bgy);

    if(!w) w='1px';

    c.style.margin='0px '+(_isR?w:'0px')+' 0px '+(_isL?w:'0px');

    e.appendChild(c);

    return e;

  };



  /** Create the top (top==true) or bottom (top==false) of the border */

  var crTB=function(top){

    var ca=RUZEE.Borders.cache[_cacheID+'.'+top];

    if(ca){

      if(top){

        _psT=ca.ps;

      }else{

        _psB=ca.ps;

      }

      return ca.el.cloneNode(true);

    }

    var sh=top?-_shadowShift:_shadowShift;

    var cxc=_shadowPadding-_cornerRadius-1;

    var cxb=cxc;

    var cxe=cxc+_cornerRadius;

    var exb=0;

    var exe=cxc-1;

    var syc=_cornerRadius-_shadowPadding+sh+1;

    var yb,ye;

    var cwb=_wBorder;

    if(cwb==0) cwb=1;



    if(top){

      if(!_isT){

        _psT=1;

        return crDiv(null,'1px');

      }

      yb=syc+_shadowRadius-1;

      ye=cwb>_shadowRadius?syc+_shadowRadius-cwb-1:syc-1;

      yi=-1;

      _psT=yb-ye;

    }else{

      if(!_isB) {

        _psB=1;

        return crDiv(null,'1px');;

      }

      yb=cwb>_shadowRadius?syc+_shadowRadius-cwb:syc;

      yb=yb<0?yb:0;

      ye=syc+_shadowRadius;

      yi=1;

      _psB=ye-yb;

    }



    var e=crDiv(null, Math.abs(yb-ye)+'px',null,'hidden');

    for(var y=yb; y!=ye; y+=yi){

      var co;

      if(y<=_cornerRadius-cwb){

        co=_coBgIn;

      }else if(y<=_cornerRadius){

        co=_coBorder;

      }else if(y-syc<0){

        co=_coShadow;

      }else{

        co=rzBlend(_coShadow,_coBgOut,(y-syc)/_shadowRadius);

      }

      var line=crDiv(null,'1px',rzC2S(co),'hidden');

      var fstLine=line;

      var xbg=null;

      for(var x=0; x<_shadowRadius; ++x){

        var isIn=false, doBgImg=false;

        var sd, out=0;

        if(y<syc){

          sd=x;

        }else{

          sd=Math.sqrt(Math.sqr(x)+Math.sqr(y-syc));

        }

        if(_shadowRadius>_cornerRadius && sd<=_shadowRadius){

          co=rzBlend(_coShadow, _coBgOut, sd/_shadowRadius);

        }else{

          co=_coBgOut;

          out++;

        }

        if(y<=_cornerRadius){

          if(x>=exb && x<=exe){

            if(y>_cornerRadius-cwb){

              co=_coBorder;

            }else{

              isIn=true;

            }

          }else if(x>=cxb && x<=cxe){

            var cd=Math.sqrt(Math.sqr(x-cxc)+Math.sqr(y))-_cornerRadius;

            if(y<0){

              if(x-cxc>_cornerRadius-_wBorder){

                co=_coBorder;

              }else{ 

                isIn=true;

              }

            }else if(cd<-cwb){

              isIn=true;

            }else if(cd<-cwb+1){

              // first on border! do bgimg

/*              if(top&&_imgBgInURL){

                setBgImg=true;

              }else*/

                co=rzBlend(_coBgIn,_coBorder,cd+cwb);

            }else if(cd<0){

              co=_coBorder;

            }else if(cd<=1){

              co=rzBlend(_coBorder,co,cd);

            }else{

              out++;

            }

          }

        }else{

          out++;

        }

        if(!isIn&&line==fstLine&&y<=_cornerRadius-cwb&&top){

          setBgImg(fstLine,_shadowRadius-x,yb-y);

        }

        if(out>1){

          line=addLR(line,'transparent',(_shadowRadius-x)+'px');

          x=_shadowRadius; // done

        }else{

          if(!isIn){

            // fix a strange IE bug where the 12ths recursion seems to get lost...

            if(RUZEE.isIE&&x==_shadowRadius-12) line=addLR(line);

            line=addLR(line,rzC2S(co));

          }

          if(doBgImg) setBgImg(line,_shadowRadius-x,yb-y+1);

        }

      }

      e.appendChild(line);

    }

    var ce={ el:e, ps:top?_psT:_psB };

    RUZEE.Borders.cache[_cacheID+'.'+top]=ce;

    return e;

  };



  /** Create the left and right of the border */

  var crLR=function(e){

    var coBgInS=rzC2S(_coBgIn);

    var coBS=rzC2S(_coBorder);

    e.style.position='relative';

    if(_wBorder>0) e=addLR(e,coBS,_wBorder+'px');

    e.style.position='relative';

    for(var x=_shadowPadding; x<_shadowRadius; ++x){

      coS=rzC2S(rzBlend(_coShadow,_coBgOut,x/_shadowRadius));

      e=addLR(e,coS);

      e.style.position='relative';

    }

    return e;

  };



  var setEdges=function(ed){

    ed=ed?ed.toLowerCase():'lrtb';

    _isL=ed.indexOf('l')>=0;

    _isR=ed.indexOf('r')>=0;

    _isT=ed.indexOf('t')>=0;

    _isB=ed.indexOf('b')>=0;

  };



  /** Calculate the border around e */

  var calcP=function(e){

    RUZEE.isXHTML=typeof window.RUZEE.isXHTML != 'undefined'

      ?window.RUZEE.isXHTML

      :(/html\:/.test(document.getElementsByTagName('body')[0].nodeName));



    if(!e) return;

    if(e.constructor==Array){

      for(var i=0; i<e.length; ++i) calcP(e[i]);

      return;

    }



    // Get the bg image

    _imgBgInURL=rzGetStyle(e,'background-image');

    if(_imgBgInURL&&_imgBgInURL=='none') _imgBgInURL=null;

    if(_imgBgInURL){

      _imgBgInRepeat=rzGetStyle(e,'background-repeat');

    }

    _coBgIn=rzS2C(rzGetBg(e));

    _coBgOut=rzS2C(rzGetBg(e.parentNode));

    var borderCSS='border-'+(_isT?'top-':'bottom-');

    var bs=rzGetStyle(e,borderCSS+'style','none');

    if(bs && bs!='' && bs!='none' && bs!='hidden'){

      _coBorder=rzS2C(rzGetStyle(e,borderCSS+'color','black'));

      _wBorder=rzPX2I(rzGetStyle(e,borderCSS+'width','1px'));

    }else{

      _coBorder=_coBgIn;

      _wBorder=0;

    }

    _coShadow=_coShadowS=='.fade'?_coBorder:rzS2C(_coShadowS);



    _cacheID=

      rzC2S(_coBgIn)+'.'+rzC2S(_coBgOut)+'.'+

      rzC2S(_coBorder)+'.'+rzC2S(_coShadow)+'.'+

      _wBorder+'.'+_isL+_isR+_isT+_isB+'.'+

      _cornerRadius+'.'+_shadowRadius+'.'+

      _shadowPadding+'.'+this.shadowShift+'.'+

      _imgBgInURL+'.'+_imgBgInRepeat;



    var eb=crDiv(); // e border (2nd!)

    var elOb=crDiv(); // out border

    var elO=crDiv(); // out

    var elI=crDiv(); // in

    var elCw=crDiv(); // content wrapper

    var elCb=crDiv(); // content border

    var elC=crDiv(); // content



    eb.style.position=elC.style.position=elCw.style.position='relative';

    elC.style.zIndex=2; // Konq fix



    eb.appendChild(elOb);

    elOb.appendChild(crDiv(null,'1px')); // filler div (1)

    elOb.appendChild(elO);

    elOb.appendChild(crDiv(null,'1px')); // filler div (2)

    elI.appendChild(elCw);

    elCw.appendChild(elCb);

    elCb.appendChild(elC);



    elO.appendChild(crTB(true));

    var elTB=crLR(elI);

    elO.appendChild(elTB);

    elO.appendChild(crTB(false));

    var psLR=_shadowRadius-_shadowPadding+_wBorder;

    var psL=_isL?psLR:0;

    var psR=_isR?psLR:0;

    var isTB=_isT&&_isB;

    var psT=_psT;

    var psB=_psB;



    var bgImgY=_psT;

    setBgImg(elI,psL,bgImgY);

    elI.style.backgroundColor=rzC2S(_coBgIn);



    // work around for other browsers for sebs problem TODO:check it's working

    // add clearer DIVs

    var end=crDiv('1px','1px');

    elI.insertBefore(end,elCw);

    elI.appendChild(end.cloneNode(true));

    psT++; psB++;



    if(_height){

      elC.style.height=_height+'px';

    }

    var update=function(l,ps){

      var padL='padding-'+l; var padCC=rzCC(padL);

      var marL='margin-'+l; var marCC=rzCC(marL);

      var borL='border-'+l+'-width'; var borCC=rzCC(borL);



      var pad=rzGetStyle(e,padL);

      var borPx=rzPX2I(rzGetStyle(e,borL));

      var borPxNeg=(l=='top'||l=='bottom')?-borPx-1:-borPx; // -1 because of filler div (1) and (2)

      if(!_isB && l=='bottom') borPx-=2; // why???

      if(!_isT && l=='top') borPx-=2; // why???



      eb.style[marCC]=borPx+'px';

      elO.style[marCC]='-'+pad;

      elOb.style[marCC]=borPxNeg+'px';

      elCw.style[marCC]=(-ps)+'px';

      elC.style[marCC]=pad;

      elCb.style[marCC]=borPx+'px';



      return function(){

        // IE quirks... why oh why?

        if(RUZEE.isIE){

           if(l=='top') elOb.style[marCC]='-1px'; // remove top border

           if(l=='bottom') e.style[padCC]='1px'; // reduce bottom padding

        }

      };

    };



    var funcs=[update('top',psT),update('bottom',psB),

               update('left',psL),update('right',psR)];

    RUZEE.Borders.addCalc(function(){

      for(var i=0; i<funcs.length; ++i) funcs[i]();

      e.style.border='none';

      e.style.background='transparent';

      e.style.backgroundImage='none';

      if(RUZEE.isIE){

        e.style.height='1%';

      }

      e.style.position='relative';

      e.appendChild(eb);

      while (e.childNodes.length>1){

        elC.appendChild(e.removeChild(e.childNodes[0]));

      }

    });

  };



  var pub={

    init:function(d){

      var rad=d.cornerRadius||8;

      _height=d.height||0;

      _shadowShift=0;

      setEdges(d.edges||'lrtb');

      switch(d.borderType){

        case 'simple':

          _cornerRadius=_shadowRadius=_shadowPadding=rad;

          _coShadowS='000';

          break;

        case 'shadow':

          var sw=d.shadowWidth||8;

          _cornerRadius=rad;

          _shadowRadius=rad+sw*2;

          _shadowPadding=rad+sw;

          _shadowShift=Math.round(sw/2);

          _coShadowS=d.shadowColor||'000';

          break;

        case 'fade':

          _cornerRadius=_shadowPadding=1;

          _shadowRadius=rad;

          _coShadowS='.fade';

          break;

        case 'glow':

          _cornerRadius=_shadowPadding=rad;

          _shadowRadius=rad+(d.glowWidth||rad);

          _coShadowS=d.glowColor||'fff';

          break;

        default:

          alert('Unknown borderType: '+d.borderType);

      }

    },



    calc:calcP,



    /** Render the border around e */

    render:function(e){

      t.calc(e);

      RUZEE.Borders.renderCalcs();

    },



    // DEPRECATED STUFF - WILL BE REMOVED IN ONE OF THE NEXT RELEASES!

    draw:function(e,edges){

      setEdges(edges?edges.toLowerCase():'lrtb');

      if(typeof e=='string'){

        if(e.charAt(0)!='.') e='#'+e;

        e=RUZEE.Borders.cssQuery(e);

      }

      t.render(e);

    }

  };



  pub.init(d);

  delete pub.init;

  for(m in pub) t[m]=pub[m];

}; // of Border class



// add an event handler for render() if RUZEE.Events are available

if(RUZEE.Events){

  RUZEE.Events.add(window,'domload',function(){

    if(RUZEE.Borders.autoRender) RUZEE.Borders.render();

  });

}



// internal tools



Math.sqr=function(x){

  return x*x;

};



function rzCC(s){

  for(var exp=/-([a-z])/; exp.test(s); s=s.replace(exp,RegExp.$1.toUpperCase()));

  return s;

};



function rzGetStyle(e,a,d){

  if(e==null) return d;

  var v=null;

  if(document.defaultView && document.defaultView.getComputedStyle){

    var cs=document.defaultView.getComputedStyle(e,null);

    if(cs && cs.getPropertyValue) v=cs.getPropertyValue(a);

  }

  if(!v && e.currentStyle) v=e.currentStyle[rzCC(a)];

  return v?v:d?d:null;

};



function rzGetBg(e){

  var v=rzGetStyle(e,'background-color');

  // KHTML bug fix: transparent is #000000 - if you want black, use #010101 in your CSS.

  // Safari work around: transparent is 'rgba(0, 0, 0, 0)'

  while (!v || v=='transparent' || v=='#000000' || v=='rgba(0, 0, 0, 0)'){

    if(e==document.body) v='fff'; else {

      e=e.parentNode;

      v=rzGetStyle(e,'background-color');

    }

  }

  return v;

};



function rzPX2I(px){

  if(!px) return 0;

  var p=/\s*(\d\d*)px/.exec(px);

  if(p) return parseInt(p[1]);

  return 0;

};



function rzS2C(s,d){

    if (!s) return d?rzS2C(d):[0,0,0,0];

    if (s.charAt(0)=='#') s=s.substr(1,6);

    s=s.replace(/ /g,'').toLowerCase();

    // The CSS 2.1 colors

    var COLORS = {

         aqua:'00ffff', black:'000000', blue:'0000ff', fuchsia:'ff00ff',

         gray:'808080', green:'008000', lime:'00ff00', maroon:'800000',

         navy:'000080', olive:'808000', orange:'ffa500', purple:'800080',

         red:'ff0000', silver:'c0c0c0', teal:'008080', white:'ffffff',

         yellow:'ffff00'

    };

    for (var key in COLORS) if (s==key) s=COLORS[key];



    var p=/^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/.exec(s);

    if(p) return [parseInt(p[1]),parseInt(p[2]),parseInt(p[3]),parseInt(p[4])];

    var p=/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/.exec(s);

    if(p) return [parseInt(p[1]),parseInt(p[2]),parseInt(p[3]),255];

    p=/^(\w{2})(\w{2})(\w{2})$/.exec(s);

    if(p) return [parseInt(p[1],16),parseInt(p[2],16),parseInt(p[3],16),255];

    p=/^(\w{1})(\w{1})(\w{1})$/.exec(s);

    if(p) return [parseInt(p[1]+p[1],16),parseInt(p[2]+p[2],16),parseInt(p[3]+p[3],16),255];

    return d?rzS2C(d):[0,0,0,0];

};



function rzC2S(c){

  if(typeof c=='string') return c;

  r='0'+c[0].toString(16);

  g='0'+c[1].toString(16);

  b='0'+c[2].toString(16);

  return '#'

    +r.substring(r.length-2)

    +g.substring(g.length-2)

    +b.substring(b.length-2);

};



function rzBlend(a,b,w){

  return Array(

    Math.round(a[0]+(b[0]-a[0])*w),

    Math.round(a[1]+(b[1]-a[1])*w),

    Math.round(a[2]+(b[2]-a[2])*w),

    Math.round(a[3]+(b[3]-a[3])*w));

};



// DEPRECATED STUFF - WILL BE REMOVED IN ONE OF THE NEXT RELEASES!

function rzCrSimpleBorder(rad){

  return new RUZEE.Borders.Border({ borderType:'simple', cornerRadius:rad });

};



function rzCrShadowBorder(rad,smar,coShadowS){

  return new RUZEE.Borders.Border({

    borderType:'shadow', cornerRadius:rad, shadowWidth:smar, shadowColor:coShadowS });

};



function rzCrFadeBorder(rad){

  return new RUZEE.Borders.Border({ borderType:'fade', cornerRadius:rad });

};



function rzCrGlowBorder(rad,gmar,coGlowS){

  return new RUZEE.Borders.Border({ borderType:'glow', cornerRadius:rad, glowWidth:gmar, glowColor:coGlowS });

};

