Edit in JSFiddle

function main() {
    Ab = assembleStiffnessMatrixAndLoadVector();
    var solution = solveLinearSystem(Ab[0], Ab[1]);
    displaySolution(solution);
}

function assembleStiffnessMatrixAndLoadVector() {

    var vertex2Border = [];
    for (i = 0; i < border.length; ++i) {
        vertex2Border[border[i]] = 1;
    }

    var nbVertices = vertices.length / 2,
        nbTriangles = triangles.length / 3;

    var A = numeric.rep([nbVertices, nbVertices], 0);
    var b = numeric.rep([nbVertices], 0);

    for (var ti = 0; ti < nbTriangles; ++ti) {

        var q = [];
        for (i = 0; i < 3; ++i) {
            var si = 3 * ti + i,
                sj = 3 * ti + ((i + 1) % 3);
            q[i] = [vertices[2 * triangles[si]] - vertices[2 * triangles[sj]],
            vertices[2 * triangles[si] + 1] - vertices[2 * triangles[sj] + 1]];
        }

        var area = 0.5 * numeric.det([q[0], q[1]]);

        for (i = 0; i < 3; ++i) {
            var vi = triangles[3 * ti + i];
            if (vertex2Border[vi] != 1) {
                for (j = 0; j < 3; ++j) {
                    var vj = triangles[3 * ti + j];
                    if (vertex2Border[vj] != 1) {
                        var qi = (i + 1) % 3,
                            qj = (j + 1) % 3;
                        A[vi][vj] += numeric.dot(q[qi], q[qj]) / (4 * area);
                    }
                }
                b[vi] += -area / 3;
            }
        }
    }

    return [A, b];
}

function solveLinearSystem(A, b) {
    return numeric.ccsLUPSolve(numeric.ccsLUP(numeric.ccsSparse(A)), b);
}

var c_w, c_h, prMatrix, mvMat, mvMatLoc, rotMat;

function displaySolution(sol) {

    var solMin = sol[0],
        solMax = sol[0];

    for (i = 0; i < sol.length; ++i) {
        if (sol[i] < solMin) {
            solMin = sol[i];
        } else if (sol[i] > solMax) {
            solMax = sol[i];
        }
    }

    function anim() {
        drawScene();
        requestAnimationFrame(anim);
    }

    initGL();
    transl = -1.5;
    c_w = window.innerWidth - 50;
    c_h = window.innerHeight - 10;
    canvas.width = c_w;
    canvas.height = c_h;

    var prog_show = gl.createProgram();
    gl.attachShader(prog_show, getShader(gl, "shader-vs"));
    gl.attachShader(prog_show, getShader(gl, "shader-fs"));
    gl.linkProgram(prog_show);
    gl.useProgram(prog_show);

    var posLocation = gl.getAttribLocation(prog_show, "aPos");
    gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
    gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(posLocation);

    var solLocation = gl.getAttribLocation(prog_show, "aSol");
    gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(sol), gl.STATIC_DRAW);
    gl.vertexAttribPointer(solLocation, 1, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(solLocation);

    gl.uniform1f(gl.getUniformLocation(prog_show, 'solMin'), solMin);
    gl.uniform1f(gl.getUniformLocation(prog_show, 'solMax'), solMax);

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(triangles), gl.STATIC_DRAW);

    prMatrix = new CanvasMatrix4();
    prMatrix.perspective(45, c_w / c_h, 0.1, 100);
    gl.uniformMatrix4fv(gl.getUniformLocation(prog_show, "prMatrix"),
    false, new Float32Array(prMatrix.getAsArray()));
    mvMatrix = new CanvasMatrix4();
    rotMat = new CanvasMatrix4();
    rotMat.makeIdentity();
    rotMat.rotate(-45, 1, 0, 0);

    mvMatLoc = gl.getUniformLocation(prog_show, "mvMatrix");

    gl.enable(gl.DEPTH_TEST);
    gl.depthFunc(gl.LEQUAL);
    gl.clearDepth(1.0);
    gl.clearColor(0, 0, 0, 1);

    anim();
}

function drawScene() {
    gl.viewport(0, 0, c_w, c_h);

    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    rotMat.rotate(xRot / 3, 1, 0, 0);
    rotMat.rotate(yRot / 3, 0, 1, 0);
    rotMat.rotate(zRot, 0, 0, 1);
    yRot = xRot = zRot = 0;

    mvMatrix.makeIdentity();
    mvMatrix.translate(-0.5, -0.5, 0);
    mvMatrix.multRight(rotMat);
    mvMatrix.translate(0, 0, transl);
    gl.uniformMatrix4fv(mvMatLoc, false, new Float32Array(mvMatrix.getAsArray()));

    gl.drawElements(gl.TRIANGLES, triangles.length, gl.UNSIGNED_SHORT, 0);

    gl.flush();
}

main();
<body>
    <script id="shader-vs" type="x-shader/x-vertex">
        attribute vec2 aPos;
        attribute float aSol;
        varying float sol;

        uniform mat4 mvMatrix;
        uniform mat4 prMatrix;

        uniform float solMin, solMax;

        void main(void) {
            gl_Position = prMatrix * mvMatrix * vec4(aPos, 10. * aSol, 1.);
            sol = 1. - (aSol - solMin) / (solMax - solMin);
        }
    </script>
    <script id="shader-fs" type="x-shader/x-fragment">
        precision highp float;
        varying float sol;

        vec3 heatcolor() {

            float h = 4. * sol,
            s = 1.,
            v = 0.8,
            f = h - floor(h),
            p = v * (1. - s),
            q = v * (1. - s * f),
            t = v * (1. - s * (1. - f));

            if (h <= 1.) {
                return vec3(v, t, p);
            }

            if (h <= 2.) {
                return vec3(q, v, p);
            }

            if (h <= 3.) {
                return vec3(p, v, t);
            }

            return vec3(p, q, v);
        }

        void main(void) {
            gl_FragColor = vec4(heatcolor(), 1.);
        }
    </script>
    <canvas id="canvas" width="400" height="300"></canvas>
</body>

              

External resources loaded into this fiddle: