Edit in JSFiddle

(function ($, window) {
    
    function Vector2d(x, y) {
        this.x = x;
        this.y = y;
    }
    
    Vector2d.prototype.dot = function(vector) {
        return this.x * vector.x + this.y * vector.y;
    }
        
    Vector2d.prototype.add = function(vector) {
        return new Vector2d(this.x + vector.x, this.y + vector.y);
    }
    
    Vector2d.prototype.subtract = function(vector) {
        return new Vector2d(this.x - vector.x, this.y - vector.y);
    }
        
    Vector2d.prototype.length = function() {
        return Math.sqrt(this.x*this.x + this.y*this.y);
    }
        
    Vector2d.prototype.multiply = function(scaleFactor) {
        return new Vector2d(this.x * scaleFactor, this.y * scaleFactor);
    }
        
    Vector2d.prototype.normalize = function() {
        var len = this.length();
        if (len == 0) {
            this.x = 0;
            this.y = 0;
            return this;
        } else {
            this.x = this.x / len;
            this.y = this.y / len;
            return this;
        }
    }
    
    function Ball(pos, vel, radius, mass, color) {
        this.pos = pos;
        this.vel = vel;
        this.radius = radius;
        this.color = color;
        this.mass = mass;
    }
    
    Ball.prototype.render = function(ctx) {
        ctx.fillStyle = this.color;
        ctx.strokeStyle = this.color;
        ctx.beginPath();
        ctx.arc(this.pos.x, this.pos.y, this.radius, 0, Math.PI*2, false);
        ctx.fill();
    }
    
    Ball.prototype.resolveCollision = function(ball) {
        var delta = this.pos.subtract(ball.pos);
        var r = this.radius + ball.radius;
        var dist2 = delta.dot(delta);
        
        if (dist2 > r*r) { return; /* not colliding */ } 
        
        var d = delta.length();
        var mtd;
        
        if (d != 0) {
            mtd = delta.multiply(((this.radius + ball.radius)-d)/d);
        } else { // special case, balls are exactly on top of eachother
            d = ball.radius + this.radius - 1.0;
            delta = new Vector2d(this.radius + ball.radius, 0);
            mtd = delta.multiply(((this.radius + ball.radius)-d)/d);
        }
        
        // resolve intersection
        var im1 = 1 / this.mass;
        var im2 = 1 / ball.mass;
        
        // push/pull them apart
        this.pos = this.pos.add(mtd.multiply(im1 / (im1 + im2)));
        ball.pos = ball.pos.subtract(mtd.multiply( im2 / (im1 + im2)));
        
        // impact speed
        var v = this.vel.subtract(ball.vel);
        var vn = v.dot(mtd.normalize());
            
        // sphere intersecting but moving away from each other already
        if (vn > 0.0) { return; }
            
        var i = (-(1.0 + Bouncer.RESTITUTION) * vn) / (im1 + im2);
        var impulse = mtd.multiply(i);
        
        this.vel = this.vel.add(impulse.multiply(im1));
        ball.vel = ball.vel.subtract(impulse.multiply(im2));
    }
      
    function Bouncer(ctx) {                                     
        this.ctx = ctx;
        this.balls = [];
        this.now = undefined;
        this.last = undefined;
        this.launchBall = undefined;
    }
    
    Bouncer.GRAVITY = 700; /* pixels per second */
    Bouncer.RESTITUTION = 0.75;
    
    Bouncer.prototype.init = function() {
        var self = this;
        
        $(self.ctx.canvas).bind('mousedown', function(e) {
            var x = e.pageX-$(self.ctx.canvas).offset().left;
            var y = e.pageY-$(self.ctx.canvas).offset().top;  
            self.launchBall = new Ball(new Vector2d(x, y), new Vector2d(x, y), 10, 1, "#00FF00");
        });
        
        $(document).bind('mouseup', function(e) {
            if (self.launchBall) {
                
                var x = e.pageX-$(self.ctx.canvas).offset().left;
                var y = e.pageY-$(self.ctx.canvas).offset().top; 
                
                self.addBall(new Vector2d(self.launchBall.pos.x, self.launchBall.pos.y), 
                             new Vector2d((self.launchBall.vel.x - self.launchBall.pos.x) * 5,   
                                          (self.launchBall.vel.y - self.launchBall.pos.y) * 5), 
                             self.launchBall.radius, 
                             1,
                             "#FF0000");
                
                self.launchBall = undefined;
            }
        });
                
        $(document).bind('mousemove', function(e) {
            if (self.launchBall) {
                var x1 = self.launchBall.pos.x;
                var y1 = self.launchBall.pos.y;
                var x2 = e.pageX-$('#canvas').offset().left;
                var y2 = e.pageY-$('#canvas').offset().top;
                var dx = Math.abs(x2 - x1);
                var dy = Math.abs(y2 - y1);
                
                //console.log("x1:" + x1 + " y1:" + y1 + " xV2:" + self.launchBall.xVel + " yV2:" + self.launchBall.yVel);
                //console.log("x2:" + x2 + " y2: " + y2 + " dx:" + dx + " dy:" + dy);
                
                if ((x2 - x1) < 0) {
                    self.launchBall.vel.x = x1 + dx;
                } else {
                    self.launchBall.vel.x = x1 - dx;
                }
                
                if ((y2 - y1) < 0) {
                    self.launchBall.vel.y = y1 + dy;
                } else {
                    self.launchBall.vel.y = y1 - dy;
                }
            }
        });
        
        this.last = new Date();
        this.step();
    }
                       
    Bouncer.prototype.render = function() { 
        // Modify canvas dimensions
        this.ctx.canvas.width = window.innerWidth - 50;
        this.ctx.canvas.height = window.innerHeight - 50;
        
        // Clear
        this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);  
        
        // Render balls
        for(var i = 0; i < this.balls.length; i++) {
            this.balls[i].render(this.ctx);
        }
        
        // Render launching ball
        if (this.launchBall) {
            this.launchBall.render(this.ctx);
            this.ctx.moveTo(this.launchBall.pos.x, this.launchBall.pos.y);
            this.ctx.lineTo(this.launchBall.vel.x, this.launchBall.vel.y);
            this.ctx.strokeStyle = "#FF6633";
            this.ctx.stroke();
        }
    }
        
    Bouncer.prototype.step = function() {
        this.now = + new Date;
        var dt = (this.now - this.last) / 1000;
        this.last = this.now;
  
        this.tick(dt);
        this.render(); 
        
        var self = this;
        setTimeout(function() { self.step() }, 0);
    }
        
    Bouncer.prototype.tick = function(dt) {
        for(var i = 0; i < this.balls.length; i++) {
            this.balls[i].vel.y += Bouncer.GRAVITY * dt;
            this.balls[i].pos.y += this.balls[i].vel.y * dt;
            this.balls[i].pos.x += this.balls[i].vel.x * dt;
        }  
        
        this.checkWallCollisions();
        this.checkBallCollisions();
    }
        
    Bouncer.prototype.checkBallCollisions = function() {
        for(var i = 0; i < this.balls.length; i++) {
            for(var j = i; j < this.balls.length; j++) {
                this.balls[i].resolveCollision(this.balls[j]);
            }
        }
    }
        
    Bouncer.prototype.checkWallCollisions = function() {
         for(var i = 0; i < this.balls.length; i++) {
             if ((this.balls[i].pos.x- this.balls[i].radius) < 0) {
                 this.balls[i].pos.x = this.balls[i].radius;
                 this.balls[i].vel.x = -this.balls[i].vel.x * Bouncer.RESTITUTION;
             }
             
             if ((this.balls[i].pos.x + this.balls[i].radius) > this.ctx.canvas.width) {
                 this.balls[i].pos.x = this.ctx.canvas.width - this.balls[i].radius;
                 this.balls[i].vel.x = -this.balls[i].vel.x * Bouncer.RESTITUTION;    
             }
             
             if ((this.balls[i].pos.y - this.balls[i].radius) < 0) {
                 this.balls[i].pos.y = this.balls[i].radius;
                 this.balls[i].vel.y = -this.balls[i].vel.y * Bouncer.RESTITUTION;
             }
             
             if ((this.balls[i].pos.y + this.balls[i].radius) > this.ctx.canvas.height) {
                 this.balls[i].pos.y = this.ctx.canvas.height - this.balls[i].radius;
                 this.balls[i].vel.y = -this.balls[i].vel.y * Bouncer.RESTITUTION;    
             }               
         }
    }
        
    Bouncer.prototype.addBall = function(pos, vel, radius, mass, color) {   
        this.balls.push(new Ball(pos, vel, radius, mass, color));
    }
    
    $(function() {
        var canvas = $('#canvas')[0];
        var ctx = canvas.getContext('2d');   
        
        var bouncer = new Bouncer(ctx, canvas);
        bouncer.init();
    });
    
}(jQuery, window));
<canvas id="canvas" width="600" height="600" />