<commit_before>var software_update = (function() {

var mostRecentTrack = null;
var mostRecentVersion = 0;
var versions = {};
var errorsChecking = 0;

$(document).on("general", function(event, data) {

	if (data.header == "activatedExtension") {
		if (data.content.extension == "software-update") {

			$("#earlier-updates").addClass("hidden");
		}
	}

});

$(document).on("software-update", function(event, data) {

	if (data.header == "checking" || data.header == "updateList") {
		if (data.content && data.content.checking) {
			$(".checking-for-update").removeClass("hidden");
			$(".update-check-error").addClass("hidden");
			$(".no-update-available").addClass("hidden");
		} else {
			$(".checking-for-update").addClass("hidden");
			if (errorsChecking && !mostRecentTrack && checkedSuccessfully <= 2) {
				$(".update-check-error").removeClass("hidden");
			} else if (!mostRecentTrack) {
				$(".no-update-available").removeClass("hidden");
				$(".software-update-available").addClass("hidden");
			}
		}
	}

	if (data.header == "updateList") {
		if (data.content && data.content.versions) {
			versions = data.content.versions;
			mostRecentTrack = null;
			mostRecentVersion = 0;
			errorsChecking = 0;
			checkedSuccessfully = 0;
			for (track in versions) {
				if (versions[track].error) errorsChecking++;
				if (versions[track].lastChecked) checkedSuccessfully++;
				if (versions[track].version) {
					if (parseInt(versions[track].version) > mostRecentVersion) {
						mostRecentVersion = parseInt(versions[track].version);
						mostRecentTrack = track;
					}
				}
			}
			if (mostRecentTrack) {
				if (mostRecentTrack == "experimental") {
					$("#main-pre-release-warning").removeClass("hidden");
				} else {
					$("#main-pre-release-warning").addClass("hidden");
				}
				menuOptions = {
					value: mostRecentVersion,
					static: true
				}
				if ($("body").hasClass("hifiberry-os")) {
					menuOptions.label = "HiFiBerryOS";
					menuOptions.icon = extensions["product-information"].assetPath+"/symbols-black/hifiberry.svg"
				} else {
					menuOptions.label = "Beocreate 2";
					menuOptions.icon = extensions["product-information"].assetPath+"/symbols-black/create.svg"
				}
				$("#update-available-container").empty();
				$("#update-available-container").append(beo.createMenuItem(menuOptions));

				$("#update-release-notes").html(generateMarkupForUpdate(mostRecentTrack));
				$(".software-update-available").removeClass("hidden");
			}

			$("#earlier-updates").addClass("hidden");
			$("#earlier-updates-container").empty();
			for (track in versions) {
				if (track != mostRecentTrack) {
					//if (versions[track].version) {
					if (versions[track].version && parseInt(versions[track].version) != mostRecentVersion) {
						$("#earlier-updates").removeClass("hidden");
						menuOptions = {
							value: versions[track].version,
							label: getTrackName(track),
							onclick: "software_update.showEarlierUpdate('"+track+"');"
						}
						if ($("body").hasClass("hifiberry-os")) {
							menuOptions.icon = extensions["product-information"].assetPath+"/symbols-black/hifiberry.svg"
						} else {
							menuOptions.icon = extensions["product-information"].assetPath+"/symbols-black/create.svg"
						}

						$("#earlier-updates-container").append(beo.createMenuItem(menuOptions));
					}
				}
			}
		}
	}

	if (data.header == "badge") {
		if (data.content && data.content.badge) {
			$(".software-update-badge").text("1").addClass("badge");
		} else {
			$(".software-update-badge").text("").removeClass("badge");
		}
	}

	if (data.header == "autoUpdateMode") {
		if (data.content.mode != undefined) {
			$(".auto-update-mode-selector > .menu-item").removeClass("checked");
			updateMode = null;
			switch (data.content.mode) {
				case "critical":
					$("#auto-update-critical").addClass("checked");
					updateMode = "Critical only";
					break;
				case "stable":
					$("#auto-update-stable").addClass("checked");
					updateMode = "Regular";
					break;
				case "latest":
					$("#auto-update-latest").addClass("checked");
					updateMode = "Quick";
					break;
				case "experimental":
					updateMode = "Pre-release";
					break;
				case false:
					updateMode = "Off";
					break;
			}
			if (updateMode) {
				$(".auto-update-mode").text(updateMode);
			}
			if (data.content.showExperimental) {
				$("#show-experimental-updates").removeClass("hidden");
			} else {
				$("#show-experimental-updates").addClass("hidden");
			}
		}
	}

	if (data.header == "updateAvailable" && data.content.version) {
		$(".checking-for-update").addClass("hidden");
		newVersion = data.content.version;
		menuOptions = {
			value: newVersion,
			static: true
		}
		if ($("body").hasClass("hifiberry-os")) {
			menuOptions.label = "HiFiBerryOS";
			menuOptions.icon = extensions["product-information"].assetPath+"/symbols-black/hifiberry.svg"
		} else {
			menuOptions.label = "Beocreate 2";
			menuOptions.icon = extensions["product-information"].assetPath+"/symbols-black/create.svg"
		}

		$(".no-update-available").addClass("hidden");
		$(".software-update-available").removeClass("hidden");
		$(".update-check-error").addClass("hidden");
		$("#update-available-container").empty();
		$("#update-available-container").append(beo.createMenuItem(menuOptions));

		$("#update-release-notes").empty();

	}

	if (data.header == "upToDate") {
		$(".checking-for-update").addClass("hidden");
		$(".no-update-available").removeClass("hidden");
		$(".software-update-available").addClass("hidden");
		$(".update-check-error").addClass("hidden");
		newVersion = null;
	}

	if (data.header == "errorChecking") {
		$(".checking-for-update").addClass("hidden");
		$(".no-update-available").addClass("hidden");
		$(".software-update-available").addClass("hidden");
		$(".update-check-error").removeClass("hidden");
		newVersion = null;
	}

	if (data.header == "updating") {
		notifyOptions = {title: "Updating product...", timeout: false, icon: "attention"};
		if (data.content.progress != undefined) {
			notifyOptions.progress = data.content.progress;
		}
		switch (data.content.phase) {
			case "download":
				notifyOptions.message = "Downloading...";
				break;
			case "extractingFirmware":
			case "resizing":
			case "extractingKernel":
				notifyOptions.message = "Unpacking, this will take some time...";
				break;
			case "copyingFiles":
				notifyOptions.message = "Moving things over...";
				break;
			case "finalising":
				notifyOptions.message = "Finalising...";
				break;
			case "done":
				notifyOptions.title = "Product updated";
				notifyOptions.message = "The product has been updated and it will now restart to finish the process. This may take some time, please wait.";
				beo.sendToProductView({header: "autoReconnect", content: {status: "updateComplete", systemID: product_information.systemID(), systemName: product_information.systemName()}});
				noConnectionNotifications = true;
				maxConnectionAttempts = 30;
				reloadOnReconnect = true;
				break;
			case "doneSimulation":
				notifyOptions.title = "Product updated";
				notifyOptions.message = "The product update simulation has finished. The product would now restart, in case of a real update. Start Beocreate 2 in non-developer mode to update.";
				notifyOptions.buttonTitle = "Done";
				notifyOptions.buttonAction = "close";
				notifyOptions.icon = null;
				break;
		}
		beo.notify(notifyOptions, "software-update");
	}

	if (data.header == "updateError") {
		notifyOptions = {title: "Update unsuccessful", timeout: false, buttonTitle: "Dismiss", buttonAction: "close"};
		if (data.content.reason) {
			switch (data.content.reason) {
				case "downloadError":
					notifyOptions.message = "The update could not be downloaded. Please try again later, or contact support if the problem persists.";
					break;
			}
		}
		beo.notify(notifyOptions, "software-update");
	}

	if (data.header == "previousVersion") {
		if (!data.content.previousVersion) {
			$("#previous-version-information").text("Not available");
			$("#restore-previous-version-button").addClass("disabled");
		} else if (data.content.previousVersion == true) {
			$("#previous-version-information").text("Available");
			$("#restore-previous-version-button").removeClass("disabled");
		} else {
			$("#previous-version-information").text(data.content.previousVersion);
			$("#restore-previous-version-button").removeClass("disabled");
		}
	}

	if (data.header == "restoringPreviousVersion") {
		if (data.content.stage == "start") {
			noConnectionNotifications = true;
			maxConnectionAttempts = 30;
			reloadOnReconnect = true;
			beo.notify({title: "Restoring previous version...", message: "The product will restart with the previous software version and settings. If the product name or network settings have changed, you may need to reconnect to the product manually.", timeout: false, icon: "attention"}, "software-update");
		}
		if (data.content.stage == "fail") {
			noConnectionNotifications = false;
			maxConnectionAttempts = 5;
			reloadOnReconnect = false;
			notifyOptions = {title: "Restore unsuccesful", timeout: false, buttonTitle: "Dismiss", buttonAction: "close"};
			if (data.content.reason == "notFound") notifyOptions.message = "Previous version was not found.";
			if (data.content.reason == "unknownPartition") notifyOptions.message = "Unknown backup partition.";
			beo.notify(notifyOptions, "software-update");
		}
	}
});

function generateMarkupForUpdate(track) {
	if (versions[track] && versions[track].releaseNotes) {
		releaseNotes = versions[track].releaseNotes.split("\n");
		openUL = "";
		notesHTML = ""
		for (var i = 0; i < releaseNotes.length; i++) {
			if (!(i == 0 && releaseNotes[i].trim() == versions[track].version)) {
				if (releaseNotes[i].trim().charAt(0) == "-") {
					// A dash is a list item.
					if (!openUL) {
						openUL += "\n
";
					}
					openUL += "\n
"+releaseNotes[i].trim().substring(2)+"
";
					//console.log(openUL);
				} else {
					// Normal lines make p elements.
					if (openUL) {
						openUL += "\n
";
						notesHTML += openUL;
						openUL = "";
					}
					notesHTML += "
"+releaseNotes[i].trim()+"
";
				}
			}
		}
		if (openUL) {
			openUL += "\n
";
			notesHTML += openUL;
		}
		return notesHTML
	} else {
		return "
No release notes included.
";
	}
}

function getTrackName(track) {
	switch (track) {
		case "critical":
			return "Critical Release";
			break;
		case "stable":
			return "Regular Release";
			break;
		case "latest":
			return "Latest Release";
			break;
		case "experimental":
			return "Pre-Release";
			break;
	}
}

function showEarlierUpdate(track) {
	if (versions[track].version) {
		$("#earlier-release-notes").html(generateMarkupForUpdate(track));
		if (track == "experimental") {
			$("#earlier-pre-release-warning").removeClass("hidden");
		} else {
			$("#earlier-pre-release-warning").addClass("hidden");
		}
		beo.ask("earlier-update-info-prompt", [getTrackName(track)], [function() {
			install(track);
		}]);
	}
}

function install(track = mostRecentTrack) {
	beo.sendToProduct("software-update", "install", {track: mostRecentTrack});
}

function setAutoUpdate(mode) {
	beo.ask();
	beo.sendToProduct("software-update", {header: "autoUpdateMode", content: {mode: mode}});
}

function setManualUpdateMode(mode) {
	beo.sendToProduct("software-update", {header: "manualUpdateMode", content: {mode: mode}});
}

function restore(confirmed) {
	if (!confirmed) {
		beo.ask("restore-previous-version-prompt");
	} else {
		beo.ask();
		beo.sendToProduct("software-update", {header: "restorePreviousVersion"});
	}
}

return {
	install: install,
	setAutoUpdate: setAutoUpdate,
	setManualUpdateMode: setManualUpdateMode,
	restore: restore,
	showEarlierUpdate: showEarlierUpdate
};

})();<commit_msg>Increase reconnect time after software update<commit_after>var software_update = (function() {

var mostRecentTrack = null;
var mostRecentVersion = 0;
var versions = {};
var errorsChecking = 0;

$(document).on("general", function(event, data) {

	if (data.header == "activatedExtension") {
		if (data.content.extension == "software-update") {

			$("#earlier-updates").addClass("hidden");
		}
	}

});

$(document).on("software-update", function(event, data) {

	if (data.header == "checking" || data.header == "updateList") {
		if (data.content && data.content.checking) {
			$(".checking-for-update").removeClass("hidden");
			$(".update-check-error").addClass("hidden");
			$(".no-update-available").addClass("hidden");
		} else {
			$(".checking-for-update").addClass("hidden");
			if (errorsChecking && !mostRecentTrack && checkedSuccessfully <= 2) {
				$(".update-check-error").removeClass("hidden");
			} else if (!mostRecentTrack) {
				$(".no-update-available").removeClass("hidden");
				$(".software-update-available").addClass("hidden");
			}
		}
	}

	if (data.header == "updateList") {
		if (data.content && data.content.versions) {
			versions = data.content.versions;
			mostRecentTrack = null;
			mostRecentVersion = 0;
			errorsChecking = 0;
			checkedSuccessfully = 0;
			for (track in versions) {
				if (versions[track].error) errorsChecking++;
				if (versions[track].lastChecked) checkedSuccessfully++;
				if (versions[track].version) {
					if (parseInt(versions[track].version) > mostRecentVersion) {
						mostRecentVersion = parseInt(versions[track].version);
						mostRecentTrack = track;
					}
				}
			}
			if (mostRecentTrack) {
				if (mostRecentTrack == "experimental") {
					$("#main-pre-release-warning").removeClass("hidden");
				} else {
					$("#main-pre-release-warning").addClass("hidden");
				}
				menuOptions = {
					value: mostRecentVersion,
					static: true
				}
				if ($("body").hasClass("hifiberry-os")) {
					menuOptions.label = "HiFiBerryOS";
					menuOptions.icon = extensions["product-information"].assetPath+"/symbols-black/hifiberry.svg"
				} else {
					menuOptions.label = "Beocreate 2";
					menuOptions.icon = extensions["product-information"].assetPath+"/symbols-black/create.svg"
				}
				$("#update-available-container").empty();
				$("#update-available-container").append(beo.createMenuItem(menuOptions));

				$("#update-release-notes").html(generateMarkupForUpdate(mostRecentTrack));
				$(".software-update-available").removeClass("hidden");
			}

			$("#earlier-updates").addClass("hidden");
			$("#earlier-updates-container").empty();
			for (track in versions) {
				if (track != mostRecentTrack) {
					//if (versions[track].version) {
					if (versions[track].version && parseInt(versions[track].version) != mostRecentVersion) {
						$("#earlier-updates").removeClass("hidden");
						menuOptions = {
							value: versions[track].version,
							label: getTrackName(track),
							onclick: "software_update.showEarlierUpdate('"+track+"');"
						}
						if ($("body").hasClass("hifiberry-os")) {
							menuOptions.icon = extensions["product-information"].assetPath+"/symbols-black/hifiberry.svg"
						} else {
							menuOptions.icon = extensions["product-information"].assetPath+"/symbols-black/create.svg"
						}

						$("#earlier-updates-container").append(beo.createMenuItem(menuOptions));
					}
				}
			}
		}
	}

	if (data.header == "badge") {
		if (data.content && data.content.badge) {
			$(".software-update-badge").text("1").addClass("badge");
		} else {
			$(".software-update-badge").text("").removeClass("badge");
		}
	}

	if (data.header == "autoUpdateMode") {
		if (data.content.mode != undefined) {
			$(".auto-update-mode-selector > .menu-item").removeClass("checked");
			updateMode = null;
			switch (data.content.mode) {
				case "critical":
					$("#auto-update-critical").addClass("checked");
					updateMode = "Critical only";
					break;
				case "stable":
					$("#auto-update-stable").addClass("checked");
					updateMode = "Regular";
					break;
				case "latest":
					$("#auto-update-latest").addClass("checked");
					updateMode = "Quick";
					break;
				case "experimental":
					updateMode = "Pre-release";
					break;
				case false:
					updateMode = "Off";
					break;
			}
			if (updateMode) {
				$(".auto-update-mode").text(updateMode);
			}
			if (data.content.showExperimental) {
				$("#show-experimental-updates").removeClass("hidden");
			} else {
				$("#show-experimental-updates").addClass("hidden");
			}
		}
	}

	if (data.header == "updateAvailable" && data.content.version) {
		$(".checking-for-update").addClass("hidden");
		newVersion = data.content.version;
		menuOptions = {
			value: newVersion,
			static: true
		}
		if ($("body").hasClass("hifiberry-os")) {
			menuOptions.label = "HiFiBerryOS";
			menuOptions.icon = extensions["product-information"].assetPath+"/symbols-black/hifiberry.svg"
		} else {
			menuOptions.label = "Beocreate 2";
			menuOptions.icon = extensions["product-information"].assetPath+"/symbols-black/create.svg"
		}

		$(".no-update-available").addClass("hidden");
		$(".software-update-available").removeClass("hidden");
		$(".update-check-error").addClass("hidden");
		$("#update-available-container").empty();
		$("#update-available-container").append(beo.createMenuItem(menuOptions));

		$("#update-release-notes").empty();

	}

	if (data.header == "upToDate") {
		$(".checking-for-update").addClass("hidden");
		$(".no-update-available").removeClass("hidden");
		$(".software-update-available").addClass("hidden");
		$(".update-check-error").addClass("hidden");
		newVersion = null;
	}

	if (data.header == "errorChecking") {
		$(".checking-for-update").addClass("hidden");
		$(".no-update-available").addClass("hidden");
		$(".software-update-available").addClass("hidden");
		$(".update-check-error").removeClass("hidden");
		newVersion = null;
	}

	if (data.header == "updating") {
		notifyOptions = {title: "Updating product...", timeout: false, icon: "attention"};
		if (data.content.progress != undefined) {
			notifyOptions.progress = data.content.progress;
		}
		switch (data.content.phase) {
			case "download":
				notifyOptions.message = "Downloading...";
				break;
			case "extractingFirmware":
			case "resizing":
			case "extractingKernel":
				notifyOptions.message = "Unpacking, this will take some time...";
				break;
			case "copyingFiles":
				notifyOptions.message = "Moving things over...";
				break;
			case "finalising":
				notifyOptions.message = "Finalising...";
				break;
			case "done":
				notifyOptions.title = "Product updated";
				notifyOptions.message = "The product has been updated and it will now restart to finish the process. This may take some time, please wait.";
				beo.sendToProductView({header: "autoReconnect", content: {status: "updateComplete", systemID: product_information.systemID(), systemName: product_information.systemName()}});
				noConnectionNotifications = true;
				maxConnectionAttempts = 60;
				reloadOnReconnect = true;
				break;
			case "doneSimulation":
				notifyOptions.title = "Product updated";
				notifyOptions.message = "The product update simulation has finished. The product would now restart, in case of a real update. Start Beocreate 2 in non-developer mode to update.";
				notifyOptions.buttonTitle = "Done";
				notifyOptions.buttonAction = "close";
				notifyOptions.icon = null;
				break;
		}
		beo.notify(notifyOptions, "software-update");
	}

	if (data.header == "updateError") {
		notifyOptions = {title: "Update unsuccessful", timeout: false, buttonTitle: "Dismiss", buttonAction: "close"};
		if (data.content.reason) {
			switch (data.content.reason) {
				case "downloadError":
					notifyOptions.message = "The update could not be downloaded. Please try again later, or contact support if the problem persists.";
					break;
			}
		}
		beo.notify(notifyOptions, "software-update");
	}

	if (data.header == "previousVersion") {
		if (!data.content.previousVersion) {
			$("#previous-version-information").text("Not available");
			$("#restore-previous-version-button").addClass("disabled");
		} else if (data.content.previousVersion == true) {
			$("#previous-version-information").text("Available");
			$("#restore-previous-version-button").removeClass("disabled");
		} else {
			$("#previous-version-information").text(data.content.previousVersion);
			$("#restore-previous-version-button").removeClass("disabled");
		}
	}

	if (data.header == "restoringPreviousVersion") {
		if (data.content.stage == "start") {
			noConnectionNotifications = true;
			maxConnectionAttempts = 30;
			reloadOnReconnect = true;
			beo.notify({title: "Restoring previous version...", message: "The product will restart with the previous software version and settings. If the product name or network settings have changed, you may need to reconnect to the product manually.", timeout: false, icon: "attention"}, "software-update");
		}
		if (data.content.stage == "fail") {
			noConnectionNotifications = false;
			maxConnectionAttempts = 5;
			reloadOnReconnect = false;
			notifyOptions = {title: "Restore unsuccesful", timeout: false, buttonTitle: "Dismiss", buttonAction: "close"};
			if (data.content.reason == "notFound") notifyOptions.message = "Previous version was not found.";
			if (data.content.reason == "unknownPartition") notifyOptions.message = "Unknown backup partition.";
			beo.notify(notifyOptions, "software-update");
		}
	}
});

function generateMarkupForUpdate(track) {
	if (versions[track] && versions[track].releaseNotes) {
		releaseNotes = versions[track].releaseNotes.split("\n");
		openUL = "";
		notesHTML = ""
		for (var i = 0; i < releaseNotes.length; i++) {
			if (!(i == 0 && releaseNotes[i].trim() == versions[track].version)) {
				if (releaseNotes[i].trim().charAt(0) == "-") {
					// A dash is a list item.
					if (!openUL) {
						openUL += "\n
";
					}
					openUL += "\n
"+releaseNotes[i].trim().substring(2)+"
";
					//console.log(openUL);
				} else {
					// Normal lines make p elements.
					if (openUL) {
						openUL += "\n
";
						notesHTML += openUL;
						openUL = "";
					}
					notesHTML += "
"+releaseNotes[i].trim()+"
";
				}
			}
		}
		if (openUL) {
			openUL += "\n
";
			notesHTML += openUL;
		}
		return notesHTML
	} else {
		return "
No release notes included.
";
	}
}

function getTrackName(track) {
	switch (track) {
		case "critical":
			return "Critical Release";
			break;
		case "stable":
			return "Regular Release";
			break;
		case "latest":
			return "Latest Release";
			break;
		case "experimental":
			return "Pre-Release";
			break;
	}
}

function showEarlierUpdate(track) {
	if (versions[track].version) {
		$("#earlier-release-notes").html(generateMarkupForUpdate(track));
		if (track == "experimental") {
			$("#earlier-pre-release-warning").removeClass("hidden");
		} else {
			$("#earlier-pre-release-warning").addClass("hidden");
		}
		beo.ask("earlier-update-info-prompt", [getTrackName(track)], [function() {
			install(track);
		}]);
	}
}

function install(track = mostRecentTrack) {
	beo.sendToProduct("software-update", "install", {track: mostRecentTrack});
}

function setAutoUpdate(mode) {
	beo.ask();
	beo.sendToProduct("software-update", {header: "autoUpdateMode", content: {mode: mode}});
}

function setManualUpdateMode(mode) {
	beo.sendToProduct("software-update", {header: "manualUpdateMode", content: {mode: mode}});
}

function restore(confirmed) {
	if (!confirmed) {
		beo.ask("restore-previous-version-prompt");
	} else {
		beo.ask();
		beo.sendToProduct("software-update", {header: "restorePreviousVersion"});
	}
}

return {
	install: install,
	setAutoUpdate: setAutoUpdate,
	setManualUpdateMode: setManualUpdateMode,
	restore: restore,
	showEarlierUpdate: showEarlierUpdate
};

})();<|endoftext|>


<commit_before>/**
 * Created by Matthew on 10/21/15.
 */

//Get canvas's element.  Used for drawing the grids and whatnot
map = document.getElementById("map");
var ctx = map.getContext("2d");

mapContainer = document.getElementById("mapContainer");

//length of edge, or radius from center to vertex.
var hexRadius = 30;

//viewport variables.  Default to geographic 0,0 being middle of screen.
var viewX = 0 - map.width/2;
var viewY = 0 - map.height/2;

//movement speed, pixels per frame that the viewport moves when you press the movement buttons.
var moveSpeed = 3;

//When moving (between mousedown and mouseup) store movement vector in these two variables.
var currentViewMovementX = 0;
var currentViewMovementY = 0;

/**
 * Draws a hexagon centered at the given x/y coordinates.
 * @param ctx
 * @param x
 * @param y
 */
function drawHex(ctx, x, y) {
    var a = (Math.PI * 2)/6;
    ctx.beginPath();
    ctx.translate(x - viewX,y - viewY); //offset by the viewport here
    ctx.rotate(0);
    ctx.moveTo(hexRadius,0);
    for (var i = 1; i < 6; i++) {
        ctx.lineTo(hexRadius*Math.cos(a * i), hexRadius*Math.sin(a * i));
    }
    ctx.closePath();
    ctx.fillStyle = "#B8E68A";
    ctx.strokeStyle = "#000000";
    ctx.stroke();
    ctx.fill();
    //Undo translation.  Is this the way I want to do it though?  It's a little dirty...
    ctx.translate(0 - (x - viewX), 0 - (y - viewY)); //reset the context back to the original position.
}

/**
 * Takes in cubic coordinates.  Converts them to cartesian, then draws a hexagon there.
 * @param x
 * @param y
 * @param z
 */
function drawHexFromCubic(x,y,z) {
    var coords = getCartFromCubic(x,y,z);
    drawHex(ctx, coords.x, coords.y);
}

/**
 * Takes in cubic coordinates, verifies they are reasonable, and returns a cartesian coordinate pair.
 * Coordinates centered around (0,0,0)/(0,0) point.
 * @param x
 * @param y
 * @param z
 * @returns {{x: number, y: number}}
 */
function getCartFromCubic(x,y,z) {
    if(x + y + z != 0) {
        console.log("Error:  your cubic coordinates don't add up.");
    }
    var cartX = x * 1.5 * hexRadius;
    var cartY = Math.sqrt(3) * ((x/2) + z) * hexRadius;
    return {x: cartX, y: cartY}; //object with .x and .y coordinates
}

//Setup event listeners for the movement buttons
document.getElementById("westButton").addEventListener("mousedown", moveViewWest);
document.getElementById("eastButton").addEventListener("mousedown", moveViewEast);
document.getElementById("northButton").addEventListener("mousedown", moveViewNorth);
document.getElementById("southButton").addEventListener("mousedown", moveViewSouth);

//Add movement termination event, on mouse up
window.addEventListener("mouseup", stopViewMovement);

//Setup the actual functions for how movement works
function moveViewWest() {currentViewMovementX = 0 - moveSpeed;}
function moveViewEast() {currentViewMovementX = moveSpeed;}
function moveViewNorth() {currentViewMovementY = 0 - moveSpeed;}
function moveViewSouth() {currentViewMovementY = moveSpeed;}

/**
 * Stops all movement of the view.  Used when mouseup is detected.
 */
function stopViewMovement() {
    currentViewMovementX = 0;
    currentViewMovementY = 0;
}

/**
 * If there is a nonzero movement vector, apply it to the viewport.  Run this function every frame.
 */
function updateMovement() {
    viewX += currentViewMovementX;
    viewY += currentViewMovementY;
}

/**
 * update holds all the "every frame do this" things for now.  Later might separate these into
 * many functions, but for now it will hold every update function and thing to do every frame
 */
function update() {
    ctx.clearRect(0,0,map.width,map.height);
    drawSampleHexes(); //DEBUG
    updateMovement();
    scaleCanvasToContainer();
}

function scaleCanvasToContainer() {
    if(map.width != mapContainer.clientWidth || map.height != mapContainer.clientHeight) {
        console.log("mw=" + map.width +" mh=" + map.height +
            " mcw=" + mapContainer.clientWidth + " mch=" + mapContainer.clientHeight);
        map.width = mapContainer.clientWidth;
        map.height = mapContainer.clientHeight;
        //recenter viewport.  TODO:  Make it not snap back to center after resizing
        viewX = 0 - map.width/2;
        viewY = 0 - map.height/2;
    }
}

/**
 * DEBUG:  Draws a bunch of various hexagons around the map.
 */
function drawSampleHexes() {
    drawHexFromCubic(0,0,0);
    drawHexFromCubic(1,0,-1);
    drawHexFromCubic(6,-4,-2);
    drawHexFromCubic(-1,-2,3);
    drawHexFromCubic(2,-2,0);
    drawHexFromCubic(1,4,-5);
}

//Set regular screen updates via updateDisplay()
setInterval(update, 1000/60);

/*
 Resources I've been using for stuff.  Will probably come in handy later.

 y = 3/2 * s * b
 b = 2/3 * y / s
 x = sqrt(3) * s * ( b/2 + r)
 x = - sqrt(3) * s * ( b/2 + g )
 r = (sqrt(3)/3 * x - y/3 ) / s
 g = -(sqrt(3)/3 * x + y/3 ) / s

 r + b + g = 0

 http://i.imgur.com/AJoDm.gif
 http://www.redblobgames.com/grids/hexagons/

 Current stackoverflow thread for full tesselation:
 http://stackoverflow.com/questions/33271449/tessellating-hexagons-over-a-rectangle
 */<commit_msg>removed view resetting when resizing canvas<commit_after>/**
 * Created by Matthew on 10/21/15.
 */

//Get canvas's element.  Used for drawing the grids and whatnot
map = document.getElementById("map");
var ctx = map.getContext("2d");

mapContainer = document.getElementById("mapContainer");

//length of edge, or radius from center to vertex.
var hexRadius = 30;

//viewport variables.  Default to geographic 0,0 being middle of screen.
var viewX = 0 - map.width/2;
var viewY = 0 - map.height/2;

//movement speed, pixels per frame that the viewport moves when you press the movement buttons.
var moveSpeed = 3;

//When moving (between mousedown and mouseup) store movement vector in these two variables.
var currentViewMovementX = 0;
var currentViewMovementY = 0;

/**
 * Draws a hexagon centered at the given x/y coordinates.
 * @param ctx
 * @param x
 * @param y
 */
function drawHex(ctx, x, y) {
    var a = (Math.PI * 2)/6;
    ctx.beginPath();
    ctx.translate(x - viewX,y - viewY); //offset by the viewport here
    ctx.rotate(0);
    ctx.moveTo(hexRadius,0);
    for (var i = 1; i < 6; i++) {
        ctx.lineTo(hexRadius*Math.cos(a * i), hexRadius*Math.sin(a * i));
    }
    ctx.closePath();
    ctx.fillStyle = "#B8E68A";
    ctx.strokeStyle = "#000000";
    ctx.stroke();
    ctx.fill();
    //Undo translation.  Is this the way I want to do it though?  It's a little dirty...
    ctx.translate(0 - (x - viewX), 0 - (y - viewY)); //reset the context back to the original position.
}

/**
 * Takes in cubic coordinates.  Converts them to cartesian, then draws a hexagon there.
 * @param x
 * @param y
 * @param z
 */
function drawHexFromCubic(x,y,z) {
    var coords = getCartFromCubic(x,y,z);
    drawHex(ctx, coords.x, coords.y);
}

/**
 * Takes in cubic coordinates, verifies they are reasonable, and returns a cartesian coordinate pair.
 * Coordinates centered around (0,0,0)/(0,0) point.
 * @param x
 * @param y
 * @param z
 * @returns {{x: number, y: number}}
 */
function getCartFromCubic(x,y,z) {
    if(x + y + z != 0) {
        console.log("Error:  your cubic coordinates don't add up.");
    }
    var cartX = x * 1.5 * hexRadius;
    var cartY = Math.sqrt(3) * ((x/2) + z) * hexRadius;
    return {x: cartX, y: cartY}; //object with .x and .y coordinates
}

//Setup event listeners for the movement buttons
document.getElementById("westButton").addEventListener("mousedown", moveViewWest);
document.getElementById("eastButton").addEventListener("mousedown", moveViewEast);
document.getElementById("northButton").addEventListener("mousedown", moveViewNorth);
document.getElementById("southButton").addEventListener("mousedown", moveViewSouth);

//Add movement termination event, on mouse up
window.addEventListener("mouseup", stopViewMovement);

//Setup the actual functions for how movement works
function moveViewWest() {currentViewMovementX = 0 - moveSpeed;}
function moveViewEast() {currentViewMovementX = moveSpeed;}
function moveViewNorth() {currentViewMovementY = 0 - moveSpeed;}
function moveViewSouth() {currentViewMovementY = moveSpeed;}

/**
 * Stops all movement of the view.  Used when mouseup is detected.
 */
function stopViewMovement() {
    currentViewMovementX = 0;
    currentViewMovementY = 0;
}

/**
 * If there is a nonzero movement vector, apply it to the viewport.  Run this function every frame.
 */
function updateMovement() {
    viewX += currentViewMovementX;
    viewY += currentViewMovementY;
}

/**
 * update holds all the "every frame do this" things for now.  Later might separate these into
 * many functions, but for now it will hold every update function and thing to do every frame
 */
function update() {
    ctx.clearRect(0,0,map.width,map.height);
    drawSampleHexes(); //DEBUG
    updateMovement();
    scaleCanvasToContainer();
}

function scaleCanvasToContainer() {
    if(map.width != mapContainer.clientWidth || map.height != mapContainer.clientHeight) {
        console.log("mw=" + map.width +" mh=" + map.height +
            " mcw=" + mapContainer.clientWidth + " mch=" + mapContainer.clientHeight);
        map.width = mapContainer.clientWidth;
        map.height = mapContainer.clientHeight;
        //Don't need to do anything to viewport coordinates, it works out on its own somehow.
    }
}

/**
 * DEBUG:  Draws a bunch of various hexagons around the map.
 */
function drawSampleHexes() {
    drawHexFromCubic(0,0,0);
    drawHexFromCubic(1,0,-1);
    drawHexFromCubic(6,-4,-2);
    drawHexFromCubic(-1,-2,3);
    drawHexFromCubic(2,-2,0);
    drawHexFromCubic(1,4,-5);
}

//Set regular screen updates via updateDisplay()
setInterval(update, 1000/60);

/*
 Resources I've been using for stuff.  Will probably come in handy later.

 y = 3/2 * s * b
 b = 2/3 * y / s
 x = sqrt(3) * s * ( b/2 + r)
 x = - sqrt(3) * s * ( b/2 + g )
 r = (sqrt(3)/3 * x - y/3 ) / s
 g = -(sqrt(3)/3 * x + y/3 ) / s

 r + b + g = 0

 http://i.imgur.com/AJoDm.gif
 http://www.redblobgames.com/grids/hexagons/

 Current stackoverflow thread for full tesselation:
 http://stackoverflow.com/questions/33271449/tessellating-hexagons-over-a-rectangle
 */<|endoftext|>


<commit_before>define(function() {

	// Renderer for white keys.
	var WhiteKeyRenderer = function(config) {
		this.key = config.key;
		this.width = (config.keyboardWidth / config.numWhiteKeys);
		this.height = config.keyboardHeight;
	};
	_.extend(WhiteKeyRenderer.prototype, {
		isWhite: true,
		offsetX: function(whiteKeyIndex) {
			return (whiteKeyIndex * this.width);
		},
		render: function(paper, whiteKeyIndex) {
			var el = paper.rect(this.offsetX(whiteKeyIndex), 0, this.width, this.height);
			el.attr({'stroke': '#000', 'fill': '#fff'});
			el.toBack();
			el.mouseup(function() {
				this.attr('fill', '#fff');
			});
			this.el = el;
			return this;
		}
	});

	// Renderer for black keys.
	var BlackKeyRenderer = function(config) {
		this.key = config.key;
		this.offsetWidth = (config.keyboardWidth / config.numWhiteKeys);
		this.width = (config.keyboardWidth / config.numWhiteKeys) / 2;
		this.height = 0.75 * config.keyboardHeight;
	};
	_.extend(BlackKeyRenderer.prototype, {
		isWhite: false,
		offsetX: function(whiteKeyIndex) {
			return (whiteKeyIndex * this.offsetWidth) - (this.width / 2);
		},
		render: function(paper, whiteKeyIndex) {
			var el = paper.rect(this.offsetX(whiteKeyIndex), 0, this.width, this.height);
			el.attr('fill', '90-#333-#000');
			el.toFront();
			el.mouseup(function() {
				this.attr('fill', '90-#333-#000');
			});
			this.el = el;
			return this;
		}
	});

	// Factory to create white or black key renderers.
	var KeyRenderer = function() {};
	KeyRenderer.create = function(config) {
		if(config.isWhite) {
			return new WhiteKeyRenderer(config);
		}
		return new BlackKeyRenderer(config);
	};

	return KeyRenderer;
});
<commit_msg>fixed missing dep<commit_after>define(['lodash'], function(_) {

	// Renderer for white keys.
	var WhiteKeyRenderer = function(config) {
		this.key = config.key;
		this.width = (config.keyboardWidth / config.numWhiteKeys);
		this.height = config.keyboardHeight;
	};
	_.extend(WhiteKeyRenderer.prototype, {
		isWhite: true,
		offsetX: function(whiteKeyIndex) {
			return (whiteKeyIndex * this.width);
		},
		render: function(paper, whiteKeyIndex) {
			var el = paper.rect(this.offsetX(whiteKeyIndex), 0, this.width, this.height);
			el.attr({'stroke': '#000', 'fill': '#fff'});
			el.toBack();
			el.mouseup(function() {
				this.attr('fill', '#fff');
			});
			this.el = el;
			return this;
		}
	});

	// Renderer for black keys.
	var BlackKeyRenderer = function(config) {
		this.key = config.key;
		this.offsetWidth = (config.keyboardWidth / config.numWhiteKeys);
		this.width = (config.keyboardWidth / config.numWhiteKeys) / 2;
		this.height = 0.75 * config.keyboardHeight;
	};
	_.extend(BlackKeyRenderer.prototype, {
		isWhite: false,
		offsetX: function(whiteKeyIndex) {
			return (whiteKeyIndex * this.offsetWidth) - (this.width / 2);
		},
		render: function(paper, whiteKeyIndex) {
			var el = paper.rect(this.offsetX(whiteKeyIndex), 0, this.width, this.height);
			el.attr('fill', '90-#333-#000');
			el.toFront();
			el.mouseup(function() {
				this.attr('fill', '90-#333-#000');
			});
			this.el = el;
			return this;
		}
	});

	// Factory to create white or black key renderers.
	var KeyRenderer = function() {};
	KeyRenderer.create = function(config) {
		if(config.isWhite) {
			return new WhiteKeyRenderer(config);
		}
		return new BlackKeyRenderer(config);
	};

	return KeyRenderer;
});
<|endoftext|>


<commit_before>$(function() {

	var slides = $( 'section.slide' );

	function fullScreen() {
		return (
			window.screenX == 0 &&
			window.screenY == 0 &&
			screen.width == window.outerWidth &&
			screen.height == window.outerHeight
		) ? true : false;
	}

	function turnSlide( e ) {
		if( !fullScreen() ) return;
		var current = $( document.location.hash );
		switch ( e.which ) {
			case 33 : // PgUp
			case 38 : // Up
			case 37 : // Left
				var target = current.prev( slides );
				break;
			case 34 : // PgDown
			case 40 : // Down
			case 39 : // Right
				var target = current.next( slides );
				break;
			case 32 : // Space
				var target = current[e.shiftKey ? "prev" : "next"]( slides );
				break;
			default:
				return;
		}
		e.preventDefault();
		if( !target.length ) return;
		else document.location.hash = '#' + target.attr( 'id' );
	}

	function updateView() {
		var screen = $( 'link[title=screen]' ),
			projection = $( 'link[title=projection]' ),
			fullscreen = fullScreen();
		screen.attr( 'disabled', fullscreen );
		projection.attr( 'disabled', !fullscreen );
		if( !fullscreen || $( document.location.hash ).length ) return;
		else document.location.hash = '#' + slides.first().attr( 'id' );
	}

	$( document ).
		keyup( turnSlide );

	$( window ).
		ready( updateView ).
		resize( updateView );

});<commit_msg>Delete trailing spaces.<commit_after>$(function() {

	var slides = $( 'section.slide' );

	function fullScreen() {
		return (
			window.screenX == 0 &&
			window.screenY == 0 &&
			screen.width == window.outerWidth &&
			screen.height == window.outerHeight
		) ? true : false;
	}

	function turnSlide( e ) {
		if( !fullScreen() ) return;
		var current = $( document.location.hash );
		switch ( e.which ) {
			case 33 : // PgUp
			case 38 : // Up
			case 37 : // Left
				var target = current.prev( slides );
				break;
			case 34 : // PgDown
			case 40 : // Down
			case 39 : // Right
				var target = current.next( slides );
				break;
			case 32 : // Space
				var target = current[e.shiftKey ? "prev" : "next"]( slides );
				break;
			default:
				return;
		}
		e.preventDefault();
		if( !target.length ) return;
		else document.location.hash = '#' + target.attr( 'id' );
	}

	function updateView() {
		var screen = $( 'link[title=screen]' ),
			projection = $( 'link[title=projection]' ),
			fullscreen = fullScreen();
		screen.attr( 'disabled', fullscreen );
		projection.attr( 'disabled', !fullscreen );
		if( !fullscreen || $( document.location.hash ).length ) return;
		else document.location.hash = '#' + slides.first().attr( 'id' );
	}

	$( document ).
		keyup( turnSlide );

	$( window ).
		ready( updateView ).
		resize( updateView );

});<|endoftext|>


<commit_before>const http = require('http');
const fs = require('fs');
const nearestColor = require('../node_modules/nearest-color/nearestColor.js');
const colors = JSON.parse(
  fs.readFileSync(__dirname + '/../dist/colornames.json', 'utf8')
);
const port = process.env.PORT || 8080;
const baseUrl = 'v1/';

let colorsObj = {};

colors.forEach((c) => {
  colorsObj[c.name] = c.hex;
});

const nc = nearestColor.from(colorsObj);
/**
 * validates a hex color
 * @param   {string} color hex representation of color
 * @return {boolen}
 */
function validateColor(color) {
  return /(^[0-9A-F]{6}$)|(^[0-9A-F]{3}$)/i.test(color);
}
/**
 * names an array of colors
 * @param   {array} colorArr array containing hex values without the hash
 * @return  {object}         object containing all nearest colors
 */
function nameColors(colorArr) {
  let colors = {};
  colorArr.forEach((hex) => {
    const closestColor = nc('#' + hex);
    colors['#' + hex] = {
      name: closestColor.name,
      hex: closestColor.value,
      rgb: closestColor.rgb,
      isExactMatch: closestColor.value.substr(1) === hex,
    };
  });
  return colors;
}

http.createServer((req, res) => {
  const isAPI = req.url.indexOf(baseUrl) !== -1;
  let status = 200;
  let colorQuery = req.url.toLowerCase();
      colorQuery = colorQuery.split(baseUrl)[1] || '';

  const urlColorList = colorQuery.split(',');
  const response = {status: '', colors: {}};

  if (!urlColorList.length) {
    response.status = 'no colors provided';
    status = 400;
  }

  if (!isAPI && status == 200) {
    response.status = 'invalid URL: make sure to provide the API version';
    status = 400;
  }

  const invalidColors = urlColorList.filter((hex) => {
    return !validateColor(hex);
  });

  if (status == 200 && invalidColors.length) {
    response.status = `'${invalidColors.join(',')}' are not valid HEX color values`;
    status = 400;
  } else if (status == 200) {
    response.status = `names for '${urlColorList.join(',')}' returned`;
    response.colors = nameColors(urlColorList);
  }

  res.writeHead(status, {
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'POST, GET, PUT, DELETE, OPTIONS',
    'Access-Control-Allow-Credentials': false,
    'Access-Control-Max-Age': '86400',
    'Access-Control-Allow-Headers': 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept',
    'Content-Type': 'application/json',
  });

  res.write(JSON.stringify(response));
  res.end();
}).listen(port, '0.0.0.0');

console.log(`Server running and listening on port ${port}`);
<commit_msg>ci($server): API can now return the full list of colors<commit_after>const http = require('http');
const fs = require('fs');
const nearestColor = require('../node_modules/nearest-color/nearestColor.js');
const colors = JSON.parse(
  fs.readFileSync(__dirname + '/../dist/colornames.json', 'utf8')
);
const port = process.env.PORT || 8080;
const baseUrl = 'v1/';

/**
 * disassembles a HEX color to its RGB components
 * @param   {string} hex hex color representatin
 * @return  {object}     {r,g,b}
 */
const hexToRgb = (hex) => {
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result ? {
      r: parseInt(result[1], 16),
      g: parseInt(result[2], 16),
      b: parseInt(result[3], 16),
  } : null;
};

// object containing the name:hex pairs for nearestColor()
const colorsObj = {};

colors.forEach((c) => {
  // populates object needed for nearestColor()
  colorsObj[c.name] = c.hex;
  // transform hex to RGB
  c.rgb = hexToRgb(c.hex);
});

const nc = nearestColor.from(colorsObj);
/**
 * validates a hex color
 * @param   {string} color hex representation of color
 * @return {boolen}
 */
const validateColor = (color) => (
  /(^[0-9A-F]{6}$)|(^[0-9A-F]{3}$)/i.test(color)
);

/**
 * names an array of colors
 * @param   {array} colorArr array containing hex values without the hash
 * @return  {object}         object containing all nearest colors
 */
const nameColors = (colorArr) => {
  let colors = {};
  colorArr.forEach((hex) => {
    const closestColor = nc('#' + hex);
    colors['#' + hex] = {
      name: closestColor.name,
      hex: closestColor.value,
      rgb: closestColor.rgb,
      isExactMatch: closestColor.value.substr(1) === hex,
    };
  });
  return colors;
};

const httpRespond = (response, responseObj = {}, statusCode = 200) => {
  response.writeHead(statusCode, {
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'POST, GET, PUT, DELETE, OPTIONS',
    'Access-Control-Allow-Credentials': false,
    'Access-Control-Max-Age': '86400',
    'Access-Control-Allow-Headers': 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept',
    'Content-Type': 'application/json',
  });

  // ends the response with the API answer
  response.end(JSON.stringify(responseObj));
};

const requestHandler = (request, response) => {
  const isAPI = request.url.indexOf(baseUrl) !== -1;
  let statusCode = 400;
  let colorQuery = request.url.toLowerCase();
      colorQuery = colorQuery.split(baseUrl)[1] || '';

  const urlColorList = colorQuery.split(',');
  const responseObj = {status: 'Someting went wrong', colors: {}};
  const invalidColors = urlColorList.filter((hex) => {
    !validateColor(hex) && hex;
  });

  if (!isAPI) {
    responseObj.status = 'invalid URL: make sure to provide the API version';
    statusCode = 400;
  } else if (!urlColorList[0]) {
    responseObj.status = 'no color(s) provided, returning all the colors';
    responseObj.colors = colors;
    statusCode = 200;
  } else if (invalidColors.length) {
    responseObj.status = `'${invalidColors.join(', ')}' is not a valid HEX color`;
    statusCode = 400;
  } else {
    responseObj.status = `names for '${urlColorList.join(',')}' returned`;
    responseObj.colors = nameColors(urlColorList);
    statusCode = 200;
  }

  httpRespond(response, responseObj, statusCode);
};

const server = http.createServer(requestHandler);
server.listen(port, '0.0.0.0', (error) => {
  if (error) {
    return console.log(`something terrible happened: ${error}`);
  }
  console.log(`Server running and listening on port ${port}`);
  console.log(`http://localhost:${port}`);
});

<|endoftext|>


<commit_before>let height = 4;
let space = height;
let rightPart = '';
const SYMBOL = '#';
const SEPARATOR = '  ';

console.log('Height : ' + height);
for (let i = 0; i < height; i++) {
    rightPart += SYMBOL;
    let leftPart = '';
    for (let k = space; k > 0; k--) {
        leftPart += ' ';
    }
    space--;
    console.log(leftPart + rightPart + SEPARATOR + rightPart);
}

<commit_msg>fix unwanted space<commit_after>let height = 4;
let space = height;
let rightPart = '';
const SYMBOL = '#';
const SEPARATOR = '  ';

console.log('Height : ' + height);
for (let i = 0; i < height; i++) {
    rightPart += SYMBOL;
    let leftPart = '';
    for (let k = space; k > 1; k--) {
        leftPart += ' ';
    }
    space--;
    console.log(leftPart + rightPart + SEPARATOR + rightPart);
}

<|endoftext|>


<commit_before>'use strict';

var number = Math.floor(Math.random() * 22) + 1;
var timer1 = 0;
var timer2 = 0;

function setSlide(noSlide) {
    clearTimeout(timer1);
    clearTimeout(timer2);
    number = noSlide - 1;
    hide();
    setTimeout("changeSlide()", 500);
}

function hide() {
    $("#slider").fadeOut(500);
}

function changeSlide() {
    number++; if (number > 22) number = 1;
    var file =`<img src="../images/slides/slide${number}.jpg"/>` ;
    document.getElementById("slider").innerHTML = file;
    $("#slider").fadeIn(500);
    timer1 = setTimeout("changeSlide()", 5000);
    timer2 = setTimeout("hide()", 4500);
}<commit_msg>use camelCase #23<commit_after>'use strict';

var number = Math.floor(Math.random() * 22) + 1;
var timer1 = 0;
var timer2 = 0;

function setSlide(noSlide) {
    clearTimeOut(timer1);
    clearTimeOut(timer2);
    number = noSlide - 1;
    hide();
    setTimeOut("changeSlide()", 500);
}

function hide() {
    $("#slider").fadeOut(500);
}

function changeSlide() {
    number++; if (number > 22) number = 1;
    var file =`<img src="../images/slides/slide${number}.jpg"/>` ;
    document.getElementById("slider").innerHTML = file;
    $("#slider").fadeIn(500);
    timer1 = setTimeOut("changeSlide()", 5000);
    timer2 = setTimeOut("hide()", 4500);
}<|endoftext|>


<commit_before>/**
 * Smoothly scrolls to an element while accounting for potential sticky headers.
 *
 * @author	Alexander Ebert
 * @copyright	2001-2017 WoltLab GmbH
 * @license	GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @module	WoltLabSuite/Core/Ui/Scroll
 */
define(['Dom/Util'], function(DomUtil) {
	"use strict";

	var _callback = null;
	var _callbackScroll = null;
	var _timeoutScroll = null;

	/**
	 * @exports     WoltLabSuite/Core/Ui/Scroll
	 */
	return {
		/**
		 * Scrolls to target element, optionally invoking the provided callback once scrolling has ended.
		 *
		 * @param       {Element}       element         target element
		 * @param       {function=}     callback        callback invoked once scrolling has ended
		 */
		element: function(element, callback) {
			if (!(element instanceof Element)) {
				throw new TypeError("Expected a valid DOM element.");
			}
			else if (callback !== undefined && typeof callback !== 'function') {
				throw new TypeError("Expected a valid callback function.");
			}
			else if (!document.body.contains(element)) {
				throw new Error("Element must be part of the visible DOM.");
			}
			else if (_callback !== null) {
				throw new Error("Cannot scroll to element, a concurrent request is running.");
			}

			if (callback) {
				_callback = callback;

				if (_callbackScroll === null) {
					_callbackScroll = this._onScroll.bind(this);
				}

				window.addEventListener('scroll', _callbackScroll);
			}

			var y = DomUtil.offset(element).top;

			if (y <= 50) {
				y = 0;
			}
			else {
				// add an offset of 50 pixel to account for a sticky header
				y -= 50;
			}

			var offset = window.pageYOffset;

			window.scrollTo({
				left: 0,
				top: y,
				behavior: 'smooth'
			});

			window.setTimeout((function () {
				// no scrolling took place
				if (offset === window.pageYOffset) {
					this._onScroll();
				}
			}).bind(this), 100);
		},

		/**
		 * Monitors scroll event to only execute the callback once scrolling has ended.
		 *
		 * @protected
		 */
		_onScroll: function() {
			if (_timeoutScroll !== null) window.clearTimeout(_timeoutScroll);

			_timeoutScroll = window.setTimeout(function() {
				_callback();

				window.removeEventListener('scroll', _callbackScroll);
				_callback = null;
				_timeoutScroll = null;
			}, 100);
		}
	};
});
<commit_msg>Added missing check for callback if page never scrolled<commit_after>/**
 * Smoothly scrolls to an element while accounting for potential sticky headers.
 *
 * @author	Alexander Ebert
 * @copyright	2001-2017 WoltLab GmbH
 * @license	GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @module	WoltLabSuite/Core/Ui/Scroll
 */
define(['Dom/Util'], function(DomUtil) {
	"use strict";

	var _callback = null;
	var _callbackScroll = null;
	var _timeoutScroll = null;

	/**
	 * @exports     WoltLabSuite/Core/Ui/Scroll
	 */
	return {
		/**
		 * Scrolls to target element, optionally invoking the provided callback once scrolling has ended.
		 *
		 * @param       {Element}       element         target element
		 * @param       {function=}     callback        callback invoked once scrolling has ended
		 */
		element: function(element, callback) {
			if (!(element instanceof Element)) {
				throw new TypeError("Expected a valid DOM element.");
			}
			else if (callback !== undefined && typeof callback !== 'function') {
				throw new TypeError("Expected a valid callback function.");
			}
			else if (!document.body.contains(element)) {
				throw new Error("Element must be part of the visible DOM.");
			}
			else if (_callback !== null) {
				throw new Error("Cannot scroll to element, a concurrent request is running.");
			}

			if (callback) {
				_callback = callback;

				if (_callbackScroll === null) {
					_callbackScroll = this._onScroll.bind(this);
				}

				window.addEventListener('scroll', _callbackScroll);
			}

			var y = DomUtil.offset(element).top;

			if (y <= 50) {
				y = 0;
			}
			else {
				// add an offset of 50 pixel to account for a sticky header
				y -= 50;
			}

			var offset = window.pageYOffset;

			window.scrollTo({
				left: 0,
				top: y,
				behavior: 'smooth'
			});

			window.setTimeout((function () {
				// no scrolling took place
				if (offset === window.pageYOffset) {
					this._onScroll();
				}
			}).bind(this), 100);
		},

		/**
		 * Monitors scroll event to only execute the callback once scrolling has ended.
		 *
		 * @protected
		 */
		_onScroll: function() {
			if (_timeoutScroll !== null) window.clearTimeout(_timeoutScroll);

			_timeoutScroll = window.setTimeout(function() {
				if (_callback !== null) _callback();

				window.removeEventListener('scroll', _callbackScroll);
				_callback = null;
				_timeoutScroll = null;
			}, 100);
		}
	};
});
<|endoftext|>


<commit_before>

var businessProperty = {};

businessProperty.initPropertyHelper = function ()
{
    businessProperty.currentInput = null;

    //if an input or a textarea lose the focus
    $("form").find('input, textarea').focusout(function () {
        //we memorize the input
        businessProperty.currentInput = $(this);
     });
};

//we add the {{ item.XXX }} string to the current input
businessProperty.addPropertyToCurrentInput = function (businessPropertyId)
{
    //get the current input
    var currentInput = businessProperty.currentInput;

    //there was an input
    if (currentInput !== null) {
        //the string to insert
        var insertString = '{{' + 'item.' + businessPropertyId + '}}';
        //we get the current string
        var currentString = currentInput.val();
        //we add the item
        var newString = currentString + insertString;
        //set the new string
        currentInput.val(newString);
    }
};<commit_msg>checkstyle<commit_after>/*global $vic*/

var businessProperty = {};

businessProperty.initPropertyHelper = function ()
{
    "use strict";
    businessProperty.currentInput = null;

    //if an input or a textarea lose the focus
    $vic("form").find('input, textarea').focusout(function () {
        //we memorize the input
        businessProperty.currentInput = $vic(this);
    });
};

//we add the {{ item.XXX }} string to the current input
businessProperty.addPropertyToCurrentInput = function (businessPropertyId)
{
    "use strict";

    //get the current input
    var currentInput = businessProperty.currentInput;

    //there was an input
    if (currentInput !== null) {
        //the string to insert
        var insertString = '{{' + 'item.' + businessPropertyId + '}}';
        //we get the current string
        var currentString = currentInput.val();
        //we add the item
        var newString = currentString + insertString;
        //set the new string
        currentInput.val(newString);
    }
};<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc service
 * @name we99App.restService
 * @description
 * # restService
 * Service in the we99App.
 */
var app = angular.module('we99App');

app.factory('RestService', ['$resource','$http','RestURLs', function ($resource,$http, RestURLs) {
  return {

    //
    // $http style calls.
    //

    //experiments
    getExperiments:  function(){
      return $http.get(RestURLs.experiment);
    },
    getExperimentById:  function(id){
      return $http.get(RestURLs.experiment+'/'+id);
    },
    createExperiment: function(exp){
      if(exp.id)
        return $http.post(RestURLs.experiment+'/'+exp.id,exp);
      else
        return $http.put(RestURLs.experiment,exp);
    },
    publishExperiment: function(expId){
      return $http.post(RestURLs.experiment + '/' + expId + '/publish');
    },
    deleteExperiment: function(id){
      return $http.delete(RestURLs.experiment+'/'+id);
    },
    setExperimentMembers: function(expId,memberIds){
      return $http.post(RestURLs.experiment+'/'+expId+'/members',memberIds);
    },
    getExperimentMembers: function(expId){
      return $http.get(RestURLs.experiment+'/'+expId+'/members');
    },

    // Plates
    getExperimentPlates: function(id){
      return $http.get(RestURLs.experiment + '/' + id + "/plates")
    },
    removeExperimentPlate: function(experimentId, plateId) {
      return $http.delete(RestURLs.experiment + '/' + experimentId  + "/plates/" + plateId);
    },

    // Plate results
    getPlateResults: function(experimentId,plateId){
      return $http.get(RestURLs.experiment+'/'+experimentId+'/plates/'+plateId+'/results');
    },
    getDoseResponseData : function(experimentId){
      return $http.get(RestURLs.experiment+'/'+experimentId+'/doseresponse/results')
    },
    updatePlateResults: function(experimentId, plateId, wellChange){
      return $http.post(RestURLs.experiment+'/'+experimentId+'/plates/'+plateId+'/results/update', wellChange);
    },
    updateDoseResponseResult: function(plateId, doseResponseId, wellChange ){
      return $http.post(RestURLs.experiment+'/'+plateId+'/doseresponse/'+doseResponseId+'/update', wellChange);
    },
    //email filter
    getEmailFilter: function(){
      return $http.get(RestURLs.emailFilter);
    },

    updateEmailFilter: function(filter){
      return $http.post(RestURLs.emailFilter,filter);
    },
    //server settings
    getServerSettings: function(){
      return $http.get(RestURLs.serverSettings);
    },
    updateServerSettings: function(emailConfig){
      return $http.post(RestURLs.serverSettings,emailConfig);
    },

    //users
    getUsers:  function(){
      return $http.get(RestURLs.user);
    },

    //returns currently logged-in User
    getCurrentUser:  function(){
      return $http.get(RestURLs.user+'/me');
    },

    //protocol
    getProtocols:  function(){
      return $http.get(RestURLs.protocol);
    },

    addProtocol:  function(proc){
      return $http.put(RestURLs.protocol,proc);
    },

    //compound
    getCompounds: function(searchFilter,pageSize){
      var config={params:{"pageSize": pageSize, page:0, q: searchFilter}};
      return $http.get(RestURLs.compoundUpload,config);
    }

  };

}]);

app.factory('PlateMergeRestService', ['$http', '$q', '$log', '$upload', 'RestURLs', function($http,$q,$log,$upload,RestURLs){
  return {
    // For Label Table Gets a partially completed platemap merge info object
    getMergeInfoTemplate: function (plateMapId, plateType) {
      return $http.post(replaceId(RestURLs.mergeInfoTemplate, plateMapId), plateType);
    },
    /** Submit to make plate from user parameters and possibly a compound list csv.
     *
     * @param experimentId
     * @param mergeInfoObject label table and some other info
     * @param compoundCsv (optional) the file Obj of the compound List csv
     * @returns {*} a promise object of the connection
     */
    submitMergeInfo: function (experimentId, mergeInfoObject, compoundCsv) {
      if (compoundCsv){
        var upload = $upload.upload({
          url: replaceId(RestURLs.mergeInfoSubmitWithCompound, experimentId),
          method: 'POST',
          file: compoundCsv,
          fields:{merge: mergeInfoObject},
          sendObjectsAsJsonBlob: true
        }).success(function(data){
            $log.info('New plate created');
          }).error(function(err){
            $log.error('Error creating plate:' + JSON.stringify(err));
          });
        return upload;
      } else {
        return $http.put(replaceId(RestURLs.mergeInfoSubmit, experimentId), mergeInfoObject);
      }
    },
    // Make plates from Full Monty Csv.
    submitPlatesWithResults: function (experimentId, plateType, csvFiles) {
      if (!csvFiles || csvFiles.length !== 1) {
        $log.error('No csv file attached');
        return null;
      }
      var pt = angular.toJson(plateType);
      var pto = angular.fromJson(pt);
      var file = csvFiles[0],
        upload = $upload.upload({
          url: RestURLs.experiment + "/" + experimentId + "/fullMonty",
          method: "POST",
          fields: {
            plateType: pto
          },
          formDataAppender: function(fd,k,v) {
            fd.append(k, new Blob([pt], {type: "application/json"}));
          },
          file: file
        }).progress(function (event) {
          var progressPercentage = parseInt(100.0 * event.loaded / event.total);
          $log.info('progress: ' + progressPercentage + '% ' +
          event.config.file.name);
        }).success(function (data, status, headers, config) {
          var result = JSON.stringify(data);
          $log.info('file ' + config.file.name + 'uploaded. Response: ' +
          result);
        }).error(function (data, status, headers, config) {
          var result = JSON.stringify(data);
          $log.error('error in file ' + config.file.name + 'uploaded. Response: ' +
          result);
        });
      return $q.when(upload);
    }
  };

  function replaceId(urlString, id) {
    return urlString.replace(':id', id);
  }
}]);
/** REST linked resource model for Plate Type */
app.factory('PlateTypeModel', ['$resource', 'RestURLs', function ($resource, RestURLs) {
  return $resource(RestURLs.plateType, {id:'@id'}, {
    query: {
      method: "GET",
      isArray: true,
      // Get an array back to exhibit expected query behavior
      transformResponse: valuesToArray
    },
    create: {
      method: "PUT" // Server takes put for creation
    }
  });
}]);

/** REST linked resource model for Plate Maps */
app.factory('PlateMapModel', ['$resource', 'RestURLs', function ($resource, RestURLs) {
  return $resource(RestURLs.plateMapById, {id:'@id'}, {
    listPlateMaps: {
      method: "GET",
      isArray: true,
      // Get an array back to exhibit expected query behavior
      transformResponse: valuesToArray
    },
    create: {
      method: "PUT" // Server takes put for creation
    }
    //// Requires a plateType in the body. remember the '$' before using because its an instance call.
    //getMergeInfo: {
    //  method:"POST",
    //  url: RestURLs.mergeInfoTemplate
    //}
  });
}]);

/** REST linked resource model for Compounds */
app.factory('CompoundModel', ['$resource', 'RestURLs', function($resource, RestURLs){
  var TYPEAHEAD_RESULT_SIZE = 4;
  return $resource(RestURLs.compound, {id: '@id'}, {
    list: {
      isArray:true,
      transformResponse: valuesToArray
    },
    // When using get typeahead, make sure to put in a parameter value for 'q'
    getTypeAhead: {
      // only grab first 4 results
      params: {q:'', pageSize:TYPEAHEAD_RESULT_SIZE},
      cache: true,
      isArray:true,
      transformResponse: valuesToArray
    },
    create: {
      method:"PUT"
    }
  }); // close $resource
}]);

/* HELPER FUNCTIONS */

/** Function to get the array of response values in 'list' style calls.
 *  needed because list style calls are returned as objects with the value information provided along with metadata
 */
function valuesToArray(data) {
  if (data) {
    return JSON.parse(data).values;
  } else {
    return null;
  }
}
<commit_msg>wired 'bulk add with compound list' using marks black magic.<commit_after>'use strict';

/**
 * @ngdoc service
 * @name we99App.restService
 * @description
 * # restService
 * Service in the we99App.
 */
var app = angular.module('we99App');

app.factory('RestService', ['$resource','$http','RestURLs', function ($resource,$http, RestURLs) {
  return {

    //
    // $http style calls.
    //

    //experiments
    getExperiments:  function(){
      return $http.get(RestURLs.experiment);
    },
    getExperimentById:  function(id){
      return $http.get(RestURLs.experiment+'/'+id);
    },
    createExperiment: function(exp){
      if(exp.id)
        return $http.post(RestURLs.experiment+'/'+exp.id,exp);
      else
        return $http.put(RestURLs.experiment,exp);
    },
    publishExperiment: function(expId){
      return $http.post(RestURLs.experiment + '/' + expId + '/publish');
    },
    deleteExperiment: function(id){
      return $http.delete(RestURLs.experiment+'/'+id);
    },
    setExperimentMembers: function(expId,memberIds){
      return $http.post(RestURLs.experiment+'/'+expId+'/members',memberIds);
    },
    getExperimentMembers: function(expId){
      return $http.get(RestURLs.experiment+'/'+expId+'/members');
    },

    // Plates
    getExperimentPlates: function(id){
      return $http.get(RestURLs.experiment + '/' + id + "/plates")
    },
    removeExperimentPlate: function(experimentId, plateId) {
      return $http.delete(RestURLs.experiment + '/' + experimentId  + "/plates/" + plateId);
    },

    // Plate results
    getPlateResults: function(experimentId,plateId){
      return $http.get(RestURLs.experiment+'/'+experimentId+'/plates/'+plateId+'/results');
    },
    getDoseResponseData : function(experimentId){
      return $http.get(RestURLs.experiment+'/'+experimentId+'/doseresponse/results')
    },
    updatePlateResults: function(experimentId, plateId, wellChange){
      return $http.post(RestURLs.experiment+'/'+experimentId+'/plates/'+plateId+'/results/update', wellChange);
    },
    updateDoseResponseResult: function(plateId, doseResponseId, wellChange ){
      return $http.post(RestURLs.experiment+'/'+plateId+'/doseresponse/'+doseResponseId+'/update', wellChange);
    },
    //email filter
    getEmailFilter: function(){
      return $http.get(RestURLs.emailFilter);
    },

    updateEmailFilter: function(filter){
      return $http.post(RestURLs.emailFilter,filter);
    },
    //server settings
    getServerSettings: function(){
      return $http.get(RestURLs.serverSettings);
    },
    updateServerSettings: function(emailConfig){
      return $http.post(RestURLs.serverSettings,emailConfig);
    },

    //users
    getUsers:  function(){
      return $http.get(RestURLs.user);
    },

    //returns currently logged-in User
    getCurrentUser:  function(){
      return $http.get(RestURLs.user+'/me');
    },

    //protocol
    getProtocols:  function(){
      return $http.get(RestURLs.protocol);
    },

    addProtocol:  function(proc){
      return $http.put(RestURLs.protocol,proc);
    },

    //compound
    getCompounds: function(searchFilter,pageSize){
      var config={params:{"pageSize": pageSize, page:0, q: searchFilter}};
      return $http.get(RestURLs.compoundUpload,config);
    }

  };

}]);

app.factory('PlateMergeRestService', ['$http', '$q', '$log', '$upload', 'RestURLs', function($http,$q,$log,$upload,RestURLs){
  return {
    // For Label Table Gets a partially completed platemap merge info object
    getMergeInfoTemplate: function (plateMapId, plateType) {
      return $http.post(replaceId(RestURLs.mergeInfoTemplate, plateMapId), plateType);
    },
    /** Submit to make plate from user parameters and possibly a compound list csv.
     *
     * @param experimentId
     * @param mergeInfoObject label table and some other info
     * @param compoundCsv (optional) the file Obj of the compound List csv
     * @returns {*} a promise object of the connection
     */
    submitMergeInfo: function (experimentId, mergeInfoObject, compoundCsv) {
      if (compoundCsv){
        var mi = angular.toJson(mergeInfoObject);
        var mio = angular.fromJson(mergeInfoObject);
        var upload = $upload.upload({
          url: replaceId(RestURLs.mergeInfoSubmitWithCompound, experimentId),
          method: 'POST',
          file: compoundCsv,
          fields:{merge: mio},
          formDataAppender: function(fd,k,v) {
            fd.append(k, new Blob([mi], {type: "application/json"}));
          }
          //sendObjectsAsJsonBlob: true
        }).success(function(data){
            $log.info('New plate created');
          }).error(function(err){
            $log.error('Error creating plate:' + JSON.stringify(err));
          });
        return upload;
      } else {
        return $http.put(replaceId(RestURLs.mergeInfoSubmit, experimentId), mergeInfoObject);
      }
    },
    // Make plates from Full Monty Csv.
    submitPlatesWithResults: function (experimentId, plateType, csvFiles) {
      if (!csvFiles || csvFiles.length !== 1) {
        $log.error('No csv file attached');
        return null;
      }
      var pt = angular.toJson(plateType);
      var pto = angular.fromJson(pt);
      var file = csvFiles[0],
        upload = $upload.upload({
          url: RestURLs.experiment + "/" + experimentId + "/fullMonty",
          method: "POST",
          fields: {
            plateType: pto
          },
          formDataAppender: function(fd,k,v) {
            fd.append(k, new Blob([pt], {type: "application/json"}));
          },
          file: file
        }).progress(function (event) {
          var progressPercentage = parseInt(100.0 * event.loaded / event.total);
          $log.info('progress: ' + progressPercentage + '% ' +
          event.config.file.name);
        }).success(function (data, status, headers, config) {
          var result = JSON.stringify(data);
          $log.info('file ' + config.file.name + 'uploaded. Response: ' +
          result);
        }).error(function (data, status, headers, config) {
          var result = JSON.stringify(data);
          $log.error('error in file ' + config.file.name + 'uploaded. Response: ' +
          result);
        });
      return $q.when(upload);
    }
  };

  function replaceId(urlString, id) {
    return urlString.replace(':id', id);
  }
}]);
/** REST linked resource model for Plate Type */
app.factory('PlateTypeModel', ['$resource', 'RestURLs', function ($resource, RestURLs) {
  return $resource(RestURLs.plateType, {id:'@id'}, {
    query: {
      method: "GET",
      isArray: true,
      // Get an array back to exhibit expected query behavior
      transformResponse: valuesToArray
    },
    create: {
      method: "PUT" // Server takes put for creation
    }
  });
}]);

/** REST linked resource model for Plate Maps */
app.factory('PlateMapModel', ['$resource', 'RestURLs', function ($resource, RestURLs) {
  return $resource(RestURLs.plateMapById, {id:'@id'}, {
    listPlateMaps: {
      method: "GET",
      isArray: true,
      // Get an array back to exhibit expected query behavior
      transformResponse: valuesToArray
    },
    create: {
      method: "PUT" // Server takes put for creation
    }
    //// Requires a plateType in the body. remember the '$' before using because its an instance call.
    //getMergeInfo: {
    //  method:"POST",
    //  url: RestURLs.mergeInfoTemplate
    //}
  });
}]);

/** REST linked resource model for Compounds */
app.factory('CompoundModel', ['$resource', 'RestURLs', function($resource, RestURLs){
  var TYPEAHEAD_RESULT_SIZE = 4;
  return $resource(RestURLs.compound, {id: '@id'}, {
    list: {
      isArray:true,
      transformResponse: valuesToArray
    },
    // When using get typeahead, make sure to put in a parameter value for 'q'
    getTypeAhead: {
      // only grab first 4 results
      params: {q:'', pageSize:TYPEAHEAD_RESULT_SIZE},
      cache: true,
      isArray:true,
      transformResponse: valuesToArray
    },
    create: {
      method:"PUT"
    }
  }); // close $resource
}]);

/* HELPER FUNCTIONS */

/** Function to get the array of response values in 'list' style calls.
 *  needed because list style calls are returned as objects with the value information provided along with metadata
 */
function valuesToArray(data) {
  if (data) {
    return JSON.parse(data).values;
  } else {
    return null;
  }
}
<|endoftext|>


<commit_before>var UploadBox = React.createClass({
  onDrop: function (files) {
    this.props.uploadInit();

    files.forEach((file)=> {
      console.log('Uploading file: %s', file.name);

      var data = new FormData();
      data.append(file.name, file);

      $.ajax({
        url: this.props.url + "/" + file.name,
        type: 'POST',
        data: data,
        context: this,
        cache: false,
        dataType: 'json',
        processData: false, // Don't process the files
        contentType: false, // Set content type to false as jQuery will tell the server its a query string request
        success: function(data, textStatus, jqXHR) {
          this.props.uploadCompleted({file: file.name, status: jqXHR.status, data: jqXHR.responseText});
        },
        error: function(jqXHR, textStatus, err) {
          var status = jqXHR.status;
          if (status === 0) {
            status = -22;
          }

          console.log('Could not upload file %s, code: %d: %s/%s', file.name, jqXHR.statusCode(), textStatus, err.toString());
          this.props.uploadCompleted({file: file.name, status: status, data: jqXHR.responseText});
        }
      });
    });
  },

  render: function () {
    return (

        <Dropzone onDrop={this.onDrop}>

Try dropping some files here, or click to select files to upload.

        </Dropzone>

    );
  }
});

var UploadCompletion = React.createClass({
  render: function() {
    var bucket = "error";
    var url = "#";
    if (this.props.status === 200) {
      var js = JSON.parse(this.props.data);
      bucket = js["bucket"];
      url = this.props.get_url + "/" + bucket + "/" + this.props.file;
    }
      return (

File: {this.props.file}, Bucket: {bucket}, Status: {this.props.status}

      );
  }
});

var UploadStatus = React.createClass({
  render: function() {
    var get_url = this.props.get_url;
    var upload_completion = this.props.completions.map(function(cmp) {
      return (
        <UploadCompletion key={cmp.file} file={cmp.file} status={cmp.status} data={cmp.data} get_url={get_url} />
      );
    });

    return (

  	{upload_completion}

    );
  }
});

var UploadCtl = React.createClass({
  getInitialState: function() {
    return {
      completions: [],
    };
  },

  upload_init: function() {
    this.setState({completions: []});
  },

  upload_completed: function(cmp) {
    var cmps = this.state.completions;
    var new_cmps = cmps.concat([cmp]);
    this.setState({completions: new_cmps});
  },

  render: function() {
      return (

          <UploadStatus completions={this.state.completions} get_url={this.props.get_url} />
          <UploadBox url={this.props.upload_url} uploadCompleted={this.upload_completed} uploadInit={this.upload_init} />

      );
  }
});

window.UploadCtl = UploadCtl;
<commit_msg>upload: use KeyInfo instead of hand-crafted component, update index after file has been written, return list of failed to upload keys<commit_after>var UploadBox = React.createClass({
  onSuccess: function(cmp) {
    this.props.onSuccess(cmp);
  },
  onError: function(cmp) {
    this.props.onError(cmp);
  },

  onDrop: function (files) {
    this.props.uploadInit();

    files.forEach((file)=> {
      console.log('Uploading file: %s', file.name);

      var data = new FormData();
      data.append(file.name, file);

      $.ajax({
        url: this.props.url + "/" + file.name,
        type: 'POST',
        data: data,
        cache: false,
        dataType: 'json',
        processData: false, // Don't process the files
        contentType: false, // Set content type to false as jQuery will tell the server its a query string request
        success: function(data, textStatus, jqXHR) {
          this.onSuccess({file: file.name, status: jqXHR.status, data: jqXHR.responseText});
        }.bind(this),
        error: function(jqXHR, textStatus, err) {
          var status = jqXHR.status;
          if (status === 0) {
            status = -22;
          }

          this.onError({file: file.name, status: status, data: jqXHR.responseText});
        }.bind(this),
      });
    });
  },

  render: function () {
    return (

        <Dropzone onDrop={this.onDrop}>

Try dropping some files here, or click to select files to upload.

        </Dropzone>

    );
  }
});

var UploadCompletion = React.createClass({
  render: function() {
    console.log("UploadCompletion: %o", this.props.reply);
    var obj = JSON.parse(this.props.reply.data);
    return (
      <KeyInfo get_url={this.props.get_url} bucket={obj.bucket} filename={obj.key} />
    );
  }
});

var UploadError = React.createClass({
  render: function() {
    return (

File: {this.props.reply.file}, Status: {this.props.reply.status}, Reply: {this.props.reply.data}

    );
  }
});

var UploadStatus = React.createClass({
  render: function() {
    var upload_completions = this.props.completions.map(function(cmp) {
      console.log("completed: %o", cmp);
      return (
        <UploadCompletion reply={cmp} get_url={this.props.get_url} key={cmp.file} />
      );
    }, this);

    var upload_errors = this.props.errors.map(function(cmp) {
      return (
        <UploadError filename={cmp.file} reply={cmp} key={cmp.file} />
      );
    }, this);

    return (

        { upload_completions.length >= 1 ? "You have uploaded following files in the last uploading session" : "You have not uploaded any files yet" }
        {upload_completions}
        { upload_errors.length >= 1 ? "Following files have not been uploaded because of errors" : null }
        {upload_errors}

    );
  }
});

var UploadCtl = React.createClass({
  getInitialState: function() {
    return {
      completions: [],
      errors: [],
    };
  },

  upload_init: function() {
    this.setState({completions: []});
  },

  index_update: function(cmp) {
    var reply = JSON.parse(cmp.data);
    var idx = {};
    var fidx = {};
    fidx.key = reply.key;
    fidx.bucket = reply.bucket;
    fidx.tags = [];

    idx.files = [fidx];

    $.ajax({
      url: this.props.index_url,
      type: 'POST',
      data: JSON.stringify(idx),
      cache: false,
      dataType: 'json',
      processData: false, // Don't process the files
      contentType: false, // Set content type to false as jQuery will tell the server its a query string request
      success: function(data) {
        cmp.index = data;
        var cmps = this.state.completions;
        var new_cmps = cmps.concat([cmp]);
        this.setState({completions: new_cmps});
      }.bind(this),
      error: function(jqXHR, textStatus, err) {
        var status = jqXHR.status;
        if (status === 0) {
          status = -22;
        }

        this.upload_error({file: cmp.file, status: status, data: jqXHR.responseText});
      }.bind(this),
    });
  },

  upload_completed: function(cmp) {
    this.index_update(cmp);
  },

  upload_error: function(cmp) {
    var cmps = this.state.errors;
    var new_cmps = cmps.concat([cmp]);
    this.setState({errors: new_cmps});
  },

  render: function() {
      return (

          <UploadStatus completions={this.state.completions} errors={this.state.errors} get_url={this.props.get_url} />
          <UploadBox url={this.props.upload_url}
            onSuccess={this.upload_completed} onError={this.upload_error} uploadInit={this.upload_init} />

      );
  }
});

window.UploadCtl = UploadCtl;
<|endoftext|>


<commit_before>'use strict';
/*global $*/
function cdDojoEventsListCtrl($scope, $state, $location, $translate, $q, cdEventsService, cdUsersService, cdDojoService, tableUtils, alertService, auth, utilsService) {
  var dojoId = $scope.dojoId;
  $scope.filter = {dojo_id:dojoId};
  $scope.itemsPerPage = 10;
  $scope.applyData = {};

  auth.get_loggedin_user(function (user) {
    $scope.currentUser = user;

    //Get users current user types in this Dojo.
    cdDojoService.getUsersDojos({userId:$scope.currentUser.id, dojoId:dojoId}, function (response) {
      if(!_.isEmpty(response)) {
        var userDojo = response[0];
        var userTypes = userDojo.userTypes;
        $scope.isParent = _.contains(userTypes, 'parent-guardian');

        if($scope.isParent) {
          //retrieve this parent's children
          var query = {userId:$scope.currentUser.id};
          cdUsersService.listProfiles(query, function (response) {
            var parentProfile = response;
            var children = parentProfile.children;
            var childProfiles = [];
            async.each(children, function (child, cb) {
              cdUsersService.listProfiles({userId:child}, function (response) {
                if(response.userType === 'attendee-u13') {
                  childProfiles.push(response);
                }
                cb();
              });
            }, function (err) {
              console.error(err);
              alertService.showError($translate.instant('Error loading events'));
              var childUsers = [];
              async.each(childProfiles, function (childProfile, cb) {
                //Load sys_user objects
                cdUsersService.load(childProfile.userId, function (response) {
                  childUsers.push(response);
                  cb();
                });
              }, function (err) {
                console.error(err);
                alertService.showError($translate.instant('Error loading events'));
                $scope.childUsers = childUsers;
              });
            });
          });
        }
      }
    });
  });

  $scope.loadPage = function (filter, resetFlag, cb) {
    cb = cb || function () {};

    $scope.sort = $scope.sort ? $scope.sort: {dates: 1};

    var query = _.omit({
      dojoId: filter.dojoId,
    }, function (value) { return value === '' || _.isNull(value) || _.isUndefined(value) });

    var loadPageData = tableUtils.loadPage(resetFlag, $scope.itemsPerPage, $scope.pageNo, query);
    $scope.pageNo = loadPageData.pageNo;
    $scope.events = [];

    cdEventsService.search({dojoId: dojoId, status: 'published', filterPastEvents: true, public: true, limit$: $scope.itemsPerPage, skip$: loadPageData.skip, sort$: $scope.sort}).then(function (result) {
      var events = [];
      _.each(result, function (event) {
        if(event.type === 'recurring') {
          var startDate = _.first(event.dates);
          var endDate = _.last(event.dates);
          event.dateRange = moment(startDate).format('Do MMMM YY') + ' - ' + moment(endDate).format('Do MMMM YY, HH:mm');
          event.formattedDates = [];
          _.each(event.dates, function (eventDate) {
            event.formattedDates.push(moment(eventDate).format('Do MMMM YY'));
          });
          event.day = moment(_.first(event.dates), 'YYYY-MM-DD HH:mm:ss').format('dddd');
          event.time = moment(_.first(event.dates)).format('HH:mm');
          if(event.recurringType === 'weekly') {
            event.formattedRecurringType = $translate.instant('Weekly');
          } else {
            event.formattedRecurringType = $translate.instant('Every two weeks');
          }
        } else {
          //One-off event
          var eventDate = _.first(event.dates);
          event.formattedDate = moment(eventDate).format('Do MMMM YY, HH:mm');
        }

        var userType = event.userType;
        //TODO: translate event.type
        event.for = $translate.instant(userType);
        events.push(event);
      });
      $scope.events = events;
      cdEventsService.search({dojoId: dojoId, status: 'published', filterPastEvents: true}).then(function (result) {
        $scope.totalItems = result.length;
      }, function (err) {
        console.error(err);
        alertService.showError($translate.instant('Error loading events'));
      });
    }, function (err) {
      console.error(err);
      alertService.showError($translate.instant('Error loading events'));
    });

  }

  $scope.loadPage($scope.filter, true);

  $scope.tableRowIndexExpandedCurr = '';

  $scope.eventCollapsed = function (eventIndex) {
    $scope.events[eventIndex].isCollapsed = false;
  }

  $scope.pageChanged = function () {
    $scope.loadPage($scope.filter, false);
  };

  $scope.showEventInfo = function (index, eventId) {
    if (typeof $scope.events[index].isCollapsed === 'undefined') {
      $scope.eventCollapsed(index);
    }

    if ($scope.events[index].isCollapsed === false) {
      $scope.tableRowIndexExpandedCurr = index;
      $scope.events[index].isCollapsed = true;
    } else if ($scope.events[index].isCollapsed === true) {
      $scope.events[index].isCollapsed = false;
    }
  }

  $scope.toggleSort = function ($event, columnName) {
    var className, descFlag, sortConfig = {};
    var DOWN = 'glyphicon-chevron-down';
    var UP = 'glyphicon-chevron-up';

    function isDesc(className) {
      var result = className.indexOf(DOWN);
      return result > -1 ? true : false;
    }

    className = $($event.target).attr('class');

    descFlag = isDesc(className);
    if (descFlag) {
      sortConfig[columnName] = 1;
    } else {
      sortConfig[columnName] = -1;
    }

    $scope.sort = sortConfig;
    $scope.loadPage($scope.filter, true);
  }

  $scope.getSortClass = utilsService.getSortClass;

}

angular.module('cpZenPlatform')
    .controller('dojo-events-list-controller', ['$scope', '$state', '$location', '$translate', '$q', 'cdEventsService', 'cdUsersService', 'cdDojoService', 'tableUtils', 'alertService', 'auth', 'utilsService', cdDojoEventsListCtrl]);
<commit_msg>fix apply for event for u13 on dojo detail page<commit_after>'use strict';
/*global $*/
function cdDojoEventsListCtrl($scope, $state, $location, $translate, $q, cdEventsService, cdUsersService, cdDojoService, tableUtils, alertService, auth, utilsService) {
  var dojoId = $scope.dojoId;
  $scope.filter = {dojo_id:dojoId};
  $scope.itemsPerPage = 10;
  $scope.applyData = {};

  auth.get_loggedin_user(function (user) {
    $scope.currentUser = user;

    //Get users current user types in this Dojo.
    cdDojoService.getUsersDojos({userId:$scope.currentUser.id, dojoId:dojoId}, function (response) {
      if(!_.isEmpty(response)) {
        //retrieve this parent's children
        var query = {userId:$scope.currentUser.id};
        cdUsersService.listProfiles(query, function (response) {
          var parentProfile = response;
          var children = parentProfile.children;
          var childProfiles = [];
          async.each(children, function (child, cb) {
            cdUsersService.listProfiles({userId:child}, function (response) {
              if(response.userType === 'attendee-u13') {
                childProfiles.push(response);
              }
              cb();
            });
          }, function (err) {
            console.error(err);
            alertService.showError($translate.instant('Error loading events'));
            var childUsers = [];
            async.each(childProfiles, function (childProfile, cb) {
              //Load sys_user objects
              cdUsersService.load(childProfile.userId, function (response) {
                childUsers.push(response);
                cb();
              });
            }, function (err) {
              console.error(err);
              alertService.showError($translate.instant('Error loading events'));
              $scope.childUsers = childUsers;
            });
          });
        });
      }
    });
  });

  $scope.loadPage = function (filter, resetFlag, cb) {
    cb = cb || function () {};

    $scope.sort = $scope.sort ? $scope.sort: {dates: 1};

    var query = _.omit({
      dojoId: filter.dojoId,
    }, function (value) { return value === '' || _.isNull(value) || _.isUndefined(value) });

    var loadPageData = tableUtils.loadPage(resetFlag, $scope.itemsPerPage, $scope.pageNo, query);
    $scope.pageNo = loadPageData.pageNo;
    $scope.events = [];

    cdEventsService.search({dojoId: dojoId, status: 'published', filterPastEvents: true, public: true, limit$: $scope.itemsPerPage, skip$: loadPageData.skip, sort$: $scope.sort}).then(function (result) {
      var events = [];
      _.each(result, function (event) {
        if(event.type === 'recurring') {
          var startDate = _.first(event.dates);
          var endDate = _.last(event.dates);
          event.dateRange = moment(startDate).format('Do MMMM YY') + ' - ' + moment(endDate).format('Do MMMM YY, HH:mm');
          event.formattedDates = [];
          _.each(event.dates, function (eventDate) {
            event.formattedDates.push(moment(eventDate).format('Do MMMM YY'));
          });
          event.day = moment(_.first(event.dates), 'YYYY-MM-DD HH:mm:ss').format('dddd');
          event.time = moment(_.first(event.dates)).format('HH:mm');
          if(event.recurringType === 'weekly') {
            event.formattedRecurringType = $translate.instant('Weekly');
          } else {
            event.formattedRecurringType = $translate.instant('Every two weeks');
          }
        } else {
          //One-off event
          var eventDate = _.first(event.dates);
          event.formattedDate = moment(eventDate).format('Do MMMM YY, HH:mm');
        }

        var userType = event.userType;
        //TODO: translate event.type
        event.for = $translate.instant(userType);
        events.push(event);
      });
      $scope.events = events;
      cdEventsService.search({dojoId: dojoId, status: 'published', filterPastEvents: true}).then(function (result) {
        $scope.totalItems = result.length;
      }, function (err) {
        console.error(err);
        alertService.showError($translate.instant('Error loading events'));
      });
    }, function (err) {
      console.error(err);
      alertService.showError($translate.instant('Error loading events'));
    });

  }

  $scope.loadPage($scope.filter, true);

  $scope.tableRowIndexExpandedCurr = '';

  $scope.eventCollapsed = function (eventIndex) {
    $scope.events[eventIndex].isCollapsed = false;
  }

  $scope.pageChanged = function () {
    $scope.loadPage($scope.filter, false);
  };

  $scope.showEventInfo = function (index, eventId) {
    if (typeof $scope.events[index].isCollapsed === 'undefined') {
      $scope.eventCollapsed(index);
    }

    if ($scope.events[index].isCollapsed === false) {
      $scope.tableRowIndexExpandedCurr = index;
      $scope.events[index].isCollapsed = true;
    } else if ($scope.events[index].isCollapsed === true) {
      $scope.events[index].isCollapsed = false;
    }
  }

  $scope.toggleSort = function ($event, columnName) {
    var className, descFlag, sortConfig = {};
    var DOWN = 'glyphicon-chevron-down';
    var UP = 'glyphicon-chevron-up';

    function isDesc(className) {
      var result = className.indexOf(DOWN);
      return result > -1 ? true : false;
    }

    className = $($event.target).attr('class');

    descFlag = isDesc(className);
    if (descFlag) {
      sortConfig[columnName] = 1;
    } else {
      sortConfig[columnName] = -1;
    }

    $scope.sort = sortConfig;
    $scope.loadPage($scope.filter, true);
  }

  $scope.getSortClass = utilsService.getSortClass;

}

angular.module('cpZenPlatform')
    .controller('dojo-events-list-controller', ['$scope', '$state', '$location', '$translate', '$q', 'cdEventsService', 'cdUsersService', 'cdDojoService', 'tableUtils', 'alertService', 'auth', 'utilsService', cdDojoEventsListCtrl]);
<|endoftext|>