<|start_filename|>lecture4/domcollect-solution.js<|end_filename|>

// Get the elements of a certain tag rooted at the node 'id'
var getElementsRootedAt = function(tagName, id) {
	var el = document.getElementById(id);
	if (el==null) return null;
	var t = el.getElementsByTagName(tagName);
	return t;
};

// Search for a text in the DOM-subtree rooted at node 
// Only textnodes are searched here. Return true if found
var search = function(node, text) {
	var found = false;
	if (node.nodeType == 3) {
		if (node.nodeValue == text) found = true;
	} else {
		var cn = node.childNodes;
		if (cn) {
			for (var i=0; i<cn.length; i++) {
				found = found || search(cn[i], text);
			}
		}	
	};
	return found;	
};

// Concatenate all the text in the subtree of a node
var concatenateSubtree = function(node) {
	var result = "";
	if (! node) return result;
	if (node.nodeType == 3) {
		result = result + node.nodeValue;
	} else {
		var cn = node.childNodes;
		if (cn) {
			for (var i=0; i<cn.length; i++) {
				result = result + concatenateSubtree(cn[i]);
			}
		}
	};
	return result;
};

// Solution to class activity on Slide 30
// Concatenate all the textnodes in the siblings of text node with the ID= id
var concatenateSiblings = function(id, includeSubtrees) {
	var node = document.getElementById(id);
	var result = "";
	var parent = node.parentNode;
	if (parent && parent.childNodes) {
		var siblings = parent.childNodes;
		for (var i=0; i< siblings.length; i++) {
			var sibling = siblings[i];
			if (sibling && sibling.nodeType == 3) {
				result = result + sibling.nodeValue;
			}
			if (includeSubtrees) {
				result = result + concatenateSubtree(sibling);
			}
		}
	}
	return result;
};


window.onload = function() {
	// Find all div elements rooted at the DOM with id=one	
	var s = getElementsRootedAt("div", "one");
	console.log(s);

	// Find the text "is" starting from node one
	var found = search(document.getElementById("one"), " vsp "); 	
	console.log(found);	

	// Concatenate the siblings of text nodes rooted at node one
	var str = concatenateSiblings("one", true);
	console.log(str);
};


<|start_filename|>lecture5/dom.js<|end_filename|>
// Solution to class activity

var popup = function(name) {
	var foo = alert;
	return function(e) {
		console.log(this);
		foo(name + " : " + e.target);
	}
};

window.onload = function() {
	alert("document finished loading");
	var setupBtn = document.getElementById("reset");
	var runBtn = document.getElementById("increment");
	var doneBtn = document.getElementById("done");
	setupBtn.addEventListener( "click", popup("setup"), false);
	runBtn.addEventListener( "click", popup("increment"), false);
	doneBtn.addEventListener( "click", popup("done"), false);
}


<|start_filename|>lecture8/calculate.js<|end_filename|>
var Calculator = function() { 
	this.lastResult = 0;
	this.sum = function(a, b) {
		this.lastResult = a + b;
		return this.lastResult;
	};
	this.product = function(a, b) {
		this.lastResult = a * b;
		return this.lastResult;
	};
	this.add = function(a) {
		this.lastResult = this.lastResult + a;
		return this.lastResult;
	};
	this.multiply = function(a) {
		this.lastResult = this.lastResult * a;
		return this.lastResult;
	};
	this.toString = function() {
		return "lastResult : " + this.lastResult;
	};
};
 
module.exports = Calculator;


<|start_filename|>lecture2/variables.js<|end_filename|>
console.log(":: variables.js ::");

var foo = 0;
console.log(foo); // 0

foo = foo + 2;
console.log(foo); // 2

foo = "My name is ";
foo += "Julien";
console.log(foo); // "My name is Julien"

var bar = foo + ":-)"
console.log(bar); // "My name is Julien :-)"


<|start_filename|>lecture6/shapes.js<|end_filename|>
// Implementation using classical (constructor) inheritance

var Point = function (x, y) {
	this.x = x;
	this.y = y;
	this.area = function() {
		return 0;
	}
};  

Point.prototype.toString = function() {
	return "(" + this.x + "," + this.y + ")";
};

console.log(Point);

var Circle = function(x, y, r) {
	Point.call(this, x, y);
	this.r = r;
	this.area = function() {
		return 3.1412 * this.r * this.r;
	}
};

Circle.prototype = new Point();
Circle.prototype.constructor = Circle;

Circle.prototype.toString = function() {
	return "(" + this.x + "," + this.y + ", " + this.r + ")";
}

var Ellipse = function(x, y, r1, r2) { 
	Circle.call(this, x, y, r1);
	this.r2 = r2;
	this.area = function() {
		return 3.1412 * this.r * this.r2;
	} 

};

Ellipse.prototype = new Circle();
Ellipse.prototype.constructor = Ellipse;
Ellipse.prototype.toString = function() {
	return "(" + this.x + "," + this.y + ", " + this.r + "," + this.r2 + ")";
} 

function iterateOverProperties(obj) {
	var e; var str = "{ ";
	var proto = Object.getPrototypeOf(obj);
	for (e in obj) {
		if ( ( obj.hasOwnProperty(e) ) 
		  && ( typeof(obj[e]) != "function") 
		  && (e in proto ) ) {
				str = str + e + " = " + obj[e] + " , ";
		} 
	}
	str = str + " } ";
	return str;
}

var p = new Point(10, 20);
var c = new Circle(20, 30, 5);
var e = new Ellipse(5, 10, 5, 2);


document.writeln( "Point p = " + p );
document.writeln( "p's area = " + p.area() );

console.log( Object.getPrototypeOf(p) );
console.log( "p instanceof Point = " + (p instanceof Point) );
console.log( "p instanceof Object = " + (p instanceof Object) );

document.writeln( "Circle c = " + c );
document.writeln( "c's area = " + c.area() );
console.log( Object.getPrototypeOf(c) );
console.log( "p instanceof Circle = " + (p instanceof Circle) );
console.log( "c instanceof Point = " + (c instanceof Point) );


document.writeln( "Ellipse e = " + e );
document.writeln( "e's area = " + e.area() );
console.log( Object.getPrototypeOf(e) );
console.log( "e instanceof Ellipse = " + (e instanceof Ellipse) );
console.log( "e instanceof Circle = " + (e instanceof Circle) );
console.log( "e instanceof Point = " + (e instanceof Point) );

delete e.area;  // Now this reverts to circle's area
document.writeln( "e's area (wrong!) = " + e.area() );

console.log( "p's properties " + iterateOverProperties(p) );
console.log( "c's properties " + iterateOverProperties(c) );
console.log( "e's properties " + iterateOverProperties(e) );


<|start_filename|>lecture8/wordCount-noStream.js<|end_filename|>
var fs = require("fs");
var length = 0;
var fileName = "sample.txt";
fs.readFile(fileName, function(err, buf) {
		if (err) throw err;	
		length = buf.length;;
		console.log("Number of characters read = " + length);
	}
);

console.log("End of program");


<|start_filename|>lecture5/interval.js<|end_filename|>
// Solution to the class activity using setItnerval

var invokeTimes = function(func, noTimes, time) {
    console.log("Setting up interval " + noTimes + " " + time);
    var count = 0;
    var interval;
    var intervalHandler = function() {
	console.log( "invocation " + count);
	func(count);
	count = count + 1;
	if (count == noTimes) {
	    clearInterval(interval);
	}
    };
    if (noTimes >0)
	interval = setInterval(intervalHandler, time);
};

var setup = function() {
    invokeTimes( function(i) { alert("hello " + i); }, 10, 1000 );
}

setup();


<|start_filename|>lecture6/shapes2.js<|end_filename|>
// This shows how to use Prototypal inheritance in JavaScript

var Point = {
	init: function(x, y) {
		this.x = x;
		this.y = y;
	},
	area : function() {
		return 0;
	},
	toString: function() {
		return "(" + this.x + "," + this.y + ")";
	}
}; 


var Circle = Object.create(Point);
Circle.init = function(x, y, r) {
	Point.init.call(this, x, y);
	this.r = r;
};
Circle.area = function () {
	return 3.14 * this.r * this.r;
};	
Circle.toString =  function() {
	return "(" + this.x + "," + this.y + ", " + this.r + ")";
};

var Ellipse = Object.create(Circle);
Ellipse.init = function(x, y, r, r2) {
	Circle.init.call(this, x, y, r);
	this.r2 = r2;
};	
Ellipse.area = function() { 
	return 3.14 * this.r * this.r2;
};	
Ellipse.toString = function() {
	return "(" + this.x + "," + this.y + ", " + this.r + " , " + this.r2 + ")";
};

var p = Object.create(Point);
p.init(10, 20);
document.writeln( "Point p = " + p );
document.writeln( "p's area = " + p.area() );
console.log( Object.getPrototypeOf(p) );

var c = Object.create(Circle);
c.init(20, 30, 5);
document.writeln( "Circle c = " + c );
document.writeln( "c's area = " + c.area() );
console.log( Object.getPrototypeOf(c) );

var e = Object.create(Ellipse);
e.init(5, 10, 5, 2);
document.writeln( "Ellipse e = " + e );
document.writeln( "e's area = " + e.area() );
console.log( Object.getPrototypeOf(e) ); 
console.log( Object.getPrototypeOf( Object.getPrototypeOf(e) ) );

var e2 = Object.create(Ellipse);
e2.init(0, 0, 0, 0); 
document.writeln( "Ellipse e = " + e );
document.writeln( "Ellipse e2 = " + e2 );
console.log( Object.getPrototypeOf(e2) ); 
console.log( Object.getPrototypeOf( Object.getPrototypeOf(e2) ) );

function iterateOverProperties(obj) {
	var e; var str = "{ ";
	var proto = Object.getPrototypeOf(obj);
	console.log(proto);
	for (e in obj) {
		if ( ( obj.hasOwnProperty(e) ) 
		  && ( typeof(obj[e]) != "function") 
		  && (e in proto ) ) {
				str = str + e + " = " + obj[e] + " , ";
		} 
	}
	str = str + " } ";
	return str;
}

console.log( "p's properties " + iterateOverProperties(p) );
console.log( "c's properties " + iterateOverProperties(c) );
console.log( "e's properties " + iterateOverProperties(e) );


<|start_filename|>lecture8/streamCopy.js<|end_filename|>
var fs = require("fs");
if (! fs) process.exit(1);

var fileName1 = "sample.txt";
var fileName2 = "sample-copy.txt";
var readStream = fs.createReadStream(fileName1);
var writeStream = fs.createWriteStream(fileName2);

readStream.on("data", function(blob) {
			console.log("Read " + blob.length);
			writeStream.write(blob);
		} );

readStream.on("end", function() {
		console.log("End of stream");
		writeStream.end();
	} );



<|start_filename|>lecture8/wordFind2.js<|end_filename|>
// Searches for a given string in a file. Called with two command line arguments: fileName and string to search for.
// Does not assume length of the string being searched < length of buffer being read at any time 

var fs = require('fs');
if (! fs) process.exit(1);

if (process.argv.length < 4) {
    console.log("Syntax: fileName string");
    process.exit(2);
}

var fileName = process.argv[2];
var textToFind = process.argv[3];	
var readStream = fs.createReadStream(fileName);;
var index = -1;
var matchIndex = 0;

readStream.on("data", function(blob) {
    var str = blob.toString();
    console.log("Read " + blob.length + " bytes");
    for (var i=0; i<str.length; ++i) {
	// Increment matchIndex for every contiguous character that matches
	if (str[i]== textToFind[matchIndex]) { 
	    matchIndex++;
	    if (matchIndex==textToFind.length) {
		// If all the characters match, we have found it
		index = i;
		readStream.emit("end");	
		break;
	    }
	} else if (matchIndex > 0){
	    // reset the matchIndex even if a single character doesn't match
	    matchIndex = 0;
	}
    }
} );

readStream.on("end", function() {
    if (index>=0)
	console.log("Found string " + textToFind); 
    else	
	console.log("Did not find string " + textToFind);
} );

readStream.on("error", function() {
    console.log("Error occurred when reading from file " + fileName);
} );

console.log("End of program");


<|start_filename|>lecture2/functions.js<|end_filename|>
console.log(":: functions ::");

function areaOfCircle(radius) {
    var PI = 3.1416;
    return PI * square(radius);
}

function square(x) {
    return x*x;
}

var A = areaOfCircle(2);
console.log("Area of circle of radius 2 = " + A);

// ----------

function areaOfCircle2(radius) {
    var PI = 3.1416;
    
    function square(x) {
	return x*x;
    }
    
    return PI * square(radius);
}

var B = areaOfCircle2(2);
console.log("Area of circle of radius 2 = " + B);

// ----------

function areaOfCircle3(radius) {
    var PI = 3.1416;
    
    // This is a Nested function
    function PIsquare(x) {
	var sq = x * x;
	return PI * sq; 
    }
    
    return PIsquare(radius); 
}

var C = areaOfCircle3(2);
console.log("Area of circle of radius 2 = " + C);


<|start_filename|>lecture8/eventCounter.js<|end_filename|>
// Solution to class activity on Slide 18

var EventEmitter = require('events').EventEmitter;
if (! EventEmitter) process.exit(1);
var fs = require("fs");

function registerEvents(emitter, keywords) {
	var counts = [];
	var incrementCounter = function(index) {
		return function() {
			counts[index]++;		
		}
	}
	for (var i=0; i<keywords.length; ++i) {
		var keyword = keywords[i];
		counts[i] = 0;
		emitter.on(keyword, incrementCounter(i) );	
	}
	return function() {
		console.log("Counters: ");	
		for (var i=0; i<counts.length; i++) {
			var keyword = keywords[i];
			console.log("\tCount[ " + keyword + " ]\t=\t" + counts[i]);
		}
	}
};

// Read the contents of the file and setup the handlers to scan for words
var text = fs.readFileSync("sample.txt").toString();
var keywords = ["a", "the", "this", "is", "an", "test"];

var e = new EventEmitter();
var printCounts = registerEvents(e, keywords);

// Read the file contents and emit it to the stream one word at a time
printCounts();
// e.emit("the");
// e.emit("a");
// e.emit("the");
var words = text.split(" ");
words.forEach( function(word){
		e.emit(word.trim());	
	});
printCounts();

 



<|start_filename|>lecture8/httprequest.js<|end_filename|>
// http server demonstrating the use of streams within serveRequest

var http = require('http');
if (! http) throw { msg: "Cannot find http" };

// Create a simple function to serve a request
var serveRequest = function(request, response) {
	console.log("Calling serveRequest : " + request.url );
	request.on("end", function() {
		console.log("Request ended");
		response.write("Ok");
		response.end();	
	});
};

// Start the server on the port and setup response
var port = 8080;
var server = http.createServer(serveRequest);
server.listen(port);


<|start_filename|>lecture2/runall.html<|end_filename|>
<html>
  <head>
    <title>My JavaScript Page</title>
  </head>
  <body>
    <!-- Include our JS demos -->

    Please open your browser's log window (found in the dev tools) to view the output of each of these JS scripts.
    
    <script type="text/javascript" src="variables.js"></script>
    <script type="text/javascript" src="arithmetic.js"></script>
    <script type="text/javascript" src="functions.js"></script>
    <script type="text/javascript" src="arrays.js"></script>
    <script type="text/javascript" src="conditionals.js"></script>
    <script type="text/javascript" src="loops.js"></script>
    <script type="text/javascript" src="objects.js"></script>
    <script type="text/javascript" src="classactivity.js"></script>
    
  </body>
</html>


<|start_filename|>lecture2/arithmetic.js<|end_filename|>
console.log(":: arithmetic.js ::");

var foo = 5;
foo = foo + 1 - 2 * (4 - 1);
console.log(foo); // 0

var bar = 4;
bar += bar++;
console.log(bar); // 8

var baz = 4;
baz += ++baz;
console.log(baz); // 9


<|start_filename|>lecture3/functions.js<|end_filename|>
// This is an example of a higher-order function
var map = function( array, fn ) {
        // Applies fn to each element of list, returns a new list
        var result = [];
        for (var i = 0; i < array.length; i++) {
                var element = array[i];
                result.push( fn(element) );
        }
        return result;
};

var l = [3, 1, 5, 7, 2];
console.log( map(l, function(num) { return num + 10; }) );

var add = function(a, b) {
	return a + b;
};

// This is an example of function currying
var add20 = add.bind(null, 20);
console.log( map(l, add20) )

// Solution to the class activity for the filter function is below;
var filter = function( array, fn ) {
        var result = [];
        for (var i = 0; i < array.length; i++) {
                var element = array[i];
                if (fn(element) ) result.push(element);
        }
        return result;
};

var lesserThan = function(a, b) { return (a < b) ? true:false; }
var greaterThan5 = lesserThan.bind(null, 5);

var a = [ 1, 3, 10, 8, 2, 7, 6 ];
console.log(a);
var c = filter( a, greaterThan5);
console.log(c);





<|start_filename|>lecture2/objects.js<|end_filename|>
console.log(":: objects.js ::");

var vspResults = {
    Karthik:99,
    Bob:96,
    Kevin:93,
    Julien:91,
    John:41};

console.log(vspResults["Karthik"]); // prints 99
console.log(vspResults["Bob"]); // prints 96

for (var e in vspResults) {
	console.log(e);             // Print the name
	console.log(vspResults[e]); // Print the score
}

console.log(vspResults.Karthik); // prints 99



<|start_filename|>lecture8/events.js<|end_filename|>
// Example of EventEmitter in node.js 
// Source: Node.js succinctly

var eventMod = require('events');
var EventEmitter = eventMod.EventEmitter;
if (! EventEmitter) process.exit(1);

var connection = function(id) {
	console.log("client id : " + id); 
};

var message = function(msg) {
	console.log("message : " + msg); 
};

var myEmitter = new EventEmitter();
myEmitter.on("connection", connection);
myEmitter.on("message", message);

// test cases for the above
// should print 1, 2, hello to the console
myEmitter.emit("connection", 1);
myEmitter.emit("connection", 2);
myEmitter.emit("message", "hello");

// Because we removed the listener, it shouldn't print world
// myEmitter.removeListener("message", message);
myEmitter.emit("message", "world");







<|start_filename|>lecture6/employee.js<|end_filename|>
var Person = function(firstName, lastName, gender) {
	this.firstName = firstName;	
	this.lastName = lastName;
	this.gender = gender;
	this.name = function() { // this is how you add a method 
		return this.firstName + " " + this.lastName;
	}
}

var p1 = new Person("John", "Smith", "Male");
console.log( p1.firstName );
console.log( p1["lastName"] );
console.log( p1.name );

Person.prototype.print = function() { // this is a method of the prototype
	console.log( this.name() + " " + this.gender );
}

console.log(p1);
console.log(Person.prototype);
var proto1 = Object.getPrototypeOf(p1);
console.log(proto1);
console.log(Object.getPrototypeOf(proto1));
console.log(Object.getPrototypeOf(Person));

var p2 = new Person("Linda", "James", "Female");
console.log(p2);
var proto2 = Object.getPrototypeOf(p2);
console.log(proto2);

p1.print();
p2.print();
console.log( proto1.constructor );

var Employee = function(firstName, lastName, gender, title) {
	Person.call(this, firstName, lastName, gender);
	this.title = title;	
};

Employee.prototype = new Person();
Employee.prototype.constructor = Employee;

Employee.prototype.print = function() {
	console.log( this.name() + " " + this.gender + " " + this.title );
}

var e1 = new Employee("XYZ", "ABC", "Male", "Manager");
console.log( Employee.prototype );
console.log( Object.getPrototypeOf(e1) );

// Print all the people and the employees
e1.print();
p1.print();
p2.print();

// COMMENT OUT THIS CODE OR YOU"LL GET UNEXPECTED RESULTS
// EXERCISE: Can you figure out what would happen otherwise ?
// Employee.prototype = Object.prototype;

// Check the instances and the prototypes
console.log(e1 instanceof Employee);
console.log(e1 instanceof Person);
console.log(e1 instanceof Object);

console.log(p1 instanceof Employee);
console.log(p1 instanceof Person);
console.log(p1 instanceof Object);

console.log(p2 instanceof Employee);
console.log(p2 instanceof Person);
console.log(p2 instanceof Object);

console.log( "firstName" in p1 );
console.log( "lastName" in p1 );
console.log( "title" in p1 );

console.log( "firstName" in e1 );
console.log( "lastName" in e1 );
console.log( "title" in e1 );

console.log( p1.hasOwnProperty("firstName") );
console.log( p1.hasOwnProperty("lastName") );
console.log( p1.hasOwnProperty("print") );
console.log( e1.hasOwnProperty("firstName") );
console.log( e1.hasOwnProperty("lastName") );
console.log( e1.hasOwnProperty("print") );


<|start_filename|>lecture2/arrays.js<|end_filename|>
console.log(":: arrays.js ::");

var vspResults = [99, 96, 93, 91, /* ... */ 41];
console.log(vspResults);
/* Printing the grade of the top 3 students -- be careful,
   in most programming languages, the first index is 0! */
console.log("Grade of the 1st student: " + vspResults[0]);
console.log("Grade of the 2nd student: " + vspResults[1]);
console.log("Grade of the 3rd student: " + vspResults[2]);

// Adding an item
vspResults.push(39);
console.log(vspResults);

// Removing an item
vspResults.pop(); // Removes 39
console.log(vspResults);

// Length of array
console.log( vspResults.length );


<|start_filename|>lecture3/person.js<|end_filename|>
// This is a Person object
var Person = function(firstName, lastName, gender) {
	this.firstName = firstName;	
	this.lastName = lastName;
	this.gender = gender;
	this.name = function() { // this is how you add a method 
		return this.firstName + " " + this.lastName;
	}
	this.info = function() {
		return this.name() + " " + this.gender; 
	} 
}

var p1 = new Person("John", "Smith", "Male");
console.log( p1.firstName );
console.log( p1["lastName"] );
console.log( p1.name() );
console.log( p1.info() );
console.log(p1);


<|start_filename|>lecture5/timeout2.js<|end_filename|>
// Another Solution to the class activity
// We need to use nested closures to preserve the state here

var invokeTimes = function(func, noTimes, time) {
    console.log("Setting up interval " + noTimes + " " + time);
    
    for (var i = 0; i < noTimes; ++i) {
	var timeoutHandler = function(count) {
	    // timeOutHandler is a closure
	    return function() {
		console.log( "invocation " + count);
		func(count);
	    }
	}
	setTimeout(timeoutHandler(i), time * i);
    }
};

var setup = function() {
    invokeTimes( function(i) { alert("hello " + i); }, 5, 1000 );
}

setup();


<|start_filename|>lecture5/prop.js<|end_filename|>
var bubbleHandler = function(name) {
	return function(e) {
		console.log("Bubble handle invoked on : " + name);
		console.log("Event target " + e.target);
	};
};

var captureHandler = function(name) {
	return function(e) {
		console.log("Capture handle invoked on : " + name);
		console.log("Event target " + e.target);
	};
	
}

window.onload = function() {
	var div1 = document.getElementById("one");
	var div2 = document.getElementById("two");
	var div3 = document.getElementById("three");
	var div4 = document.getElementById("four");
	var btn = document.getElementById("btn");

	div1.addEventListener("click", bubbleHandler("div1"), false);
	div2.addEventListener("click", bubbleHandler("div2"), false);
	div3.addEventListener("click", bubbleHandler("div3"), false);
	div4.addEventListener("click", bubbleHandler("div4"), false);
	btn.addEventListener("click", bubbleHandler("btn"), false);

	div1.addEventListener("click", captureHandler("div1"), true);
	div2.addEventListener("click", captureHandler("div2"), true);
	div3.addEventListener("click", captureHandler("div3"), true);
	div4.addEventListener("click", captureHandler("div4"), true);
	btn.addEventListener("click", captureHandler("btn"), true);
};


<|start_filename|>lecture3/array.js<|end_filename|>
// This illustrates common array operations

var a = [5, 1, 3, 48, 29, 40, 30, 1, 25, 10 ];

function arraySum(arr) {
	var sum = 0;
	// compute sum here
	for (var i = 0; i<arr.length; i++)
		sum += arr[i];
	return sum;
}

function maxArray(arr) {
	if (arr.length==0) return 0;
	var max = arr[0];
	// compute max here
	for (var i =0; i<arr.length; i++) {
		if (max < arr[i]) max = arr[i];
	}
	return max;
}

function printArray(arr) {
	var i;
	console.log("Length = " + arr.length);
	for (i=0; i<arr.length; i++) {
		console.log("\ta[ " + i + "] = " + arr[i]);
	}
}		

printArray(a);
console.log(arraySum(a)); 
console.log(maxArray(a));



<|start_filename|>lecture7/client/ajaxrequest.js<|end_filename|>
// Simple AJAX request issuer - keeps track of multiple requests

// Display the list of messages in flight
function displayInFlight(inflight) {
	return function() {	
		if (inflight.length > 0) {
			var result = "In flight messages : ";
			for (var i=0; i<inflight.length; i++) {
				result = result + " (" + inflight[i] + ")";
			}
			console.log(result);
		}
	};
};

// Cancel the last message in flight
function CancelInflight(inflight) {
	return function() {
		if (inflight.length > 0) {
			inflight[inflight.length - 1].abort();
		} else {
			alert("No messages in flight");
		}
	};
}

var RequestCount = function(msg, inflight) {
	var count = 0;
	var sendRequest = function() {
		var xhr = new XMLHttpRequest();
		var name = "XHR " + count;
		var index = 0;
		xhr.open("GET", msg + '-' + count);
		count = count + 1;
		var removeFromList = function() {
			index = inflight.indexOf(xhr);
			if (index > -1) {
				inflight.splice(index, 1);
			} else {
				alert(name + " not found !");
			}
		};
		xhr.onload = function() {
			if (xhr.status==200) {
				console.log(name + " : Received " + xhr.responseText);
			} else {	
				console.log(name + " : Received error code : " + xhr.status);
			}
			removeFromList();
		};		
		xhr.ontimeout = function() {
			console.log(name + " : Timed out after " + xhr.timeout + " ms");
			removeFromList();
		}
		xhr.onerror = function() {
			console.log(name + " : Resulted in an error !");
			removeFromList();
		};  
		xhr.onabort = function() {
			console.log(name + " : Aborted");
			removeFromList();
		};
		xhr.toString = function() {
			return name;
		};
		// All the handlers are setup, so send the message
		xhr.timeout = 5000;	 // Wait at most 5000 ms for a response
		console.log("Sending request " + xhr);
		inflight.push(xhr);	 // Add it to the inflight messages before sending it
		xhr.send();
	}
	return sendRequest;
};


window.onload = function() {
	var ok = document.getElementById("OK");
	var count = 0
	var inflight = [];
	ok.addEventListener("click", RequestCount("/hello", inflight), false);	// sendRequest upon button click		
	var cancel = document.getElementById("Cancel");
	cancel.addEventListener("click", CancelInflight(inflight), false);	// cancel last sent request
	setInterval(displayInFlight(inflight), 1000);			// Display the inflight list
}


<|start_filename|>lecture3/addPoints.js<|end_filename|>
var Point = function(x,y)  {
	this.x = x;
  this.y = y;
}

var p1 = new Point(1,1);
var p2 = new Point(2,2);
var p3 = new Point(undefined,3);

var addAll = function() {
	var p = new Point(0,0);
  for (var i=0; i<arguments.length; i++) {
  	var point = arguments[i];
    // TODO: return current sum of points up
    // to the first occurence of an error
    // while throwing the exception
    if (point.x === undefined ||
    	point.y === undefined)
    {
    	throw {
      	name: TypeError, 
      	message: "Error",
        Pt:p
      };
    }
    p.x += point.x;
    p.y += point.y;
  }
  return p;
}

try {
	var sumPoint = addAll(p1,p2,p3);
  console.log(sumPoint);
} catch (exception) {
	console.log(exception.Pt);
}


<|start_filename|>lecture2/conditionals.js<|end_filename|>
console.log(":: conditionals.js ::");

var x = 5;

console.log(x == 5);    // true
console.log(x != 4);    // true
console.log(x > 5);     // false
console.log(x >= 5);    // true
console.log(x < 5);     // false
console.log(x <= 5);    // true

console.log(x === 5);   // true - equals+same type
console.log(x === "5"); // false - different type
console.log(x !== 5);   // false - not equals
console.log(x !== "5"); // true - different type

var foo = "VSP";
console.log(foo == "VSP");    // true
console.log(foo === "VSP");   // true
console.log(foo != "UBC");    // true
console.log(foo !== "42");    // true

console.log(" -------- ");

// --------

// Returns true if value >= min and value <= max
function isBetween(value, min, max) {
    return ( (value >= min) && (value <= max) );
}

console.log( isBetween( 10, 5, 15) ); // true
console.log( isBetween( 10, 5, 8 ) ); // false

console.log(" -------- ");

// --------

var condition = false;
if (condition)
    console.log("This line executes if condition is true");
console.log("This line will ALWAYS execute");

console.log(" -------- ");

// --------

if ( isBetween(15, 10, 20) ) {
    console.log("Number within range!");
} else {
    console.log("Number not within range!");
}

console.log(" -------- ");

// Equivalent to -->

if ( (15 >= 10) && (15 <= 20) ) {
    console.log("Number within range!");
} else {
    console.log("Number not within range!");
}

console.log(" -------- ");

// --------

if ( isBetween(15, 10, 20) ) {
    if ( isBetween(15, 14, 16) ) {	
	console.log("Excellent!");
    } else {
	console.log("Good.");
    }
} else {
    console.log("Bad!");
}

console.log(" -------- ");

// --------

var score = 75;
var grade = "";

if ( score >= 80 ) {
    grade = "A";
} else if (score >= 70) {
    grade = "B";
} else if (score >= 60) {
    grade = "C";
} else if (score >= 50) {
    grade = "D";
} else {
    grade = "F";
}

console.log("Your grade is " + grade);



<|start_filename|>lecture4/domadd.js<|end_filename|>
var newDiv = function(node, id) {
	// Write you solution here
};

window.onload = function() {
	var div4 = document.getElementById("four");
	if (div4 && div4.childNodes.length >= 1) {
		var textNode = div4.getElementsByTagName("p")[0];
		newDiv( textNode, "five" );
	}
	console.log(div4);
};


<|start_filename|>lecture1/activity.css<|end_filename|>
#news { background-color: silver; font-style: italic; color: black; }

.sports { color:blue; text-decoration:underline; }

H3, H4 { font-family: sans-serif; }

.latest { color: green; }

#news span { color: red; }

P.select { font-size: medium; }





<|start_filename|>lecture5/timeout.js<|end_filename|>
// Solution to class activity using timeouts

var invokeTimes = function(func, noTimes, time) {
    console.log("Setting up interval " + noTimes + " " + time);
    var count = 0;
    var timeoutHandler = function() {
	// timeOutHandler is a closure
	console.log( "invocation " + count);
	func(count);
	count = count + 1;
	if (count < noTimes) {
	    setTimeout(timeoutHandler, time);
	}
    };
    if (count==0) setTimeout(timeoutHandler, time);
};

var setup = function() {
    invokeTimes( function(i) { alert("hello " + i); }, 10, 1000 );
}

setup();


<|start_filename|>lecture5/counter.js<|end_filename|>
// Simple Adder functions to illustrate closures
function Adder(val) {
    var value = val;
    return function(inc) {
	value = value + inc;
	return value;
    }
};

var f = Adder(5);
console.log( f(3) );
console.log( f(5) );

var f2 = Adder(100);
console.log( f2(2) );
console.log( f2(3) );

console.log( f(1) );

// Counter closure returning an object
function Counter(initial) {
    var val = initial;
    return {	
	increment : function() { val += 1; },
	reset: function() { val = initial; },
	get: function() { return val; }
    };
};

var f = Counter(5), g = Counter(10);
f.increment();
g.increment();
f.reset();
f.increment();
g.increment();
console.log( f.get() + "," + g.get() );

// Closure that keeps a pointer to the enclosing function itself
var MultiCounter = {
    create: function(initial) {
	
	var that = this;
	var val = [];	
	console.log(this);
	this.init = function() {
	    val = [];
	    for (var i=0; i<initial.length; i++) {
		val.push(  initial[i] );
	    };
	};
	this.init();
	return {
	    increment: function(i) { val[i] += 1; },
	    resetAll: function() { that.init(); },
	    getValues: function() { return val; }
	};
    }
};
var m = MultiCounter.create( [1, 2, 3] );
m.increment(0);
m.increment(2);
m.increment(0);
m.resetAll();
m.increment(1);
console.log( m );
console.log( m.getValues() );

// Warning: BAD code! This function is broken. Functions MakeCounters2 and MakeCounters3 are better examples.
var MakeCounters1 = function(n) {
    var counters = [];
    for (var i=0; i<n; i++) {
	var val = i;
	counters[i] = {
	    increment: function() { val++; },
 	    get: function() { return val; },
	    reset: function() { val = i; }
	}
    }
    return counters;
} 
var m = MakeCounters1(10);
for (var i=0; i<10; i++) {
    document.writeln("Counter[ " + i + "] = " + m[i].get());
}

/* BAD SOLUTION: There is only one instance of the loop variable i. After the loop is done executing, when counters is returned, i==n (this is the stop condition of the loop). Therefore, all 3 functions of the counter object will try to access element i (n) of val, which doesn't exist -- therefore, undefined is returned.*/
var MakeCounters1a = function(n) {
    var counters = [];
    var val = [];
    for (var i=0; i<n; i++) {
	val.push(i);
	counters[i] = {
	    increment: function() { val[i]++; },
 	    get: function() { return val[i]; },
	    reset: function() { val[i] = i; }
	}
    }
    return counters;
} 
m = MakeCounters1a(10);
for (var i=0; i<10; i++) {
    document.writeln("Counter[ " + i + "] = " + m[i].get());
}

// This version works, but introduces two new fields in counters -- not the best idea
var MakeCounters2 = function(n) {
    var counters = [];
    for (var i=0; i<n; i++) {
	counters[i] = {
	    val : i,
	    initial : i,
	    increment: function() { this.val++; },
	    get: function() { return this.val; },
	    reset: function() { this.val = this.initial; }
	}
    }
    return counters;
} 
m = MakeCounters2(10);
for (var i=0; i<10; i++) {
    document.writeln("Counter[ " + i + "] = " + m[i].get());
}

// This function avoid the addition of two fields in counters
var MakeCounters3 = function(n) {
    var counters = [];
    for (var i=0; i<n; i++) {
	counters[i] = function( ) {
	    var initial = i, val = initial;
	    return {	
		increment: function() { val++; },
 		get: function() { return val; },
		reset: function() { val = initial; }
	    }
	}();	// Why do we need the parentheses () ?
    }
    return counters;
} 
m = MakeCounters3(10);
for (var i=0; i<10; i++) {
	document.writeln("Counter[ " + i + "] = " + m[i].get());
}


<|start_filename|>lecture2/loops.js<|end_filename|>
console.log(":: loops.js ::");

var vspResults = [99, 96, 93, 91, 89, 87, 80, 75, 74, 63, 61, 52, 49, 47, 43, /* ... */ 41];
for (var i = 0; i < 3; i++) {
    console.log("Score #" + (i+1) + ": " + vspResults[i]);
}

console.log(" -------- ");

// --------

// Print the top 10 results but stop when they get below 90:
for (var i = 0; ( (i < 10) && (vspResults[i] >= 90) ); i++) {
    console.log("Score #" + (i+1) + ": " + vspResults[i]);
}

console.log(" -------- ");

// --------

var passingGrade = 50;

// Print all results which are above or equal to the passing grade
var i = 0;
while (vspResults[i] >= passingGrade) {
    console.log(vspResults[i]);
    i++;
}

console.log(" -------- ");

// --------

// Print the first result, and then print all results which are above or equal to the passing grade

passingGrade = 50;

var i = 0;
do {
    console.log(vspResults[i]);
    i++;
} while (vspResults[i] >= passingGrade);



<|start_filename|>lecture8/httpserver.js<|end_filename|>
// Example of a simple http server written using node.js
// Source: node.js succinctly

var http = require('http');
if (! http) throw { msg: "Cannot find http" };

// Create a simple function to serve a request
var serveRequest = function(request, response) {
	console.log( request.headers );
	response.setHeader("AppId", "hello");
	response.write("Welcome to node.js");
	response.end();	
};

// Start the server on the port and setup response
var port = 8080;
var server = http.createServer(serveRequest);
server.listen(port);
console.log("Starting server on port " + port);



<|start_filename|>lecture3/shapes.js<|end_filename|>
// Example of different ways to call a function and prototype chains

function Point(x, y) {
	this.x = x;
	this.y = y;
	this.dist = function(point) {
		return Math.sqrt( (this.x - point.x) * (this.x - point.x)
				+ (this.y - point.y) * (this.y - point.y) );
	};
	return 0;	
};

var add = function(p1, p2) {
	console.log(this);
	return new Point(p1.x + p2.x, p1.y + p2.y);
};

var p1 = new Point(2, 3);
var p2 = new Point(5, 7);

console.log( "Distance between p1 and p2 = " + p1.dist(p2) );
var res1 = add(p1, p2);
console.log( "Add result (" + res1.x + "," + res1.y + ")" ); 

var addAll = function() {
        var p = new Point(0,0);
        for (var i = 0; i < arguments.length; i++) {
                var point = arguments[i];
		if (point.x==undefined || point.y==undefined) {
                        throw { etype: TypeError,
                                message: "Object " + point + " is not of type point",
                        	sum: p
			};      
                }       
                p.x += point.x; 
                p.y += point.y; 
        }               
        return p;
};             

var p3 = new Point(5, 4);
var p4 = new Point(11, 12);

try {
	var res2 = addAll(p1, p2, p3, "VSP", p4);
	console.log("Addall result = (" + res2.x + "," + res2.y + ")");
} catch (e) {
	console.log("Exception Type: " + e.etype);
	console.log("Exception Message: " + e.message);
	console.log("Partial (" + e.sum.x + " , " + e.sum.y + ")"); 
} 


<|start_filename|>lecture8/ajaxserver-solution.js<|end_filename|>
// This is the server corresponding to the AJAX client we developed earlier

var http = require("http");
if (! http) process.exit(1);

var fs = require("fs");
if (! fs) process.exit(2);

var path="./client";
var counts = {};	// Number of requests from each address

var serveRequest = function(request, response) {
	if ( request.url.startsWith("/hello") ) {
		// If it's an AJAX request, return world
		console.log( "Received " + request.url );
		var addr = request.connection.remoteAddress;
		if (addr in counts)
			counts[addr]++;
		else
			counts[addr] = 0;
		var instance = counts[addr];
		var fileName = path + "/file"+ addr;
		console.log(fileName);
		fs.appendFile(fileName, request.url + "\n", function(err) {
			if (err) console.log("Error writing to file " + fileName);	
		});
		setTimeout( function() {
			var count = request.url.split("-")[1];
			response.write("world-" + count);
			response.statusCode = 200;
			response.end();
		}, 3000);
	} else if ( request.url.endsWith(".html") || request.url.endsWith(".js")) {
		// If it's a HTML or JS file, retrieve the file in the request
		response.statusCode = 200;
		var fileName = path + request.url;
		var rs = fs.createReadStream(fileName);
		console.log("Reading from file " + fileName);
		rs.on("error", function(error) {	
			console.log(error);
			response.write("Unable to read file : " + fileName);
			response.statusCode = 404;
		});
		rs.on("data", function(data) {
			response.write(data);
		});
		rs.on("end", function() {
			response.end();
		});
	} else {
		response.write("Unknown request " + request.url);
		response.statusCode = 404;
		response.end();
	}
};


// Start the server on the port and setup response
var port = 8080;
var server = http.createServer(serveRequest);
server.listen(port);
console.log("Starting server on port " + port);


<|start_filename|>lecture2/classactivity.js<|end_filename|>
console.log(":: classactivity.js ::");

function getRandomInt(min, max) {
    min = Math.ceil(min); max = Math.floor(max);
    return Math.floor(Math.random() * (max - min)) + min;
    //The maximum is exclusive and the minimum is inclusive
}

function randomArray(n, min, max) {
    var arr = [];
    for (var i=0; i<n; i++)
	arr.push(getRandomInt(min, max));
    return arr;
}

/* Note: taken from https://khan4019.github.io/front-end-Interview-Questions/sort.html
   sortArray uses the Bubble Sort algorithm which is O(n^2).
   The function will alter the original array. A copy could be made first if this is to
   be avoided. */
function sortArray(arr){
   var len = arr.length;
   for (var i = len-1; i>=0; i--){
     for(var j = 1; j<=i; j++){
       if(arr[j-1]>arr[j]){
           var temp = arr[j-1];
           arr[j-1] = arr[j];
           arr[j] = temp;
        }
     }
   }
   return arr;
}

// Test code:
var arr = randomArray(10, 0, 50);
var sortedArr = sortArray(arr);
console.log(sortedArr);


<|start_filename|>lecture8/wordCount-stream.js<|end_filename|>
// Counts the total number of characters in a given text file

var fs = require('fs');
if (! fs) process.exit(1);

var length = 0;
var fileName = "sample.txt";

var readStream = fs.createReadStream(fileName);;

readStream.on("data", function(blob) {
			console.log("Read " + blob.length);
			length += blob.length;	
		} );

readStream.on("end", function() {
		console.log("Total number of chars read = " + length);
	} );

readStream.on("error", function() {
		console.log("Error occurred when reading from file " + fileName);
	} );

console.log("End of program");


<|start_filename|>lecture8/wordFind.js<|end_filename|>
// Searches for a given string in a file. Called with two command line arguments: fileName and string to search for.
// Assumes that length of the string being searched < length of buffer being read at any time 
// The above assumption is necessary as it concatenates atmost two buffers

var fs = require('fs');
if (! fs) process.exit(1);

if (process.argv.length < 4) {
    console.log("Syntax: fileName string");
    process.exit(2);
}

var fileName = process.argv[2];
var textToFind = process.argv[3];	
var readStream = fs.createReadStream(fileName);;
var oldBlob = "";
var index = -1;

readStream.on("data", function(blob) {
    console.log("Read " + blob.length +  " bytes");
    var newBlob = oldBlob + blob;
    index = newBlob.indexOf(textToFind);
    if (index >= 0) readStream.emit("end");
    oldBlob = blob;
} );

readStream.on("end", function() {
    if (index>=0)
	console.log("Found string " + textToFind);
    else	
	console.log("Did not find string " + textToFind);
} );

readStream.on("error", function() {
    console.log("Error occurred when reading from file " + fileName);
} );

console.log("End of program");


<|start_filename|>lecture4/domadd-solution.js<|end_filename|>
var newDiv = function(node, id) {
	var div = document.createElement("div");
	div.id = id;
	if (node && node.parentNode) {
		node.parentNode.replaceChild(div, node);
		div.appendChild(node);
	}
};

window.onload = function() {
	var div4 = document.getElementById("four");
	if (div4 && div4.childNodes.length >= 1) {
		var textNode = div4.getElementsByTagName("p")[0];
		newDiv( textNode, "five" );
	}
	console.log(div4);
};


<|start_filename|>lecture8/pipeCopy.js<|end_filename|>
// Copies files using pipes
var fs = require("fs");
if (! fs) process.exit(1);

// Open the read and write streams
var readStream = fs.createReadStream("sample.txt");
var writeStream = fs.createWriteStream("sample-copy.txt");

// Copies contents of read stream to write stream
readStream.pipe( writeStream );


 


<|start_filename|>lecture4/changeImage.js<|end_filename|>
var changeImages = function(id,  offset) {
	// Write your solution here 


}

window.onload = function() {
	setInterval( function() { 
		changeImages("parent", 1);
	}, 5000);
};


<|start_filename|>lecture5/example.js<|end_filename|>
var myVar;

function setupTimeout(i) {
	
	return	function() {
		alert("Hello " + i);
	}

}

function cancelTimeout() {
	i = 0;
	clearTimeout(myVar);
}

for (var k=0; k<10; k++) {
	myVar = setTimeout(setupTimeout(k), 3000);
}


<|start_filename|>lecture8/test.js<|end_filename|>
// Example of using modules in node.js

var Calculator = require("./calculate.js");
var calculator = new Calculator();
var c = calculator.sum(10,20);
console.log(c);
var d = calculator.add(30);
console.log(d);
var e = calculator.multiply(10);
console.log(e);
var f = calculator.product(100, 100);
console.log(f);
console.log(calculator);


<|start_filename|>lecture1/style2.css<|end_filename|>
p { color:blue; text-decoration:underline }
strong { color:red }


<|start_filename|>lecture1/style3.css<|end_filename|>
strong { color: red; }
.carrot { color: orange; }
.spinach { color: green; }
#first { font-style: italic; }


<|start_filename|>lecture4/changeImage-solution.js<|end_filename|>
// This is the solution to the class activity

var changeImages = function(id,  offset) {

	// Get the images rooted at div 
	var div = document.getElementById(id);
	var imgtags = div.getElementsByTagName("img");

	// Nested function to rotate the images above
	function changeImage() {
		if (imgtags.length==0) return;
		var first = imgtags[0].src;
		for (var i=0; i<imgtags.length; i++) {
			var img = imgtags[i];
			var nextIndex = (i + 1);
			console.log("Replacing " + i + " with " + nextIndex); 
			if (nextIndex==imgtags.length) 
				img.src = first;
			else
				img.src = imgtags[nextIndex].src;
		}
	}
	
	for (var k=0; k<offset; k++)
		changeImage();
}

window.onload = function() {
	setInterval(function() { 
		changeImages("parent", 1);
	}, 5000);
};
