Lagrange Polynomial Interpolation

This calculates the Lagrange polynomial from the control points. Simply drag them around

HTML

<script src="https://gist.github.com/raw/995144/4e63de3ec684c96d02899b34056d5d7a984efb0c/lagrange.js"></script>
<div id="widget">
    <canvas id="widget-canvas" width="450" height="300"></canvas>
</div>
<button id="add">Add Control Point</button>

CSS

#widget {
    position: absolute; 
    top: 40px;
    left: 20px;
    width: 450px;
    height: 300px;
    background-color: #dcdcd4;
}

#add {
    position: absolute;
    left: 20px;
    top: 350px;
}

.point {
    position: absolute;
    margin: -3px;
    top: 7px;
    left: 7px;
    width: 6px;
    height: 6px;
    border-radius: 3px;
    background-color: red;
}

.point-wrapper {
    position: absolute;
    width: 14px;
    height: 14px;
}

JavaScript

// class to enable dragging of the control points
var Movable = function(target) {
    
    this.onmove = function() {};

    var self = this;
    target.onmousedown = function(event) {
        var initialXOffset = target.offsetLeft - event.pageX;
        var initialYOffset = target.offsetTop - event.pageY;

        document.onmousemove = function(event) {
            var x = event.pageX + initialXOffset;
            var y = event.pageY + initialYOffset;
            target.style.left = x + 'px';
            target.style.top = y + 'px';
            
            self.onmove(x, y);
        };

        document.onmouseup = function() {
            document.onmousemove = null;
            document.onmouseup = null;
        };

        return false;
    };
};

// renders the polynomial
function drawCurve(ctx, curve, w, h) {
    var incr = 5;
    
    ctx.clearRect(0, 0, w, h);
    
    ctx.beginPath();
    
    ctx.moveTo(0, h - curve.valueOf(0) * h);
    
    for (var x = incr; x <= w; x += incr) {
        ctx.lineTo(x, h - curve.valueOf(x/w) * h);
    }
    
    ctx.stroke();
}

// creates the dom elements for a control point
function createControlPointEl(x, y) {
    var el = document.createElement('div');
    el.setAttribute('class', 'point-wrapper');
    el.style.left = x + 'px';
    el.style.top = y + 'px';
    
    var p = document.createElement('div');
    p.setAttribute('class', 'point');
    
    el.appendChild(p);
    canvas.parentNode.appendChild(el);
    
    return el;
}

// adds a new control point
function addControlPoint(index) {
    var w = parseInt(canvas.width);
    var h = parseInt(canvas.height);
    
    var x = Math.random() * w;
    var y = Math.random() * h;
    
    var el = createControlPointEl(x, y);
    
    var movable = new Movable(el);

    function getPointUpdateFunc(index) {
        return function(x, y) {
            var bias = 7;
            lagrange.changePoint(index, (x + bias) / w,
                                 1 - (y + bias) /...