CSS callout connectors

by secretgspot

HTML

<link rel="stylesheet" href="http://static.maklarpaket.se/css/jquery-ui-custom.css">
<div id="anchor"></div>

<div class="ui-tooltip ui-tooltip-arrow-tc ui-widget ui-widget-content ui-corner-all">
    Drag me around the gray box
    <div class="ui-tooltip-arrow">
        <div class="ui-tooltip-arrow-fill">
        </div>
    </div>
</div>

CSS

body, html {
    font-size: 14px;
    font-family: Arial;
}

#anchor {
    position: absolute;
    height: 50px;
    width: 50px;
    border: 1px solid #666666;
    left: 45%;
    top: 45%;
    background-color: #ccc;
}


.ui-tooltip {
    padding: 8px;
    position: absolute;
    z-index: 9998;
    -o-box-shadow: 2px 2px 2px #ccc;
    -moz-box-shadow: 2px 2px 2px #ccc;
    -webkit-box-shadow: 2px 2px 2px #ccc;
    box-shadow: 2px 2px 2px #ccc;
    background: rgba(255,255,255,80);
    min-width: 100px;
    max-width: 200px;
}

.ui-tooltip-arrow {
    border-color: transparent;
    border-style: solid;
    border-width: 9px;
    height:0;
    width:0;
    position: absolute;
}

/* IE6 */
* .ui-tooltip-arrow {
    _border-left-color: pink;
    _border-bottom-color: pink;
    _border-right-color: pink;
    _filter: chroma(color=pink);
}

.ui-tooltip-arrow-fill {
    border-color: transparent;
    border-style: solid;
    border-width: 9px;
    height: 0;
    width: 0;
    position: absolute;
    left: -9px;
    bottom: -9px;
}

.ui-tooltip-arrow-tc .ui-tooltip-arrow {
    border-bottom-color: #666666;
    top: -19px;
    left: 100px;
}

.ui-tooltip-arrow-tc .ui-tooltip-arrow-fill {
    border-bottom-color: #ffffff;
    bottom: -10px;
}

.ui-tooltip-arrow-tr .ui-tooltip-arrow,
.ui-tooltip-arrow-tr .ui-tooltip-arrow-fill {
    border-right-width: 18px;
    border-top-width: 11px;
    border-bottom-width: 0;
}

.ui-tooltip-arrow-tr .ui-tooltip-arrow {
    border-right-color: #666666;
    top: -12px;
    left: 80%;
}

.ui-tooltip-arrow-tr .ui-tooltip-arrow-fill {
    border-right-width: 17px;
    border-top-width: 10px;
    border-right-color: #ffffff;
    bottom: -1px;
    left: -9px;
}

.ui-tooltip-arrow-tl .ui-tooltip-arrow,
.ui-tooltip-arrow-tl .ui-tooltip-arrow-fill {
    border-left-width: 18px;
    border-top-width: 11px;
    border-bottom-width: 0;
}

.ui-tooltip-arrow-tl .ui-tooltip-arrow {
    border-left-color: #666666;
    top: -12px;
    left:...

JavaScript

// refactor: merge getY and getX into one function - the calculations are the same, just t/b vs. l/r
function getY(y1, y1u, y2, y2u) {
    var retVal,    ori;
    
    if(y2 > y1 && y2u < y1u){
        retVal = y1 + (y2-y1) + 0.5*(y2u-y2);
        ori = "c";
    }else if(y2 < y1 && y2u > y1u) {
        retVal = y1 + 0.5*(y1u - y1);
        ori = "c";
    }else if(y2 > y1 && y2u > y1u){
        retVal = y1u - 0.5*(y1u - y2);
        ori = "b";
    }else{
        retVal = y1 + 0.5*(y2u-y1);
        ori = "t";
    }
    return ({
        cutY : retVal,
        orientation: ori
    });
};
            
function getX(x1,x1r,x2,x2r){
    var retVal, ori;
    
    if(x2 > x1 && x2r < x1r){
        retVal = x1 + (x2-x1) + 0.5*(x2r-x2);
        ori = "c";
    }else if(x2 < x1 && x2r > x1r) {
        retVal = x1 + 0.5*(x1r - x1);
        ori = "c";
    }else if(x2 > x1 && x2r > x1r){
        retVal = x1r - 0.5*(x1r - x2);
        ori = "r";
    }else{
        retVal = x1 + 0.5*(x2r-x1);
        ori = "l";
    }
    return ({
        cutX : retVal,
        orientation: ori
    });
};
        
function calc(x1, y1, w1, h1, x2, y2, w2, h2, offsetX, offsetY) {
    // corners
    var cutX = 0,
    cutY = 0,
    orientation = "lt";

    var x1r = x1 + w1;
    var y1u = y1 + h1;

    var x2r = x2 + w2;
    var y2u = y2 + h2;
    
    // right
    if(x2 > x1r){
    // below --> cornerarrow
        if(y2 > y1u){
            orientation = "br";
            offsetX = 0;
            offsetY += 4;
            cutX = x1r - 4;
            cutY = y1u;
        }
    
    // above --> cornerarrow
        else if(y1 > y2u){
            orientation = "tr";
            offsetX = 0;
            offsetY -= 26;
            cutX = x1r - 10;
            cutY = y1;
        }
    
    // right --> centerarrow
        else{
            offsetX += 4;
            offsetY = 0;
            cutX = x1r;
            var vals = getY(y1,y1u,y2,y2u);
            cutY = vals.cutY;
            orientation = "r" +...