Object.getOwnPropertyNames(Math).map(function(p) {
window[p] = Math[p];
});
var DIM = 900, EXPF = 1.3, RPF = .028,
κ = 1.2, ρ = 4,
ζ = document, rp = round(RPF*DIM),
np = 4, demo, ε,
svg = ζ.querySelector('svg'),
rect, curve, msl = null, mdrg = null;
var Meas = function(id, c0) {
var bg, lbl, cc, c0 = c0 || 0, id = id;
this.select = function() {
if(lbl) lbl.classList.toggle('sel');
if(bg) bg.classList.toggle('sel');
if(cc) cc.classList.toggle('sel');
};
this.init = (function() {
var bb, r, pad, ptt, attr, sel;
lbl = ζ.getElementById('lbl-' + id);
if(lbl) {
lbl.textContent = DIM;
bg = ζ.getElementById('bg-' + id);
bb = lbl.getBBox();
c0 -= 2(κ - 1)bb.height;
attr = (id === 'w') ? 'y' : 'x';
lbl.setAttribute(attr, c0);
if(bg) {
bb = lbl.getBBox();
r = .4RPFDIM;
pad = .5(κ - 1)bb.height;
ptt = 2*pad;
bg._attr({
'x': round(bb.x - pad),
'y': round(bb.y - pad),
'width': round(bb.width + ptt),
'height': round(bb.height + ptt),
'rx': r, 'ry': r
});
}
sel = '.token--val .hl--' + id;
cc = ζ.querySelector(sel);
}
})();
};
var Point = function(el, x, y, r) {
var el = el, lbl, bg, on, cc, q = 0,
r = r || rp, cx, cy,
selected = false;
this.moveTo = function(x, y) {
var cls, _new, β, bb, ptt, pad;
cx = x || 0;
cy = y || 0;
if(el)
el._attr({'cx': cx, 'cy': cy});
if(lbl) {
if(el.id.indexOf('p') !== -1) {
β = atan2(y, x);
if(β < 0) β += 2PI;
q = ~~(2β/PI)
cls = lbl.className.baseVal;
_new = 'rq' + q;
if(cls.indexOf('rq') < 0) {
cls += ' ' + _new;
}
else {
cls = cls.replace(/rq./, _new);
}
lbl.className.baseVal =
lbl.className.animVal = cls;
}
this.posLbl((q + .5).5PI);
this.updateLbl([x, y]);
if(bg) {
bb = lbl.getBBox();
pad = .5(κ - 1)bb.height;
ptt = 2*pad;
bg._attr({
'x': round(bb.x - pad),
'y': round(bb.y - pad),
'width': round(bb.width + ptt),
'height': round(bb.height + ptt)
});
}
}
if(on) {
on._attr({'x': cx, 'y': cy})
}
if(cc) { cc.textContent = [cx, cy]; }
};
this.updateLbl = function(txt) {
if(lbl) lbl.textContent = txt;
};
this.posLbl = function(θ) {
if(lbl) {
lbl._attr({
'x': 1 + ~~(cx + 2rcos(θ)),
'y': 1 + ~~(cy + 2rsin(θ))
});
}
};
this.attachCode = function(s) {
var sel, s = s || ',';
if(el) {
sel = '.token--val .hl--' + el.id;
cc = ζ.querySelector(sel);
cc.textContent = [cx, cy].join(s);
}
};
this.coord = function(f) {
if(f) return [cx, cy];
return {'x': cx, 'y': cy};
};
this.select = function() {
selected = !selected;
if(el) {
el.classList.toggle('sel');
if(lbl) {
lbl.classList.toggle('sel');
}
if(on) {
on.classList.toggle('sel');
}
if(bg) {
bg.classList.toggle('sel');
}
if(cc) {
cc.classList.toggle('sel');
}
}
};
this.selected = function() {
return selected;
};
this.init = (function() {
var lid, onid, bgid;
if(el) {
el._attr({'r': r});
lid = 'lbl-' + el.id;
lbl = ζ.getElementById(lid);
bgid = 'bg-' + el.id;
bg = ζ.getElementById(bgid);
if(bg) {
bg._attr({
'rx': .4r, 'ry': .4r
});
}
onid = 'on-' + el.id;
on = ζ.getElementById(onid);
}
})();
this.moveTo(x, y);
};
var Guide = function(el, points) {
var el = el, points = points,
nl = points.length;
this.movePointTo = function(i, x, y) {
var c;
if(el) {
c = el._attr('points').split(' ');
c[i] = [x, y].join();
el._attr({'points': c.join(' ')});
}
points[i].moveTo(x, y);
};
this.points = function() {
return points;
};
this.init = (function() {
var coords = [];
for(var i = 0; i < nl; i++) {
coords.push(points[i].coord(1));
}
if(el) {
el._attr({
'points': coords.join(' ')
});
}
})();
};
var CCurve = function(el, guide) {
var el = el, guide = guide,
points = guide.points(),
nl = points.length,
prf = ['M', 'C', ''];
this.movePointTo = function(i, x, y) {
var d, p;
if(el) {
d = el._attr('d').split(' ');
p = d[i].charAt(0);
p = (p === 'M' || p === 'C') ? p : '';
d[i] = p + [x, y];
el._attr({'d': d.join(' ')});
}
guide.movePointTo(i, x, y);
};
this.select = function(i) {
points[i].select();
};
this.points = function() {
return points;
};
this.init = (function() {
var d = [], c;
if(el) {
for(var i = 0; i < nl; i++) {
c = points[i].coord(1);
d.push(prf[min(2, i)] + c);
}
el._attr({'d': d.join(' ')});
}
})();
};
var Demo = function() {
var tl, orig, a0, a1, meas = {};
this.tl = function() { return tl; };
this.size = function() {
var r = ρε, w = 5r, h=4*r;
a0._attr({
'markerWidth': w,
'markerHeight': h
});
a1._attr({
'markerWidth': w,
'markerHeight': h
});
};
this.select = function(id) {
meas[id].select();
};
this.meas = function(id) {
return meas[id];
};
this.arrow = (function(){
a0 = ζ.getElementById('arrow0'),
a1 = ζ.getElementById('arrow1');
})();
this.viewBox = (function() {
var sz = EXPFDIM, o = -.5sz,
vb_tl = ζ.getElementById('vb-tl'),
vb_w = ζ.getElementById('vb-w'),
vb_h = ζ.getElementById('vb-h'),
tlel = ζ.getElementById('tl');
svg._attr({
'viewBox': [o, o, sz, sz].join(' ')
});
o = -.5*DIM;
vb_tl.textContent = [o, o].join(' ');
vb_w.textContent =
vb_h.textContent = DIM;
tl = new Point(tlel, o, o, round(.35*rp));
tl.attachCode(' ');
})();
this.delim = (function() {
var rd = ζ.getElementById('delim'),
invp = round(100/EXPF),
o = round(-.5*invp);
rd._attr({
'x': o + '%',
'y': o + '%',
'width': invp + '%',
'height': invp + '%'
});
})();
this.axes = (function() {
var cf = (EXPF - 1)/1.5 + 1,
c1 = round(50/cf) + '%',
c2 = '-' + c1,
ax = ζ.getElementById('axis-x'),
ay = ζ.getElementById('axis-y');
ax._attr({'x1': c1, 'x2': c2});
ay._attr({'y1': c1, 'y2': c2});
})();
this.origin = (function() {
var el = ζ.getElementById('o');
orig = new Point(el, 0, 0, round(.25*rp));
})();
this.minit = (function() {
var f = (EXPF - 1)/6, cf = -(.5 + f),
o = .5DIM, c0 = cfDIM, bb,
w = ζ.getElementById('w'),
h = ζ.getElementById('h');
w._attr({
'x1': -o, 'y1': c0,
'x2': o, 'y2': c0
});
h._attr({
'y1': -o, 'x1': c0,
'y2': o, 'x2': c0
});
meas.w = new Meas('w', c0);
meas.h = new Meas('h', c0);
})();
};
Node.prototype._attr = function(a) {
if(typeof a === 'string')
return this.getAttribute(a);
if(typeof a === 'object') {
for(p in a) {
this.setAttribute(p, a[p]);
}
}
};
var rand = function(max, min, int) {
var max = ((max - 1) || 0) + 1,
min = min || 0,
gen = min + (max - min)*random();
return int ? (~~gen) : gen;
};
var size = function() {
rect = svg.getBoundingClientRect();
ε = (EXPF*DIM)/rect.width;
demo.size();
};
var toggleSel = function(e) {
var t = e.target, cl = t.className, i;
if(cl) {
if(typeof cl === 'object') {
cl = cl.baseVal;
}
if(cl.indexOf('hl--p') !== -1) {
i = ~~cl.match(/[0-9]/)[0];
msl = curve.points()[i];
curve.select(i);
return;
}
}
if(t.id.indexOf('tl') !== -1) {
msl = demo.tl();
demo.tl().select();
return;
}
i = t.id.match(/-[w|h]$/);
if(i) {
i = i[0].charAt(1);
demo.select(i);
msl = demo.meas(i);
}
};
(function init() {
var pts = [], g, el,
r = .4DIM, e = .3r, β, x, y
demo = new Demo;
size();
for(var i = 0; i < np; i++) {
el = ζ.getElementById('p' + i);
β = (i + 1.5).5PI;
x = round(rcos(β) + rand(e, -e));
y = round(rsin(β) + rand(e, -e));
pts.push(new Point(el, x, y));
pts[i].attachCode();
};
el = ζ.getElementById('guide');
g = new Guide(el, pts);
el = ζ.getElementById('curve');
curve = new CCurve(el, g);
})();
addEventListener('resize', size, false);
addEventListener('mouseover', toggleSel, false);
addEventListener('mousedown', function(e) {
var t = e.target;
if(t.id.match(/^p[0-3]/)) {
mdrg = ~~t.id.charAt(1);
}
}, false);
addEventListener('mousemove', function(e) {
var x, y;
if(mdrg != null) {
x = (e.clientX - rect.left)/rect.width ;
x = round(EXPFDIM(x- .5));
y = (e.clientY - rect.top)/rect.height;
y = round(EXPFDIM(y - .5));
curve.movePointTo(mdrg, x, y);
}
}, false);
addEventListener('mouseup', function(e) {
if(mdrg != null) {
mdrg = null;
}
}, false);
addEventListener('mouseout', toggleSel, false);