/** * RuzeeBorders 0.13 * (c) 2006 Steffen Rusitschka <steffen@rusitschka.de> ** RuzeeBorders is freely distributable under the terms of an MIT-style license. * For details, see http://www.ruzee.com/ */
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.isStrict=typeof window.RUZEE.isStrict != 'undefined'
?window.RUZEE.isStrict
:(document.compatMode?document.compatMode!='BackCompat':RUZEE.userAgent.indexOf('safari')==-1?false:true);
RUZEE.Borders={
autoRender:true,
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:function(onfinished){
if(onfinished) RUZEE.Borders.onfinished=onfinished;
var start=new Date().getTime();
for(rule in RUZEE.Borders.mappings){
var e=RUZEE.Borders.cssQuery(rule);
var b=new RUZEE.Borders.Border(RUZEE.Borders.mappings[rule]);
delete RUZEE.Borders.mappings[rule];
b.calc(e);
if(new Date().getTime()-start>3000){
setTimeout('RUZEE.Borders.render()',0);
return;
}
}
RUZEE.Borders.renderCalcs();
if(RUZEE.Borders.onfinished) RUZEE.Borders.onfinished();
},
Border:function(d){
var rad=d.cornerRadius||8;
this.shadowShift=0;
this.setEdges(d.edges||'lrtb');
this.height=d.height||0;
var b=null;
switch(d.borderType){
case 'simple':
this.cornerRadius=this.shadowRadius=this.shadowPadding=rad;
this.coShadowS='000';
break;
case 'shadow':
var sw=d.shadowWidth||8;
this.cornerRadius=rad;
this.shadowRadius=rad+sw*2;
this.shadowPadding=rad+sw;
this.shadowShift=Math.round(sw/2);
this.coShadowS=d.shadowColor||'000';
break;
case 'fade':
this.cornerRadius=this.shadowPadding=1;
this.shadowRadius=rad;
this.coShadowS='.fade';
break;
case 'glow':
this.cornerRadius=this.shadowPadding=rad;
this.shadowRadius=rad+(d.glowWidth||rad);
this.coShadowS=d.glowColor||'fff';
break;
default:
alert('Unknown borderType: '+d.borderType);
}
},
mappings:{},
cache:{},
calcs:[],
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 [];
},
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=[];
}
};
RUZEE.Borders.Border.prototype={
setBgImg:function(e,x,y){
if(!this.imgBgInURL) return;
e.style.backgroundImage=this.imgBgInURL;
x=-x;y=-y;
e.style.backgroundPosition=x+'px '+y+'px';
if(this.imgBgInRepeat) e.style.backgroundRepeat=this.imgBgInRepeat;
},
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.display='block';
d.style.border='none';
d.style.width=w?w:'auto';
if(h) { d.style.height=h; d.style.fontSize=h; }
if(!bg) bg='transparent';
d.style.background=bg;
if(o) d.style.overflow=o;
return d;
},
addLR:function(c,co,w,h,bgx,bgy){
var e=this.crDiv(null,h,co);
if(typeof bgx!='undefined') this.setBgImg(e,bgx,bgy);
if(!w) w='1px';
c.style.margin='0px '+(this.isR?w:'0px')+' 0px '+(this.isL?w:'0px');
e.appendChild(c);
return e;
},
crTB:function(top){
var ca=RUZEE.Borders.cache[this.cacheID+'.'+top];
if(ca){
if(top){
this.psT=ca.ps;
this.inSh=ca.inSh;
}else{
this.psB=ca.ps;
}
return ca.el.cloneNode(true);
}
var sh=top?-this.shadowShift:this.shadowShift;
var cxc=this.shadowPadding-this.cornerRadius-1;
var cxb=cxc;
var cxe=cxc+this.cornerRadius;
var exb=0;
var exe=cxc-1;
var syc=this.cornerRadius-this.shadowPadding+sh+1;
var yb,ye;
if(top){
if(!this.isT){
this.psT=0;
return;
}
yb=syc+this.shadowRadius-1;
ye=syc-1;
yi=-1;
this.inSh=syc-1;
this.psT=yb-ye;
}else{
if(!this.isB) {
this.psB=0;
return;
}
yb=syc<0?syc:0;
ye=syc+this.shadowRadius;
yi=1;
this.psB=ye-yb;
}
var cwb=this.wBorder;
if(cwb==0) cwb=1;
var e=this.crDiv(null, Math.abs(yb-ye)+'px',null,'hidden');
for(var y=yb; y!=ye; y+=yi){
var co;
if(y<=this.cornerRadius-cwb){
co=this.coBgIn;
}else if(y<=this.cornerRadius){
co=this.coBorder;
}else if(y-syc<0){
co=this.coShadow;
}else{
co=rzBlend(this.coShadow,this.coBgOut,(y-syc)/this.shadowRadius);
}
var line=this.crDiv(null,'1px',rzC2S(co),'hidden');
var fstLine=line;
var xbg=null;
for(var x=0; x<this.shadowRadius; ++x){
var isIn=false, setBgImg=false;
var sd, out=0;
if(y<syc){
sd=x;
}else{
sd=Math.sqrt(Math.sqr(x)+Math.sqr(y-syc));
}
if(this.shadowRadius>this.cornerRadius && sd<=this.shadowRadius){
co=rzBlend(this.coShadow, this.coBgOut, sd/this.shadowRadius);
}else{
co=this.coBgOut;
out++;
}
if(y<=this.cornerRadius){
if(x>=exb && x<=exe){
if(y>this.cornerRadius-cwb){
co=this.coBorder;
}else{
isIn=true;
}
}else if(x>=cxb && x<=cxe){
var cd=Math.sqrt(Math.sqr(x-cxc)+Math.sqr(y))-this.cornerRadius;
if(y<0){
if(x-cxc>this.cornerRadius-this.wBorder){
co=this.coBorder;
}else{
isIn=true;
}
}else if(cd<-cwb){
isIn=true;
}else if(cd<-cwb+1){
if(top&&this.imgBgInURL){
setBgImg=true;
}else
co=rzBlend(this.coBgIn,this.coBorder,cd+cwb);
}else if(cd<0){
co=this.coBorder;
}else if(cd<=1){
co=rzBlend(this.coBorder,co,cd);
}else{
out++;
}
}
}else{
out++;
}
if(!isIn&&line==fstLine&&y<=this.cornerRadius-cwb&&top){
this.setBgImg(fstLine,this.shadowRadius-x,yb-y);
}
if(out>1){
line=this.addLR(line,'transparent',(this.shadowRadius-x)+'px');
x=this.shadowRadius; // done
}else{
if(!isIn){
if(RUZEE.isIE&&x==this.shadowRadius-12) line=this.addLR(line);
line=this.addLR(line,rzC2S(co));
}
if(setBgImg) this.setBgImg(line,this.shadowRadius-x,yb-y+1);
}
}
e.appendChild(line);
}
var ce={ el:e, ps:top?this.psT:this.psB };
if(top) ce.inSh=this.inSh;
RUZEE.Borders.cache[this.cacheID+'.'+top]=ce;
return e;
},
crLR:function(e){
var coBgInS=rzC2S(this.coBgIn);
var coBS=rzC2S(this.coBorder);
if(this.wBorder>0) e=this.addLR(e,coBS,this.wBorder+'px');
for(var x=this.shadowPadding; x<this.shadowRadius; ++x){
coS=rzC2S(rzBlend(this.coShadow,this.coBgOut,x/this.shadowRadius));
e=this.addLR(e,coS);
}
return e;
},
setEdges:function(ed){
ed=ed?ed.toLowerCase():'lrtb';
this.isL=ed.indexOf('l')>=0;
this.isR=ed.indexOf('r')>=0;
this.isT=ed.indexOf('t')>=0;
this.isB=ed.indexOf('b')>=0;
},
calc: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) this.calc(e[i]);
return;
}
this.inSh=0;
this.imgBgInURL=rzGetStyle(e,'background-image');
if(this.imgBgInURL&&this.imgBgInURL=='none') this.imgBgInURL=null;
if(this.imgBgInURL){
this.imgBgInRepeat=rzGetStyle(e,'background-repeat');
}
this.coBgIn=rzS2C(rzGetBg(e));
this.coBgOut=rzS2C(rzGetBg(e.parentNode));
var borderCSS='border-'+(this.isT?'top-':'bottom-');
var bs=rzGetStyle(e,borderCSS+'style','none');
if(bs && bs!='' && bs!='none' && bs!='hidden'){
this.coBorder=rzS2C(rzGetStyle(e,borderCSS+'color','black'));
this.wBorder=rzPX2I(rzGetStyle(e,borderCSS+'width','1px'));
}else{
this.coBorder=this.coBgIn;
this.wBorder=0;
}
this.coShadow=this.coShadowS=='.fade'?this.coBorder:rzS2C(this.coShadowS);
this.cacheID=
rzC2S(this.coBgIn)+'.'+rzC2S(this.coBgOut)+'.'+
rzC2S(this.coBorder)+'.'+rzC2S(this.coShadow)+'.'+
this.wBorder+'.'+this.isL+this.isR+this.isT+this.isB+'.'+
this.cornerRadius+'.'+this.shadowRadius+'.'+
this.shadowPadding+'.'+this.shadowShift+'.'+
this.imgBgInURL+'.'+this.imgBgInRepeat;
var wr=this.crDiv();
var cwr=this.crDiv();
this.psT=0;
this.psB=0;
if(this.isT) wr.appendChild(this.crTB(true));
wr.appendChild(this.crLR(cwr));
if(this.isB) wr.appendChild(this.crTB(false));
var psLR=this.shadowRadius-this.shadowPadding+this.wBorder;
var psL=this.isL?psLR:0;
var psR=this.isR?psLR:0;
var isTB=this.isT&&this.isB;
if(!isTB)this.inSh=0;
var psT=isTB?Math.floor((this.psT+this.psB+this.inSh)/2):this.psT+Math.floor(this.inSh/2);
var psB=this.psB+this.psT+this.inSh-psT;
var cwrbg=cwr;
if(this.inSh!=0){
var up1=this.crDiv(); cwr.appendChild(up1);
var up2=this.crDiv(); up1.appendChild(up2);
cwr.style.position=up1.style.position='relative';
up1.style.top=up2.style.marginBottom=this.inSh+'px';
if(RUZEE.isIE) cwr.style.height='1%';
cwrbg=up1; cwr=up2;
}
this.setBgImg(cwrbg,psL,this.psT+this.inSh);
cwrbg.style.backgroundColor=rzC2S(this.coBgIn);
if(RUZEE.isIE){
e.style.height=cwr.style.height='1%'; // fix IE 3px jog when floated
}else{
var end=this.crDiv(null,'1px');
end.style.marginBottom='-1px';
e.appendChild(end);
cwr.appendChild(end.cloneNode(true));
}
if(this.height>0){
var h=(RUZEE.isStrict?this.height:(this.height-this.psB-this.psT));
if(h>0) cwr.style.height=h+'px';
}
var funcs=[
rzUpdatePad(e,wr,cwr,'top',psT),
rzUpdatePad(e,wr,cwr,'bottom',psB),
rzUpdatePad(e,wr,cwr,'left',psL),
rzUpdatePad(e,wr,cwr,'right',psR)];
RUZEE.Borders.addCalc(function(){
for(var i=0; i<funcs.length; ++i) funcs[i]();
e.style.background='transparent';
e.style.backgroundImage='none';
e.appendChild(wr);
while (e.childNodes.length>1){
cwr.appendChild(e.removeChild(e.childNodes[0]));
}
});
},
render:function(e){
this.calc(e);
RUZEE.Borders.renderCalcs();
},
draw:function(e,edges){
this.setEdges(edges?edges.toLowerCase():'lrtb');
if(typeof e=='string'){
if(e.charAt(0)!='.') e='#'+e;
e=RUZEE.Borders.cssQuery(e);
}
this.render(e);
}
};
if(RUZEE.Events){
RUZEE.Events.add(window,'domload',function(){
if(RUZEE.Borders.autoRender) RUZEE.Borders.render();
});
}
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');
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 rzUpdatePad(org,newo,newi,l,subPx,isSet){
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(org,padL);
var bor=rzGetStyle(org,borL);
var r=rzPX2I(pad)+rzPX2I(bor);
var v=r-subPx;
v=(v<0?0:v)+'px';
if(RUZEE.isStrict){
newo.style[marCC]=(-r)+'px';
newi.style[padCC]=v;
return function(){
org.style[borCC]='0px';
org.style[padCC]=r+'px';
};
}else{
newi.style[padCC]=v;
return function(){
org.style[borCC]=org.style[padCC]='0px';
};
}
};
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();
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));
};
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 });
};
