<commit_before>/*
 * @namespace Util
 *
 * Various utility functions, used by Leaflet internally.
 */

L.Util = {

	// @function extend(dest: Object, src?: Object): Object
	// Merges the properties of the `src` object (or multiple objects) into `dest` object and returns the latter. Has an `L.extend` shortcut.
	extend: function (dest) {
		var i, j, len, src;

		for (j = 1, len = arguments.length; j < len; j++) {
			src = arguments[j];
			for (i in src) {
				dest[i] = src[i];
			}
		}
		return dest;
	},

	// @function create(proto: Object, properties?: Object): Object
	// Compatibility polyfill for [Object.create](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/create)
	create: Object.create || (function () {
		function F() {}
		return function (proto) {
			F.prototype = proto;
			return new F();
		};
	})(),

	// @function bind(fn: Function, …): Function
	// Returns a new function bound to the arguments passed, like [Function.prototype.bind](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function/bind).
	// Has a `L.bind()` shortcut.
	bind: function (fn, obj) {
		var slice = Array.prototype.slice;

		if (fn.bind) {
			return fn.bind.apply(fn, slice.call(arguments, 1));
		}

		var args = slice.call(arguments, 2);

		return function () {
			return fn.apply(obj, args.length ? args.concat(slice.call(arguments)) : arguments);
		};
	},

	// @function stamp(obj: Object): Number
	// Returns the unique ID of an object, assiging it one if it doesn't have it.
	stamp: function (obj) {
		/*eslint-disable */
		obj._leaflet_id = obj._leaflet_id || ++L.Util.lastId;
		return obj._leaflet_id;
		/*eslint-enable */
	},

	// @property lastId: Number
	// Last unique ID used by [`stamp()`](#util-stamp)
	lastId: 0,

	// @function throttle(fn: Function, time: Number, context: Object): Function
	// Returns a function which executes function `fn` with the given scope `context`
	// (so that the `this` keyword refers to `context` inside `fn`'s code). The arguments received by the bound function will be any arguments passed when binding the function, followed by any arguments passed when invoking the bound function. Has an `L.bind` shortcut.
	throttle: function (fn, time, context) {
		var lock, args, wrapperFn, later;

		later = function () {
			// reset lock and call if queued
			lock = false;
			if (args) {
				wrapperFn.apply(context, args);
				args = false;
			}
		};

		wrapperFn = function () {
			if (lock) {
				// called too soon, queue to call later
				args = arguments;

			} else {
				// call and lock until later
				fn.apply(context, arguments);
				setTimeout(later, time);
				lock = true;
			}
		};

		return wrapperFn;
	},

	// @function wrapNum(num: Number, range: Number[], includeMax?: Boolean): Number
	// Returns the number `num` modulo `range` in such a way so it lies within
	// `range[0]` and `range[1]`. The returned value will be always smaller than
	// `range[1]` unless `includeMax` is set to `true`.
	wrapNum: function (x, range, includeMax) {
		var max = range[1],
		    min = range[0],
		    d = max - min;
		return x === max && includeMax ? x : ((x - min) % d + d) % d + min;
	},

	// @function falseFn(): Function
	// Returns a function which always returns `false`.
	falseFn: function () { return false; },

	// @function formatNum(num: Number, digits?: Number): Number
	// Returns the number `num` rounded to `digits` decimals, or to 5 decimals by default.
	formatNum: function (num, digits) {
		var pow = Math.pow(10, digits || 5);
		return Math.round(num * pow) / pow;
	},

	// @function trim(str: String): String
	// Compatibility polyfill for [String.prototype.trim](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)
	trim: function (str) {
		return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
	},

	// @function splitWords(str: String): String[]
	// Trims and splits the string on whitespace and returns the array of parts.
	splitWords: function (str) {
		return L.Util.trim(str).split(/\s+/);
	},

	// @function setOptions(obj: Object, options: Object): Object
	// Merges the given properties to the `options` of the `obj` object, returning the resulting options. See `Class options`. Has an `L.setOptions` shortcut.
	setOptions: function (obj, options) {
		if (!obj.hasOwnProperty('options')) {
			obj.options = obj.options ? L.Util.create(obj.options) : {};
		}
		for (var i in options) {
			obj.options[i] = options[i];
		}
		return obj.options;
	},

	// @function getParamString(obj: Object, existingUrl?: String, uppercase?: Boolean): String
	// Converts an object into a parameter URL string, e.g. `{a: "foo", b: "bar"}`
	// translates to `'?a=foo&b=bar'`. If `existingUrl` is set, the parameters will
	// be appended at the end. If `uppercase` is `true`, the parameter names will
	// be uppercased (e.g. `'?A=foo&B=bar'`)
	getParamString: function (obj, existingUrl, uppercase) {
		var params = [];
		for (var i in obj) {
			params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i]));
		}
		return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&');
	},

	// @function template(str: String, data: Object): String
	// Simple templating facility, accepts a template string of the form `'Hello {a}, {b}'`
	// and a data object like `{a: 'foo', b: 'bar'}`, returns evaluated string
	// `('Hello foo, bar')`. You can also specify functions instead of strings for
	// data values — they will be evaluated passing `data` as an argument.
	template: function (str, data) {
		return str.replace(L.Util.templateRe, function (str, key) {
			var value = data[key];

			if (value === undefined) {
				throw new Error('No value provided for variable ' + str);

			} else if (typeof value === 'function') {
				value = value(data);
			}
			return value;
		});
	},

	templateRe: /\{ *([\w_\-]+) *\}/g,

	// @function isArray(obj): Boolean
	// Compatibility polyfill for [Array.isArray](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray)
	isArray: Array.isArray || function (obj) {
		return (Object.prototype.toString.call(obj) === '[object Array]');
	},

	// @function indexOf(array: Array, el: Object): Number
	// Compatibility polyfill for [Array.prototype.indexOf](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf)
	indexOf: function (array, el) {
		for (var i = 0; i < array.length; i++) {
			if (array[i] === el) { return i; }
		}
		return -1;
	},

	// @property emptyImageUrl: String
	// Data URI string containing a base64-encoded empty GIF image.
	// Used as a hack to free memory from unused images on WebKit-powered
	// mobile devices (by setting image `src` to this string).
	emptyImageUrl: 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='
};

(function () {
	// inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/

	function getPrefixed(name) {
		return window['webkit' + name] || window['moz' + name] || window['ms' + name];
	}

	var lastTime = 0;

	// fallback for IE 7-8
	function timeoutDefer(fn) {
		var time = +new Date(),
		    timeToCall = Math.max(0, 16 - (time - lastTime));

		lastTime = time + timeToCall;
		return window.setTimeout(fn, timeToCall);
	}

	var requestFn = window.requestAnimationFrame || getPrefixed('RequestAnimationFrame') || timeoutDefer,
	    cancelFn = window.cancelAnimationFrame || getPrefixed('CancelAnimationFrame') ||
	               getPrefixed('CancelRequestAnimationFrame') || function (id) { window.clearTimeout(id); };

	// @function requestAnimFrame(fn: Function, context?: Object, immediate?: Boolean): Number
	// Schedules `fn` to be executed when the browser repaints. `fn` is bound to
	// `context` if given. When `immediate` is set, `fn` is called immediately if
	// the browser doesn't have native support for
	// [`window.requestAnimationFrame`](https://developer.mozilla.org/docs/Web/API/window/requestAnimationFrame),
	// otherwise it's delayed. Returns a request ID that can be used to cancel the request.
	L.Util.requestAnimFrame = function (fn, context, immediate) {
		if (immediate && requestFn === timeoutDefer) {
			fn.call(context);
		} else {
			return requestFn.call(window, L.bind(fn, context));
		}
	};

	// @function cancelAnimFrame(id: Number): undefined
	// Cancels a previous `requestAnimFrame`. See also [window.cancelAnimationFrame](https://developer.mozilla.org/docs/Web/API/window/cancelAnimationFrame).
	L.Util.cancelAnimFrame = function (id) {
		if (id) {
			cancelFn.call(window, id);
		}
	};
})();

// shortcuts for most used utility functions
L.extend = L.Util.extend;
L.bind = L.Util.bind;
L.stamp = L.Util.stamp;
L.setOptions = L.Util.setOptions;
<commit_msg>docstrings: Add description to time argument of Util.throttle (#4633)<commit_after>/*
 * @namespace Util
 *
 * Various utility functions, used by Leaflet internally.
 */

L.Util = {

	// @function extend(dest: Object, src?: Object): Object
	// Merges the properties of the `src` object (or multiple objects) into `dest` object and returns the latter. Has an `L.extend` shortcut.
	extend: function (dest) {
		var i, j, len, src;

		for (j = 1, len = arguments.length; j < len; j++) {
			src = arguments[j];
			for (i in src) {
				dest[i] = src[i];
			}
		}
		return dest;
	},

	// @function create(proto: Object, properties?: Object): Object
	// Compatibility polyfill for [Object.create](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/create)
	create: Object.create || (function () {
		function F() {}
		return function (proto) {
			F.prototype = proto;
			return new F();
		};
	})(),

	// @function bind(fn: Function, …): Function
	// Returns a new function bound to the arguments passed, like [Function.prototype.bind](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function/bind).
	// Has a `L.bind()` shortcut.
	bind: function (fn, obj) {
		var slice = Array.prototype.slice;

		if (fn.bind) {
			return fn.bind.apply(fn, slice.call(arguments, 1));
		}

		var args = slice.call(arguments, 2);

		return function () {
			return fn.apply(obj, args.length ? args.concat(slice.call(arguments)) : arguments);
		};
	},

	// @function stamp(obj: Object): Number
	// Returns the unique ID of an object, assiging it one if it doesn't have it.
	stamp: function (obj) {
		/*eslint-disable */
		obj._leaflet_id = obj._leaflet_id || ++L.Util.lastId;
		return obj._leaflet_id;
		/*eslint-enable */
	},

	// @property lastId: Number
	// Last unique ID used by [`stamp()`](#util-stamp)
	lastId: 0,

	// @function throttle(fn: Function, time: Number, context: Object): Function
	// Returns a function which executes function `fn` with the given scope `context`
	// (so that the `this` keyword refers to `context` inside `fn`'s code). The function
	// `fn` will be called no more than one time per given amount of `time`. The arguments
	// received by the bound function will be any arguments passed when binding the
	// function, followed by any arguments passed when invoking the bound function.
	// Has an `L.bind` shortcut.
	throttle: function (fn, time, context) {
		var lock, args, wrapperFn, later;

		later = function () {
			// reset lock and call if queued
			lock = false;
			if (args) {
				wrapperFn.apply(context, args);
				args = false;
			}
		};

		wrapperFn = function () {
			if (lock) {
				// called too soon, queue to call later
				args = arguments;

			} else {
				// call and lock until later
				fn.apply(context, arguments);
				setTimeout(later, time);
				lock = true;
			}
		};

		return wrapperFn;
	},

	// @function wrapNum(num: Number, range: Number[], includeMax?: Boolean): Number
	// Returns the number `num` modulo `range` in such a way so it lies within
	// `range[0]` and `range[1]`. The returned value will be always smaller than
	// `range[1]` unless `includeMax` is set to `true`.
	wrapNum: function (x, range, includeMax) {
		var max = range[1],
		    min = range[0],
		    d = max - min;
		return x === max && includeMax ? x : ((x - min) % d + d) % d + min;
	},

	// @function falseFn(): Function
	// Returns a function which always returns `false`.
	falseFn: function () { return false; },

	// @function formatNum(num: Number, digits?: Number): Number
	// Returns the number `num` rounded to `digits` decimals, or to 5 decimals by default.
	formatNum: function (num, digits) {
		var pow = Math.pow(10, digits || 5);
		return Math.round(num * pow) / pow;
	},

	// @function trim(str: String): String
	// Compatibility polyfill for [String.prototype.trim](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)
	trim: function (str) {
		return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
	},

	// @function splitWords(str: String): String[]
	// Trims and splits the string on whitespace and returns the array of parts.
	splitWords: function (str) {
		return L.Util.trim(str).split(/\s+/);
	},

	// @function setOptions(obj: Object, options: Object): Object
	// Merges the given properties to the `options` of the `obj` object, returning the resulting options. See `Class options`. Has an `L.setOptions` shortcut.
	setOptions: function (obj, options) {
		if (!obj.hasOwnProperty('options')) {
			obj.options = obj.options ? L.Util.create(obj.options) : {};
		}
		for (var i in options) {
			obj.options[i] = options[i];
		}
		return obj.options;
	},

	// @function getParamString(obj: Object, existingUrl?: String, uppercase?: Boolean): String
	// Converts an object into a parameter URL string, e.g. `{a: "foo", b: "bar"}`
	// translates to `'?a=foo&b=bar'`. If `existingUrl` is set, the parameters will
	// be appended at the end. If `uppercase` is `true`, the parameter names will
	// be uppercased (e.g. `'?A=foo&B=bar'`)
	getParamString: function (obj, existingUrl, uppercase) {
		var params = [];
		for (var i in obj) {
			params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i]));
		}
		return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&');
	},

	// @function template(str: String, data: Object): String
	// Simple templating facility, accepts a template string of the form `'Hello {a}, {b}'`
	// and a data object like `{a: 'foo', b: 'bar'}`, returns evaluated string
	// `('Hello foo, bar')`. You can also specify functions instead of strings for
	// data values — they will be evaluated passing `data` as an argument.
	template: function (str, data) {
		return str.replace(L.Util.templateRe, function (str, key) {
			var value = data[key];

			if (value === undefined) {
				throw new Error('No value provided for variable ' + str);

			} else if (typeof value === 'function') {
				value = value(data);
			}
			return value;
		});
	},

	templateRe: /\{ *([\w_\-]+) *\}/g,

	// @function isArray(obj): Boolean
	// Compatibility polyfill for [Array.isArray](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray)
	isArray: Array.isArray || function (obj) {
		return (Object.prototype.toString.call(obj) === '[object Array]');
	},

	// @function indexOf(array: Array, el: Object): Number
	// Compatibility polyfill for [Array.prototype.indexOf](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf)
	indexOf: function (array, el) {
		for (var i = 0; i < array.length; i++) {
			if (array[i] === el) { return i; }
		}
		return -1;
	},

	// @property emptyImageUrl: String
	// Data URI string containing a base64-encoded empty GIF image.
	// Used as a hack to free memory from unused images on WebKit-powered
	// mobile devices (by setting image `src` to this string).
	emptyImageUrl: 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='
};

(function () {
	// inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/

	function getPrefixed(name) {
		return window['webkit' + name] || window['moz' + name] || window['ms' + name];
	}

	var lastTime = 0;

	// fallback for IE 7-8
	function timeoutDefer(fn) {
		var time = +new Date(),
		    timeToCall = Math.max(0, 16 - (time - lastTime));

		lastTime = time + timeToCall;
		return window.setTimeout(fn, timeToCall);
	}

	var requestFn = window.requestAnimationFrame || getPrefixed('RequestAnimationFrame') || timeoutDefer,
	    cancelFn = window.cancelAnimationFrame || getPrefixed('CancelAnimationFrame') ||
	               getPrefixed('CancelRequestAnimationFrame') || function (id) { window.clearTimeout(id); };

	// @function requestAnimFrame(fn: Function, context?: Object, immediate?: Boolean): Number
	// Schedules `fn` to be executed when the browser repaints. `fn` is bound to
	// `context` if given. When `immediate` is set, `fn` is called immediately if
	// the browser doesn't have native support for
	// [`window.requestAnimationFrame`](https://developer.mozilla.org/docs/Web/API/window/requestAnimationFrame),
	// otherwise it's delayed. Returns a request ID that can be used to cancel the request.
	L.Util.requestAnimFrame = function (fn, context, immediate) {
		if (immediate && requestFn === timeoutDefer) {
			fn.call(context);
		} else {
			return requestFn.call(window, L.bind(fn, context));
		}
	};

	// @function cancelAnimFrame(id: Number): undefined
	// Cancels a previous `requestAnimFrame`. See also [window.cancelAnimationFrame](https://developer.mozilla.org/docs/Web/API/window/cancelAnimationFrame).
	L.Util.cancelAnimFrame = function (id) {
		if (id) {
			cancelFn.call(window, id);
		}
	};
})();

// shortcuts for most used utility functions
L.extend = L.Util.extend;
L.bind = L.Util.bind;
L.stamp = L.Util.stamp;
L.setOptions = L.Util.setOptions;
<|endoftext|>


<commit_before>$(document).ready(function() {
	load();
	/*
	var credits = $("#credits");
	var creditnames = $("#creditnames");
	create_block(credits, "Me", 35, false);
	create_block(credits, "Ivan", 25, false);
	create_block(credits, "Justin", 15, false);
	create_block(credits, "Sean", 10, false);
	create_block(credits, "Others", 15, false);

	create_label(creditnames, "Me", 35, false);
	create_label(creditnames, "Ivan", 25, false);
	create_label(creditnames, "Justin", 15, false);
	create_label(creditnames, "Sean", 10, false);
	create_label(creditnames, "Others", 15, false);

	var usage = $("#usage");
	var usagenames = $("#usagenames");
	create_block(usage, "Justin", 3, true);
	create_block(usage, "Kate", 5, true);
	create_block(usage, "Man", 8, true);
	create_block(usage, "Me", 21, true);
	create_block(usage, "Kevin", 14, true);
	create_block(usage, "Others", 14, true);
	create_block(usage, "Free", 35, true);
	create_label(usagenames, "Justin", 3, true);
	create_label(usagenames, "Kate", 5, true);
	create_label(usagenames, "Man", 8, true);
	create_label(usagenames, "Me", 21, true);
	create_label(usagenames, "Kevin", 14, true);
	create_label(usagenames, "Others", 14, true);
	create_label(usagenames, "Free", 35, true);
	*/

});

/*
	Create a block with given width and background color,
	and append it to the given bar element.
*/
function create_block(bar, username, width, isClosable) {
	var block = $(document.createElement('td'));
	block.css({
		'width': width + '%',
		'background-color': '#' + color_generator(username)
	});
	var percent = $(document.createElement('span'));
	percent.text(width + '%');

	if (isClosable) {
		block.attr("id", "usage" + username);
		if (username == "Free") {
			var get = $(document.createElement('a'));
			get.attr('id','getresourcesbutton');
			get.attr('href','#');
			get.text('get');
			get.click(get_resources_dialog);
			block.append(get);

			var share = $(document.createElement('a'));
			share.attr('id','shareresourcesbutton');
			share.attr('href','#');
			share.text('share');
			share.click(share_resources_dialog);
			block.append(share);

		} else if (username != "Me" && username != "Others" ) {
			var close = $(document.createElement('a'));
			close.attr('href','#');
			close.text('x');
			close.click(function() {
				$.post("http://128.208.3.86:8081/geni_dev_sean/control/ajax_editshare",
						{ username: username, percent: width },
						function (data) {
							var json = eval('(' + data + ')');
							if (json.success) {
								edit_block(username, 0);
							} else {
								alert(json.error);
							}
						});
			});
			block.append(close);
			percent.click(change_percent);
		}
	}

	if (username == "Others") {
		percent.click(function () { show_table(isClosable) });
	}

	block.append(percent);
	bar.append(block);
}

/*
	Change the block's width both in terms of its label and
	actual width. Resize free block to	fit the width of the bar.
	Remove the block from the usage bar if width is 0
	Called by save_percent or close on the block
*/
function edit_block(username, width) {
	if (username != "Free") {
		var block = $("#usage" + username);
		var label = $("#labelusage" + username);
		var old_percent = parseInt($("#usage" + username + " span").text());
		var free_percent = parseInt($("#usageFree span").text());
		var new_free_percent = free_percent + old_percent - width;
		if (new_free_percent >= 0) {
			if (width == 0) {
				block.remove();
				label.remove();
			} else {
				$("#usage" + username + " span").text(width + '%');
				block.css("width", width + '%');
				label.css("width", width + '%');
			}
			$("#usageFree span").text(new_free_percent + '%');
			$("#usageFree").css("width", new_free_percent + '%');
			$("#labelusageFree").css("width", new_free_percent + '%');
		}
	}
}

/*
	Create a name label with given width and append it to
	the given name table.
*/
function create_label(names, username, width, isClosable) {
	var label = $(document.createElement('td'));
	if (isClosable) {
		label.attr("id", "labelusage" + username);
	}
	label.text(username);
	label.css({
		'width': width + '%'
	});
	names.append(label);
}

/*
	Display the change percent dialog box
*/
function change_percent() {
	var dialog = $(document.createElement("div"));
	dialog.attr("id", "changepercentdialog");
	dialog.html('
Change Percent
');
	var input = $(document.createElement("input"));
	input.attr("name", $(this).parent().attr("id"));
	input.attr("type", "text");
	input.val(parseInt($(this).text()));
	input.click(function () { $(this).val("") });
	var symbol = $(document.createElement("span"));
	symbol.html(" %
");
	var cancel = $(document.createElement("button"));
	cancel.text("Cancel");
	var save = $(document.createElement("button"));
	save.text("Save");
	cancel.click(function () {
		close_dialog();
		$(this).parent().remove();
	});
	save.click(save_percent);
	dialog.append(input);
	dialog.append(symbol);
	dialog.append(cancel);
	dialog.append(save);
	$("#dialogframe").append(dialog);
	$("#dialogframe").fadeIn("fast");
	$("#overlay").fadeIn("fast");
	$("#changepercentdialog").fadeIn("fast");
}

/*
	Save the percent of the the block when click "save" on the
	change_percent dialog box
*/
function save_percent() {
	var input = $("#changepercentdialog input");
	var percent = input.val();
	var username = input.attr("name").substring(5);
	$.post("http://128.208.3.86:8081/geni_dev_sean/control/ajax_editshare",
			{ username: username, percent: percent },
			function (data) {
				var json = eval(data);
				if (json.success) {
					$("#changepercentdialog").remove();
					$("#dialogframe").hide();
					$("#overlay").hide();
					edit_block(username, percent);
				} else {
					create_warning(json.error, $("#changepercentdialog h3"));
					/*
					var warning = $(document.createElement("span"));
					warning.text(json.error);
					warning.addClass("warning");
					$("#changepercentdialog").css("height", "160px");
					warning.insertBefore($("#changepercentdialog").children("input"));
					*/
				}
	   		},
			"json");
}

/*
	Toggle display the tables for small percent users
*/
function show_table(isClosable) {
	if (isClosable) {
		$("#usageothers").toggle();
	} else {
		$("#creditothers").toggle();
	}
}

function get_resources_dialog() {
	$("#dialogframe").fadeIn("fast");
	$("#overlay").fadeIn("fast");
	$("#getresourcesdialog").fadeIn("fast");
	$(".cancel").click(close_dialog);
}

function share_resources_dialog() {
	$("#dialogframe").fadeIn("fast");
	$("#overlay").fadeIn("fast");
	$("#shareresourcesdialog").fadeIn("fast");
	$(".cancel").click(close_dialog);
	$("#shareresources").click(share_resources);
}

function close_dialog() {
	$(this).parent().hide();
	$("#dialogframe").hide();
	$("#overlay").hide();
}

function share_resources() {
	var username = $("#shareresourcesdialog #username").val();
	var percent = $("#shareresourcesdialog #percent").val();

	if (percent > 0) {
		$.post("http://128.208.3.86:8081/geni_dev_sean/control/ajax_createshare",
				{ username: username, percent: percent },
				function (data) {
					var json = eval(data);
					if (json.success) {
						$("#shareresourcesdialog").hide();
						$("#dialogframe").hide();
						$("#overlay").hide();
						create_block($("#usage"), username, percent, true);
						create_label($("#usagenames"), username, percent, true);
					} else {
						create_warning(json.error, $("#shareresourcesdialog h3"));
					}
				});
	} else {
		create_warning("Percent must greater than 0", $("#shareresourcesdialog h3"));
	}
}

function create_warning(error, position) {
	var warning = $(document.createElement("span"));
	warning.text(error);
	warning.addClass("warning");
	warning.insertAfter(position);
}

/*
	Generate a color in hex notation for a username, which assigns different
	colors to different usernames.
*/

function color_generator(username) {
	var seeds = ['cc','ff'];
	var color = seeds[username.charCodeAt(0) % 2] +
				seeds[username.charCodeAt(1) % 2] +
				seeds[username.charCodeAt(username.length - 1) % 2];
	if (color == "ffffff") {
		color = "ffffcc";
	} else if (color == "cccccc") {
		color = "ccccff";
	}
	if (username == "Free") {
		color = "ffffff";
	} else if (username == "Me") {
		color = "cccccc";
	}
	return color;
}

function load() {
	$.post("http://128.208.3.86:8081/geni_dev_sean/control/ajax_getcredits",
		function (data) { update_blocks("credits", data); },
		"json");
	$.post("http://128.208.3.86:8081/geni_dev_sean/control/ajax_getshares",
		function (data) { update_blocks("shares", data); },
		"json");
}

function update_blocks(type, data) {
	if (type == "credits") {
		var credits = $("#credits");
		var creditnames = $("#creditnames");
		var json = eval('(' + data + ')');
		for (var i = 0; i < json.length; i++) {
			create_block(credits, json[i].username, json[i].percent, false);
			create_label(creditnames, json[i].username, json[i].percent, false);
		}
	} else if (type == "shares") {
		var usage = $("#usage");
		var usagenames = $("#usagenames");
		var json = eval('(' + data + ')');
		var total_percent = 0;
		for (var i = 0; i < json.length; i++) {
			create_block(usage, json[i].username, json[i].percent, true);
			create_label(usagenames, json[i].username, json[i].percent, true);
			total_percent += json[i].percent;
		}
		create_block(usage, "Free", 100 - total_percent, true);
		create_label(usagenames, "Free", 100 - total_percent, true);
	}
}
<commit_msg>fixed some bugs<commit_after>$(document).ready(function() {
	load();
	/*
	var credits = $("#credits");
	var creditnames = $("#creditnames");
	create_block(credits, "Me", 35, false);
	create_block(credits, "Ivan", 25, false);
	create_block(credits, "Justin", 15, false);
	create_block(credits, "Sean", 10, false);
	create_block(credits, "Others", 15, false);

	create_label(creditnames, "Me", 35, false);
	create_label(creditnames, "Ivan", 25, false);
	create_label(creditnames, "Justin", 15, false);
	create_label(creditnames, "Sean", 10, false);
	create_label(creditnames, "Others", 15, false);

	var usage = $("#usage");
	var usagenames = $("#usagenames");
	create_block(usage, "Justin", 3, true);
	create_block(usage, "Kate", 5, true);
	create_block(usage, "Man", 8, true);
	create_block(usage, "Me", 21, true);
	create_block(usage, "Kevin", 14, true);
	create_block(usage, "Others", 14, true);
	create_block(usage, "Free", 35, true);
	create_label(usagenames, "Justin", 3, true);
	create_label(usagenames, "Kate", 5, true);
	create_label(usagenames, "Man", 8, true);
	create_label(usagenames, "Me", 21, true);
	create_label(usagenames, "Kevin", 14, true);
	create_label(usagenames, "Others", 14, true);
	create_label(usagenames, "Free", 35, true);
	*/

});

/*
	Create a block with given width and background color,
	and append it to the given bar element.
*/
function create_block(bar, username, width, isClosable) {
	var block = $(document.createElement('td'));
	block.css({
		'width': width + '%',
		'background-color': '#' + color_generator(username)
	});
	var percent = $(document.createElement('span'));
	percent.text(width + '%');

	if (isClosable) {
		block.attr("id", "usage" + username);
		if (username == "Free") {
			var get = $(document.createElement('a'));
			get.attr('id','getresourcesbutton');
			get.attr('href','#');
			get.text('get');
			get.click(get_resources_dialog);
			block.append(get);

			var share = $(document.createElement('a'));
			share.attr('id','shareresourcesbutton');
			share.attr('href','#');
			share.text('share');
			share.click(share_resources_dialog);
			block.append(share);

		} else if (username != "Me" && username != "Others" ) {
			var close = $(document.createElement('a'));
			close.attr('href','#');
			close.text('x');
			close.click(function() {
				$.post("http://128.208.3.86:8081/geni_dev_sean/control/ajax_editshare",
						{ username: username, percent: width },
						function (data) {
							var json = eval('(' + data + ')');
							if (json.success) {
								edit_block(username, 0);
							} else {
								alert(json.error);
							}
						});
			});
			block.append(close);
			percent.click(change_percent);
		}
	}

	if (username == "Others") {
		percent.click(function () { show_table(isClosable) });
	}

	block.append(percent);
	bar.append(block);
}

/*
	Change the block's width both in terms of its label and
	actual width. Resize free block to	fit the width of the bar.
	Remove the block from the usage bar if width is 0
	Called by save_percent or close on the block
*/
function edit_block(username, width) {
	if (username != "Free") {
		var block = $("#usage" + username);
		var label = $("#labelusage" + username);
		var old_percent = parseInt($("#usage" + username + " span").text());
		var free_percent = parseInt($("#usageFree span").text());
		var new_free_percent = free_percent + old_percent - width;
		if (new_free_percent >= 0) {
			if (width == 0) {
				block.remove();
				label.remove();
			} else {
				$("#usage" + username + " span").text(width + '%');
				block.css("width", width + '%');
				label.css("width", width + '%');
			}
			$("#usageFree span").text(new_free_percent + '%');
			$("#usageFree").css("width", new_free_percent + '%');
			$("#labelusageFree").css("width", new_free_percent + '%');
		}
	}
}

/*
	Create a name label with given width and append it to
	the given name table.
*/
function create_label(names, username, width, isClosable) {
	var label = $(document.createElement('td'));
	if (isClosable) {
		label.attr("id", "labelusage" + username);
	}
	label.text(username);
	label.css({
		'width': width + '%'
	});
	names.append(label);
}

/*
	Display the change percent dialog box
*/
function change_percent() {
	var dialog = $(document.createElement("div"));
	dialog.attr("id", "changepercentdialog");
	dialog.html('
Change Percent
');
	var input = $(document.createElement("input"));
	input.attr("name", $(this).parent().attr("id"));
	input.attr("type", "text");
	input.val(parseInt($(this).text()));
	input.click(function () { $(this).val("") });
	var symbol = $(document.createElement("span"));
	symbol.html(" %
");
	var cancel = $(document.createElement("button"));
	cancel.text("Cancel");
	var save = $(document.createElement("button"));
	save.text("Save");
	cancel.click(function () {
		close_dialog();
		$(this).parent().remove();
	});
	save.click(save_percent);
	dialog.append(input);
	dialog.append(symbol);
	dialog.append(cancel);
	dialog.append(save);
	$("#dialogframe").append(dialog);
	$("#dialogframe").fadeIn("fast");
	$("#overlay").fadeIn("fast");
	$("#changepercentdialog").fadeIn("fast");
}

/*
	Save the percent of the the block when click "save" on the
	change_percent dialog box
*/
function save_percent() {
	var input = $("#changepercentdialog input");
	var percent = input.val();
	var username = input.attr("name").substring(5);
	$.post("http://128.208.3.86:8081/geni_dev_sean/control/ajax_editshare",
			{ username: username, percent: percent },
			function (data) {
				var json = eval(data);
				if (json.success) {
					$("#changepercentdialog").remove();
					$("#dialogframe").hide();
					$("#overlay").hide();
					edit_block(username, percent);
				} else {
					create_warning(json.error, $("#changepercentdialog h3"));
					/*
					var warning = $(document.createElement("span"));
					warning.text(json.error);
					warning.addClass("warning");
					$("#changepercentdialog").css("height", "160px");
					warning.insertBefore($("#changepercentdialog").children("input"));
					*/
				}
	   		},
			"json");
}

/*
	Toggle display the tables for small percent users
*/
function show_table(isClosable) {
	if (isClosable) {
		$("#usageothers").toggle();
	} else {
		$("#creditothers").toggle();
	}
}

function get_resources_dialog() {
	$("#dialogframe").fadeIn("fast");
	$("#overlay").fadeIn("fast");
	$("#getresourcesdialog").fadeIn("fast");
	$(".cancel").click(close_dialog);
}

function share_resources_dialog() {
	$("#dialogframe").fadeIn("fast");
	$("#overlay").fadeIn("fast");
	$("#shareresourcesdialog").fadeIn("fast");
	$(".cancel").click(close_dialog);
	$("#shareresources").click(share_resources);
}

function close_dialog() {
	$(this).parent().hide();
	$("#dialogframe").hide();
	$("#overlay").hide();
}

function share_resources() {
	var username = $("#shareresourcesdialog #username").val();
	var percent = parseInt($("#shareresourcesdialog #percent").val());

	if (percent > 0) {
		$.post("http://128.208.3.86:8081/geni_dev_sean/control/ajax_createshare",
				{ username: username, percent: percent },
				function (data) {
					var json = eval(data);
					if (json.success) {
						$("#shareresourcesdialog").hide();
						$("#dialogframe").hide();
						$("#overlay").hide();
						create_block($("#usage"), username, percent, true);
						create_label($("#usagenames"), username, percent, true);
					} else {
						create_warning(json.error, $("#shareresourcesdialog h3"));
					}
				});
	} else {
		create_warning("Percent must greater than 0", $("#shareresourcesdialog h3"));
	}
}

function create_warning(error, position) {
	var warning = $(document.createElement("span"));
	warning.text(error);
	warning.addClass("warning");
	warning.insertAfter(position);
}

/*
	Generate a color in hex notation for a username, which assigns different
	colors to different usernames.
*/

function color_generator(username) {
	var seeds = ['cc','ff'];
	var color = seeds[username.charCodeAt(0) % 2] +
				seeds[username.charCodeAt(1) % 2] +
				seeds[username.charCodeAt(username.length - 1) % 2];
	if (color == "ffffff") {
		color = "ffffcc";
	} else if (color == "cccccc") {
		color = "ccccff";
	}
	if (username == "Free") {
		color = "ffffff";
	} else if (username == "Me") {
		color = "cccccc";
	}
	return color;
}

function load() {
	$.post("http://128.208.3.86:8081/geni_dev_sean/control/ajax_getcredits",
		function (data) { update_blocks("credits", data); },
		"json");
	$.post("http://128.208.3.86:8081/geni_dev_sean/control/ajax_getshares",
		function (data) { update_blocks("shares", data); },
		"json");
}

function update_blocks(type, data) {
	if (type == "credits") {
		var credits = $("#credits");
		var creditnames = $("#creditnames");
		var json = eval('(' + data + ')');
		for (var i = 0; i < json.length; i++) {
			create_block(credits, json[i].username, json[i].percent, false);
			create_label(creditnames, json[i].username, json[i].percent, false);
		}
	} else if (type == "shares") {
		var usage = $("#usage");
		var usagenames = $("#usagenames");
		var json = eval('(' + data + ')');
		var total_percent = 0;
		for (var i = 0; i < json.length; i++) {
			create_block(usage, json[i].username, json[i].percent, true);
			create_label(usagenames, json[i].username, json[i].percent, true);
			total_percent += json[i].percent;
		}
		create_block(usage, "Free", 100 - total_percent, true);
		create_label(usagenames, "Free", 100 - total_percent, true);
	}
}
<|endoftext|>


<commit_before>/**
 * Highly inspired from Facebook connect JS SDK available at https://github.com/facebook/connect-js
 *
 * Copyright Dailymotion S.A.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *
 *
 * @provides dm.auth
 * @requires dm.prelude
 *           dm.qs
 *           dm.event
 *           dm.json
 *           dm.api
 */

/**
 * Authentication, Authorization & Sessions.
 *
 * @class dm
 * @static
 * @access private
 */
DM.provide('',
{
    getLoginStatus: function(cb)
    {
        if (cb)
        {
            cb({status: DM._userStatus, session: DM._session});
        }
    },

    getSession: function()
    {
        if (DM._session && 'expires' in DM._session && new Date().getTime() > DM._session.expires * 1000)
        {
            DM.Auth.setSession(null, 'notConnected');
        }

        return DM._session;
    },

    login: function(cb, opts)
    {
        // we try to place it at the center of the current window
        var screenX = typeof window.screenX != 'undefined' ? window.screenX : window.screenLeft,
            screenY = typeof window.screenY != 'undefined' ? window.screenY : window.screenTop,
            outerWidth = typeof window.outerWidth != 'undefined' ? window.outerWidth : document.documentElement.clientWidth,
            outerHeight = typeof window.outerHeight != 'undefined' ? window.outerHeight : (document.documentElement.clientHeight - 22), // 22 = IE toolbar height
            width = 600,
            height = 420,
            left = parseInt(screenX + ((outerWidth - width) / 2), 10),
            top = parseInt(screenY + ((outerHeight - height) / 2.5), 10),
            features = 'width=' + width + ',height=' + height + ',left=' + left + ',top=' + top;

        opts = DM.copy(opts || {},
        {
            client_id: DM._apiKey,
            response_type: 'token',
            display: 'popup',
            scope: '',
            redirect_uri: document.location.href,
            state: 'dmauth_' + DM.guid()
        });

        var win = window.open(DM.Auth.authorizeUrl + '?' + DM.QS.encode(opts), 'dmauth', features);

        if (cb)
        {
            DM.Auth._active[opts.state] = {cb: cb, win: win};
            DM.Auth._popupMonitor();
        }
    },

    logout: function(cb)
    {
        DM.api('/logout', cb);
    }
});

/**
 * Internal Authentication implementation.
 *
 * @class DM.Auth
 * @static
 * @access private
 */
DM.provide('Auth',
{
    authorizeUrl: 'https://api.dailymotion.com/oauth/authorize',
    _active: {},
    _receivedSession: null,

    /**
     * Check if session info are present in the URL fragment
     *
     * @access private
     */
     readFragment: function()
     {
         var h = window.location.hash.replace('%23', '#'), fragment = h.substr(h.lastIndexOf('#') + 1);
         if (fragment.indexOf('access_token=') >= 0 || fragment.indexOf('error=') >= 0)
         {
             var session = DM.QS.decode(fragment);

             if (window.opener && window.opener.DM.Auth.setSession && window.name == 'dmauth' && window.opener.name != 'dmauth')
             {
                 // Display none helps prevent loading of some stuff
                 document.documentElement.style.display = 'none';

                 window.opener.DM.Auth.recvSession(session);
             }
             else if (session && ('state' in session) && session.state.indexOf('dmauth_') == 0) // Ensure it's our session
             {
                 // The session have been received as fragment, but we can't find a valid opener.
                 // This happen either when the user is redirected to the authorization page or when the agent
                 // doesn't fully support window.open, and replace the current window by the opened one
                 // (i.e.: iPhone fullscreen webapp mode)
                 DM.Auth._receivedSession = session;
                 // Remove the session from the fragment
                 window.location.hash = h.substr(0, h.lastIndexOf('#'));
             }
         }
     },

    /**
     * Recieve the authorization server response
     *
     * @access private
     * @param session {Object}  the new Session
     */
    recvSession: function(session)
    {
        if (!session)
        {
            DM.error('Received invalid session');
        }

        if ('error' in session)
        {
            DM.error('Received auth error `' + session.error + '\': ' + session.error_description);
        }

        if (!('state' in session))
        {
            DM.error("Received a session with not `state' field");
            return;
        }

        if (!(session.state in DM.Auth._active))
        {
            DM.error('Received a session from an inactive window');
            return;
        }

        DM.Auth._active[session.state].session = session;
    },

    /**
     * Set a new session value. Invokes all the registered subscribers
     * if needed.
     *
     * @access private
     * @param session {Object}  the new Session
     * @param status  {String}  the new status
     * @return        {Object}  the "response" object
     */
    setSession: function(session, status)
    {
        // detect special changes before changing the internal session
        var login = !DM._session && session,
            logout = DM._session && !session,
            both = false, // DM._session && session && DM._session.uid != session.uid,
            sessionChange = login || logout || (DM._session && session && DM._session.access_token != session.access_token),
            statusChange = status != DM._userStatus;

        if (session && 'expires_in' in session)
        {
            // CAVEAT: the expires here will actually only be valid on the client as end-user machines
            //         clock is rarely synced
            session.expires = Math.round(new Date().getTime() / 1000) + parseInt(session.expires_in, 10);
            delete session.expires_in;
        }

        var response =
        {
            session: session,
            status: status
        };

        DM._session = session;
        DM._userStatus = status;

        // If cookie support is enabled, set the cookie. Cookie support does not
        // rely on events, because we want the cookie to be set _before_ any of the
        // event handlers are fired. Note, this is a _weak_ dependency on Cookie.
        if (sessionChange && DM.Cookie && DM.Cookie.getEnabled())
        {
            DM.Cookie.set(session);
        }

        // events
        if (statusChange)
        {
            /**
             * Fired when the status changes.
             *
             * @event auth.statusChange
             */
            DM.Event.fire('auth.statusChange', response);
        }
        if (logout || both)
        {
            /**
             * Fired when a logout action is performed.
             *
             * @event auth.logout
             */
            DM.Event.fire('auth.logout', response);
        }
        if (login || both)
        {
            /**
             * Fired when a login action is performed.
             *
             * @event auth.login
             */
            DM.Event.fire('auth.login', response);
        }
        if (sessionChange)
        {
            /**
             * Fired when the session changes. This includes a session being
             * refreshed, or a login or logout action.
             *
             * @event auth.sessionChange
             */
            DM.Event.fire('auth.sessionChange', response);
        }

        return response;
    },

    /**
     * Start and manage the window monitor interval. This allows us to invoke
     * the default callback for a window when the user closes the window
     * directly.
     *
     * @access private
     */
    _popupMonitor: function()
    {
        // check all open windows
        for (var id in DM.Auth._active)
        {
            if ('win' in DM.Auth._active[id])
            {
                try
                {
                    // found a closed window
                    if (DM.Auth._active[id].win.closed)
                    {
                        delete DM.Auth._active[id].win;
                        DM.Auth.recvSession({error:'access_denied', error_description:'Client closed the window', state:id});
                    }
                }
                catch (e)
                {
                }
            }

            if ('session' in DM.Auth._active[id])
            {
                var callInfo = DM.Auth._active[id];
                delete DM.Auth._active[id];

                var session = callInfo.session;
                if ('access_token' in session)
                {
                    DM.Auth.setSession(session, 'connected');
                }
                else
                {
                    DM.Auth.setSession(null, 'notConnected');
                }

                if ('win' in callInfo)
                {
                    callInfo.win.close();
                }

                if ('cb' in callInfo)
                {
                    callInfo.cb({status: DM._userStatus, session: DM._session});
                }
            }
        }

        var hasActive = false;
        for (var id in DM.Auth._active)
        {
            hasActive = true;
            break;
        }
        if (hasActive && !DM.Auth._popupInterval)
        {
            // start the monitor if needed and it's not already running
            DM.Auth._popupInterval = window.setInterval(DM.Auth._popupMonitor, 100);
        }
        else if (!hasActive && DM.Auth._popupInterval)
        {
            // shutdown if we have nothing to monitor but it's running
            window.clearInterval(DM.Auth._popupInterval);
            DM.Auth._popupInterval = null;
        }
    }
});

DM.Auth.readFragment();
<commit_msg>Do not use popup window if display option is not 'popup'<commit_after>/**
 * Highly inspired from Facebook connect JS SDK available at https://github.com/facebook/connect-js
 *
 * Copyright Dailymotion S.A.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *
 *
 * @provides dm.auth
 * @requires dm.prelude
 *           dm.qs
 *           dm.event
 *           dm.json
 *           dm.api
 */

/**
 * Authentication, Authorization & Sessions.
 *
 * @class dm
 * @static
 * @access private
 */
DM.provide('',
{
    getLoginStatus: function(cb)
    {
        if (cb)
        {
            cb({status: DM._userStatus, session: DM._session});
        }
    },

    getSession: function()
    {
        if (DM._session && 'expires' in DM._session && new Date().getTime() > DM._session.expires * 1000)
        {
            DM.Auth.setSession(null, 'notConnected');
        }

        return DM._session;
    },

    login: function(cb, opts)
    {
        // we try to place it at the center of the current window
        var screenX = typeof window.screenX != 'undefined' ? window.screenX : window.screenLeft,
            screenY = typeof window.screenY != 'undefined' ? window.screenY : window.screenTop,
            outerWidth = typeof window.outerWidth != 'undefined' ? window.outerWidth : document.documentElement.clientWidth,
            outerHeight = typeof window.outerHeight != 'undefined' ? window.outerHeight : (document.documentElement.clientHeight - 22), // 22 = IE toolbar height
            width = 600,
            height = 420,
            left = parseInt(screenX + ((outerWidth - width) / 2), 10),
            top = parseInt(screenY + ((outerHeight - height) / 2.5), 10),
            features = 'width=' + width + ',height=' + height + ',left=' + left + ',top=' + top;

        opts = DM.copy(opts || {},
        {
            client_id: DM._apiKey,
            response_type: 'token',
            display: 'popup',
            scope: '',
            redirect_uri: document.location.href,
            state: 'dmauth_' + DM.guid()
        });

        if (opts.display === 'popup')
        {
            var win = window.open(DM.Auth.authorizeUrl + '?' + DM.QS.encode(opts), 'dmauth', features);

            if (cb)
            {
                DM.Auth._active[opts.state] = {cb: cb, win: win};
                DM.Auth._popupMonitor();
            }
        }
        else
        {
            location.href = DM.Auth.authorizeUrl + '?' + DM.QS.encode(opts);
        }
    },

    logout: function(cb)
    {
        DM.api('/logout', cb);
    }
});

/**
 * Internal Authentication implementation.
 *
 * @class DM.Auth
 * @static
 * @access private
 */
DM.provide('Auth',
{
    authorizeUrl: 'https://api.dailymotion.com/oauth/authorize',
    _active: {},
    _receivedSession: null,

    /**
     * Check if session info are present in the URL fragment
     *
     * @access private
     */
    readFragment: function()
    {
        var h = window.location.hash.replace('%23', '#'), fragment = h.substr(h.lastIndexOf('#') + 1);
        if (fragment.indexOf('access_token=') >= 0 || fragment.indexOf('error=') >= 0)
        {
            var session = DM.QS.decode(fragment);

            if (window.opener && window.opener.DM.Auth.setSession && window.name == 'dmauth' && window.opener.name != 'dmauth')
            {
                // Display none helps prevent loading of some stuff
                document.documentElement.style.display = 'none';

                window.opener.DM.Auth.recvSession(session);
            }
            else if (session && ('state' in session) && session.state.indexOf('dmauth_') == 0) // Ensure it's our session
            {
                // The session have been received as fragment, but we can't find a valid opener.
                // This happen either when the user is redirected to the authorization page or when the agent
                // doesn't fully support window.open, and replace the current window by the opened one
                // (i.e.: iPhone fullscreen webapp mode)
                if ('access_token' in session)
                {
                    DM.Auth._receivedSession = session;
                }
                // Remove the session from the fragment
                window.location.hash = h.substr(0, h.lastIndexOf('#'));
            }
        }
    },

    /**
     * Recieve the authorization server response
     *
     * @access private
     * @param session {Object}  the new Session
     */
    recvSession: function(session)
    {
        if (!session)
        {
            DM.error('Received invalid session');
        }

        if ('error' in session)
        {
            DM.error('Received auth error `' + session.error + '\': ' + session.error_description);
        }

        if (!('state' in session))
        {
            DM.error("Received a session with not `state' field");
            return;
        }

        if (!(session.state in DM.Auth._active))
        {
            DM.error('Received a session from an inactive window');
            return;
        }

        DM.Auth._active[session.state].session = session;
    },

    /**
     * Set a new session value. Invokes all the registered subscribers
     * if needed.
     *
     * @access private
     * @param session {Object}  the new Session
     * @param status  {String}  the new status
     * @return        {Object}  the "response" object
     */
    setSession: function(session, status)
    {
        // detect special changes before changing the internal session
        var login = !DM._session && session,
            logout = DM._session && !session,
            both = false, // DM._session && session && DM._session.uid != session.uid,
            sessionChange = login || logout || (DM._session && session && DM._session.access_token != session.access_token),
            statusChange = status != DM._userStatus;

        if (session && 'expires_in' in session)
        {
            // CAVEAT: the expires here will actually only be valid on the client as end-user machines
            //         clock is rarely synced
            session.expires = Math.round(new Date().getTime() / 1000) + parseInt(session.expires_in, 10);
            delete session.expires_in;
        }

        var response =
        {
            session: session,
            status: status
        };

        DM._session = session;
        DM._userStatus = status;

        // If cookie support is enabled, set the cookie. Cookie support does not
        // rely on events, because we want the cookie to be set _before_ any of the
        // event handlers are fired. Note, this is a _weak_ dependency on Cookie.
        if (sessionChange && DM.Cookie && DM.Cookie.getEnabled())
        {
            DM.Cookie.set(session);
        }

        // events
        if (statusChange)
        {
            /**
             * Fired when the status changes.
             *
             * @event auth.statusChange
             */
            DM.Event.fire('auth.statusChange', response);
        }
        if (logout || both)
        {
            /**
             * Fired when a logout action is performed.
             *
             * @event auth.logout
             */
            DM.Event.fire('auth.logout', response);
        }
        if (login || both)
        {
            /**
             * Fired when a login action is performed.
             *
             * @event auth.login
             */
            DM.Event.fire('auth.login', response);
        }
        if (sessionChange)
        {
            /**
             * Fired when the session changes. This includes a session being
             * refreshed, or a login or logout action.
             *
             * @event auth.sessionChange
             */
            DM.Event.fire('auth.sessionChange', response);
        }

        return response;
    },

    /**
     * Start and manage the window monitor interval. This allows us to invoke
     * the default callback for a window when the user closes the window
     * directly.
     *
     * @access private
     */
    _popupMonitor: function()
    {
        // check all open windows
        for (var id in DM.Auth._active)
        {
            if ('win' in DM.Auth._active[id])
            {
                try
                {
                    // found a closed window
                    if (DM.Auth._active[id].win.closed)
                    {
                        delete DM.Auth._active[id].win;
                        DM.Auth.recvSession({error:'access_denied', error_description:'Client closed the window', state:id});
                    }
                }
                catch (e)
                {
                }
            }

            if ('session' in DM.Auth._active[id])
            {
                var callInfo = DM.Auth._active[id];
                delete DM.Auth._active[id];

                var session = callInfo.session;
                if ('access_token' in session)
                {
                    DM.Auth.setSession(session, 'connected');
                }
                else
                {
                    DM.Auth.setSession(null, 'notConnected');
                }

                if ('win' in callInfo)
                {
                    callInfo.win.close();
                }

                if ('cb' in callInfo)
                {
                    callInfo.cb({status: DM._userStatus, session: DM._session});
                }
            }
        }

        var hasActive = false;
        for (var id in DM.Auth._active)
        {
            hasActive = true;
            break;
        }
        if (hasActive && !DM.Auth._popupInterval)
        {
            // start the monitor if needed and it's not already running
            DM.Auth._popupInterval = window.setInterval(DM.Auth._popupMonitor, 100);
        }
        else if (!hasActive && DM.Auth._popupInterval)
        {
            // shutdown if we have nothing to monitor but it's running
            window.clearInterval(DM.Auth._popupInterval);
            DM.Auth._popupInterval = null;
        }
    }
});

DM.Auth.readFragment();
<|endoftext|>


<commit_before>/*
	Base is extended from Scale, it is used for the basic/ folder section. All mixined or extended modules will have all its behavior. Where you define your absolutely needed methods for the APIs. Internal use only, never use it for displaying a chart.

	Initalization:
		initialize: function(containerInfo) {
			var chart =  this.mixin('Base',  axisG, {
				info: containerInfo,
				x: 'ordinal',
				y: 'log',
				width: this.base.attr('width'),  // optional
				height: this.base.attr('height')   // optional
			});
		}

		// Passing options object as a third argument. Options is required.

	Arguments:
		Attributes
			since it inherit from scale.js, it will have all its private & public attr. Read core/scale.js Arguments section for details

	APIs:  ( defined in the constructor level )
	# THOSE APIs EXIST IN ALL EXTENDED MODULES
		constructor.box(_width, _height)
			# setter/getter container width value and height values, when only one value, height is the same as width

		constructor.w(_width)
			# setter/getter container width value  // always recommend to use constructor.box() instead

		constructor.h(_height)
			# setter/getter container height value  // always recommend to use constructor.box() instead

	PRIVATE APIs:
		_bindMouseEnterOutEvents(chart, single)
			# when it is entering, binding datum with each element, single element will bind 'mouseenter' event with our custom 'd3maMouseenter', bind 'mouseout' with our custom event 'd3maMouseout'.
			For example, quick internal binding to reduce duplicated code in modules like circle.js, bars.js etc

		1. _resize()  # called from d3.ma.onResize() or d3.ma.resize()
		2. _onWindowResize(chart, single)  # called from each individual module. It has to defined in each module basis. Since it has to pass the chart, single info in this.layer lifeevent enter event. No way to know its context in base.js level.
		3. _redraw(e, chart, single)  # called from each individual module
		4. _unbind(e, chart, single) # called from each individual module
		5. _updateScale(_width, _height) # called from each individual module
		6. _update(_width, _height, chart, single)  # this methods should be handled by each module, normally defined for special cases

		Here is the logic on those private methods above.
		When each instance attach an function of resize(context, context ...), E.G. d3.ma.onResize(line._resize, line); `1. _resize()` is called automatically, it will figure it out current width and height, dispatch 'd3maOnWindowResize' or 'd3maOffWindowResize' accordingly, passing the correct data object to the handlers.

		Each module ( like line, bar, circle etc ) will handle it to trigger `2. _onWindowResize()` this._onWindowResize() like Line, Axis or chart._onWindowResize(chart, this) inside this.layer enter lifeevent. _onWindowResize defined the global handler on 'd3maOnWindowResize' or 'd3maOffWindowResize', passing three arguments (e, chart, single).
		e is the object received from 'd3maOnWindowResize' or 'd3maOffWindowResize'.
		chart refer to this context, used it to access xScale, yScale, width, height, etc. chart property.
		single refer to each individual group just appended by insert command.

		`3. _redraw(e, chart, single)` will be triggered on 'd3maOnWindowResize'. First, it will trigger `5. _updateScale(_width, _height)`, based on the current xScale string value, yScale string value, update the xScale, yScale range array. ( defined in scale.js ) and update the module box width and height attribute.  Second, it will dispatch another global d3.ma event. 'd3maSingleWindowResize', passing (chart, single) as its arguments.  Third, defined a recommended method called `6. update()`. E.G. this.update( _width, _height, chart, single ).  so any module could hook into this method and attach its own custom updates based on current context and its useful values like width, height, chart info and single info

		`4. _unbind(e, chart, single)` will be triggered on 'd3maOffWindowResize'. It will auto trigger `5. _updateScale(_width, _height)` and `6. update( _width, _height, chart, single )` for modifying the scale range and domain

		`5. update, a public function, it will be called when _redraw or _unbind are being called. You could update the domain, range or whatever in your module. It need to be handled in the module level`

		'd3maSingleWindowResize': `3. _redraw(e, chart, single)` dispatch an event of `d3maSingleWindowResize`, each instance of the module should handle it separately based on its settings. (like in index.html).
			E.G.
				circles.dispatch.on('d3maSingleWindowResize', function(chart, single){
					var chart = chart || this;
					single.attr({
						'cx': area.line.x(),
						'cy': area.line.y()
					});
				});

	Events:  ( defined in the instance level )
		# Used for constructor.dispatch.on trigger events  E.G: Custom d3maMouseenter and mouseout events
		# syntax: constructor.dispatch.on('d3maMouseenter', function(e){ });

		# Currently support:
			d3maMouseenter   # each individual element mouse enter event
			d3maMouseout	# each individual element mouse out event
			d3maSingleWindowResize   # each individual element window resize event, normally, update scale domain, individual attrs
			d3maOnWindowResize		# window resize event, elements need to update its scales, and other attrs
			d3maOffWindowResize		# window resize event, elements do not update its scale, attrs, reset to original
 */
d3.chart('Scale').extend('Base', {

	initialize: function(options) {

		options = options || {};

		this.box(this.width, this.height);

		this.dispatch = d3.dispatch('d3maMouseenter', 'd3maMouseout', 'd3maOnWindowResize', 'd3maOffWindowResize', 'd3maSingleWindowResize');
	},

	w: function(_width) {
		if (arguments.length === 0) {
			return this.width;
		}
		this.width = _width;
		this.base.attr('width', this.width);
		return this;
	},

	h: function(_height) {
		if (arguments.length === 0) {
			return this.height;
		}
		this.height = _height;
		this.base.attr('height', this.height);
		return this;
	},

	box: function(_width, _height) {
		if(!arguments.length) {
			return {
				'width': this.width,
				'height': this.height
			};
		}

		this.w(_width);
		this.h((_height) ? _height : _width);

		return this;
	},

	// chart  # refer to this context, used it to access xScale, yScale, width, height, etc. chart property
	// this    # refer to each individual group just appended by insert command
	_bindMouseEnterOutEvents: function(chart, single) {
		var chart = chart || this;

		single.on('mouseenter', function(d, i){
			d3.select(this).classed('hover', true);
			var obj = {};
			if(chart.onDataMouseenter) {
				obj = chart.onDataMouseenter(d, i, chart);
			}
			chart.dispatch.d3maMouseenter(obj);
		});

		single.on('mouseout', function(d, i){
			d3.select(this).classed('hover', false);
			var obj = {};
			if(chart.onDataMouseout) {
				obj = chart.onDataMouseout(d, i, chart);
			}
			chart.dispatch.d3maMouseout(obj);
		});
	},

	_resize: function() {
		// NOTE: this here is the context where you definied in the 2nd param when initialized
		// ex: d3.ma.onResize(line._resize, line);
		// in this case, the context here is  line

		var containerInfo = this.info,
			widthOffset = d3.ma.$$(containerInfo.parentNode).offsetLeft + containerInfo.marginLeft + containerInfo.marginRight,
			heightOffset = d3.ma.$$(containerInfo.parentNode).offsetTop + containerInfo.marginTop + containerInfo.marginBottom,
			windowWidth = d3.ma.windowSize().width - widthOffset,
			windowHeight = d3.ma.windowSize().height - heightOffset;

		// var containerInfo = this.info,
		// 	windowWidth = d3.ma.windowSize().width,
		// 	windowHeight = d3.ma.windowSize().height;

		if( windowWidth < containerInfo.containerW || windowHeight < containerInfo.containerH ) {
			var onObj = {
				width: ( windowWidth < containerInfo.containerW ) ? windowWidth : containerInfo.containerW,
				height: ( windowHeight < containerInfo.containerH ) ? windowHeight : containerInfo.containerH
			};
			this.dispatch.d3maOnWindowResize(onObj);
		} else {
			var offObj = {
				width: containerInfo.canvasW,
				height: containerInfo.canvasH
			};
			var origObj = {
				width: containerInfo.containerW,
				height: containerInfo.containerH
			};
			// dispatch the _redraw back to the original container box
			this.dispatch.d3maOnWindowResize(origObj);
			// unbind the window resize event
			this.dispatch.d3maOffWindowResize(offObj);
		}
	},

	// it is the handler for the internal _resize() which definied above this one
	_onWindowResize: function(chart, single){
		var self = this;

		this.dispatch.on('d3maOnWindowResize', function(e){
			self._redraw(e, chart, single);
		});

		this.dispatch.on('d3maOffWindowResize', function(e){
			self._unbind(e, chart, single);
		});
	},

	// this will trigger the _update internal fn
	// look at the line.js _update fn for details
	_redraw: function(e, chart, single) {
		var containerInfo = this.info,
			_width = e.width - containerInfo.marginLeft - containerInfo.marginRight,
			_height = e.height - containerInfo.marginTop - containerInfo.marginBottom;

		//handle this in base.js below this fn. dealing with Scale updates
		this._updateScale(_width, _height);

		//dealing with the single element, trigger 'd3maSingleWindowResize'
		//handle event in the each instance for details updates.
		//usage on rects, circles, like multiple repeated elements.
		this.dispatch.d3maSingleWindowResize(chart, single);

		// handle this in individual modules
		// Optional step, if defined in each module, could
		// setup the global default in this module, or setup global attrs
		if (this.update)
			this.update( _width, _height, chart, single );
	},

	// this will trigger the _update internal fn
	// look at the line.js _update fn for details
	_unbind: function(e, chart, single) {
		// find out the current width & height of line g container. convert it to number
		var containerInfo = this.info,
			currentWidth = +(this.base.attr('width')),
			currentHeight = +(this.base.attr('height')),
			_canvasW = containerInfo.canvasW,
			_canvasH = containerInfo.canvasH;

		if( currentWidth !== _canvasW || currentHeight !== _canvasH)  {
			// same usage like _redraw fn for  _updateScale  &  _update
			this._updateScale(_canvasW, _canvasH);

			if (this.update)
				this.update(_canvasW, _canvasH, chart, single);
		}
	},

	// Update Scale, Box Size
	_updateScale: function(_width, _height) {
		// trigger the Scale in scale.js
		this._switchXScale(this._x, _width);
		this._switchYScale(this._y, _height);

		this.box(_width, _height);
	}

});
<commit_msg>update the _bindMouseEnterOutEvents to pass the current hover dom element<commit_after>/*
	Base is extended from Scale, it is used for the basic/ folder section. All mixined or extended modules will have all its behavior. Where you define your absolutely needed methods for the APIs. Internal use only, never use it for displaying a chart.

	Initalization:
		initialize: function(containerInfo) {
			var chart =  this.mixin('Base',  axisG, {
				info: containerInfo,
				x: 'ordinal',
				y: 'log',
				width: this.base.attr('width'),  // optional
				height: this.base.attr('height')   // optional
			});
		}

		// Passing options object as a third argument. Options is required.

	Arguments:
		Attributes
			since it inherit from scale.js, it will have all its private & public attr. Read core/scale.js Arguments section for details

	APIs:  ( defined in the constructor level )
	# THOSE APIs EXIST IN ALL EXTENDED MODULES
		constructor.box(_width, _height)
			# setter/getter container width value and height values, when only one value, height is the same as width

		constructor.w(_width)
			# setter/getter container width value  // always recommend to use constructor.box() instead

		constructor.h(_height)
			# setter/getter container height value  // always recommend to use constructor.box() instead

	PRIVATE APIs:
		_bindMouseEnterOutEvents(chart, single)
			# when it is entering, binding datum with each element, single element will bind 'mouseenter' event with our custom 'd3maMouseenter', bind 'mouseout' with our custom event 'd3maMouseout'.
			For example, quick internal binding to reduce duplicated code in modules like circle.js, bars.js etc

		1. _resize()  # called from d3.ma.onResize() or d3.ma.resize()
		2. _onWindowResize(chart, single)  # called from each individual module. It has to defined in each module basis. Since it has to pass the chart, single info in this.layer lifeevent enter event. No way to know its context in base.js level.
		3. _redraw(e, chart, single)  # called from each individual module
		4. _unbind(e, chart, single) # called from each individual module
		5. _updateScale(_width, _height) # called from each individual module
		6. _update(_width, _height, chart, single)  # this methods should be handled by each module, normally defined for special cases

		Here is the logic on those private methods above.
		When each instance attach an function of resize(context, context ...), E.G. d3.ma.onResize(line._resize, line); `1. _resize()` is called automatically, it will figure it out current width and height, dispatch 'd3maOnWindowResize' or 'd3maOffWindowResize' accordingly, passing the correct data object to the handlers.

		Each module ( like line, bar, circle etc ) will handle it to trigger `2. _onWindowResize()` this._onWindowResize() like Line, Axis or chart._onWindowResize(chart, this) inside this.layer enter lifeevent. _onWindowResize defined the global handler on 'd3maOnWindowResize' or 'd3maOffWindowResize', passing three arguments (e, chart, single).
		e is the object received from 'd3maOnWindowResize' or 'd3maOffWindowResize'.
		chart refer to this context, used it to access xScale, yScale, width, height, etc. chart property.
		single refer to each individual group just appended by insert command.

		`3. _redraw(e, chart, single)` will be triggered on 'd3maOnWindowResize'. First, it will trigger `5. _updateScale(_width, _height)`, based on the current xScale string value, yScale string value, update the xScale, yScale range array. ( defined in scale.js ) and update the module box width and height attribute.  Second, it will dispatch another global d3.ma event. 'd3maSingleWindowResize', passing (chart, single) as its arguments.  Third, defined a recommended method called `6. update()`. E.G. this.update( _width, _height, chart, single ).  so any module could hook into this method and attach its own custom updates based on current context and its useful values like width, height, chart info and single info

		`4. _unbind(e, chart, single)` will be triggered on 'd3maOffWindowResize'. It will auto trigger `5. _updateScale(_width, _height)` and `6. update( _width, _height, chart, single )` for modifying the scale range and domain

		`5. update, a public function, it will be called when _redraw or _unbind are being called. You could update the domain, range or whatever in your module. It need to be handled in the module level`

		'd3maSingleWindowResize': `3. _redraw(e, chart, single)` dispatch an event of `d3maSingleWindowResize`, each instance of the module should handle it separately based on its settings. (like in index.html).
			E.G.
				circles.dispatch.on('d3maSingleWindowResize', function(chart, single){
					var chart = chart || this;
					single.attr({
						'cx': area.line.x(),
						'cy': area.line.y()
					});
				});

	Events:  ( defined in the instance level )
		# Used for constructor.dispatch.on trigger events  E.G: Custom d3maMouseenter and mouseout events
		# syntax: constructor.dispatch.on('d3maMouseenter', function(e){ });

		# Currently support:
			d3maMouseenter   # each individual element mouse enter event
			d3maMouseout	# each individual element mouse out event
			d3maSingleWindowResize   # each individual element window resize event, normally, update scale domain, individual attrs
			d3maOnWindowResize		# window resize event, elements need to update its scales, and other attrs
			d3maOffWindowResize		# window resize event, elements do not update its scale, attrs, reset to original
 */
d3.chart('Scale').extend('Base', {

	initialize: function(options) {

		options = options || {};

		this.box(this.width, this.height);

		this.dispatch = d3.dispatch('d3maMouseenter', 'd3maMouseout', 'd3maOnWindowResize', 'd3maOffWindowResize', 'd3maSingleWindowResize');
	},

	w: function(_width) {
		if (arguments.length === 0) {
			return this.width;
		}
		this.width = _width;
		this.base.attr('width', this.width);
		return this;
	},

	h: function(_height) {
		if (arguments.length === 0) {
			return this.height;
		}
		this.height = _height;
		this.base.attr('height', this.height);
		return this;
	},

	box: function(_width, _height) {
		if(!arguments.length) {
			return {
				'width': this.width,
				'height': this.height
			};
		}

		this.w(_width);
		this.h((_height) ? _height : _width);

		return this;
	},

	// chart  # refer to this context, used it to access xScale, yScale, width, height, etc. chart property
	// this    # refer to each individual group just appended by insert command
	// single[0][i]  # refer to the current hover DOM element
	_bindMouseEnterOutEvents: function(chart, single) {
		var chart = chart || this;

		single.on('mouseenter', function(d, i){
			d3.select(this).classed('hover', true);
			var obj = {};
			if(chart.onDataMouseenter) {
				obj = chart.onDataMouseenter(d, i, chart, single[0][i]);
			}
			chart.dispatch.d3maMouseenter(obj);
		});

		single.on('mouseout', function(d, i){
			d3.select(this).classed('hover', false);
			var obj = {};
			if(chart.onDataMouseout) {
				obj = chart.onDataMouseout(d, i, chart, single[0][i]);
			}
			chart.dispatch.d3maMouseout(obj);
		});
	},

	_resize: function() {
		// NOTE: this here is the context where you definied in the 2nd param when initialized
		// ex: d3.ma.onResize(line._resize, line);
		// in this case, the context here is  line

		var containerInfo = this.info,
			widthOffset = d3.ma.$$(containerInfo.parentNode).offsetLeft + containerInfo.marginLeft + containerInfo.marginRight,
			heightOffset = d3.ma.$$(containerInfo.parentNode).offsetTop + containerInfo.marginTop + containerInfo.marginBottom,
			windowWidth = d3.ma.windowSize().width - widthOffset,
			windowHeight = d3.ma.windowSize().height - heightOffset;

		// var containerInfo = this.info,
		// 	windowWidth = d3.ma.windowSize().width,
		// 	windowHeight = d3.ma.windowSize().height;

		if( windowWidth < containerInfo.containerW || windowHeight < containerInfo.containerH ) {
			var onObj = {
				width: ( windowWidth < containerInfo.containerW ) ? windowWidth : containerInfo.containerW,
				height: ( windowHeight < containerInfo.containerH ) ? windowHeight : containerInfo.containerH
			};
			this.dispatch.d3maOnWindowResize(onObj);
		} else {
			var offObj = {
				width: containerInfo.canvasW,
				height: containerInfo.canvasH
			};
			var origObj = {
				width: containerInfo.containerW,
				height: containerInfo.containerH
			};
			// dispatch the _redraw back to the original container box
			this.dispatch.d3maOnWindowResize(origObj);
			// unbind the window resize event
			this.dispatch.d3maOffWindowResize(offObj);
		}
	},

	// it is the handler for the internal _resize() which definied above this one
	_onWindowResize: function(chart, single){
		var self = this;

		this.dispatch.on('d3maOnWindowResize', function(e){
			self._redraw(e, chart, single);
		});

		this.dispatch.on('d3maOffWindowResize', function(e){
			self._unbind(e, chart, single);
		});
	},

	// this will trigger the _update internal fn
	// look at the line.js _update fn for details
	_redraw: function(e, chart, single) {
		var containerInfo = this.info,
			_width = e.width - containerInfo.marginLeft - containerInfo.marginRight,
			_height = e.height - containerInfo.marginTop - containerInfo.marginBottom;

		//handle this in base.js below this fn. dealing with Scale updates
		this._updateScale(_width, _height);

		//dealing with the single element, trigger 'd3maSingleWindowResize'
		//handle event in the each instance for details updates.
		//usage on rects, circles, like multiple repeated elements.
		this.dispatch.d3maSingleWindowResize(chart, single);

		// handle this in individual modules
		// Optional step, if defined in each module, could
		// setup the global default in this module, or setup global attrs
		if (this.update)
			this.update( _width, _height, chart, single );
	},

	// this will trigger the _update internal fn
	// look at the line.js _update fn for details
	_unbind: function(e, chart, single) {
		// find out the current width & height of line g container. convert it to number
		var containerInfo = this.info,
			currentWidth = +(this.base.attr('width')),
			currentHeight = +(this.base.attr('height')),
			_canvasW = containerInfo.canvasW,
			_canvasH = containerInfo.canvasH;

		if( currentWidth !== _canvasW || currentHeight !== _canvasH)  {
			// same usage like _redraw fn for  _updateScale  &  _update
			this._updateScale(_canvasW, _canvasH);

			if (this.update)
				this.update(_canvasW, _canvasH, chart, single);
		}
	},

	// Update Scale, Box Size
	_updateScale: function(_width, _height) {
		// trigger the Scale in scale.js
		this._switchXScale(this._x, _width);
		this._switchYScale(this._y, _height);

		this.box(_width, _height);
	}

});
<|endoftext|>


<commit_before>/*
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

(function() {

  var isServer = typeof process === 'object';
  var isWorker = typeof importScripts !== 'undefined';

  function createLoadBrowser() {
    var path = document.currentScript && document.currentScript.src;

    // document.currentScript isn't supported on all browsers, so the following
    // hack gets the job done on those browsers.
    if ( ! path ) {
      var scripts = document.getElementsByTagName('script');
      for ( var i = 0 ; i < scripts.length ; i++ ) {
        if ( scripts[i].src.match(/\/foam.js$/) ) {
          path = scripts[i].src;
          break;
        }
      }
    }

    path = path.substring(0, path.lastIndexOf('/')+1);

    return function(filename) {
      document.writeln(
        '<script type="text/javascript" src="' + path + filename + '.js"></script>\n');
    }
  }

  function loadServer(filename) {
    require('./' + filename + '.js');
  }

  function createLoadWorker(filename) {
    var path = FOAM_BOOT_PATH;
    return function(filename) {
      importScripts(path + filename + '.js');
    };
  }

  [
    "stdlib",
    "array",
    "events",
    "fn",
    "string",
    "compare",
    "date",
    "Context",
    "Boot",
    "Slot",
    "debug",
    "Window",
    "JSON",
    "objects",
    "patterns",
    "types",
    "parse",
    "templates",
    "Action",
    "../lib/Timer",
    [ "../lib/graphics", ! isServer ],
    "../lib/dao",
    "../lib/mlang",
    ["../lib/Physical", ! isServer ],
    ["../lib/Collider", ! isServer ],
    ["../lib/PhysicsEngine", ! isServer ],
    ["../lib/PhysicalCircle", ! isServer ],
    [ "../lib/node/json_dao", isServer ]
  ].
      filter(function (f) { return ! Array.isArray(f) || f[1]; }).
      map(function(f) { return Array.isArray(f) ? f[0] : f; }).
      forEach(isServer ? loadServer :
              isWorker ? createLoadWorker() :
              createLoadBrowser());
})();
<commit_msg>Enable physics engine in nodejs, only PhysicalCircle needs to be excluded.<commit_after>/*
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

(function() {

  var isServer = typeof process === 'object';
  var isWorker = typeof importScripts !== 'undefined';

  function createLoadBrowser() {
    var path = document.currentScript && document.currentScript.src;

    // document.currentScript isn't supported on all browsers, so the following
    // hack gets the job done on those browsers.
    if ( ! path ) {
      var scripts = document.getElementsByTagName('script');
      for ( var i = 0 ; i < scripts.length ; i++ ) {
        if ( scripts[i].src.match(/\/foam.js$/) ) {
          path = scripts[i].src;
          break;
        }
      }
    }

    path = path.substring(0, path.lastIndexOf('/')+1);

    return function(filename) {
      document.writeln(
        '<script type="text/javascript" src="' + path + filename + '.js"></script>\n');
    }
  }

  function loadServer(filename) {
    require('./' + filename + '.js');
  }

  function createLoadWorker(filename) {
    var path = FOAM_BOOT_PATH;
    return function(filename) {
      importScripts(path + filename + '.js');
    };
  }

  [
    "stdlib",
    "array",
    "events",
    "fn",
    "string",
    "compare",
    "date",
    "Context",
    "Boot",
    "Slot",
    "debug",
    "Window",
    "JSON",
    "objects",
    "patterns",
    "types",
    "parse",
    "templates",
    "Action",
    "../lib/Timer",
    [ "../lib/graphics", ! isServer ],
    "../lib/dao",
    "../lib/mlang",
    "../lib/Physical",
    "../lib/Collider",
    "../lib/PhysicsEngine",
    ["../lib/PhysicalCircle", ! isServer ],
    [ "../lib/node/json_dao", isServer ]
  ].
      filter(function (f) { return ! Array.isArray(f) || f[1]; }).
      map(function(f) { return Array.isArray(f) ? f[0] : f; }).
      forEach(isServer ? loadServer :
              isWorker ? createLoadWorker() :
              createLoadBrowser());
})();
<|endoftext|>


<commit_before>webfont.WebFont = function(domHelper, fontModuleLoader, htmlElement, asyncCall,
    userAgent) {
  this.domHelper_ = domHelper;
  this.fontModuleLoader_ = fontModuleLoader;
  this.htmlElement_ = htmlElement;
  this.asyncCall_ = asyncCall;
  this.userAgent_ = userAgent;
  this.moduleLoading_ = 0;
  this.moduleFailedLoading_ = 0;
};

webfont.WebFont.prototype.addModule = function(name, factory) {
  this.fontModuleLoader_.addModuleFactory(name, factory);
};

webfont.WebFont.prototype.load = function(configuration) {
  var eventDispatcher = new webfont.EventDispatcher(
      this.domHelper_, this.htmlElement_, configuration);

  if (this.userAgent_.isSupportingWebFont()) {
    this.load_(eventDispatcher, configuration);
  } else {
    eventDispatcher.dispatchInactive();
  }
};

webfont.WebFont.prototype.isModuleSupportingUserAgent_ = function(module, eventDispatcher,
    fontWatcher, support) {
  if (!support) {
    var allModulesLoaded = --this.moduleLoading_ == 0;

    this.moduleFailedLoading_--;
    if (allModulesLoaded) {
      if (this.moduleFailedLoading_ == 0) {
        eventDispatcher.dispatchInactive();
      } else {
        eventDispatcher.dispatchLoading();
      }
    }
    fontWatcher.watch([], allModulesLoaded);
    return;
  }
  module.load(webfont.bind(this, this.onModuleReady_, eventDispatcher,
      fontWatcher));
};

webfont.WebFont.prototype.onModuleReady_ = function(eventDispatcher, fontWatcher,
    fontFamilies, opt_fontDescriptions) {
  var allModulesLoaded = --this.moduleLoading_ == 0;

  if (allModulesLoaded) {
    eventDispatcher.dispatchLoading();
  }
  this.asyncCall_(webfont.bind(this, function(_fontWatcher, _fontFamilies,
      _allModulesLoaded, _fontDescriptions) {
    _fontWatcher.watch(_fontFamilies, _fontDescriptions, _allModulesLoaded);
  }, fontWatcher, fontFamilies, opt_fontDescriptions, allModulesLoaded));
};

webfont.WebFont.prototype.load_ = function(eventDispatcher, configuration) {
  var modules = this.fontModuleLoader_.getModules(configuration),
      self = this;

  this.moduleFailedLoading_ = this.moduleLoading_ = modules.length;

  var fontWatcher = new webfont.FontWatcher(this.domHelper_,
      eventDispatcher, {
        getWidth: function(elem) {
          return elem.offsetWidth;
        }}, self.asyncCall_, function() {
          return +new Date();
        });

  for (var i = 0, len = modules.length; i < len; i++) {
    var module = modules[i];

    module.supportUserAgent(this.userAgent_,
        webfont.bind(this, this.isModuleSupportingUserAgent_, module,
        eventDispatcher, fontWatcher));
  }
};

window['webfont']['WebFont'] = webfont.WebFont;
webfont.WebFont.prototype['load'] = webfont.WebFont.prototype.load;
webfont.WebFont.prototype['addModule'] = webfont.WebFont.prototype.addModule;
window['WebFont'] = function() {
  var domHelper = new webfont.DomHelper(document);
  var userAgentParser = new webfont.UserAgentParser(navigator.userAgent);
  var userAgent = userAgentParser.parse();

  return new webfont.WebFont(domHelper, new webfont.FontModuleLoader(),
      document.documentElement, function(func, timeout) {
        setTimeout(func, timeout);
      }, userAgent);
}();
<commit_msg>fix watcher in the inactive case, and make the fontDescriptions arg to onReady optional<commit_after>webfont.WebFont = function(domHelper, fontModuleLoader, htmlElement, asyncCall,
    userAgent) {
  this.domHelper_ = domHelper;
  this.fontModuleLoader_ = fontModuleLoader;
  this.htmlElement_ = htmlElement;
  this.asyncCall_ = asyncCall;
  this.userAgent_ = userAgent;
  this.moduleLoading_ = 0;
  this.moduleFailedLoading_ = 0;
};

webfont.WebFont.prototype.addModule = function(name, factory) {
  this.fontModuleLoader_.addModuleFactory(name, factory);
};

webfont.WebFont.prototype.load = function(configuration) {
  var eventDispatcher = new webfont.EventDispatcher(
      this.domHelper_, this.htmlElement_, configuration);

  if (this.userAgent_.isSupportingWebFont()) {
    this.load_(eventDispatcher, configuration);
  } else {
    eventDispatcher.dispatchInactive();
  }
};

webfont.WebFont.prototype.isModuleSupportingUserAgent_ = function(module, eventDispatcher,
    fontWatcher, support) {
  if (!support) {
    var allModulesLoaded = --this.moduleLoading_ == 0;

    this.moduleFailedLoading_--;
    if (allModulesLoaded) {
      if (this.moduleFailedLoading_ == 0) {
        eventDispatcher.dispatchInactive();
      } else {
        eventDispatcher.dispatchLoading();
      }
    }
    fontWatcher.watch([], {}, allModulesLoaded);
    return;
  }
  module.load(webfont.bind(this, this.onModuleReady_, eventDispatcher,
      fontWatcher));
};

webfont.WebFont.prototype.onModuleReady_ = function(eventDispatcher, fontWatcher,
    fontFamilies, opt_fontDescriptions) {
  var allModulesLoaded = --this.moduleLoading_ == 0;

  if (allModulesLoaded) {
    eventDispatcher.dispatchLoading();
  }
  this.asyncCall_(webfont.bind(this, function(_fontWatcher, _fontFamilies,
      _fontDescriptions, _allModulesLoaded) {
    _fontWatcher.watch(_fontFamilies, _fontDescriptions || {}, _allModulesLoaded);
  }, fontWatcher, fontFamilies, opt_fontDescriptions, allModulesLoaded));
};

webfont.WebFont.prototype.load_ = function(eventDispatcher, configuration) {
  var modules = this.fontModuleLoader_.getModules(configuration),
      self = this;

  this.moduleFailedLoading_ = this.moduleLoading_ = modules.length;

  var fontWatcher = new webfont.FontWatcher(this.domHelper_,
      eventDispatcher, {
        getWidth: function(elem) {
          return elem.offsetWidth;
        }}, self.asyncCall_, function() {
          return +new Date();
        });

  for (var i = 0, len = modules.length; i < len; i++) {
    var module = modules[i];

    module.supportUserAgent(this.userAgent_,
        webfont.bind(this, this.isModuleSupportingUserAgent_, module,
        eventDispatcher, fontWatcher));
  }
};

window['webfont']['WebFont'] = webfont.WebFont;
webfont.WebFont.prototype['load'] = webfont.WebFont.prototype.load;
webfont.WebFont.prototype['addModule'] = webfont.WebFont.prototype.addModule;
window['WebFont'] = function() {
  var domHelper = new webfont.DomHelper(document);
  var userAgentParser = new webfont.UserAgentParser(navigator.userAgent);
  var userAgent = userAgentParser.parse();

  return new webfont.WebFont(domHelper, new webfont.FontModuleLoader(),
      document.documentElement, function(func, timeout) {
        setTimeout(func, timeout);
      }, userAgent);
}();
<|endoftext|>


<commit_before>var Game = {
    map: null,
    maps: [],
    lastMapId: null,

    initialize: function () {
        Canvas.initialize();
        Keyboard.bind();
    },

    start: function () {
        Canvas.$canvas.hide();

        // Clear out the persistent map cache so the entire game world is reset.
        this.maps = [];
        this.lastMapId = null;

        // Generate the backstory for this game session randomly.
        // This will generate the characters, where they were, what they did, what they know, etc.
        Story.generateStory();

        // Show the intro text (nametag / time)
        IntroText.run(function (e) {
            // Load up the main hall / living room and spawn the guests in the living room.
            this.loadMap('main_room', function (map) {
                e.done();

                Story.spawnGuests(map);

                Music.loopSound('rain_loop.mp3');

                map.runScript(scrWalkIn);
            });
        }.bind(this));

    },

    resetting: false,

    reset: function (callback) {
        if (callback == null) {
            callback = function() { };
        }

        if (this.resetting) {
            return;
        }

        this.resetting = true;

        Dialogue.hide();
        $('#hud').hide();

        if (this.map != null) {
            this.map.pause();
        }

        var completeReset = function() {
            this.map = null;
            this.start();
            this.resetting = false;
        }.bind(this);

        Canvas.$canvas.fadeOut(3000, function() {
            Music.stopAll();
            window.setTimeout(completeReset, 1000);
        });
    },

    loadMap: function (id, loadCallback) {
        if (loadCallback == null) {
            loadCallback = function () { };
        }

        var mapReady = function () {
            loadCallback(this.map);

            Canvas.$canvas.fadeIn(this.lastMapId == null ? 2000 : 'fast');
            this.lastMapId = id;

            Camera.onMapLoaded();
        }.bind(this);

        var execLoad = function() {
            if (typeof this.maps[id] == 'undefined') {
                this.map = new Map();
                this.maps[id] = this.map;
                this.map.load(id, function (okay) {
                    if (!okay) {
                        alert('Something went wrong, could not load the next part of the game. Sorry... we let you down.');
                        return;
                    }

                    if (!this.map.paused) {
                        $('#hud').show();
                    }

                    mapReady();
                }.bind(this));
            } else {
                this.map = this.maps[id];
                this.map.redeploy();
                mapReady();
            }
        }.bind(this);

        if (!Canvas.$canvas.is(':visible')) {
            execLoad();
        } else {
            Canvas.$canvas.fadeOut('fast', execLoad);
        }
    },

    draw: function (ctx) {
        if (this.map != null) {
            this.map.draw(ctx);
        }
    },

    update: function () {
        if (this.map != null) {
            this.map.update();
        }

        Dialogue.update();
        Keyboard.update();
        Camera.update();
    }
};<commit_msg>UI: Fix issue where location name is not updated after revisiting rooms.<commit_after>var Game = {
    map: null,
    maps: [],
    lastMapId: null,

    initialize: function () {
        Canvas.initialize();
        Keyboard.bind();
    },

    start: function () {
        Canvas.$canvas.hide();

        // Clear out the persistent map cache so the entire game world is reset.
        this.maps = [];
        this.lastMapId = null;

        // Generate the backstory for this game session randomly.
        // This will generate the characters, where they were, what they did, what they know, etc.
        Story.generateStory();

        // Show the intro text (nametag / time)
        IntroText.run(function (e) {
            // Load up the main hall / living room and spawn the guests in the living room.
            this.loadMap('main_room', function (map) {
                e.done();

                Story.spawnGuests(map);

                Music.loopSound('rain_loop.mp3');

                map.runScript(scrWalkIn);
            });
        }.bind(this));

    },

    resetting: false,

    reset: function (callback) {
        if (callback == null) {
            callback = function() { };
        }

        if (this.resetting) {
            return;
        }

        this.resetting = true;

        Dialogue.hide();
        $('#hud').hide();

        if (this.map != null) {
            this.map.pause();
        }

        var completeReset = function() {
            this.map = null;
            this.start();
            this.resetting = false;
        }.bind(this);

        Canvas.$canvas.fadeOut(3000, function() {
            Music.stopAll();
            window.setTimeout(completeReset, 1000);
        });
    },

    loadMap: function (id, loadCallback) {
        if (loadCallback == null) {
            loadCallback = function () { };
        }

        var mapReady = function () {
            loadCallback(this.map);

            Canvas.$canvas.fadeIn(this.lastMapId == null ? 2000 : 'fast');
            this.lastMapId = id;

            Camera.onMapLoaded();

            $('#location').text(this.map.properties.name);
        }.bind(this);

        var execLoad = function() {
            if (typeof this.maps[id] == 'undefined') {
                this.map = new Map();
                this.maps[id] = this.map;
                this.map.load(id, function (okay) {
                    if (!okay) {
                        alert('Something went wrong, could not load the next part of the game. Sorry... we let you down.');
                        return;
                    }

                    if (!this.map.paused) {
                        $('#hud').show();
                    }

                    mapReady();
                }.bind(this));
            } else {
                this.map = this.maps[id];
                this.map.redeploy();
                mapReady();
            }
        }.bind(this);

        if (!Canvas.$canvas.is(':visible')) {
            execLoad();
        } else {
            Canvas.$canvas.fadeOut('fast', execLoad);
        }
    },

    draw: function (ctx) {
        if (this.map != null) {
            this.map.draw(ctx);
        }
    },

    update: function () {
        if (this.map != null) {
            this.map.update();
        }

        Dialogue.update();
        Keyboard.update();
        Camera.update();
    }
};<|endoftext|>