Bezier curve editor

by halfsoft

HTML

<label for="strokeWidth">Stroke:</label>
<input id="strokeWidth" value="5" size="1" />
<button id="animateBut">Animate</button>
<button id="showCodeBut">Print code</button>
<button id="loadCodeBut">Load code</button>
<button id="addCurveBut">Add curve</button>
<button id="delCurveBut">Remove mode</button>
<input type="checkbox" id="snappingEnabled" checked />
<label for="snappingEnabled">snapping</label>
<br/>
<label for="uploadimage">Map Image</label>
<input type="file" size="65" id="uploadimage" />
<br/>
<canvas id="canvas" height="800" width="800" class="bezier"></canvas>
<div id="dialog" title="Load curve data">
    <textarea id="loadData"></textarea>
</div>
<div id="printCodeDialog" title="Curve data">
    <textarea id="printCodeDialogText"></textarea>
</div>

CSS

canvas {
      border: 1px solid black;
  }
  body {
      -webkit-touch-callout: none;
      -webkit-user-select: none;
      -khtml-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;
  }
  #dialog {
      overflow:hidden;
  }
  #loadData {
      width: 100%;
      height: 100%;
      font-size: x-small;
  }
  #printCodeDialogText {
      width: 100%;
      height: 100%;
      font-size: x-small;
  }

JavaScript

(function () {
    function curvePoint() {
        this.x = 0;
        this.y = 0;
        this.computeDistance = function (pt) {
            var xd = pt.x - this.x,
                yd = pt.y - this.y;
            return Math.sqrt(xd * xd + yd * yd);
        };
    }

    function curve() {
        this.isValid = false;

        this.p1 = new curvePoint();
        this.p2 = new curvePoint();
        this.cp1 = new curvePoint();
        this.cp2 = new curvePoint();

        this.set = function (params) {
            params = params.replace(/[^0-9,]/g, '');
            params = params.replace(/,,/g, '');
            var split = params.split(",");
            this.p1.x = 1 * split[0];
            this.p1.y = 1 * split[1];
            this.cp1.x = 1 * split[2];
            this.cp1.y = 1 * split[3];
            this.cp2.x = 1 * split[4];
            this.cp2.y = 1 * split[5];
            this.p2.x = 1 * split[6];
            this.p2.y = 1 * split[7];

            this.isValid = (split.length >= 8);
        };
    }

    var current = 0;
    var curves = [];

    var selectionRadius;
    var deleteMode = false;
    var canvas, ctx, code, style, drag = null,
        dPoint;

    var animating = false;
    var currentAnimCurve = 0;

    var animationSpeed = 1000;
    var animStart = 0;
    var date = new Date();
    
    function animate() {
        currentAnimCurve = 0;
        animating = !animating;
        animStart = date.getTime();
    }

    function addCurve() {
        var curveParams = prompt("Enter curve params", "100,250,150,100,350,100,400,250");
        var tCurve = new curve();
        tCurve.set(curveParams);


        if (tCurve.isValid) curves.push(tCurve);
        DrawCanvas();
    }

    function delCurve() {
        deleteMode = !deleteMode;
        DrawCanvas();
    }


    // define initial points
    function Init() {
        // default styles
        style = {
            curve: {
                width: 10,
                color: "#00F"
        ...