JSFiddle - React, Tailwind, and code Playground

HTML

<script src="http://cloud.github.com/downloads/uxebu/bonsai/bonsai.iframe-0.3.6.min.js"></script>
<div id="stage"></div>

<script>
(function(){
  var s="script",
      i="code",
      n='\n',
      d=document,
      b=d.getElementsByTagName(s)[2].innerHTML.split(n);
    console.log(b.slice(1,b.length-2).join(n));
    d.write('<' + s + ' type="text/bonsaijs" id="' + i + '">' +
          b.slice(2,b.length-3).join(n)+'</'+s+'>')
  }
)();
</script>

<script>
  $(function() {
    var stage = document.getElementById('stage');
    bonsai.run(stage, {
      code: document.getElementById('code').innerHTML
    });
  });
</script>

JavaScript

// visual interactive demonstration of line intersection algorithm

// actual algo
function intersects(ax, ay, aax, aay, bx, by, bbx, bby){
  // http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect#answer-1968345
  var sax = aax - ax;
  var say = aay - ay;
  var sbx = bbx - bx;
  var sby = bby - by;

  var s = (-say * (ax - bx) + sax * (ay - by)) / (-sbx * say + sax * sby);
  var t = ( sbx * (ay - by) - sby * (ax - bx)) / (-sbx * say + sax * sby);

  if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
    var x = ax + (t*sax);
    var y = ay + (t*say);

    return {x:x, y:y};
  }

  return null;
}

// rest is interactive demo stuff
function showAB(ax, ay, aax, aay, bx, by, bbx, bby){
  var A = new Path().moveTo(ax, ay).lineTo(aax, aay).stroke('red', 1).addTo(stage);
  var B = new Path().moveTo(bx, by).lineTo(bbx, bby).stroke('blue', 1).addTo(stage);
  
  var A1 = {x:ax, y:ay, O:A};
  var A2 = {x:aax, y:aay, O:A};
  var B1 = {x:bx, y:by, O:B};
  var B2 = {x:bbx, y:bby, O:B};
  
  var point = intersects(ax, ay, aax, aay, bx, by, bbx, bby);
  var C = new Circle(point.x, point.y, 10).fill('green').addTo(stage);

  function update(){
    var point = intersects(A1.x, A1.y, A2.x, A2.y, B1.x, B1.y, B2.x, B2.y);
    if (point) C.attr({ x:point.x, y:point.y, opacity:1 });
    else C.attr('opacity', 0);
  }

  function drawPoint(N, P, PP, left){
    var c = new Circle(N.x, N.y, 10).fill('black').addTo(stage)
      .on('pointerdown', function(){
        var drag, up;
        var x = N.x, y = N.y;
        c.on('multi:drag', drag=function(e){
          N.x = x + e.diffX;
          N.y = y + e.diffY;
          c.attr({x:N.x, y:N.y});
          N.O.clear().moveTo(P.x, P.y).lineTo(PP.x, PP.y);
          update();
        })
        .on('pointerup', up=function(e){
          c.removeListener('multi:drag', drag);
          c.removeListener('pointerup', up);
        });
      });
  }

  drawPoint(A1, A1, A2, true);
  drawPoint(A2, A1, A2);
 ...