<commit_before>/* Magic Mirror
 * The Core App (Server)
 *
 * By Michael Teeuw https://michaelteeuw.nl
 * MIT Licensed.
 */
var fs = require("fs");
var path = require("path");
var Log = require(__dirname + "/logger.js");
var Server = require(__dirname + "/server.js");
var Utils = require(__dirname + "/utils.js");
var defaultModules = require(__dirname + "/../modules/default/defaultmodules.js");

// Alias modules mentioned in package.js under _moduleAliases.
require("module-alias/register");

// Get version number.
global.version = JSON.parse(fs.readFileSync("package.json", "utf8")).version;
Log.log("Starting MagicMirror: v" + global.version);

// global absolute root path
global.root_path = path.resolve(__dirname + "/../");

if (process.env.MM_CONFIG_FILE) {
	global.configuration_file = process.env.MM_CONFIG_FILE;
}

// FIXME: Hotfix Pull Request
// https://github.com/MichMich/MagicMirror/pull/673
if (process.env.MM_PORT) {
	global.mmPort = process.env.MM_PORT;
}

// The next part is here to prevent a major exception when there
// is no internet connection. This could probable be solved better.
process.on("uncaughtException", function (err) {
	Log.error("Whoops! There was an uncaught exception...");
	Log.error(err);
	Log.error("MagicMirror will not quit, but it might be a good idea to check why this happened. Maybe no internet connection?");
	Log.error("If you think this really is an issue, please open an issue on GitHub: https://github.com/MichMich/MagicMirror/issues");
});

/* App - The core app.
 */
var App = function () {
	var nodeHelpers = [];

	/* loadConfig(callback)
	 * Loads the config file. combines it with the defaults,
	 * and runs the callback with the found config as argument.
	 *
	 * argument callback function - The callback function.
	 */
	var loadConfig = function (callback) {
		Log.log("Loading config ...");
		var defaults = require(__dirname + "/defaults.js");

		// For this check proposed to TestSuite
		// https://forum.magicmirror.builders/topic/1456/test-suite-for-magicmirror/8
		var configFilename = path.resolve(global.root_path + "/config/config.js");
		if (typeof global.configuration_file !== "undefined") {
			configFilename = path.resolve(global.configuration_file);
		}

		try {
			fs.accessSync(configFilename, fs.F_OK);
			var c = require(configFilename);
			checkDeprecatedOptions(c);
			var config = Object.assign(defaults, c);
			callback(config);
		} catch (e) {
			if (e.code === "ENOENT") {
				Log.error(Utils.colors.error("WARNING! Could not find config file. Please create one. Starting with default configuration."));
			} else if (e instanceof ReferenceError || e instanceof SyntaxError) {
				Log.error(Utils.colors.error("WARNING! Could not validate config file. Starting with default configuration. Please correct syntax errors at or above this line: " + e.stack));
			} else {
				Log.error(Utils.colors.error("WARNING! Could not load config file. Starting with default configuration. Error found: " + e));
			}
			callback(defaults);
		}
	};

	var checkDeprecatedOptions = function (userConfig) {
		var deprecated = require(global.root_path + "/js/deprecated.js");
		var deprecatedOptions = deprecated.configs;

		var usedDeprecated = [];

		deprecatedOptions.forEach(function (option) {
			if (userConfig.hasOwnProperty(option)) {
				usedDeprecated.push(option);
			}
		});
		if (usedDeprecated.length > 0) {
			Log.warn(Utils.colors.warn("WARNING! Your config is using deprecated options: " + usedDeprecated.join(", ") + ". Check README and CHANGELOG for more up-to-date ways of getting the same functionality."));
		}
	};

	/* loadModule(module)
	 * Loads a specific module.
	 *
	 * argument module string - The name of the module (including subpath).
	 */
	var loadModule = function (module, callback) {
		var elements = module.split("/");
		var moduleName = elements[elements.length - 1];
		var moduleFolder = __dirname + "/../modules/" + module;

		if (defaultModules.indexOf(moduleName) !== -1) {
			moduleFolder = __dirname + "/../modules/default/" + module;
		}

		var helperPath = moduleFolder + "/node_helper.js";

		var loadModule = true;
		try {
			fs.accessSync(helperPath, fs.R_OK);
		} catch (e) {
			loadModule = false;
			Log.log("No helper found for module: " + moduleName + ".");
		}

		if (loadModule) {
			var Module = require(helperPath);
			var m = new Module();

			if (m.requiresVersion) {
				Log.log("Check MagicMirror version for node helper '" + moduleName + "' - Minimum version:  " + m.requiresVersion + " - Current version: " + global.version);
				if (cmpVersions(global.version, m.requiresVersion) >= 0) {
					Log.log("Version is ok!");
				} else {
					Log.log("Version is incorrect. Skip module: '" + moduleName + "'");
					return;
				}
			}

			m.setName(moduleName);
			m.setPath(path.resolve(moduleFolder));
			nodeHelpers.push(m);

			m.loaded(callback);
		} else {
			callback();
		}
	};

	/* loadModules(modules)
	 * Loads all modules.
	 *
	 * argument module string - The name of the module (including subpath).
	 */
	var loadModules = function (modules, callback) {
		Log.log("Loading module helpers ...");

		var loadNextModule = function () {
			if (modules.length > 0) {
				var nextModule = modules[0];
				loadModule(nextModule, function () {
					modules = modules.slice(1);
					loadNextModule();
				});
			} else {
				// All modules are loaded
				Log.log("All module helpers loaded.");
				callback();
			}
		};

		loadNextModule();
	};

	/**
	 * Compare two semantic version numbers and return the difference.
	 *
	 * @param {string} a Version number a.
	 * @param {string} b Version number b.
	 */
	function cmpVersions(a, b) {
		var i, diff;
		var regExStrip0 = /(\.0+)+$/;
		var segmentsA = a.replace(regExStrip0, "").split(".");
		var segmentsB = b.replace(regExStrip0, "").split(".");
		var l = Math.min(segmentsA.length, segmentsB.length);

		for (i = 0; i < l; i++) {
			diff = parseInt(segmentsA[i], 10) - parseInt(segmentsB[i], 10);
			if (diff) {
				return diff;
			}
		}
		return segmentsA.length - segmentsB.length;
	}

	/* start(callback)
	 * This methods starts the core app.
	 * It loads the config, then it loads all modules.
	 * When it's done it executes the callback with the config as argument.
	 *
	 * argument callback function - The callback function.
	 */
	this.start = function (callback) {
		loadConfig(function (c) {
			config = c;

			Log.setLogLevel(config.logLevel);

			var modules = [];

			for (var m in config.modules) {
				var module = config.modules[m];
				if (modules.indexOf(module.module) === -1 && !module.disabled) {
					modules.push(module.module);
				}
			}

			loadModules(modules, function () {
				var server = new Server(config, function (app, io) {
					Log.log("Server started ...");

					for (var h in nodeHelpers) {
						var nodeHelper = nodeHelpers[h];
						nodeHelper.setExpressApp(app);
						nodeHelper.setSocketIO(io);
						nodeHelper.start();
					}

					Log.log("Sockets connected & modules started ...");

					if (typeof callback === "function") {
						callback(config);
					}
				});
			});
		});
	};

	/* stop()
	 * This methods stops the core app.
	 * This calls each node_helper's STOP() function, if it exists.
	 * Added to fix #1056
	 */
	this.stop = function () {
		for (var h in nodeHelpers) {
			var nodeHelper = nodeHelpers[h];
			if (typeof nodeHelper.stop === "function") {
				nodeHelper.stop();
			}
		}
	};

	/* Listen for SIGINT signal and call stop() function.
	 *
	 * Added to fix #1056
	 * Note: this is only used if running `server-only`. Otherwise
	 * this.stop() is called by app.on("before-quit"... in `electron.js`
	 */
	process.on("SIGINT", () => {
		Log.log("[SIGINT] Received. Shutting down server...");
		setTimeout(() => {
			process.exit(0);
		}, 3000); // Force quit after 3 seconds
		this.stop();
		process.exit(0);
	});

	/* We also need to listen to SIGTERM signals so we stop everything when we are asked to stop by the OS.
	 */
	process.on("SIGTERM", () => {
		Log.log("[SIGTERM] Received. Shutting down server...");
		setTimeout(() => {
			process.exit(0);
		}, 3000); // Force quit after 3 seconds
		this.stop();
		process.exit(0);
	});
};

module.exports = new App();
<commit_msg>Cleanup app jsdoc<commit_after>/* Magic Mirror
 * The Core App (Server)
 *
 * By Michael Teeuw https://michaelteeuw.nl
 * MIT Licensed.
 */
var fs = require("fs");
var path = require("path");
var Log = require(__dirname + "/logger.js");
var Server = require(__dirname + "/server.js");
var Utils = require(__dirname + "/utils.js");
var defaultModules = require(__dirname + "/../modules/default/defaultmodules.js");

// Alias modules mentioned in package.js under _moduleAliases.
require("module-alias/register");

// Get version number.
global.version = JSON.parse(fs.readFileSync("package.json", "utf8")).version;
Log.log("Starting MagicMirror: v" + global.version);

// global absolute root path
global.root_path = path.resolve(__dirname + "/../");

if (process.env.MM_CONFIG_FILE) {
	global.configuration_file = process.env.MM_CONFIG_FILE;
}

// FIXME: Hotfix Pull Request
// https://github.com/MichMich/MagicMirror/pull/673
if (process.env.MM_PORT) {
	global.mmPort = process.env.MM_PORT;
}

// The next part is here to prevent a major exception when there
// is no internet connection. This could probable be solved better.
process.on("uncaughtException", function (err) {
	Log.error("Whoops! There was an uncaught exception...");
	Log.error(err);
	Log.error("MagicMirror will not quit, but it might be a good idea to check why this happened. Maybe no internet connection?");
	Log.error("If you think this really is an issue, please open an issue on GitHub: https://github.com/MichMich/MagicMirror/issues");
});

/**
 * The core app.
 *
 * @class
 */
var App = function () {
	var nodeHelpers = [];

	/**
	 * Loads the config file. Combines it with the defaults,  and runs the
	 * callback with the found config as argument.
	 *
	 * @param {Function} callback Function to be called after loading the config
	 */
	var loadConfig = function (callback) {
		Log.log("Loading config ...");
		var defaults = require(__dirname + "/defaults.js");

		// For this check proposed to TestSuite
		// https://forum.magicmirror.builders/topic/1456/test-suite-for-magicmirror/8
		var configFilename = path.resolve(global.root_path + "/config/config.js");
		if (typeof global.configuration_file !== "undefined") {
			configFilename = path.resolve(global.configuration_file);
		}

		try {
			fs.accessSync(configFilename, fs.F_OK);
			var c = require(configFilename);
			checkDeprecatedOptions(c);
			var config = Object.assign(defaults, c);
			callback(config);
		} catch (e) {
			if (e.code === "ENOENT") {
				Log.error(Utils.colors.error("WARNING! Could not find config file. Please create one. Starting with default configuration."));
			} else if (e instanceof ReferenceError || e instanceof SyntaxError) {
				Log.error(Utils.colors.error("WARNING! Could not validate config file. Starting with default configuration. Please correct syntax errors at or above this line: " + e.stack));
			} else {
				Log.error(Utils.colors.error("WARNING! Could not load config file. Starting with default configuration. Error found: " + e));
			}
			callback(defaults);
		}
	};

	/**
	 * Checks the config for deprecated options and throws a warning in the logs
	 * if it encounters one option from the deprecated.js list
	 *
	 * @param {object} userConfig The user config
	 */
	var checkDeprecatedOptions = function (userConfig) {
		var deprecated = require(global.root_path + "/js/deprecated.js");
		var deprecatedOptions = deprecated.configs;

		var usedDeprecated = [];

		deprecatedOptions.forEach(function (option) {
			if (userConfig.hasOwnProperty(option)) {
				usedDeprecated.push(option);
			}
		});
		if (usedDeprecated.length > 0) {
			Log.warn(Utils.colors.warn("WARNING! Your config is using deprecated options: " + usedDeprecated.join(", ") + ". Check README and CHANGELOG for more up-to-date ways of getting the same functionality."));
		}
	};

	/**
	 * Loads a specific module.
	 *
	 * @param {string} module The name of the module (including subpath).
	 * @param {Function} callback Function to be called after loading
	 */
	var loadModule = function (module, callback) {
		var elements = module.split("/");
		var moduleName = elements[elements.length - 1];
		var moduleFolder = __dirname + "/../modules/" + module;

		if (defaultModules.indexOf(moduleName) !== -1) {
			moduleFolder = __dirname + "/../modules/default/" + module;
		}

		var helperPath = moduleFolder + "/node_helper.js";

		var loadModule = true;
		try {
			fs.accessSync(helperPath, fs.R_OK);
		} catch (e) {
			loadModule = false;
			Log.log("No helper found for module: " + moduleName + ".");
		}

		if (loadModule) {
			var Module = require(helperPath);
			var m = new Module();

			if (m.requiresVersion) {
				Log.log("Check MagicMirror version for node helper '" + moduleName + "' - Minimum version:  " + m.requiresVersion + " - Current version: " + global.version);
				if (cmpVersions(global.version, m.requiresVersion) >= 0) {
					Log.log("Version is ok!");
				} else {
					Log.log("Version is incorrect. Skip module: '" + moduleName + "'");
					return;
				}
			}

			m.setName(moduleName);
			m.setPath(path.resolve(moduleFolder));
			nodeHelpers.push(m);

			m.loaded(callback);
		} else {
			callback();
		}
	};

	/**
	 * Loads all modules.
	 *
	 * @param {Array} modules All modules to be loaded
	 * @param {Function} callback Function to be called after loading
	 */
	var loadModules = function (modules, callback) {
		Log.log("Loading module helpers ...");

		var loadNextModule = function () {
			if (modules.length > 0) {
				var nextModule = modules[0];
				loadModule(nextModule, function () {
					modules = modules.slice(1);
					loadNextModule();
				});
			} else {
				// All modules are loaded
				Log.log("All module helpers loaded.");
				callback();
			}
		};

		loadNextModule();
	};

	/**
	 * Compare two semantic version numbers and return the difference.
	 *
	 * @param {string} a Version number a.
	 * @param {string} b Version number b.
	 *
	 * @returns {number} A positive number if a is larger than b, a negative
	 * number if a is smaller and 0 if they are the same
	 */
	function cmpVersions(a, b) {
		var i, diff;
		var regExStrip0 = /(\.0+)+$/;
		var segmentsA = a.replace(regExStrip0, "").split(".");
		var segmentsB = b.replace(regExStrip0, "").split(".");
		var l = Math.min(segmentsA.length, segmentsB.length);

		for (i = 0; i < l; i++) {
			diff = parseInt(segmentsA[i], 10) - parseInt(segmentsB[i], 10);
			if (diff) {
				return diff;
			}
		}
		return segmentsA.length - segmentsB.length;
	}

	/**
	 * Start the core app.
	 *
	 * It loads the config, then it loads all modules. When it's done it
	 * executes the callback with the config as argument.
	 *
	 * @param {Function} callback Function to be called after start
	 */
	this.start = function (callback) {
		loadConfig(function (c) {
			config = c;

			Log.setLogLevel(config.logLevel);

			var modules = [];

			for (var m in config.modules) {
				var module = config.modules[m];
				if (modules.indexOf(module.module) === -1 && !module.disabled) {
					modules.push(module.module);
				}
			}

			loadModules(modules, function () {
				var server = new Server(config, function (app, io) {
					Log.log("Server started ...");

					for (var h in nodeHelpers) {
						var nodeHelper = nodeHelpers[h];
						nodeHelper.setExpressApp(app);
						nodeHelper.setSocketIO(io);
						nodeHelper.start();
					}

					Log.log("Sockets connected & modules started ...");

					if (typeof callback === "function") {
						callback(config);
					}
				});
			});
		});
	};

	/**
	 * Stops the core app. This calls each node_helper's STOP() function, if it
	 * exists.
	 *
	 * Added to fix #1056
	 */
	this.stop = function () {
		for (var h in nodeHelpers) {
			var nodeHelper = nodeHelpers[h];
			if (typeof nodeHelper.stop === "function") {
				nodeHelper.stop();
			}
		}
	};

	/**
	 * Listen for SIGINT signal and call stop() function.
	 *
	 * Added to fix #1056
	 * Note: this is only used if running `server-only`. Otherwise
	 * this.stop() is called by app.on("before-quit"... in `electron.js`
	 */
	process.on("SIGINT", () => {
		Log.log("[SIGINT] Received. Shutting down server...");
		setTimeout(() => {
			process.exit(0);
		}, 3000); // Force quit after 3 seconds
		this.stop();
		process.exit(0);
	});

	/**
	 * Listen to SIGTERM signals so we can stop everything when we
	 * are asked to stop by the OS.
	 */
	process.on("SIGTERM", () => {
		Log.log("[SIGTERM] Received. Shutting down server...");
		setTimeout(() => {
			process.exit(0);
		}, 3000); // Force quit after 3 seconds
		this.stop();
		process.exit(0);
	});
};

module.exports = new App();
<|endoftext|>


<commit_before>var stats, scene, renderer, composer;
var camera, cameraControls;

var cube = new THREE.Object3D();

var cameraDistance = 15;

var partsInCubeFace = 3;
var cubePartSize = 1.5;
var cubePartDepth = 0.5;
var colors = {
	'white' : {
		'hex' : 0xffffff,
		'count' : 9
	},
	'black' : {
		'hex' : 0x000000,
		'count' : 9
	},
	'red'   : {
		'hex' : 0xff0000,
		'count' : 9
	},
	'green' : {
		'hex' : 0x00ff00,
		'count' : 9
	},
	'blue'  : {
		'hex' : 0x0000ff,
		'count' : 9
	},
	'yellow': {
		'hex' : 0xffff00,
		'count' : 9
	}
};

var rotations = {
	'left'   : {
		'cw' : new THREE.Euler(Math.PI / 2, 0, 0, 'XYZ'),
		'ccw' : new THREE.Euler(-Math.PI / 2, 0, 0, 'XYZ')
	},
	'middle'   : {
		'cw' : new THREE.Euler(Math.PI / 2, 0, 0, 'XYZ'),
		'ccw' : new THREE.Euler(-Math.PI / 2, 0, 0, 'XYZ')
	},
	'right'   : {
		'cw' : new THREE.Euler(Math.PI / 2, 0, 0, 'XYZ'),
		'ccw' : new THREE.Euler(-Math.PI / 2, 0, 0, 'XYZ')
	},
	'top'   : {
		'cw' : new THREE.Euler(0, 0, Math.PI / 2, 'XYZ'),
		'ccw' : new THREE.Euler(0, 0, -Math.PI / 2, 'XYZ')
	},
	'center'   : {
		'cw' : new THREE.Euler(0, 0, Math.PI / 2, 'XYZ'),
		'ccw' : new THREE.Euler(0, 0, -Math.PI / 2, 'XYZ')
	},
	'bottom'   : {
		'cw' : new THREE.Euler(0, 0, Math.PI / 2, 'XYZ'),
		'ccw' : new THREE.Euler(0, 0, -Math.PI / 2, 'XYZ')
	}
};

var cubesIDs = [];

function pickRandomProperty(obj) {
    var result;
    var count = 0;
    for (var prop in obj)
        if (Math.random() < 1 / ++count)
           result = prop;
    return result;
};

if( !init() )	animate();

function addCubePart(size, color, rotation, position) {
	if (rotation === undefined) {
		rotation = new THREE.Euler(0, 0, 0, 'XYZ');
	}
	if (position === undefined) {
		position = new THREE.Vector3(0, 0, 0);
	}
	var geometry = new THREE.BoxGeometry(size, size, size);
	for ( var i = 0; i < geometry.faces.length; i += 2) {
	    geometry.faces[i].color.setHex(color.hex);
	    geometry.faces[i + 1].color.setHex(color.hex);
	}

	var material = new THREE.MeshBasicMaterial( { color: 0xffffff, vertexColors: THREE.FaceColors } );

	var cube = new THREE.Mesh( geometry, material );
	var box = new THREE.BoxHelper( cube );

	var obj = new THREE.Object3D();
	obj.add(cube);
	obj.add(box);

	obj.position.copy(position);
	obj.rotation.copy(rotation);

	return obj;
};

function getNewColor() {
	var color = colors[pickRandomProperty(colors)];
	while (color.count < 1) {
		color = colors[pickRandomProperty(colors)];
	}
	colors[pickRandomProperty(colors)].count--;
	return color;
};

function createCube() {
	var cubePart;
	// Create a face of the cube
	for (var i = 0; i < partsInCubeFace; i++) {
		cubesIDs.push([]);
		for (var j = 0; j < partsInCubeFace; j++) {
			cubesIDs[i].push([]);
			for (var k = 0; k < partsInCubeFace; k++) {
				cubePart = 	addCubePart(
					cubePartSize,
					getNewColor(),
					undefined,
					new THREE.Vector3(
						(j - 1) * cubePartSize,
						(i - 1) * cubePartSize,
						(k - 1) * cubePartSize
					)
				);
				cubesIDs[i][j].push(cubePart.id);
				cube.add(cubePart);
			}
		}
	}
}

function rotateCube(rotation, layer) {
	var groupedCubes = new THREE.Object3D();
	for (var i = 0; i < cubesIDs.length; i++) {
		for (var j = 0; j < cubesIDs[i].length; j++) {
			groupedCubes.add(
				cube.getObjectById(
					cubesIDs[i][j][layer]
				)
			);
		}
	}
	groupedCubes.rotation.copy(rotation);
	groupedCubes.updateMatrixWorld();
	var child;
	while (groupedCubes.children.length > 0) {
		child = groupedCubes.children[0];
		cube.add(
			groupedCubes.children[0]
		);
		child.position.copy((new THREE.Vector3()).setFromMatrixPosition(child.matrixWorld));
	}
}

function addCubeFace(position, rotation) {
	if (rotation === undefined) {
		rotation = new THREE.Euler(0, 0, 0, 'XYZ');
	}
	if (position === undefined) {
		position = new THREE.Vector3(0, 0, 0);
	}

	var face = new THREE.Object3D();
	// Create a face of the cube
	for (var i = 0; i < partsInCubeFace; i++) {
		for (var j = 0; j < partsInCubeFace; j++) {
			face.add(
				addCubePart(
					cubePartSize,
					pickRandomProperty(colors),
					undefined,
					new THREE.Vector3(-1.5 + j * cubePartSize, -1.5 + i * cubePartSize, 0)
				)
			);
		}
	}

	face.position.copy(position);
	face.rotation.copy(rotation);

	return face;
}

// init the scene
function init(){

	if( Detector.webgl ){
		renderer = new THREE.WebGLRenderer({
			antialias		: true,	// to get smoother output
			preserveDrawingBuffer	: true	// to allow screenshot
		});
		renderer.setClearColor( 0xbbbbbb );
	}else{
		renderer	= new THREE.CanvasRenderer();
	}
	renderer.setSize( window.innerWidth, window.innerHeight );
	document.getElementById('container').appendChild(renderer.domElement);

	// add Stats.js - https://github.com/mrdoob/stats.js
	stats = new Stats();
	stats.domElement.style.position	= 'absolute';
	stats.domElement.style.bottom	= '0px';
	document.body.appendChild( stats.domElement );

	// create a scene
	scene = new THREE.Scene();

	// put a camera in the scene
	camera	= new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 10000 );
	camera.position.set(0, 0, cameraDistance);
	scene.add(camera);

	// create a camera contol
	cameraControls	= new THREE.TrackballControls( camera )

	// transparently support window resize
	THREEx.WindowResize.bind(renderer, camera);
	// allow 'p' to make screenshot
	THREEx.Screenshot.bindKey(renderer);
	// allow 'f' to go fullscreen where this feature is supported
	if( THREEx.FullScreen.available() ){
		THREEx.FullScreen.bindKey();
		document.getElementById('inlineDoc').innerHTML	+= "- f for fullscreen";
	}

	// here you add your objects
	// - you will most likely replace this part by your own
	var light	= new THREE.AmbientLight( Math.random() * 0xffffff );
	scene.add( light );
	var light	= new THREE.DirectionalLight( Math.random() * 0xffffff );
	light.position.set( Math.random(), Math.random(), Math.random() ).normalize();
	scene.add( light );
	var light	= new THREE.DirectionalLight( Math.random() * 0xffffff );
	light.position.set( Math.random(), Math.random(), Math.random() ).normalize();
	scene.add( light );
	var light	= new THREE.PointLight( Math.random() * 0xffffff );
	light.position.set( Math.random()-0.5, Math.random()-0.5, Math.random()-0.5 )
				.normalize().multiplyScalar(1.2);
	scene.add( light );
	var light	= new THREE.PointLight( Math.random() * 0xffffff );
	light.position.set( Math.random()-0.5, Math.random()-0.5, Math.random()-0.5 )
				.normalize().multiplyScalar(1.2);
	scene.add( light );

	createCube();
	scene.add(
		cube
	);

}

function handleKeyUp(event) {
  if (event.keyCode === 81) {
    window.isQDown = true;
  }
}

window.addEventListener('keyup', handleKeyUp, false);

// animation loop
function animate() {

	// loop on request animation loop
	// - it has to be at the begining of the function
	// - see details at http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
	requestAnimationFrame( animate );

	if (window.isQDown) {
		window.isQDown = false;
		rotateCube(rotations.top.cw, 1);
	}

	// do the render
	render();

	// update stats
	stats.update();
}

// render the scene
function render() {
	// variable which is increase by Math.PI every seconds - usefull for animation
	var PIseconds	= Date.now() * Math.PI;

	// update camera controls
	cameraControls.update();

	// actually render the scene
	renderer.render( scene, camera );
}<commit_msg>Rotation for TTB is working<commit_after>var stats, scene, renderer, composer;
var camera, cameraControls;

var cube = new THREE.Object3D();

var cameraDistance = 15;

var partsInCubeFace = 3;
var cubePartSize = 1.5;
var cubePartDepth = 0.5;
var colors = {
	'white' : {
		'hex' : 0xffffff,
		'count' : 9
	},
	'black' : {
		'hex' : 0x000000,
		'count' : 9
	},
	'red'   : {
		'hex' : 0xff0000,
		'count' : 9
	},
	'green' : {
		'hex' : 0x00ff00,
		'count' : 9
	},
	'blue'  : {
		'hex' : 0x0000ff,
		'count' : 9
	},
	'yellow': {
		'hex' : 0xffff00,
		'count' : 9
	}
};

var cubesIDs = [];

var rotations = {
	'LTR'   : {
		'CW' : new THREE.Euler(Math.PI / 2, 0, 0, 'XYZ'),
		'CCW' : new THREE.Euler(-Math.PI / 2, 0, 0, 'XYZ')
	},
	'TTB'   : {
		'CW' : new THREE.Euler(0, 0, Math.PI / 2, 'XYZ'),
		'CCW' : new THREE.Euler(0, 0, -Math.PI / 2, 'XYZ')
	},
	'FTH' : {
		'CW' : new THREE.Euler(0, Math.PI / 2, 0, 'XYZ'),
		'CCW' : new THREE.Euler(0, -Math.PI / 2, 0, 'XYZ')
	}
};

var groupingFunctions = {
	'TTB' : function(layer) {
		var groupedCubes = new THREE.Object3D();
		for (var i = 0; i < cubesIDs.length; i++) {
			for (var j = 0; j < cubesIDs[i].length; j++) {
				groupedCubes.add(
					cube.getObjectById(
						cubesIDs[i][j][layer]
					)
				);
			}
		}
		return groupedCubes;
	},
	'LTR' : function(layer) {
		var groupedCubes = new THREE.Object3D();
		for (var i = 0; i < cubesIDs[layer].length; i++) {
			for (var j = 0; j < cubesIDs[layer][i].length; j++) {
				groupedCubes.add(
					cube.getObjectById(
						cubesIDs[layer][i][j]
					)
				);
			}
		}

		return groupedCubes;
	},
	'FTH' : function(layer) {
		var groupedCubes = new THREE.Object3D();
		for (var i = 0; i < cubesIDs.length; i++) {
			for (var j = 0; j < cubesIDs[i][layer].length; j++) {
				groupedCubes.add(
					cube.getObjectById(
						cubesIDs[i][layer][j]
					)
				);
			}
		}

		return groupedCubes;
	}
}

function pickRandomProperty(obj) {
    var result;
    var count = 0;
    for (var prop in obj)
        if (Math.random() < 1 / ++count)
           result = prop;
    return result;
};

if( !init() )	animate();

function addCubePart(size, color, rotation, position) {
	if (rotation === undefined) {
		rotation = new THREE.Euler(0, 0, 0, 'XYZ');
	}
	if (position === undefined) {
		position = new THREE.Vector3(0, 0, 0);
	}
	var geometry = new THREE.BoxGeometry(size, size, size);
	for ( var i = 0; i < geometry.faces.length; i += 2) {
	    geometry.faces[i].color.setHex(color.hex);
	    geometry.faces[i + 1].color.setHex(color.hex);
	}

	var material = new THREE.MeshBasicMaterial( { color: 0xffffff, vertexColors: THREE.FaceColors } );

	var cube = new THREE.Mesh( geometry, material );
	var box = new THREE.BoxHelper( cube );

	var obj = new THREE.Object3D();
	obj.add(cube);
	obj.add(box);

	obj.position.copy(position);
	obj.rotation.copy(rotation);

	return obj;
};

function getNewColor() {
	var color = colors[pickRandomProperty(colors)];
	while (color.count < 1) {
		color = colors[pickRandomProperty(colors)];
	}
	colors[pickRandomProperty(colors)].count--;
	return color;
};

function createCube() {
	var cubePart;
	// Create a face of the cube
	for (var i = 0; i < partsInCubeFace; i++) {
		cubesIDs.push([]);
		for (var j = 0; j < partsInCubeFace; j++) {
			cubesIDs[i].push([]);
			for (var k = 0; k < partsInCubeFace; k++) {
				cubePart = 	addCubePart(
					cubePartSize,
					getNewColor(),
					undefined,
					new THREE.Vector3(
						(i - 1) * cubePartSize,
						(j - 1) * cubePartSize,
						(k - 1) * cubePartSize
					)
				);
				cubesIDs[i][j].push(cubePart.id);
				cube.add(cubePart);
			}
		}
	}

	cube.rotation.copy(new THREE.Euler(Math.PI / 2, 0, 0, 'XYZ'));
}

function rotateCube(rotation, direction, layer) {
	var groupedCubes = groupingFunctions[rotation](layer);

	groupedCubes.rotation.copy(rotations[rotation][direction]);
	groupedCubes.updateMatrixWorld();
	var child;
	while (groupedCubes.children.length > 0) {
		child = groupedCubes.children[0];
		cube.add(
			groupedCubes.children[0]
		);
		child.position.copy((new THREE.Vector3()).setFromMatrixPosition(child.matrixWorld));
	}
}

function addCubeFace(position, rotation) {
	if (rotation === undefined) {
		rotation = new THREE.Euler(0, 0, 0, 'XYZ');
	}
	if (position === undefined) {
		position = new THREE.Vector3(0, 0, 0);
	}

	var face = new THREE.Object3D();
	// Create a face of the cube
	for (var i = 0; i < partsInCubeFace; i++) {
		for (var j = 0; j < partsInCubeFace; j++) {
			face.add(
				addCubePart(
					cubePartSize,
					pickRandomProperty(colors),
					undefined,
					new THREE.Vector3(-1.5 + j * cubePartSize, -1.5 + i * cubePartSize, 0)
				)
			);
		}
	}

	face.position.copy(position);
	face.rotation.copy(rotation);

	return face;
}

// init the scene
function init(){

	if( Detector.webgl ){
		renderer = new THREE.WebGLRenderer({
			antialias		: true,	// to get smoother output
			preserveDrawingBuffer	: true	// to allow screenshot
		});
		renderer.setClearColor( 0xbbbbbb );
	}else{
		renderer	= new THREE.CanvasRenderer();
	}
	renderer.setSize( window.innerWidth, window.innerHeight );
	document.getElementById('container').appendChild(renderer.domElement);

	// add Stats.js - https://github.com/mrdoob/stats.js
	stats = new Stats();
	stats.domElement.style.position	= 'absolute';
	stats.domElement.style.bottom	= '0px';
	document.body.appendChild( stats.domElement );

	// create a scene
	scene = new THREE.Scene();

	// put a camera in the scene
	camera	= new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 10000 );
	camera.position.set(0, 0, cameraDistance);
	scene.add(camera);

	// create a camera contol
	cameraControls	= new THREE.TrackballControls( camera )

	// transparently support window resize
	THREEx.WindowResize.bind(renderer, camera);
	// allow 'p' to make screenshot
	THREEx.Screenshot.bindKey(renderer);
	// allow 'f' to go fullscreen where this feature is supported
	if( THREEx.FullScreen.available() ){
		THREEx.FullScreen.bindKey();
		document.getElementById('inlineDoc').innerHTML	+= "- f for fullscreen";
	}

	// here you add your objects
	// - you will most likely replace this part by your own
	var light	= new THREE.AmbientLight( Math.random() * 0xffffff );
	scene.add( light );
	var light	= new THREE.DirectionalLight( Math.random() * 0xffffff );
	light.position.set( Math.random(), Math.random(), Math.random() ).normalize();
	scene.add( light );
	var light	= new THREE.DirectionalLight( Math.random() * 0xffffff );
	light.position.set( Math.random(), Math.random(), Math.random() ).normalize();
	scene.add( light );
	var light	= new THREE.PointLight( Math.random() * 0xffffff );
	light.position.set( Math.random()-0.5, Math.random()-0.5, Math.random()-0.5 )
				.normalize().multiplyScalar(1.2);
	scene.add( light );
	var light	= new THREE.PointLight( Math.random() * 0xffffff );
	light.position.set( Math.random()-0.5, Math.random()-0.5, Math.random()-0.5 )
				.normalize().multiplyScalar(1.2);
	scene.add( light );

	createCube();
	scene.add(
		cube
	);

}

function handleKeyUp(event) {
	window.keyEvent = {
		pressed : true,
	};
	switch (event.keyCode) {
		case 81: // 'Q'
		case 87: // 'W'
			window.keyEvent.rotation = 'TTB';
			window.keyEvent.direction = event.keyCode === 81 ? 'CW' : 'CCW';
			window.keyEvent.layer = 0;
			break;
		case 65: // 'A'
		case 83: // 'S'
			window.keyEvent.rotation = 'TTB';
			window.keyEvent.direction = event.keyCode === 65 ? 'CW' : 'CCW';
			window.keyEvent.layer = 1;
			break;
		case 88: //'X'
		case 90: //'Z'
			window.keyEvent.rotation = 'TTB';
			window.keyEvent.direction = event.keyCode === 90 ? 'CW' : 'CCW';
			window.keyEvent.layer = 2;
			break;

		default:
			window.keyEvent.pressed = false;
	}
}

window.addEventListener('keyup', handleKeyUp, false);

// animation loop
function animate() {

	// loop on request animation loop
	// - it has to be at the begining of the function
	// - see details at http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
	requestAnimationFrame( animate );

	if (window.keyEvent === undefined) {
		window.keyEvent = {};
	}

	if (window.keyEvent.pressed) {
		window.keyEvent.pressed = false;
		rotateCube(window.keyEvent.rotation, window.keyEvent.direction, window.keyEvent.layer);
	}

	// do the render
	render();

	// update stats
	stats.update();
}

// render the scene
function render() {
	// variable which is increase by Math.PI every seconds - usefull for animation
	var PIseconds	= Date.now() * Math.PI;

	// update camera controls
	cameraControls.update();

	// actually render the scene
	renderer.render( scene, camera );
}<|endoftext|>


<commit_before>$.fn.random = function() {
  return this.eq(Math.floor(Math.random() * this.length));
}

Array.prototype.max = function() {
  return Math.max.apply(null, this);
};

$(document).ready(function() {
    "use strict";

    var $ = window.jQuery;
    window.sliMpd = $.extend(true, window.sliMpd, {
        modules : {},

        drawFaviconTimeout : 0,

        xwax : false,

        /**
		 * adds get-paramter to url, respecting existing and not-existing params
		 * TODO: currently not compatible with urlstring that contains a #hash
		 * @param {string} urlstring
		 * @param {string} paramName
		 * @param {string} paramValue
		 */
		setGetParameter : function(urlstring, paramName, paramValue) {
		    if (urlstring.indexOf(paramName + "=") >= 0) {
		        var prefix = urlstring.substring(0, urlstring.indexOf(paramName));
		        var suffix = urlstring.substring(urlstring.indexOf(paramName));
		        suffix = suffix.substring(suffix.indexOf("=") + 1);
		        suffix = (suffix.indexOf("&") >= 0) ? suffix.substring(suffix.indexOf("&")) : "";
		        urlstring = prefix + paramName + "=" + paramValue + suffix;
		    } else {
			    urlstring += (urlstring.indexOf("?") < 0)
			        ? "?" + paramName + "=" + paramValue
			    	: "&" + paramName + "=" + paramValue;
		    }
		    return urlstring;
		},

		drawFavicon : function() {
			clearTimeout(window.sliMpd.drawFaviconTimeout);
			window.sliMpd.currentPlayer.drawFavicon();
			window.sliMpd.drawFaviconTimeout = setTimeout(window.sliMpd.drawFavicon, 2000);
		},

		fireRequestAndNotify : function(url) {
			$.get(url).done(function(response) {
				window.sliMpd.checkNotify(response);
			});
		},

		checkNotify : function(endcodedResponse) {
			try {
	        	var notifyConf = JSON.parse(endcodedResponse);
	        	if (typeof notifyConf.notify !== 'undefined') {
	        		this.notify(notifyConf);
	        	}
		    } catch(e) {
		    	//console.log(e + ' no json response in SliMpd::checkNotify()');
			}
		},

		// TODO: respect playersize + visible xwax gui for positioning
		notify : function(notifyConf) {
    		$.notify({
				// options
				message: notifyConf.message
			},{
				// settings
				type: (notifyConf.type || 'info'),
				z_index: 10000,
				offset: {
					x: '10',
					y: '110'
				},
				placement: {
					from: "bottom",
					align: "right"
				},
			});
		},

		notifyError : function(errorUrl) {
			// TODO: get message from language file
    		this.notify({
				message : "
OOOPS!
 something went wrong...
" + errorUrl + "",
				type : "danger"
			});
		},

		/* toggle between mpd-control and local player (jPlayer) */
		togglePlayer : function() {
			$('.player-local,.player-mpd').toggleClass('hidden');
			if(window.sliMpd.currentPlayer.mode === 'mpd') {
				// activate local player
				window.sliMpd.currentPlayer = window.sliMpd.localPlayer;
				window.sliMpd.mpdPlayer.pollWorker.postMessage({
					cmd: 'setMiliseconds',
					value: window.sliMpd.mpdPlayer.intervalInactive
				});
				$('body')
					.removeClass(window.sliMpd.conf.color.mpd.bodyclass)
					.addClass(window.sliMpd.conf.color.local.bodyclass);
			} else {
				// pause local player when switching to mpd
				window.sliMpd.currentPlayer.process({'action':'pause'});
				// activate mpd player
				window.sliMpd.currentPlayer = window.sliMpd.mpdPlayer;
				window.sliMpd.mpdPlayer.pollWorker.postMessage({
					cmd: 'setMiliseconds',
					value: window.sliMpd.mpdPlayer.intervalActive
				});
				window.sliMpd.currentPlayer.refreshInterval();
				$('body')
					.removeClass(window.sliMpd.conf.color.local.bodyclass)
					.addClass(window.sliMpd.conf.color.mpd.bodyclass);
			}
			$.cookie("playerMode", window.sliMpd.currentPlayer.mode, { expires : 365, path: '/' });
			window.sliMpd.drawFavicon();
			window.sliMpd.currentPlayer.drawWaveform();
		}
    });

    window.sliMpd.navbar = new window.sliMpd.modules.NavbarView({
    	el : 'nav.main-nav'
    });
    window.sliMpd.navbar.render();

    window.sliMpd.xwax = new window.sliMpd.modules.XwaxView({
		el : '.player-xwax',
		showWaveform : true
    });
    window.sliMpd.xwax.render();

	window.sliMpd.modal = new window.sliMpd.modules.ModalView({
    	el : '#global-modal .modal-content'
    });

    window.sliMpd.localPlayer = new window.sliMpd.modules.LocalPlayer({
    	el : '.permaplayer.player-local'
    });
    window.sliMpd.mpdPlayer = new window.sliMpd.modules.MpdPlayer({
    	el : '.permaplayer.player-mpd'
    });

    window.sliMpd.currentPlayer = ($.cookie("playerMode") === 'mpd')
		? window.sliMpd.mpdPlayer
    	: window.sliMpd.localPlayer;

    window.sliMpd.router = new window.sliMpd.modules.Router();

    window.Backbone.history.start({
    	pushState : true
    });

	window.sliMpd.drawFavicon();

	/* toggle playersize */
	$('.playerSizeToggle a').on('click', function(e) {
		e.preventDefault();
		$('body').toggleClass('slimplayer');
		$(this).find('i').toggleClass('fa-chevron-down').toggleClass('fa-chevron-up');
		window.sliMpd.currentPlayer.drawWaveform();
	});

	/* toggle between display tags and display filepath */
	$('.fileModeToggle a').on('click', function(e) {
		e.preventDefault();
		$('body').toggleClass('ffn');
		$(this).find('i').toggleClass('fa-toggle-off').toggleClass('fa-toggle-on');
	});

	// delegate calls to data-toggle="lightbox"
	$(document).delegate('*[data-toggle="lightbox"]', 'click', function(event) {
		event.preventDefault();
		return $(this).ekkoLightbox({
			always_show_close: true,
			gallery_parent_selector: 'body'
		});
	});

	$(document).on('keydown', null, 'ctrl+space', function(){
		// FIXME: this does not work with open autocomplete-widget. obviously ac overrides key bindings
		$('#mainsearch').focus().select();
		return false;
	});

	$('.navbar-upper').affix({
  		offset: {bottom: 200}
	});

	NProgress.configure({
		showSpinner: false,
		parent: '#nprog-container',
		speed: 100,
		trickleRate: 0.02,
		trickleSpeed: 800
	});

	// TODO: is it correct to place this here (excluded from all bootstrap-views)?
	$(function(){
	    $('#top-link-block').removeClass('hidden').affix({
	        // how far to scroll down before link "slides" into view
	        offset: {top:100}
	    });
	});
	$('#top-link-block a').on('click', function(e) {
		e.preventDefault();
		$('html,body').animate({scrollTop:0},'fast');
		return false;
	});

	/*
	 * force confirmation when user leaves sliMpd in case local audio is playing
	 * as the browser is not displaying the text there is no nedd to fetch string from language file
	 */
	window.onbeforeunload=function(){
		if(window.sliMpd.currentPlayer.mode === 'local' && window.sliMpd.currentPlayer.nowPlayingState === 'play') {
			return 'local audio is currently playing';
		}
	}

	/*
	 * add lazy resize listener
	 */
	$(window).bind('resizeEnd', function() {
		window.sliMpd.currentPlayer.drawWaveform();
		window.sliMpd.currentPlayer.drawTimeGrid();
	});
	$(window).resize(function() {
		if(this.resizeTO) clearTimeout(this.resizeTO);
		this.resizeTO = setTimeout(function() {
			$(this).trigger('resizeEnd');
		}, 500);
	});
});

<commit_msg>added flip animation to playermode toggle (local/mpd)<commit_after>$.fn.random = function() {
  return this.eq(Math.floor(Math.random() * this.length));
}

Array.prototype.max = function() {
  return Math.max.apply(null, this);
};

$(document).ready(function() {
    "use strict";

    var $ = window.jQuery;
    window.sliMpd = $.extend(true, window.sliMpd, {
        modules : {},

        drawFaviconTimeout : 0,

        xwax : false,

        /**
		 * adds get-paramter to url, respecting existing and not-existing params
		 * TODO: currently not compatible with urlstring that contains a #hash
		 * @param {string} urlstring
		 * @param {string} paramName
		 * @param {string} paramValue
		 */
		setGetParameter : function(urlstring, paramName, paramValue) {
		    if (urlstring.indexOf(paramName + "=") >= 0) {
		        var prefix = urlstring.substring(0, urlstring.indexOf(paramName));
		        var suffix = urlstring.substring(urlstring.indexOf(paramName));
		        suffix = suffix.substring(suffix.indexOf("=") + 1);
		        suffix = (suffix.indexOf("&") >= 0) ? suffix.substring(suffix.indexOf("&")) : "";
		        urlstring = prefix + paramName + "=" + paramValue + suffix;
		    } else {
			    urlstring += (urlstring.indexOf("?") < 0)
			        ? "?" + paramName + "=" + paramValue
			    	: "&" + paramName + "=" + paramValue;
		    }
		    return urlstring;
		},

		drawFavicon : function() {
			clearTimeout(window.sliMpd.drawFaviconTimeout);
			window.sliMpd.currentPlayer.drawFavicon();
			window.sliMpd.drawFaviconTimeout = setTimeout(window.sliMpd.drawFavicon, 2000);
		},

		fireRequestAndNotify : function(url) {
			$.get(url).done(function(response) {
				window.sliMpd.checkNotify(response);
			});
		},

		checkNotify : function(endcodedResponse) {
			try {
	        	var notifyConf = JSON.parse(endcodedResponse);
	        	if (typeof notifyConf.notify !== 'undefined') {
	        		this.notify(notifyConf);
	        	}
		    } catch(e) {
		    	//console.log(e + ' no json response in SliMpd::checkNotify()');
			}
		},

		// TODO: respect playersize + visible xwax gui for positioning
		notify : function(notifyConf) {
    		$.notify({
				// options
				message: notifyConf.message
			},{
				// settings
				type: (notifyConf.type || 'info'),
				z_index: 10000,
				offset: {
					x: '10',
					y: '110'
				},
				placement: {
					from: "bottom",
					align: "right"
				},
			});
		},

		notifyError : function(errorUrl) {
			// TODO: get message from language file
    		this.notify({
				message : "
OOOPS!
 something went wrong...
" + errorUrl + "",
				type : "danger"
			});
		},

		/* toggle between mpd-control and local player (jPlayer) */
		togglePlayer : function() {
			var perspective = -1100;
			var origin = '50% 50%';
			var ease = Power2.easeInOut;
			var speed = 0.5;
			var classToRemove = window.sliMpd.conf.color.mpd.bodyclass;
			var classToAdd = window.sliMpd.conf.color.local.bodyclass;

			var transformPreviousPlayerFrom = {
				transformOrigin: origin,
				transformPerspective: perspective,
				display: 'block',
				rotationX: 0,
				y: 0,
				ease: ease
			}
			var transformPreviousPlayerTo = {
				rotationX: 90,
				y: 50,
				opacity: 0,
				ease: ease
			}
			var transformNewPlayerFrom = {
				transformOrigin: origin,
				transformPerspective: perspective,
				display: 'block',
				rotationX: -90,
				y: -50
			}
			var transformNewPlayerTo = {
				rotationX: 0,
				y:0,
				ease: ease,
				opacity: 1
			}

			$('.player-local,.player-mpd').removeClass('hidden');

			if(window.sliMpd.currentPlayer.mode === 'mpd') {
				// activate local player
				window.sliMpd.currentPlayer = window.sliMpd.localPlayer;

				// reduce poll amount of inactive mpd player
				window.sliMpd.mpdPlayer.pollWorker.postMessage({
					cmd: 'setMiliseconds',
					value: window.sliMpd.mpdPlayer.intervalInactive
				});

				// flip animation for both players
				TweenLite.fromTo($('.player-mpd'), speed, transformPreviousPlayerFrom, transformPreviousPlayerTo);
				TweenLite.fromTo($('.player-local'), speed, transformNewPlayerFrom, transformNewPlayerTo);
			} else {
				// pause local player when switching to mpd
				window.sliMpd.currentPlayer.process({'action':'pause'});

				// activate mpd player
				window.sliMpd.currentPlayer = window.sliMpd.mpdPlayer;

				// increase poll amount as mpd player is now active
				window.sliMpd.mpdPlayer.pollWorker.postMessage({
					cmd: 'setMiliseconds',
					value: window.sliMpd.mpdPlayer.intervalActive
				});
				window.sliMpd.currentPlayer.refreshInterval();

				// flip animation for both players
				TweenLite.fromTo($('.player-local'), speed, transformPreviousPlayerFrom, transformPreviousPlayerTo);
				TweenLite.fromTo($('.player-mpd'), speed, transformNewPlayerFrom, transformNewPlayerTo);

				classToRemove = window.sliMpd.conf.color.local.bodyclass;
				classToAdd = window.sliMpd.conf.color.mpd.bodyclass;
			}

			// change body-class for colorizing all links
			$('body').addClass(classToAdd).removeClass(classToRemove);

			$.cookie("playerMode", window.sliMpd.currentPlayer.mode, { expires : 365, path: '/' });
			window.sliMpd.drawFavicon();
			window.sliMpd.currentPlayer.drawWaveform();
		}
    });

    window.sliMpd.navbar = new window.sliMpd.modules.NavbarView({
    	el : 'nav.main-nav'
    });
    window.sliMpd.navbar.render();

    window.sliMpd.xwax = new window.sliMpd.modules.XwaxView({
		el : '.player-xwax',
		showWaveform : true
    });
    window.sliMpd.xwax.render();

	window.sliMpd.modal = new window.sliMpd.modules.ModalView({
    	el : '#global-modal .modal-content'
    });

    window.sliMpd.localPlayer = new window.sliMpd.modules.LocalPlayer({
    	el : '.permaplayer.player-local'
    });
    window.sliMpd.mpdPlayer = new window.sliMpd.modules.MpdPlayer({
    	el : '.permaplayer.player-mpd'
    });

    window.sliMpd.currentPlayer = ($.cookie("playerMode") === 'mpd')
		? window.sliMpd.mpdPlayer
    	: window.sliMpd.localPlayer;

    window.sliMpd.router = new window.sliMpd.modules.Router();

    window.Backbone.history.start({
    	pushState : true
    });

	window.sliMpd.drawFavicon();

	/* toggle playersize */
	$('.playerSizeToggle a').on('click', function(e) {
		e.preventDefault();
		$('body').toggleClass('slimplayer');
		$(this).find('i').toggleClass('fa-chevron-down').toggleClass('fa-chevron-up');
		window.sliMpd.currentPlayer.drawWaveform();
	});

	/* toggle between display tags and display filepath */
	$('.fileModeToggle a').on('click', function(e) {
		e.preventDefault();
		$('body').toggleClass('ffn');
		$(this).find('i').toggleClass('fa-toggle-off').toggleClass('fa-toggle-on');
	});

	// delegate calls to data-toggle="lightbox"
	$(document).delegate('*[data-toggle="lightbox"]', 'click', function(event) {
		event.preventDefault();
		return $(this).ekkoLightbox({
			always_show_close: true,
			gallery_parent_selector: 'body'
		});
	});

	$(document).on('keydown', null, 'ctrl+space', function(){
		// FIXME: this does not work with open autocomplete-widget. obviously ac overrides key bindings
		$('#mainsearch').focus().select();
		return false;
	});

	$('.navbar-upper').affix({
  		offset: {bottom: 200}
	});

	NProgress.configure({
		showSpinner: false,
		parent: '#nprog-container',
		speed: 100,
		trickleRate: 0.02,
		trickleSpeed: 800
	});

	// TODO: is it correct to place this here (excluded from all bootstrap-views)?
	$(function(){
	    $('#top-link-block').removeClass('hidden').affix({
	        // how far to scroll down before link "slides" into view
	        offset: {top:100}
	    });
	});
	$('#top-link-block a').on('click', function(e) {
		e.preventDefault();
		$('html,body').animate({scrollTop:0},'fast');
		return false;
	});

	/*
	 * force confirmation when user leaves sliMpd in case local audio is playing
	 * as the browser is not displaying the text there is no nedd to fetch string from language file
	 */
	window.onbeforeunload=function(){
		if(window.sliMpd.currentPlayer.mode === 'local' && window.sliMpd.currentPlayer.nowPlayingState === 'play') {
			return 'local audio is currently playing';
		}
	}

	/*
	 * add lazy resize listener
	 */
	$(window).bind('resizeEnd', function() {
		window.sliMpd.currentPlayer.drawWaveform();
		window.sliMpd.currentPlayer.drawTimeGrid();
	});
	$(window).resize(function() {
		if(this.resizeTO) clearTimeout(this.resizeTO);
		this.resizeTO = setTimeout(function() {
			$(this).trigger('resizeEnd');
		}, 500);
	});
});

<|endoftext|>


<commit_before>
function ArticleObj(art) {
  this.title = art.title;
  this.imgName = art.imgName;
  this.imgPath = 'images/' + art.imgName + '.jpg';
  this.about = art.about;
  this.link = art.link;
  this.publishedOn = art.publishedOn;
  this.category = art.category;
  this.author = art.author;
  ArticleObj.all.push(this);
};

ArticleObj.all = []; //was articleContent?

ArticleObj.prototype.contentDisplay = function() {
  var templateIndex = $('#blogArticle').html();
  var template = Handlebars.compile(templateIndex);
  return template(this);
};

ArticleObj.prototype.setDates = function() {
  //Create method to make new dates
};

ArticleObj.checkLocal = function() {
  if (localStorage.rawData) {
    rawData = JSON.parse(localStorage.rawData);
    console.log('rawData from the localStorage is ' + rawData);
    ArticleObj.loadArticles(rawData);
  } else {
    ArticleObj.getRawData();
    console.log('rawData gotten from .json file');
  }
};

ArticleObj.loadArticles = function(rawData) {
  rawData.map(function(ele) {
    console.log(ele);
    return new ArticleObj(ele);
  });
};

ArticleObj.getRawData = function() {
  $.getJSON('data/article.json', function(rawData) {
    ArticleObj.loadArticles(rawData);
    localStorage.rawData = JSON.stringify(rawData);
  });
};

ArticleObj.checkLocal();

//
// articleDisplay.getFromServer = function () {
//   //use AJAX to get content form json file
// };
//
// articleDisplay.checkLatest = function() {
//   //getAjax head deal?
//   //Check to see if local storage is up to date.
// };

//Create a method to sort articles by date so that the most recent is presented first.

// $(document).ready(function() {
//   articles.forEach(function(ele){
//     var art = new ArticleObj(ele);
//   });

//   articleContent.forEach(function(ar) {
//     $('#projects').append(ar.contentDisplay());
//   });
// });
<commit_msg>Updated render method. Articles from .json file display on page.<commit_after>
function ArticleObj(art) {
  this.title = art.title;
  this.imgName = art.imgName;
  this.imgPath = 'images/' + art.imgName + '.jpg';
  this.about = art.about;
  this.link = art.link;
  this.publishedOn = art.publishedOn;
  this.category = art.category;
  this.author = art.author;
  ArticleObj.all.push(this);
};

ArticleObj.all = []; //was articleContent?

ArticleObj.prototype.contentDisplay = function() {
  var templateIndex = $('#blogArticle').html();
  var template = Handlebars.compile(templateIndex);
  return template(this);
};

ArticleObj.prototype.setDates = function() {
  //Create method to make new dates
};

ArticleObj.checkLocal = function() {
  if (localStorage.rawData) {
    rawData = JSON.parse(localStorage.rawData);
    console.log('rawData from the localStorage is ' + rawData);
    ArticleObj.loadArticles(rawData);
  } else {
    ArticleObj.getRawData();
    console.log('rawData gotten from .json file');
  }
};

ArticleObj.loadArticles = function(rawData) {
  rawData.map(function(ele) {
    console.log(ele);
    return new ArticleObj(ele);
  });
};

ArticleObj.getRawData = function() {
  $.getJSON('data/article.json', function(rawData) {
    ArticleObj.loadArticles(rawData);
    localStorage.rawData = JSON.stringify(rawData);
  });
};

// articleDisplay.getFromServer = function () {
//   //use AJAX to get content form json file
// };
//
// articleDisplay.checkLatest = function() {
//   //getAjax head deal?
//   //Check to see if local storage is up to date.
// };

// Create a method to sort articles by date so that the most recent is presented first.

$(document).ready(function() {

  ArticleObj.checkLocal();

  ArticleObj.all.forEach(function(ar) {
    $('#projects').append(ar.contentDisplay());
  });
});
<|endoftext|>


<commit_before>var parser,
    sourceCode,
    pegedit_opts,
    return_val = [],
    remove_child_objs,
    traverse,
    symbol_table,
    debug = {};

$('document').ready( function() {
  initializeFoundation();

  var editor = initializeAceEditor('editor'),
      terminal = initializeAceEditor('terminal'),
      contents_uri = 'https://api.github.com/repos/bekroogle/cspotrun-grammar/contents/cspotrun.pegjs';

  debug.editor = editor;
  debug.terminal = terminal;

  buildParserFromRepo(contents_uri);
  setAceOptions(editor, terminal);

  loadEditorContent(editor);

  createEventHandlers(editor,terminal);

  $(window).on('resize', function() {
    setAceHeight('editor');
    setAceHeight('terminal');
  });
});

var initializeFoundation = function() {
  $(document).foundation();
};

var buildParserFromRepo = function(uri) {
  $.get(uri, function(repo) {
    parser = PEG.buildParser(atob(repo.content));
  });
};

var initializeAceEditor = function(id) {
  var aceElement = ace.edit(id);
  setAceHeight(id);
  return aceElement;
};

var setAceHeight = function(id) {
  $('#' + id).height(window.innerHeight);
};

var setAceOptions = function(editor, terminal) {
  setEditorOptions(editor);
  setTerminalOptions(terminal);
};

var setEditorOptions = function(id) {
  id.setTheme('ace/theme/monokai');
  id.getSession().setMode('ace/mode/python');
};

var setTerminalOptions = function(terminal) {
  terminal.setTheme('ace/theme/chrome');
  terminal.setOption('showGutter', false);
  terminal.setReadOnly(true);
};

var loadEditorContent = function(editor) {
  if (localStorage.hasOwnProperty('editorContent')) {
    editor.setValue(localStorage.getItem('editorContent'));
  }
};

var createEventHandlers = function(editor, terminal) {
  createAceEventHandlers(editor, terminal);

  createButtonHandlers(editor, terminal);
};

var createAceEventHandlers = function(editor, terminal) {
  editor.getSession().on('change', function(e) {
    localStorage.setItem('editorContent', editor.getValue());
  });
};

var createButtonHandlers = function(input, output) {
  $('#run-btn').click( function(evt) {
    evt.preventDefault();

    if (!parser) { buildParserFromRepo(); }
    runProgram(input,output);
  });
};

var runProgram = function(input,output) {
  var ast = parser.parse(input.getValue());
  output.setValue(traverse(ast),-1);
};
<commit_msg>Fixes #10.<commit_after>var parser,
    sourceCode,
    pegedit_opts,
    return_val = [],
    remove_child_objs,
    traverse,
    symbol_table,
    debug = {};

$('document').ready( function() {
  initializeFoundation();

  var editor = initializeAceEditor('editor'),
      terminal = initializeAceEditor('terminal'),
      contents_uri = 'https://api.github.com/repos/bekroogle/cspotrun-grammar/contents/cspotrun.pegjs';

  debug.editor = editor;
  debug.terminal = terminal;

  buildParserFromRepo(contents_uri);
  setAceOptions(editor, terminal);

  loadEditorContent(editor);

  createEventHandlers(editor,terminal);

  $(window).on('resize', function() {
    setAceHeight('editor');
    setAceHeight('terminal');
  });
});

var initializeFoundation = function() {
  $(document).foundation();
};

var buildParserFromRepo = function(uri) {
  $.get(uri, function(repo) {
    parser = PEG.buildParser(atob(repo.content));
  });
};

var initializeAceEditor = function(id) {
  var aceElement = ace.edit(id);
  setAceHeight(id);
  return aceElement;
};

var setAceHeight = function(id) {
  $('#' + id).height(window.innerHeight-$('nav').height());
};

var setAceOptions = function(editor, terminal) {
  setEditorOptions(editor);
  setTerminalOptions(terminal);
};

var setEditorOptions = function(id) {
  id.setTheme('ace/theme/monokai');
  id.getSession().setMode('ace/mode/python');
};

var setTerminalOptions = function(terminal) {
  terminal.setTheme('ace/theme/chrome');
  terminal.setOption('showGutter', false);
  terminal.setReadOnly(true);
};

var loadEditorContent = function(editor) {
  if (localStorage.hasOwnProperty('editorContent')) {
    editor.setValue(localStorage.getItem('editorContent'));
  }
};

var createEventHandlers = function(editor, terminal) {
  createAceEventHandlers(editor, terminal);

  createButtonHandlers(editor, terminal);
};

var createAceEventHandlers = function(editor, terminal) {
  editor.getSession().on('change', function(e) {
    localStorage.setItem('editorContent', editor.getValue());
  });
};

var createButtonHandlers = function(input, output) {
  $('#run-btn').click( function(evt) {
    evt.preventDefault();

    if (!parser) { buildParserFromRepo(); }
    runProgram(input,output);
  });
};

var runProgram = function(input,output) {
  var ast = parser.parse(input.getValue());
  output.setValue(traverse(ast),-1);
};
<|endoftext|>


<commit_before>angular.module('martina', ['ui.router', 'controllers', 'services'])

.config(function ($stateProvider, $urlRouterProvider) {

  $stateProvider

  .state('home', {
    url: '/home',
    views: {
      'nav': {
        templateUrl: 'partials/nav.html',
        controller: 'NavCtrl'
      },
      'content': {
        templateUrl: 'partials/content.html',
        controller: 'HomeCtrl',
        resolve: {
          json: ["$http", function ($http) {
            return $http({url: "martina/data/data.json"}).success(function (data) {
              return data
            })
          }]
        }
      }
    }
  })

  $urlRouterProvider.otherwise('/home')

});
<commit_msg>Last fix relative link<commit_after>angular.module('martina', ['ui.router', 'controllers', 'services'])

.config(function ($stateProvider, $urlRouterProvider) {

  $stateProvider

  .state('home', {
    url: '/home',
    views: {
      'nav': {
        templateUrl: 'partials/nav.html',
        controller: 'NavCtrl'
      },
      'content': {
        templateUrl: 'partials/content.html',
        controller: 'HomeCtrl',
        resolve: {
          json: ["$http", function ($http) {
            return $http({url: "data/data.json"}).success(function (data) {
              return data
            })
          }]
        }
      }
    }
  })

  $urlRouterProvider.otherwise('/home')

});
<|endoftext|>


<commit_before>var App = (function(md) {

  if(localStorage.getItem("__author_darkmode") == "true") {
    document.body.classList.add("dark");
  }

  var content  = document.getElementById("content"),
         preview = document.getElementById("rendered");

   var body = content;
   var start = null;
   var currentFileName = null;
   var isPreviewing = false;

   var loadFile = function(fName) {
     var text= localStorage.getItem(fName);

     content.value = text;
   };

   var saveFile = function(fileName, content) {
     localStorage.setItem(fileName, content);
   };

   document.getElementById("save").addEventListener("click", function() {
     var name = currentFileName || window.prompt("Enter a filename");

     saveFile(name, content.value);
     currentFileName = name;
   });

   document.getElementById("open").addEventListener("click", function() {
     currentFileName = window.prompt("Open file", currentFileName);
     loadFile(currentFileName);
   });

   document.getElementById("new").addEventListener("click", function() {
     currentFileName = null;
     content.value = "";
   });

   document.getElementById("mode").addEventListener("click", function() {
     document.body.classList.toggle("dark");
     localStorage.setItem("__author_darkmode",
       !(localStorage.getItem("__author_darkmode") == "true"));
   });

   document.getElementById("preview").addEventListener("click", function() {
     isPreviewing = !isPreviewing;
       content.style.display = isPreviewing ? "none" : "block";
       preview.style.display = isPreviewing ? "block" : "none";
       preview.innerHTML = md.makeHtml(content.value);
   });
})(new Showdown.converter());
<commit_msg>ambient light sensing to toggle the darkmode<commit_after>var App = (function(md) {

  if(localStorage.getItem("__author_darkmode") == "true") {
    document.body.classList.add("dark");
  }

  var handleLightEvent = function(event) {
    if(event.value < 50) {
      document.body.classList.add("dark");
    } else {
      document.body.classList.remove("dark");
    }
  };

  window.addEventListener("devicelight", handleLightEvent);

  var content  = document.getElementById("content"),
         preview = document.getElementById("rendered");

   var body = content;
   var start = null;
   var currentFileName = null;
   var isPreviewing = false;

   var loadFile = function(fName) {
     var text= localStorage.getItem(fName);

     content.value = text;
   };

   var saveFile = function(fileName, content) {
     localStorage.setItem(fileName, content);
   };

   document.getElementById("save").addEventListener("click", function() {
     var name = currentFileName || window.prompt("Enter a filename");

     saveFile(name, content.value);
     currentFileName = name;
   });

   document.getElementById("open").addEventListener("click", function() {
     currentFileName = window.prompt("Open file", currentFileName);
     loadFile(currentFileName);
   });

   document.getElementById("new").addEventListener("click", function() {
     currentFileName = null;
     content.value = "";
   });

   document.getElementById("mode").addEventListener("click", function() {
     document.body.classList.toggle("dark");
     window.removeEventListener("devicelight", handleLightEvent);
     localStorage.setItem("__author_darkmode",
       !(localStorage.getItem("__author_darkmode") == "true"));
   });

   document.getElementById("preview").addEventListener("click", function() {
     isPreviewing = !isPreviewing;
       content.style.display = isPreviewing ? "none" : "block";
       preview.style.display = isPreviewing ? "block" : "none";
       preview.innerHTML = md.makeHtml(content.value);
   });
})(new Showdown.converter());
<|endoftext|>


<commit_before>import User from './user.js';
import QuestionRepository from './question-repository.js';
import VotesRepository from './votes-repository.js';
import UsersRepository from './users-repository.js';

const ref = new Firebase("https://datacontest.firebaseio.com");
const user = new User(ref);
let questionRepo = null;
let votesRepo = null;
let usersRepo = null;

const $btn = document.querySelector('.js-log-in');
const $name = document.querySelector('.js-user-name');
const $avatar = document.querySelector('.js-user-avatar');
const $avatarImage = $avatar.querySelector('.js-user-avatar-image');

const $appElement = document.querySelector('.js-app');
let windowWidth = window.innerWidth;

if(user.isAuthenticated()) {
    startApp();
} else {
    $btn.addEventListener('click', () => {
        user.authenticate()
            .then(startApp)
            .catch(showError);
    });
}

window.addEventListener('resize', setSlidesWidth);

function startApp() {
    $name.innerHTML = user.name;
    $avatar.classList.remove('js-user-avatar-hidden');
    $avatarImage.src = user.avatar;

    questionRepo = new QuestionRepository(ref);
    questionRepo.onReady(initQuestions);
    questionRepo.onQuestionChange(questionChanged);
    questionRepo.onError(showError);

    votesRepo = new VotesRepository(ref, user.id);

    usersRepo = new UsersRepository(ref);
    usersRepo.register(user);

    usersRepo.onUsersChange(() => {
        let usersList = document.querySelector('.js-loggedin-users');
        usersList.innerHTML = '';

        Array.from(usersRepo.users).forEach(user => {
            let img = document.createElement('img');
            img.src = user.avatar;

            //TODO fixme - move to CSS
            img.style.maxWidth = '30px';
            img.style.maxHeight = '30px';

            usersList.appendChild(img);
        })
    });

    window.votesRepo = votesRepo;
    $btn.style.display = 'none';
}

function initQuestions(questions) {
    questions.forEach(renderQuestion);
    setSlidesWidth();
}

function questionChanged(questionIdx) {
    console.log('qchange', questionIdx);
    changeSlide(questionIdx + 1);
}

function changeBackground(questionIdx) {
    const colors = [
        '#6ed6a0',
        '#5bb8ff',
        '#ff8073',
        '#ffbe32',
    ];

    const rand = Math.floor(Math.random() * colors.length);

    if (questionIdx != 0) {
        document.body.style.backgroundColor = colors[rand];
    }
}

function showError(error) {
    let message = error;

    if(typeof message === 'object') {
        message = message.code;
    }

    console.error('error', error);
    alert(message);
}

function renderAnswer(answer, answerId, questionId) {
    let $answerTemplate = document.importNode(document.querySelector('#answer-template'), true);
    let $answerButton =  $answerTemplate.content.querySelector('.js-answer-radio-button');
    let $answerContent = $answerTemplate.content.querySelector('.js-answer-content');
    let $answerGhostLabel = $answerTemplate.content.querySelector('.js-answer-ghost-label');
    let $answer;

    $answerContent.textContent = answer;
    $answerButton.dataset.answerId = answerId;
    $answerButton.dataset.questionId = questionId;

    $answerButton.setAttribute('id', 'answer-' + questionId + '-' + answerId);
    $answerGhostLabel.setAttribute('for', 'answer-' + questionId + '-' + answerId);
    $answerContent.setAttribute('for', 'answer-' + questionId + '-' + answerId);

    $answer = document.importNode($answerTemplate.content, true);

    return $answer;
}

function renderQuestion(question, questionId) {
    let $questionTemplate = document.importNode(document.querySelector('#question-template'), true);
    let $question = $questionTemplate.content.querySelector('.js-question');
    let $questionContent = $questionTemplate.content.querySelector('.js-question-content');
    let $answersList = $questionTemplate.content.querySelector('.js-answers-list');
    let $questionClone;

    question.answers.forEach((answer, index) => {
        $answersList.appendChild(renderAnswer(answer, index, questionId));
    });

    $questionContent.textContent = question.text;
    $question.setAttribute('id', 'question-' + questionId);
    $questionClone = document.importNode($questionTemplate.content, true);
    $appElement.appendChild($questionClone);

    $question = document.getElementById('question-' + questionId);
    initBindings($question);
}

function initBindings($question) {
    let $answerRadioButtons = Array.from($question.querySelectorAll('.js-answer-radio-button'));

    $answerRadioButtons.forEach(($radioButton) => {
        $radioButton.addEventListener('change', function() {
            let questionId = parseInt($radioButton.dataset.questionId, 10);
            let answerId = parseInt($radioButton.dataset.answerId, 10);

            votesRepo.vote(questionId, answerId);
        });
    });
}

function setSlidesWidth() {
    windowWidth = window.innerWidth;
    const $slides = Array.from(document.querySelectorAll('.js-slide'));

    $slides.forEach(function($slide) {
        $slide.style.width = windowWidth + 'px';
    });
}

function changeSlide(slideIndex) {
    $appElement.style.left = - (slideIndex * windowWidth) + 'px';
    changeBackground(slideIndex);
}

setSlidesWidth();

window.changeSlide = changeSlide;
<commit_msg>Fixed sliding<commit_after>import User from './user.js';
import QuestionRepository from './question-repository.js';
import VotesRepository from './votes-repository.js';
import UsersRepository from './users-repository.js';

const ref = new Firebase("https://datacontest.firebaseio.com");
const user = new User(ref);
let questionRepo = null;
let votesRepo = null;
let usersRepo = null;

const $btn = document.querySelector('.js-log-in');
const $name = document.querySelector('.js-user-name');
const $avatar = document.querySelector('.js-user-avatar');
const $avatarImage = $avatar.querySelector('.js-user-avatar-image');

const $appElement = document.querySelector('.js-app');
let windowWidth = window.innerWidth;

if(user.isAuthenticated()) {
    startApp();
} else {
    $btn.addEventListener('click', () => {
        user.authenticate()
            .then(startApp)
            .catch(showError);
    });
}

window.addEventListener('resize', setSlidesWidth);

function startApp() {
    $name.innerHTML = user.name;
    $avatar.classList.remove('js-user-avatar-hidden');
    $avatarImage.src = user.avatar;

    questionRepo = new QuestionRepository(ref);
    questionRepo.onReady(initQuestions);
    questionRepo.onQuestionChange(questionChanged);
    questionRepo.onError(showError);

    votesRepo = new VotesRepository(ref, user.id);

    usersRepo = new UsersRepository(ref);
    usersRepo.register(user);

    usersRepo.onUsersChange(() => {
        let usersList = document.querySelector('.js-loggedin-users');
        usersList.innerHTML = '';

        Array.from(usersRepo.users).forEach(user => {
            let img = document.createElement('img');
            img.src = user.avatar;

            //TODO fixme - move to CSS
            img.style.maxWidth = '30px';
            img.style.maxHeight = '30px';

            usersList.appendChild(img);
        })
    });

    window.votesRepo = votesRepo;
    $btn.style.display = 'none';
}

function initQuestions(questions) {
    questions.forEach(renderQuestion);
    setSlidesWidth();
}

function questionChanged(questionIdx) {
    console.log('qchange', questionIdx);
    changeSlide(questionIdx + 1);
}

function changeBackground(questionIdx) {
    const colors = [
        '#6ed6a0',
        '#5bb8ff',
        '#ff8073',
        '#ffbe32',
    ];

    const rand = Math.floor(Math.random() * colors.length);

    if (questionIdx != 0) {
        document.body.style.backgroundColor = colors[rand];
    }
}

function showError(error) {
    let message = error;

    if(typeof message === 'object') {
        message = message.code;
    }

    console.error('error', error);
    alert(message);
}

function renderAnswer(answer, answerId, questionId) {
    let $answerTemplate = document.importNode(document.querySelector('#answer-template'), true);
    let $answerButton =  $answerTemplate.content.querySelector('.js-answer-radio-button');
    let $answerContent = $answerTemplate.content.querySelector('.js-answer-content');
    let $answerGhostLabel = $answerTemplate.content.querySelector('.js-answer-ghost-label');
    let $answer;

    $answerContent.textContent = answer;
    $answerButton.dataset.answerId = answerId;
    $answerButton.dataset.questionId = questionId;

    $answerButton.setAttribute('id', 'answer-' + questionId + '-' + answerId);
    $answerGhostLabel.setAttribute('for', 'answer-' + questionId + '-' + answerId);
    $answerContent.setAttribute('for', 'answer-' + questionId + '-' + answerId);

    $answer = document.importNode($answerTemplate.content, true);

    return $answer;
}

function renderQuestion(question, questionId) {
    let $questionTemplate = document.importNode(document.querySelector('#question-template'), true);
    let $question = $questionTemplate.content.querySelector('.js-question');
    let $questionContent = $questionTemplate.content.querySelector('.js-question-content');
    let $answersList = $questionTemplate.content.querySelector('.js-answers-list');
    let $questionClone;

    question.answers.forEach((answer, index) => {
        $answersList.appendChild(renderAnswer(answer, index, questionId));
    });

    $questionContent.textContent = question.text;
    $question.setAttribute('id', 'question-' + questionId);
    $questionClone = document.importNode($questionTemplate.content, true);
    $appElement.appendChild($questionClone);

    $question = document.getElementById('question-' + questionId);
    initBindings($question);
}

function initBindings($question) {
    let $answerRadioButtons = Array.from($question.querySelectorAll('.js-answer-radio-button'));

    $answerRadioButtons.forEach(($radioButton) => {
        $radioButton.addEventListener('change', function() {
            let questionId = parseInt($radioButton.dataset.questionId, 10);
            let answerId = parseInt($radioButton.dataset.answerId, 10);

            votesRepo.vote(questionId, answerId);
        });
    });
}

function setSlidesWidth() {
    windowWidth = window.innerWidth;
    const $slides = Array.from(document.querySelectorAll('.js-slide'));
    document.body.style.width = windowWidth + 'px';
    $slides.forEach(function($slide) {
        $slide.style.width = windowWidth + 'px';
    });
}

function changeSlide(slideIndex) {
    $appElement.style.left = - (slideIndex * windowWidth) + 'px';
    changeBackground(slideIndex);
}

setSlidesWidth();

window.changeSlide = changeSlide;
<|endoftext|>


<commit_before>$(document).ready(function() {

    /*
     * Data Tables
     */

    // Setup - add a text input to filtesearch footers
    $('#table-maplist tfoot th.filtersearch').each( function () {
        var title = $(this).text();
        $(this).html( '<input type="text" placeholder="filter '+title+'" />' );
    } );

    // Setup - add a dropdown to dropdownsearch footers
    $('#table-maplist tfoot th.dropdownsearch').each( function () {
        var title = $(this).text();
        $(this).html( '<select><option value=""></option><option value="yes">' + title + '</option><option value="no">no ' + title + '</option></select>' );
    } );

    var table = $('#table-maplist').DataTable( {
        "ajax": "data/maps.json",
        "lengthMenu": [[50, 100, 250, 500, 1000], [50, 100, 250, 500, 1000]],
        "pageLength": 250,
        "colReorder": true,
        "stateSave": true,
        "fixedHeader": {
            "header": true,
            "headerOffset": $('#main-nav').height()
        },
        "processing": true,
        "deferRender": true,
        "language": {
            "lengthMenu": "_MENU_",
            "processing": '
Processing a large file, this might take a second

'
        },
        "buttons": [
            {
                "extend": "csvHtml5",
                "text": '',
            },
            {
                "extend": "colvis",
                "postfixButtons": [ 'colvisRestore' ],
                "text": ''
            }
        ],
        "dom": "<'#table-controls'lB>" +
                "<'row'<'col-sm-12'tr>>" +
                "<'row'<'col-sm-5'i><'col-sm-7'p>>",
        "columns": [
            { "data": "pk3" },
            { "data": "bsp[
 ]" },
            { "data": "filesize" },
            { "data": "filesize" },
            { "data": "shasum" },
            { "data": "mapshot" },
            { "data": "title" },
            { "data": "author" },
            { "data": "gametypes[, ]" },
            { "data": "map[, ]" },
            { "data": "radar[, ]" },
            { "data": "waypoints[, ]" },
            { "data": "license" },
            { "data": "date" }
        ],
        "columnDefs": [
            {   // pk3
                "targets": 0,
                "render": function ( data, type, full, meta ) {
                    var pk3 = data;
                    if (type === 'display' && data.length > 40) {
                        data = ''+data.substr( 0, 38 )+'...';
                    }
                    return '' + data + '';
                }
            },
            {   // bsp
                "targets": 1,
                "render": function ( data, type, full, meta ) {
                    if (data != false && data.length > 0) {
            			if (data.length > 40 && data.indexOf('
') == -1) {
                            data = ''+data.substr( 0, 38 )+'...';
        		    	}
        		    }
                    return data;
                }
            },
            {   // filesize
                "targets": 2,
                "orderData": 3,
                "render": function ( data, type, full, meta ) {
                    return(bytesToSize(data));
                }
            },
            {   // filesize (bytes)
                "targets": 3,
                "visible": false,
                "searchable": false
            },
            {   // shasum
                "targets": 4,
                "visible": false,
            },
            {   // mapshot file
                "targets": 5,
                "render": function ( data, type, full, meta ) {
                    var string = "";
                    if (data.length > 0) {
                        data.forEach(function(value, index, array) {
                            string += '';
                        });
                    }
                    return string;
                }
            },
            {   // title
                "targets": 6,
                "render": function ( data, type, full, meta ) {
                    return (data != false) ? data : "";
                }
            },
            {   // author
                "targets": 7,
                "render": function ( data, type, full, meta ) {
                    return (data != false) ? data : "";
                }
            },
            {   // map file
                "targets": 9,
                "render": function ( data, type, full, meta ) {
                    return (data != false) ? "yes" : "no";
                }
            },
            {   // radar file
                "targets": 10,
                "render": function ( data, type, full, meta ) {
                    return (data != false) ? "yes" : "no";
                }
            },
            {   // waypoints file
                "targets": 11,
                "render": function ( data, type, full, meta ) {
                    return (data != false) ? "yes" : "no";
                }
            },
            {   // license file
                "targets": 12,
                "render": function ( data, type, full, meta ) {
                    return (data != false) ? "yes" : "no";
                }
            },
            {
                // date
                "targets": 13,
                "render": function ( data, type, full, meta ) {
                    d = new Date(0);
                    d.setUTCSeconds(data);
                    return d.toISOString().slice(0,10);
                }
            }
        ],
        "initComplete": function( settings, json ) {
            // clear filters on page load
            $("tfoot input").val('').trigger('change');
            $("tfoot select").val('').trigger('change');
            // Hacky way to put the controls in the navbar
            $("#table-controls .btn").addClass("btn-sm");
            $("#table-maplist_length").addClass("pull-right");
            $("#table-controls").detach().appendTo('#nav-table-controls');
            initPopovers();
        }
    } );

    // Reorder callback
    table.on( 'column-reorder', function ( e, settings, details ) {
        initPopovers();
    });

    // Popover image previews
    function initPopovers() {
        $('a[rel=popover]').popover({
            html: true,
            trigger: 'hover',
            content: function () {
                return '';
            }
        });
    }

    // Apply filtersearch and dropdownsearch
    table.columns().every( function () {
        var that = this;

        $( 'input', this.footer() ).on( 'keyup change', function () {
            if ( that.search() !== this.value ) {
                that
                    .search( this.value )
                    .draw();
            }
        } );

        $( 'select', this.footer() ).on( 'change', function () {
            if ( that.search() !== this.value ) {
                that
                    .search( this.value )
                    .draw();
            }
        } );

    } );

    /*
     * Charts
     */

    var chartData;

    function drawCharts(data) {
            $("#charts").show();

            // Pie
            c3.generate(data.mapinfos);
            c3.generate(data.mapshots);
            c3.generate(data.maps);
            c3.generate(data.radars);
            c3.generate(data.waypoints);
            c3.generate(data.licenses);

            // Scatter
            var filesizes = {
                axis: { x: { show: false }, rotated: true },
                tooltip: {
                    format: {
                        title: function (x) { return; },
                        name: function (name, ratio, id, index) { return "size"; },
                        value: function (value, ratio, id, index) { return bytesToSize(value); }
                    }
                }
            };

            $.extend(filesizes, data.filesizes);
            c3.generate(filesizes);

            // Line
            c3.generate(data.mapsbyyear);

            $("#loading-charts").hide();
    }

    // Need to hide datatables when changing tabs for fixedHeader
    var visible = true;
    var tableContainer = $(table.table().container());

    // Bootstrap tab shown event
    $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {

        // decide whether to show the table or not
        if (visible) {
            $("#nav-table-controls").hide();
            tableContainer.css('display', 'none');
        } else {
            $("#nav-table-controls").show();
            tableContainer.css('display', 'block');
        }

        table.fixedHeader.adjust();

        visible = ! visible;

        $("#charts").hide();
        $("#loading-charts").show();

        if (!chartData) {
            $.get('data/charts.json', function(data) {
                drawCharts(data);
                chartData = data;
            });
        } else {
            drawCharts(chartData);
        }

    });

} );

function bytesToSize(bytes) {
   var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
   if (bytes == 0) return '0 Byte';
   var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
   return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
};

<commit_msg>better chart performance<commit_after>$(document).ready(function() {

    /*
     * Data Tables
     */

    // Setup - add a text input to filtesearch footers
    $('#table-maplist tfoot th.filtersearch').each( function () {
        var title = $(this).text();
        $(this).html( '<input type="text" placeholder="filter '+title+'" />' );
    } );

    // Setup - add a dropdown to dropdownsearch footers
    $('#table-maplist tfoot th.dropdownsearch').each( function () {
        var title = $(this).text();
        $(this).html( '<select><option value=""></option><option value="yes">' + title + '</option><option value="no">no ' + title + '</option></select>' );
    } );

    var table = $('#table-maplist').DataTable( {
        "ajax": "data/maps.json",
        "lengthMenu": [[50, 100, 250, 500, 1000], [50, 100, 250, 500, 1000]],
        "pageLength": 250,
        "colReorder": true,
        "stateSave": true,
        "fixedHeader": {
            "header": true,
            "headerOffset": $('#main-nav').height()
        },
        "processing": true,
        "deferRender": true,
        "language": {
            "lengthMenu": "_MENU_",
            "processing": '
Processing a large file, this might take a second

'
        },
        "buttons": [
            {
                "extend": "csvHtml5",
                "text": '',
            },
            {
                "extend": "colvis",
                "postfixButtons": [ 'colvisRestore' ],
                "text": ''
            }
        ],
        "dom": "<'#table-controls'lB>" +
                "<'row'<'col-sm-12'tr>>" +
                "<'row'<'col-sm-5'i><'col-sm-7'p>>",
        "columns": [
            { "data": "pk3" },
            { "data": "bsp[
 ]" },
            { "data": "filesize" },
            { "data": "filesize" },
            { "data": "shasum" },
            { "data": "mapshot" },
            { "data": "title" },
            { "data": "author" },
            { "data": "gametypes[, ]" },
            { "data": "map[, ]" },
            { "data": "radar[, ]" },
            { "data": "waypoints[, ]" },
            { "data": "license" },
            { "data": "date" }
        ],
        "columnDefs": [
            {   // pk3
                "targets": 0,
                "render": function ( data, type, full, meta ) {
                    var pk3 = data;
                    if (type === 'display' && data.length > 40) {
                        data = ''+data.substr( 0, 38 )+'...';
                    }
                    return '' + data + '';
                }
            },
            {   // bsp
                "targets": 1,
                "render": function ( data, type, full, meta ) {
                    if (data != false && data.length > 0) {
            			if (data.length > 40 && data.indexOf('
') == -1) {
                            data = ''+data.substr( 0, 38 )+'...';
        		    	}
        		    }
                    return data;
                }
            },
            {   // filesize
                "targets": 2,
                "orderData": 3,
                "render": function ( data, type, full, meta ) {
                    return(bytesToSize(data));
                }
            },
            {   // filesize (bytes)
                "targets": 3,
                "visible": false,
                "searchable": false
            },
            {   // shasum
                "targets": 4,
                "visible": false,
            },
            {   // mapshot file
                "targets": 5,
                "render": function ( data, type, full, meta ) {
                    var string = "";
                    if (data.length > 0) {
                        data.forEach(function(value, index, array) {
                            string += '';
                        });
                    }
                    return string;
                }
            },
            {   // title
                "targets": 6,
                "render": function ( data, type, full, meta ) {
                    return (data != false) ? data : "";
                }
            },
            {   // author
                "targets": 7,
                "render": function ( data, type, full, meta ) {
                    return (data != false) ? data : "";
                }
            },
            {   // map file
                "targets": 9,
                "render": function ( data, type, full, meta ) {
                    return (data != false) ? "yes" : "no";
                }
            },
            {   // radar file
                "targets": 10,
                "render": function ( data, type, full, meta ) {
                    return (data != false) ? "yes" : "no";
                }
            },
            {   // waypoints file
                "targets": 11,
                "render": function ( data, type, full, meta ) {
                    return (data != false) ? "yes" : "no";
                }
            },
            {   // license file
                "targets": 12,
                "render": function ( data, type, full, meta ) {
                    return (data != false) ? "yes" : "no";
                }
            },
            {
                // date
                "targets": 13,
                "render": function ( data, type, full, meta ) {
                    d = new Date(0);
                    d.setUTCSeconds(data);
                    return d.toISOString().slice(0,10);
                }
            }
        ],
        "initComplete": function( settings, json ) {
            // clear filters on page load
            $("tfoot input").val('').trigger('change');
            $("tfoot select").val('').trigger('change');
            // Hacky way to put the controls in the navbar
            $("#table-controls .btn").addClass("btn-sm");
            $("#table-maplist_length").addClass("pull-right");
            $("#table-controls").detach().appendTo('#nav-table-controls');
            initPopovers();
        }
    } );

    // Reorder callback
    table.on( 'column-reorder', function ( e, settings, details ) {
        initPopovers();
    });

    // Popover image previews
    function initPopovers() {
        $('a[rel=popover]').popover({
            html: true,
            trigger: 'hover',
            content: function () {
                return '';
            }
        });
    }

    // Apply filtersearch and dropdownsearch
    table.columns().every( function () {
        var that = this;

        $( 'input', this.footer() ).on( 'keyup change', function () {
            if ( that.search() !== this.value ) {
                that
                    .search( this.value )
                    .draw();
            }
        } );

        $( 'select', this.footer() ).on( 'change', function () {
            if ( that.search() !== this.value ) {
                that
                    .search( this.value )
                    .draw();
            }
        } );

    } );

    /*
     * Charts
     */

    var chartsDrawn = false;
    var allCharts = [];

    function drawCharts(data) {
            $("#charts").show();

            // Pie
            allCharts[0] = c3.generate(data.mapinfos);
            allCharts[1] = c3.generate(data.mapshots);
            allCharts[2] = c3.generate(data.maps);
            allCharts[3] = c3.generate(data.radars);
            allCharts[4] = c3.generate(data.waypoints);
            allCharts[5] = c3.generate(data.licenses);

            // Scatter
            var filesizes = {
                axis: { x: { show: false }, rotated: true },
                tooltip: {
                    format: {
                        title: function (x) { return; },
                        name: function (name, ratio, id, index) { return "size"; },
                        value: function (value, ratio, id, index) { return bytesToSize(value); }
                    }
                }
            };

            $.extend(filesizes, data.filesizes);
            allCharts[6] = c3.generate(filesizes);

            // Line
            allCharts[7] = c3.generate(data.mapsbyyear);

            $("#loading-charts").hide();
    }

    function hideCharts() {
        allCharts.forEach(function(value, index, array) {
            value.hide();
        });
    }

    function showCharts() {
        $("#loading-charts").hide();
        $("#charts").show();
        allCharts.forEach(function(value, index, array) {
            value.show();
        });
    }

    // Need to hide datatables when changing tabs for fixedHeader
    var visible = true;
    var tableContainer = $(table.table().container());

    // Bootstrap tab shown event
    $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {

        // decide whether to show the table or not
        if (visible) { // hide table
            $("#nav-table-controls").hide();
            tableContainer.css('display', 'none');
        } else { // show table
            $("#nav-table-controls").show();
            tableContainer.css('display', 'block');
            hideCharts();
        }

        table.fixedHeader.adjust();

        visible = ! visible;

        $("#charts").hide();
        $("#loading-charts").show();

        if (!chartsDrawn) {
            $.get('data/charts.json', function(data) {
                drawCharts(data);
                chartsDrawn = true;
            });
        } else {
            showCharts();
        }

    });

} );

function bytesToSize(bytes) {
   var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
   if (bytes == 0) return '0 Byte';
   var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
   return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
};

<|endoftext|>