<commit_before>/*global ares, enyo, AresI18n, setTimeout, ServiceRegistry */

/* ilibProjectView covers Harmonia specific translations. */
var ilibHarmonia = AresI18n.resolve.bind(null, AresI18n.setBundle(navigator.language, "$assets/harmonia/resources"));

enyo.kind({
	name: "Harmonia",
	kind:"FittableColumns",
	events: {
		onRegisterMe: "",
		onMovePanel: "",
		onModifySettings: "",
		onBuild: "",
		onInstall: "",
		onRun: "",
		onRunDebug: "",
		onPreview: ""
	},
	handlers: {
		onDisableProjectMenu: "disableProjectMenu"
	},
	components: [
		{kind:"FittableRows", classes:"enyo-fit", components:[
			{kind: "onyx.MoreToolbar", classes: "ares-top-toolbar ares-harmonia-panels", components: [
				{kind: "onyx.Grabber", classes: "ares-grabber" , name: "filePanelGrabber", showing: false, ontap: "activePanel", components: [
					{kind: "aresGrabber", name: "aresGrabberDirection"}
				]},
				{kind: "onyx.MenuDecorator", classes: "aresmenu", onSelect: "menuItemSelected", components: [
					{content: ilibHarmonia("Project"), name: "projectMenu", disabled: true},
					{kind: "onyx.Menu", floating: true, classes: "sub-aresmenu", maxHeight: "100%", components: [
						{value: "doModifySettings",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_edit.png"},
							{content: ilibHarmonia("Edit...")}
						]},
						{classes: "onyx-menu-divider aresmenu-button"},
						{value: "doPreview",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_preview.png"},
							{content: ilibHarmonia("Preview")}
						]},
						{name: "buildItem", value: "doBuild",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_build.png"},
							{content: ilibHarmonia("Build...")}
						]},
						{classes: "onyx-menu-divider aresmenu-button"},
						{name: "installItem", value: "doInstall",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_install.png"},
							{content: ilibHarmonia("Install...")}
						]},
						{classes: "onyx-menu-divider aresmenu-button"},
						{name: "runItem", value: "doRun",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_run.png"},
							{content: ilibHarmonia("Run...")}
						]},
						{name: "runDebugItem", value: "doRunDebug",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_debug.png"},
							{content: ilibHarmonia("Debug...")}
						]}
					]}
				]},
				{classes:"ares-logo-container", name: "logoContainer", components:[
					{name:"logo", kind:"Ares.Logo"}
				]}
			]},
			{kind: "HermesFileTree", dragAllowed: true, menuAllowed: true}
		]},
		{classes:"hangar"}
	],
	debug: false,
	published: {
		// harcoded until ENYO-2755 is fixed
		panelIndex: 1
	},
	project: null,
	create: function() {
		ares.setupTraceLogger(this);	// Setup this.trace() function according to this.debug value
		this.inherited(arguments);
		this.doRegisterMe({name:"harmonia", reference:this});

		// i18n checking
		this.trace("ilibHarmonia: Cancel=", ilibHarmonia("Cancel"));
	},
	handleSelectProvider: function(inSender, inEvent) {
		this.trace("sender:", inSender, ", event:", inEvent);
		if (inEvent.service) {
			this.$.hermesFileTree.connectService(inEvent.service);
		}
		this.$.hermesFileTree.hideFileOpButtons();
		return true; //Stop event propagation
	},
	setProject: function(project, next) {
		ares.assertCb(next);
		this.trace("project:", project);
		if (project !== null) {
			this.$.hermesFileTree.connectProject(project, next).showFileOpButtons();
			this.project = project;
		} else {
			this.$.hermesFileTree.hideFileOpButtons().clear();
			setTimeout(next,0);
		}
	},
	showGrabber:function(){
		this.$.filePanelGrabber.show();
	},
	hideGrabber:function(){
		this.$.filePanelGrabber.hide();
	},
	switchGrabberDirection: function(active){
		this.$.aresGrabberDirection.switchGrabberDirection(active);
	},
	/**
	 * Refresh the {HermesFileTree}
	 * @param {Object} toSelectId - changed file id
	 * @param {Function} [callback] - optional callback
	 */
	refreshFileTree: function(toSelectId,next) {
		// the inversion of parameter is not an error.
		// next parameter is optional (can be null or undef)
		// ENYO-3641
		this.$.hermesFileTree.refreshFileTree(next, toSelectId);
	},
	activePanel : function(){
		this.doMovePanel({panelIndex:this.panelIndex});
	},
	showLogo:function(){
		this.$.logoContainer.show();
	},
	hideLogo:function(){
		this.$.logoContainer.hide();
	},
	/** @public */
	disableProjectMenu: function(disabled){
		this.$.projectMenu.setDisabled(disabled);
	},
	/**
	 * Generic event handler
	 * @private
	 */
	menuItemSelected: function(inSender, inEvent) {
		this.trace("sender:", inSender, ", event:", inEvent);
		var fn = inEvent && inEvent.selected && inEvent.selected.value;
		if (typeof this[fn] === 'function') {
			this[fn]({project: this.project});
		} else {
			this.trace("*** BUG: '", fn, "' is not a known function");
		}
	},
});
<commit_msg>ENYO-3761: Show/Hide the project menuItems (build, install, run & runDebug) if the project define/doesn't define a provider that implement the build interface.<commit_after>/*global ares, enyo, AresI18n, setTimeout, ServiceRegistry */

/* ilibProjectView covers Harmonia specific translations. */
var ilibHarmonia = AresI18n.resolve.bind(null, AresI18n.setBundle(navigator.language, "$assets/harmonia/resources"));

enyo.kind({
	name: "Harmonia",
	kind:"FittableColumns",
	events: {
		onRegisterMe: "",
		onMovePanel: "",
		onModifySettings: "",
		onBuild: "",
		onInstall: "",
		onRun: "",
		onRunDebug: "",
		onPreview: ""
	},
	handlers: {
		onDisableProjectMenu: "disableProjectMenu"
	},
	components: [
		{kind:"FittableRows", classes:"enyo-fit", components:[
			{kind: "onyx.MoreToolbar", classes: "ares-top-toolbar ares-harmonia-panels", components: [
				{kind: "onyx.Grabber", classes: "ares-grabber" , name: "filePanelGrabber", showing: false, ontap: "activePanel", components: [
					{kind: "aresGrabber", name: "aresGrabberDirection"}
				]},
				{kind: "onyx.MenuDecorator", classes: "aresmenu", onSelect: "menuItemSelected", components: [
					{content: ilibHarmonia("Project"), name: "projectMenu", disabled: true},
					{kind: "onyx.Menu", floating: true, classes: "sub-aresmenu", maxHeight: "100%", components: [
						{value: "doModifySettings",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_edit.png"},
							{content: ilibHarmonia("Edit...")}
						]},
						{classes: "onyx-menu-divider aresmenu-button"},
						{value: "doPreview",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_preview.png"},
							{content: ilibHarmonia("Preview")}
						]},
						{name: "buildItem", value: "doBuild",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_build.png"},
							{content: ilibHarmonia("Build...")}
						]},
						{classes: "onyx-menu-divider aresmenu-button"},
						{name: "installItem", value: "doInstall",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_install.png"},
							{content: ilibHarmonia("Install...")}
						]},
						{classes: "onyx-menu-divider aresmenu-button"},
						{name: "runItem", value: "doRun",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_run.png"},
							{content: ilibHarmonia("Run...")}
						]},
						{name: "runDebugItem", value: "doRunDebug",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_debug.png"},
							{content: ilibHarmonia("Debug...")}
						]}
					]}
				]},
				{classes:"ares-logo-container", name: "logoContainer", components:[
					{name:"logo", kind:"Ares.Logo"}
				]}
			]},
			{kind: "HermesFileTree", dragAllowed: true, menuAllowed: true}
		]},
		{classes:"hangar"}
	],
	debug: false,
	published: {
		// harcoded until ENYO-2755 is fixed
		panelIndex: 1
	},
	project: null,
	create: function() {
		ares.setupTraceLogger(this);	// Setup this.trace() function according to this.debug value
		this.inherited(arguments);
		this.doRegisterMe({name:"harmonia", reference:this});

		// i18n checking
		this.trace("ilibHarmonia: Cancel=", ilibHarmonia("Cancel"));
	},
	handleSelectProvider: function(inSender, inEvent) {
		this.trace("sender:", inSender, ", event:", inEvent);
		if (inEvent.service) {
			this.$.hermesFileTree.connectService(inEvent.service);
		}
		this.$.hermesFileTree.hideFileOpButtons();
		return true; //Stop event propagation
	},
	setProject: function(project, next) {
		ares.assertCb(next);
		this.trace("project:", project);
		if (project !== null) {
			this.$.hermesFileTree.connectProject(project, next).showFileOpButtons();
			this.project = project;
			this.manageBuildIntefaceAction();
		} else {
			this.$.hermesFileTree.hideFileOpButtons().clear();
			setTimeout(next,0);
		}
	},

	/**
	 * Enable/Disable the build interfaces actions depending on wether or not the project use a provider implement a build interface.
	 * @private
	 */
	manageBuildIntefaceAction: function() {

		if(this.checkSelectedProjectProvidersType("build")) {
			this.$.buildItem.show();
			this.$.installItem.show();
			this.$.runItem.show();
			this.$.runDebugItem.show();

		} else {
			this.$.buildItem.hide();
			this.$.installItem.hide();
			this.$.runItem.hide();
			this.$.runDebugItem.hide();
		}
	},

	/**
	 * Test if at least one of the selected project provider implement the "build" interface.
	 * @private
	 */
	checkSelectedProjectProvidersType: function(inType) {
		// Array of the providers instances of the selected project
		var allProjectProviders = Ares.Workspace.projects.getSelectedProject().attributes.config.data.providers;

		var providers = {};
		for (var p in allProjectProviders) {

			// If the provider is enabled
			// Then append this profider instance in the array {providers}
			if(allProjectProviders[p].enabled) {
				providers[p] = allProjectProviders[p];
			}
		}

		// Array of the services instances that are loaded in Client Ares IDE.
		var services = this.getServicesByType(inType);

		// Tells if the project use at least one {inType} service
		var implementInterface = false;

		// If at least one of the selected project provider implement the {inType} interface
		// Then "implementInterface" is set to "true"
		// Else "implementInterface" is set to "false"
		for(var key in providers) {
			for (var i = 0, servicesLength = services.length; i < servicesLength; i ++) {
				if(key === services[i].id) {
					implementInterface = true; break;
				}
			}
		}

		return implementInterface;
	},

	/**
	 * @return {Array} List of all the services that implement the "build" interface.
	 * @private
	 */
	getServicesByType: function(inType){
		return ServiceRegistry.instance.getServicesByType(inType);
	},

	showGrabber:function(){
		this.$.filePanelGrabber.show();
	},
	hideGrabber:function(){
		this.$.filePanelGrabber.hide();
	},
	switchGrabberDirection: function(active){
		this.$.aresGrabberDirection.switchGrabberDirection(active);
	},
	/**
	 * Refresh the {HermesFileTree}
	 * @param {Object} toSelectId - changed file id
	 * @param {Function} [callback] - optional callback
	 */
	refreshFileTree: function(toSelectId,next) {
		// the inversion of parameter is not an error.
		// next parameter is optional (can be null or undef)
		// ENYO-3641
		this.$.hermesFileTree.refreshFileTree(next, toSelectId);
	},
	activePanel : function(){
		this.doMovePanel({panelIndex:this.panelIndex});
	},
	showLogo:function(){
		this.$.logoContainer.show();
	},
	hideLogo:function(){
		this.$.logoContainer.hide();
	},
	/** @public */
	disableProjectMenu: function(disabled){
		this.$.projectMenu.setDisabled(disabled);
	},
	/**
	 * Generic event handler
	 * @private
	 */
	menuItemSelected: function(inSender, inEvent) {
		this.trace("sender:", inSender, ", event:", inEvent);
		var fn = inEvent && inEvent.selected && inEvent.selected.value;
		if (typeof this[fn] === 'function') {
			this[fn]({project: this.project});
		} else {
			this.trace("*** BUG: '", fn, "' is not a known function");
		}
	},
});
<|endoftext|>


<commit_before>/*global ares, enyo, AresI18n, setTimeout, ServiceRegistry */

/* ilibProjectView covers Harmonia specific translations. */
var ilibHarmonia = AresI18n.resolve.bind(null, AresI18n.setBundle(navigator.language, "$assets/harmonia/resources"));

enyo.kind({
	name: "Harmonia",
	kind:"FittableColumns",
	events: {
		onRegisterMe: "",
		onMovePanel: "",
		onModifySettings: "",
		onBuild: "",
		onInstall: "",
		onRun: "",
		onRunDebug: "",
		onPreview: ""
	},
	handlers: {
		onDisableProjectMenu: "disableProjectMenu"
	},
	components: [
		{kind:"FittableRows", classes:"enyo-fit", components:[
			{kind: "onyx.MoreToolbar", classes: "ares-top-toolbar ares-harmonia-panels", components: [
				{kind: "onyx.Grabber", classes: "ares-grabber" , name: "filePanelGrabber", showing: false, ontap: "activePanel", components: [
					{kind: "aresGrabber", name: "aresGrabberDirection"}
				]},
				{kind: "onyx.MenuDecorator", classes: "aresmenu", onSelect: "menuItemSelected", components: [
					{content: ilibHarmonia("Project"), name: "projectMenu", disabled: true},
					{kind: "onyx.Menu", floating: true, classes: "sub-aresmenu", maxHeight: "100%", components: [
						{value: "doModifySettings",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_edit.png"},
							{content: ilibHarmonia("Edit...")}
						]},
						{classes: "onyx-menu-divider aresmenu-button"},
						{value: "doPreview",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_preview.png"},
							{content: ilibHarmonia("Preview")}
						]},
						{name: "buildItem", value: "doBuild",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_build.png"},
							{content: ilibHarmonia("Build...")}
						]},
						{classes: "onyx-menu-divider aresmenu-button"},
						{name: "installItem", value: "doInstall",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_install.png"},
							{content: ilibHarmonia("Install...")}
						]},
						{classes: "onyx-menu-divider aresmenu-button"},
						{name: "runItem", value: "doRun",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_run.png"},
							{content: ilibHarmonia("Run...")}
						]},
						{name: "runDebugItem", value: "doRunDebug",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_debug.png"},
							{content: ilibHarmonia("Debug...")}
						]}
					]}
				]},
				{classes:"ares-logo-container", name: "logoContainer", components:[
					{name:"logo", kind:"Ares.Logo"}
				]}
			]},
			{kind: "HermesFileTree", dragAllowed: true, menuAllowed: true}
		]},
		{classes:"hangar"}
	],
	debug: false,
	published: {
		// harcoded until ENYO-2755 is fixed
		panelIndex: 1
	},
	project: null,
	create: function() {
		ares.setupTraceLogger(this);	// Setup this.trace() function according to this.debug value
		this.inherited(arguments);
		this.doRegisterMe({name:"harmonia", reference:this});

		// i18n checking
		this.trace("ilibHarmonia: Cancel=", ilibHarmonia("Cancel"));
	},
	handleSelectProvider: function(inSender, inEvent) {
		this.trace("sender:", inSender, ", event:", inEvent);
		if (inEvent.service) {
			this.$.hermesFileTree.connectService(inEvent.service);
		}
		this.$.hermesFileTree.hideFileOpButtons();
		return true; //Stop event propagation
	},
	setProject: function(project, next) {
		ares.assertCb(next);
		this.trace("project:", project);
		if (project !== null) {
			this.$.hermesFileTree.connectProject(project, next).showFileOpButtons();
			this.project = project;
			this.manageBuildIntefaceAction();
		} else {
			this.$.hermesFileTree.hideFileOpButtons().clear();
			setTimeout(next,0);
		}
	},

	/**
	 * Enable/Disable the build interfaces actions depending on wether or not the project use a provider implement a build interface.
	 * @private
	 */
	manageBuildIntefaceAction: function() {

		if(this.checkSelectedProjectProvidersType("build")) {
			this.$.buildItem.show();
			this.$.installItem.show();
			this.$.runItem.show();
			this.$.runDebugItem.show();

		} else {
			this.$.buildItem.hide();
			this.$.installItem.hide();
			this.$.runItem.hide();
			this.$.runDebugItem.hide();
		}
	},

	/**
	 * Test if at least one of the selected project provider implement the "build" interface.
	 * @private
	 */
	checkSelectedProjectProvidersType: function(inType) {
		// Array of the providers instances of the selected project
		var allProjectProviders = Ares.Workspace.projects.getSelectedProject().attributes.config.data.providers;

		var providers = {};
		for (var p in allProjectProviders) {

			// If the provider is enabled
			// Then append this profider instance in the array {providers}
			if(allProjectProviders[p].enabled) {
				providers[p] = allProjectProviders[p];
			}
		}

		// Array of the services instances that are loaded in Client Ares IDE.
		var services = this.getServicesByType(inType);

		// Tells if the project use at least one {inType} service
		var implementInterface = false;

		// If at least one of the selected project provider implement the {inType} interface
		// Then "implementInterface" is set to "true"
		// Else "implementInterface" is set to "false"
		for(var key in providers) {
			for (var i = 0, servicesLength = services.length; i < servicesLength; i ++) {
				if(key === services[i].id) {
					implementInterface = true; break;
				}
			}
		}

		return implementInterface;
	},

	/**
	 * @return {Array} List of all the services that implement the "build" interface.
	 * @private
	 */
	getServicesByType: function(inType){
		return ServiceRegistry.instance.getServicesByType(inType);
	},

	showGrabber:function(){
		this.$.filePanelGrabber.show();
	},
	hideGrabber:function(){
		this.$.filePanelGrabber.hide();
	},
	switchGrabberDirection: function(active){
		this.$.aresGrabberDirection.switchGrabberDirection(active);
	},
	/**
	 * Refresh the {HermesFileTree}
	 * @param {Object} toSelectId - changed file id
	 * @param {Function} [callback] - optional callback
	 */
	refreshFileTree: function(toSelectId,next) {
		// the inversion of parameter is not an error.
		// next parameter is optional (can be null or undef)
		// ENYO-3641
		this.$.hermesFileTree.refreshFileTree(next, toSelectId);
	},
	activePanel : function(){
		this.doMovePanel({panelIndex:this.panelIndex});
	},
	showLogo:function(){
		this.$.logoContainer.show();
	},
	hideLogo:function(){
		this.$.logoContainer.hide();
	},
	/** @public */
	disableProjectMenu: function(disabled){
		this.$.projectMenu.setDisabled(disabled);
	},
	/**
	 * Generic event handler
	 * @private
	 */
	menuItemSelected: function(inSender, inEvent) {
		this.trace("sender:", inSender, ", event:", inEvent);
		var fn = inEvent && inEvent.selected && inEvent.selected.value;
		if (typeof this[fn] === 'function') {
			this[fn]({project: this.project});
		} else {
			this.trace("*** BUG: '", fn, "' is not a known function");
		}
	},
});
<commit_msg>ENYO-3761: correct an indentation.<commit_after>/*global ares, enyo, AresI18n, setTimeout, ServiceRegistry */

/* ilibProjectView covers Harmonia specific translations. */
var ilibHarmonia = AresI18n.resolve.bind(null, AresI18n.setBundle(navigator.language, "$assets/harmonia/resources"));

enyo.kind({
	name: "Harmonia",
	kind:"FittableColumns",
	events: {
		onRegisterMe: "",
		onMovePanel: "",
		onModifySettings: "",
		onBuild: "",
		onInstall: "",
		onRun: "",
		onRunDebug: "",
		onPreview: ""
	},
	handlers: {
		onDisableProjectMenu: "disableProjectMenu"
	},
	components: [
		{kind:"FittableRows", classes:"enyo-fit", components:[
			{kind: "onyx.MoreToolbar", classes: "ares-top-toolbar ares-harmonia-panels", components: [
				{kind: "onyx.Grabber", classes: "ares-grabber" , name: "filePanelGrabber", showing: false, ontap: "activePanel", components: [
					{kind: "aresGrabber", name: "aresGrabberDirection"}
				]},
				{kind: "onyx.MenuDecorator", classes: "aresmenu", onSelect: "menuItemSelected", components: [
					{content: ilibHarmonia("Project"), name: "projectMenu", disabled: true},
					{kind: "onyx.Menu", floating: true, classes: "sub-aresmenu", maxHeight: "100%", components: [
						{value: "doModifySettings",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_edit.png"},
							{content: ilibHarmonia("Edit...")}
						]},
						{classes: "onyx-menu-divider aresmenu-button"},
						{value: "doPreview",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_preview.png"},
							{content: ilibHarmonia("Preview")}
						]},
						{name: "buildItem", value: "doBuild",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_build.png"},
							{content: ilibHarmonia("Build...")}
						]},
						{classes: "onyx-menu-divider aresmenu-button"},
						{name: "installItem", value: "doInstall",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_install.png"},
							{content: ilibHarmonia("Install...")}
						]},
						{classes: "onyx-menu-divider aresmenu-button"},
						{name: "runItem", value: "doRun",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_run.png"},
							{content: ilibHarmonia("Run...")}
						]},
						{name: "runDebugItem", value: "doRunDebug",  classes: "aresmenu-button", components: [
							{kind: "onyx.IconButton", src: "$assets/project-view/images/project_view_debug.png"},
							{content: ilibHarmonia("Debug...")}
						]}
					]}
				]},
				{classes:"ares-logo-container", name: "logoContainer", components:[
					{name:"logo", kind:"Ares.Logo"}
				]}
			]},
			{kind: "HermesFileTree", dragAllowed: true, menuAllowed: true}
		]},
		{classes:"hangar"}
	],
	debug: false,
	published: {
		// harcoded until ENYO-2755 is fixed
		panelIndex: 1
	},
	project: null,
	create: function() {
		ares.setupTraceLogger(this);	// Setup this.trace() function according to this.debug value
		this.inherited(arguments);
		this.doRegisterMe({name:"harmonia", reference:this});

		// i18n checking
		this.trace("ilibHarmonia: Cancel=", ilibHarmonia("Cancel"));
	},
	handleSelectProvider: function(inSender, inEvent) {
		this.trace("sender:", inSender, ", event:", inEvent);
		if (inEvent.service) {
			this.$.hermesFileTree.connectService(inEvent.service);
		}
		this.$.hermesFileTree.hideFileOpButtons();
		return true; //Stop event propagation
	},
	setProject: function(project, next) {
		ares.assertCb(next);
		this.trace("project:", project);
		if (project !== null) {
			this.$.hermesFileTree.connectProject(project, next).showFileOpButtons();
			this.project = project;
			this.manageBuildIntefaceAction();
		} else {
			this.$.hermesFileTree.hideFileOpButtons().clear();
			setTimeout(next,0);
		}
	},

	/**
	 * Enable/Disable the build interfaces actions depending on wether or not the project use a provider implement a build interface.
	 * @private
	 */
	manageBuildIntefaceAction: function() {

		if(this.checkSelectedProjectProvidersType("build")) {
			this.$.buildItem.show();
			this.$.installItem.show();
			this.$.runItem.show();
			this.$.runDebugItem.show();

		} else {
			this.$.buildItem.hide();
			this.$.installItem.hide();
			this.$.runItem.hide();
			this.$.runDebugItem.hide();
		}
	},

	/**
	 * Test if at least one of the selected project provider implement the "build" interface.
	 * @private
	 */
	checkSelectedProjectProvidersType: function(inType) {
		// Array of the providers instances of the selected project
		var allProjectProviders = Ares.Workspace.projects.getSelectedProject().attributes.config.data.providers;

		var providers = {};
		for (var p in allProjectProviders) {

			// If the provider is enabled
			// Then append this profider instance in the array {providers}
			if(allProjectProviders[p].enabled) {
				providers[p] = allProjectProviders[p];
			}
		}

		// Array of the services instances that are loaded in Client Ares IDE.
		var services = this.getServicesByType(inType);

		// Tells if the project use at least one {inType} service
		var implementInterface = false;

		// If at least one of the selected project provider implement the {inType} interface
		// Then "implementInterface" is set to "true"
		// Else "implementInterface" is set to "false"
		for(var key in providers) {
			for (var i = 0, servicesLength = services.length; i < servicesLength; i ++) {
				if(key === services[i].id) {
					implementInterface = true;
					break;
				}
			}
		}

		return implementInterface;
	},

	/**
	 * @return {Array} List of all the services that implement the "build" interface.
	 * @private
	 */
	getServicesByType: function(inType){
		return ServiceRegistry.instance.getServicesByType(inType);
	},

	showGrabber:function(){
		this.$.filePanelGrabber.show();
	},
	hideGrabber:function(){
		this.$.filePanelGrabber.hide();
	},
	switchGrabberDirection: function(active){
		this.$.aresGrabberDirection.switchGrabberDirection(active);
	},
	/**
	 * Refresh the {HermesFileTree}
	 * @param {Object} toSelectId - changed file id
	 * @param {Function} [callback] - optional callback
	 */
	refreshFileTree: function(toSelectId,next) {
		// the inversion of parameter is not an error.
		// next parameter is optional (can be null or undef)
		// ENYO-3641
		this.$.hermesFileTree.refreshFileTree(next, toSelectId);
	},
	activePanel : function(){
		this.doMovePanel({panelIndex:this.panelIndex});
	},
	showLogo:function(){
		this.$.logoContainer.show();
	},
	hideLogo:function(){
		this.$.logoContainer.hide();
	},
	/** @public */
	disableProjectMenu: function(disabled){
		this.$.projectMenu.setDisabled(disabled);
	},
	/**
	 * Generic event handler
	 * @private
	 */
	menuItemSelected: function(inSender, inEvent) {
		this.trace("sender:", inSender, ", event:", inEvent);
		var fn = inEvent && inEvent.selected && inEvent.selected.value;
		if (typeof this[fn] === 'function') {
			this[fn]({project: this.project});
		} else {
			this.trace("*** BUG: '", fn, "' is not a known function");
		}
	},
});
<|endoftext|>


<commit_before>$(document).ready(function(){
  $(document).ready(function () {
    var contents = document.getElementsByClassName("content")
    for(var j=0; j<contents.length; j++) {
       $(contents[j]).toggle(false);
    }
  });
});

function toggle(element) {
  var content = element.parentElement.parentElement.nextElementSibling.getElementsByClassName("content")[0];
  $(content).toggle("slow");
 }

 $(document).ready(function() {
   var loc = window.location;
   var url = loc.origin+loc.pathname+'data.json';
   $('#header #selector input').val(url);
   $.getJSON('data.json', function(data) {
      var resources = Object.keys(data['resources']);
      for(var i=0; i < resources.length; i++) {
          var resource = data['resources'][resources[i]];
          add_resource(resources[i], resource, i);
          $('#resource'+i).toggle();
      }
      add_resource_events();
      var anchor = window.location.hash.replace('!','');
          anchor = anchor.replace(/\//g,"\\/");
          anchor = anchor.replace(/:/g,'\\:');
      $(anchor).next().fadeToggle();
   });

 });

function showJSON() {
   var loc = window.location;
   var url = loc.origin+loc.pathname+'data.json';
   window.open(url,"_self")
}

function toggleMethods(i) {
  event.stopPropagation();
  $('#resource'+i).fadeToggle();
}
function add_resource_events() {
  $(".resource").hover(function(){
    $(this).css("background", "#f5f5f5");
    $(this).children('div').children().css('color', 'black');
  }, function(){
    $(this).css("background", "#fff");
    $(this).children('div').children().css('color', '#999');
  });
  $('.resource').click(function(event) {
    event.stopPropagation();
    $(event.delegateTarget).next().fadeToggle();
  });
}
function add_resource(resource, config, i) {
  var html  = '
';
      html += '
  '+resource+'
';
      html += '
'+config['title']+'
';
      html += '
 Show/Hide | Raw
';
      html += '
';
      html += add_section(resource, config['sections']['config'], config['sections']['entries'], i);
    $('.resources').append(html);
    $('#resource'+i+' .content').toggle()
    $('#resource'+i+' .method .url a').click(function(event) {
        $(this).parent().parent().next().fadeToggle();
    });
}

function add_section(resource, config, entries, i) {
  var html  = '
';
  var methods = Object.keys(config);
  for(var i=0; i < methods.length; i++) {
        var field   = config[methods[i]];
        var content = entries[methods[i].toUpperCase()];
        html += '
';
        html += '
';
        html += '
'+methods[i]+'
';
        html += '
'+field['url']+'
';
        html += '
'+field['desc']+'
';
        html += '
';
        html += '
'+content+'
';
        html += '
';
  }
  html += '
';
  return html;
}
function capitalise(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
}
<commit_msg>added a way to load external json description files<commit_after>$(document).ready(function(){
  $(document).ready(function () {
    var contents = document.getElementsByClassName("content")
    for(var j=0; j<contents.length; j++) {
       $(contents[j]).toggle(false);
    }
  });
});

function toggle(element) {
  var content = element.parentElement.parentElement.nextElementSibling.getElementsByClassName("content")[0];
  $(content).toggle("slow");
 }

 $(document).ready(function() {
   var loc = window.location;
   var url = loc.origin+loc.pathname+'data.json';
   $('#header #selector input').val(url);
   setup(url);
   $('#header #explore').click(function() {
      setup($('#header #selector input').val());
   });
 });

 function setup(jsonfile) {
   $.ajax({
     url: jsonfile,
     type: "GET",
     dataType: "json",
     success: function(data) {
       var resources = Object.keys(data['resources']);
       for(var i=0; i < resources.length; i++) {
         var resource = data['resources'][resources[i]];
         add_resource(resources[i], resource, i);
         $('#resource'+i).toggle();
       }
       add_resource_events();
       var anchor = window.location.hash.replace('!','');
       anchor = anchor.replace(/\//g,"\\/");
         anchor = anchor.replace(/:/g,'\\:');
       $(anchor).next().fadeToggle();
     },
     error: function(e) {
       $('.resources').remove()
     }
   });
 }

function showJSON() {
   var loc = window.location;
   var url = loc.origin+loc.pathname+'data.json';
   window.open(url,"_self")
}

function toggleMethods(i) {
  event.stopPropagation();
  $('#resource'+i).fadeToggle();
}
function add_resource_events() {
  $(".resource").hover(function(){
    $(this).css("background", "#f5f5f5");
    $(this).children('div').children().css('color', 'black');
  }, function(){
    $(this).css("background", "#fff");
    $(this).children('div').children().css('color', '#999');
  });
  $('.resource').click(function(event) {
    event.stopPropagation();
    $(event.delegateTarget).next().fadeToggle();
  });
}
function add_resource(resource, config, i) {
  var html  = '
';
      html += '
  '+resource+'
';
      html += '
'+config['title']+'
';
      html += '
 Show/Hide | Raw
';
      html += '
';
      html += add_section(resource, config['sections']['config'], config['sections']['entries'], i);
    $('.resources').append(html);
    $('#resource'+i+' .content').toggle()
    $('#resource'+i+' .method .url a').click(function(event) {
        $(this).parent().parent().next().fadeToggle();
    });
}

function add_section(resource, config, entries, i) {
  var html  = '
';
  var methods = Object.keys(config);
  for(var i=0; i < methods.length; i++) {
        var field   = config[methods[i]];
        var content = entries[methods[i].toUpperCase()];
        html += '
';
        html += '
';
        html += '
'+methods[i]+'
';
        html += '
'+field['url']+'
';
        html += '
'+field['desc']+'
';
        html += '
';
        html += '
'+content+'
';
        html += '
';
  }
  html += '
';
  return html;
}
function capitalise(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
}
<|endoftext|>


<commit_before>var app = require('ridge');

var FormView = require('ridge/views/form-styling');

module.exports = FormView.extend({
	events: {
		'submit': 'submit'
	},

	submit: function(e) {
		e.preventDefault();

		var query = [];

		_.each(this.$el.prop('elements'), function(elem) {
			if (elem.name && elem.value)
				query.push(encodeURIComponent(elem.name) + '=' + encodeURIComponent(elem.value).replace('%20', '+'));
		});

		var url = '/' + Backbone.history.fragment.split('?')[0];

		if (query.length) url += '?' + query.join('&');

		Backbone.history.navigate(url, { trigger: true });
	},

	initialize: function() {
		this.listenTo(this.state, 'change:query', this.attach);
	},

	attach: function(model, value) {
		var query = this.state.get('query');

		_.each(this.$el.prop('elements'), function(elem) {
			if (elem.name)
				$(elem).val(query[elem.name]).trigger('change');
		});
	}
});
<commit_msg>Removed app and set query to empty object if null.<commit_after>var FormView = require('ridge/views/form-styling');

module.exports = FormView.extend({
	events: {
		'submit': 'submit'
	},

	submit: function(e) {
		e.preventDefault();

		var query = [];

		_.each(this.$el.prop('elements'), function(elem) {
			if (elem.name && elem.value)
				query.push(encodeURIComponent(elem.name) + '=' + encodeURIComponent(elem.value).replace('%20', '+'));
		});

		var url = '/' + Backbone.history.fragment.split('?')[0];

		if (query.length) url += '?' + query.join('&');

		Backbone.history.navigate(url, { trigger: true });
	},

	initialize: function() {
		this.listenTo(this.state, 'change:query', this.attach);
	},

	attach: function(model, value) {
		var query = this.state.get('query') || {};

		_.each(this.$el.prop('elements'), function(elem) {
			if (elem.name)
				$(elem).val(query[elem.name]).trigger('change');
		});
	}
});
<|endoftext|>


<commit_before>/* jslint node: true, esnext: true */
import File from './File';

export default class Package extends File {

  async templateRepo() {
    const content = await this.originalContent();
    const pkg = JSON.parse(content);
    if (pkg.template !== undefined && pkg.template.repository !== undefined) {
      const m = pkg.template.repository.url.match(/github.com\/(.*)\.git$/);
      return m[1];
    }

    return undefined;
  }

  get merge() {
    return Promise.all([this.originalContent(), this.templateContent()]).then(contents => {
      const original = contents[0];
      const target = JSON.parse(contents[0]);
      const template = JSON.parse(contents[1]);

      const messages = ['chore: update package.json from template'];

      const properties = this.context.properties;

      if (target.module !== undefined && !target.module.match(/\{\{module\}\}/)) {
        properties.module = target.module;
      }

      properties.main = target.main && !target.main.match(/\{\{main\}\}/) ? target.main : 'dist/index.js';

      const deepPropeties = ['scripts', 'devDependencies', 'engines'];

      let extraBuild, buildOutput;

      const keepScripts = {};

      if (target.scripts !== undefined) {
        if (target.scripts.test !== undefined) {
          if (target.scripts.test.match(/rollup/) || target.scripts.test.match(/istanbul.reporter.js/)) {
            // TODO how to detect special rollup test config ?
            keepScripts.test = target.scripts.test;
            keepScripts.pretest = target.scripts.pretest;
            keepScripts.cover = target.scripts.cover;
          }
        }

        [target.scripts.build, target.scripts.prepublish].filter(s => s !== undefined).forEach(script => {
          const ma = script.match(/--output=([^\s]+)/);
          if (ma) {
            buildOutput = ma[1];
          }

          const mb = script.match(/\&\&\s*(.+)/);
          if (mb) {
            extraBuild = mb[1];
          }
        });

        delete target.scripts.build;
      }

      deepPropeties.forEach(p => {
        if (target[p] === undefined) {
          target[p] = {};
        }
        Object.assign(target[p], template[p]);
      });

      Object.keys(target.devDependencies).forEach(d => {
        if (template.devDependencies[d] === '-') {
          delete target.devDependencies[d];
          messages.push(`chore(dependencies): remove ${d}`);
        }
      });

      Object.keys(template).forEach(p => {
        if (p !== 'template') {
          if (target[p] === undefined) {
            target[p] = template[p];
          }
        }
      });

      if (target.scripts.prepublish) {
        if (buildOutput !== undefined) {
          target.scripts.prepublish = target.scripts.prepublish.replace(/--output=([^\s]+)/,
            `--output=${buildOutput}`);
        }
        if (extraBuild !== undefined) {
          target.scripts.prepublish += ` && ${extraBuild}`;
        }
      }

      target.scripts = Object.assign(target.scripts, keepScripts);

      if (target.module === '{{module}}') {
        delete target.module;
      }

      if (target.contributors !== undefined && target.author !== undefined && target.author.name !== undefined) {
        const m = target.author.name.match(/(^[^<]+)<([^>]+)>/);
        if (m !== undefined) {
          const name = String(m[1]).replace(/^\s+|\s+$/g, '');
          const email = m[2];

          if (target.contributors.find(c => c.name === name && c.email === email)) {
            delete target.author;
          }
        }
      }

      if (target.keywords !== undefined) {
        delete target.keywords['npm-package-template'];
      }

      if (template.template !== undefined && template.template.keywords !== undefined) {
        Object.keys(template.template.keywords).forEach(r =>
          addKeyword(target, new RegExp(r), template.template.keywords[r])
        );
      }

      target.template = {
        repository: {
          url: `https://github.com/${this.context.templateRepo}.git`
        }
      };

      const rcj = this.context.files.get('rollup.config.js');
      const first = (rcj !== undefined) ?
        rcj.merge.then(m => {
          if (m.content) {
            if (!m.content.match(/rollup-plugin-node-resolve/)) {
              delete target.devDependencies['rollup-plugin-node-resolve'];
            }
            if (!m.content.match(/rollup-plugin-commonjs/)) {
              delete target.devDependencies['rollup-plugin-commonjs'];
            }
          }
        }) : Promise.resolve();

      return first.then(() => {
        const content = JSON.stringify(this.context.expand(target), undefined, 2);
        return {
          content: content,
          path: this.path,
          changed: original != content,
          message: messages.join('\n')
        };
      });
    });
  }
}

function addKeyword(pkg, regex, keyword) {
  if (pkg.name.match(regex)) {
    if (!pkg.keywords.find(k => k === keyword)) {
      pkg.keywords.push(keyword);
    }
  }
}
<commit_msg>fix:(Package): prevnet duplicate commit message<commit_after>/* jslint node: true, esnext: true */
import File from './File';

export default class Package extends File {

  async templateRepo() {
    const content = await this.originalContent();
    const pkg = JSON.parse(content);
    if (pkg.template !== undefined && pkg.template.repository !== undefined) {
      const m = pkg.template.repository.url.match(/github.com\/(.*)\.git$/);
      return m[1];
    }

    return undefined;
  }

  get merge() {
    return Promise.all([this.originalContent(), this.templateContent()]).then(contents => {
      const original = contents[0];
      const target = JSON.parse(contents[0]);
      const template = JSON.parse(contents[1]);
      const messages = [];

      const properties = this.context.properties;

      if (target.module !== undefined && !target.module.match(/\{\{module\}\}/)) {
        properties.module = target.module;
      }

      properties.main = target.main && !target.main.match(/\{\{main\}\}/) ? target.main : 'dist/index.js';

      const deepPropeties = ['scripts', 'devDependencies', 'engines'];

      let extraBuild, buildOutput;

      const keepScripts = {};

      if (target.scripts !== undefined) {
        if (target.scripts.test !== undefined) {
          if (target.scripts.test.match(/rollup/) || target.scripts.test.match(/istanbul.reporter.js/)) {
            // TODO how to detect special rollup test config ?
            keepScripts.test = target.scripts.test;
            keepScripts.pretest = target.scripts.pretest;
            keepScripts.cover = target.scripts.cover;
          }
        }

        [target.scripts.build, target.scripts.prepublish].filter(s => s !== undefined).forEach(script => {
          const ma = script.match(/--output=([^\s]+)/);
          if (ma) {
            buildOutput = ma[1];
          }

          const mb = script.match(/\&\&\s*(.+)/);
          if (mb) {
            extraBuild = mb[1];
          }
        });

        delete target.scripts.build;
      }

      deepPropeties.forEach(p => {
        if (target[p] === undefined) {
          target[p] = {};
        }
        Object.assign(target[p], template[p]);
      });

      Object.keys(target.devDependencies).forEach(d => {
        if (template.devDependencies[d] === '-') {
          delete target.devDependencies[d];
          messages.push(`chore(dependencies): remove ${d}`);
        }
      });

      Object.keys(template).forEach(p => {
        if (p !== 'template') {
          if (target[p] === undefined) {
            target[p] = template[p];
          }
        }
      });

      if (target.scripts.prepublish) {
        if (buildOutput !== undefined) {
          target.scripts.prepublish = target.scripts.prepublish.replace(/--output=([^\s]+)/,
            `--output=${buildOutput}`);
        }
        if (extraBuild !== undefined) {
          target.scripts.prepublish += ` && ${extraBuild}`;
        }
      }

      target.scripts = Object.assign(target.scripts, keepScripts);

      if (target.module === '{{module}}') {
        delete target.module;
      }

      if (target.contributors !== undefined && target.author !== undefined && target.author.name !== undefined) {
        const m = target.author.name.match(/(^[^<]+)<([^>]+)>/);
        if (m !== undefined) {
          const name = String(m[1]).replace(/^\s+|\s+$/g, '');
          const email = m[2];

          if (target.contributors.find(c => c.name === name && c.email === email)) {
            delete target.author;
          }
        }
      }

      if (target.keywords !== undefined) {
        delete target.keywords['npm-package-template'];
      }

      if (template.template !== undefined && template.template.keywords !== undefined) {
        Object.keys(template.template.keywords).forEach(r =>
          addKeyword(target, new RegExp(r), template.template.keywords[r])
        );
      }

      target.template = {
        repository: {
          url: `https://github.com/${this.context.templateRepo}.git`
        }
      };

      const rcj = this.context.files.get('rollup.config.js');
      const first = (rcj !== undefined) ?
        rcj.merge.then(m => {
          if (m.content) {
            if (!m.content.match(/rollup-plugin-node-resolve/)) {
              delete target.devDependencies['rollup-plugin-node-resolve'];
            }
            if (!m.content.match(/rollup-plugin-commonjs/)) {
              delete target.devDependencies['rollup-plugin-commonjs'];
            }
          }
        }) : Promise.resolve();

      if (messages.length === 0) {
        messages.push('chore: update package.json from template');
      }

      return first.then(() => {
        const content = JSON.stringify(this.context.expand(target), undefined, 2);
        return {
          content: content,
          path: this.path,
          changed: original != content,
          message: messages.join('\n')
        };
      });
    });
  }
}

function addKeyword(pkg, regex, keyword) {
  if (pkg.name.match(regex)) {
    if (!pkg.keywords.find(k => k === keyword)) {
      pkg.keywords.push(keyword);
    }
  }
}
<|endoftext|>


<commit_before>var restify = require('restify'),
    request = require('request'),
    rand = require('csprng'),
    sha1 = require('sha1'),
    uuid = require('node-uuid');

function validateHTTP(req, res, next) {
    // checks to see if the username is in the URL
    if (req.params.user != req.authorization.basic.username) {
        return next(new restify.ForbiddenError('You can\'t access that user'));
    }
    // checks it contains  content type application/json
    if (req.headers['content-type'] !== 'application/json') {
        return next(new restify.UnsupportedMediaTypeError('Bad Content-Type'));
    }
    // checks if it has basic authorization
    if (req.authorization.scheme !== 'Basic') {
        return next(new restify.UnauthorizedError('Basic HTTP auth required'));
    }
}

module.exports.validateHTTP = validateHTTP;<commit_msg>Changed [0] in validateHTTP<commit_after>var restify = require('restify'),
    request = require('request'),
    rand = require('csprng'),
    sha1 = require('sha1'),
    uuid = require('node-uuid');

function validateHTTP(req, res, next) {
    // checks to see if the username is in the URL
    if (req.params.user[0] != req.authorization.basic.username) {
        return next(new restify.ForbiddenError('You can\'t access that user'));
    }
    // checks it contains  content type application/json
    if (req.headers['content-type'] !== 'application/json') {
        return next(new restify.UnsupportedMediaTypeError('Bad Content-Type'));
    }
    // checks if it has basic authorization
    if (req.authorization.scheme !== 'Basic') {
        return next(new restify.UnauthorizedError('Basic HTTP auth required'));
    }
}

module.exports.validateHTTP = validateHTTP;<|endoftext|>


<commit_before>$(function() {
    var statTable = {
        $tableBody: $("#statTableBody"),
        init: function(stats) {
            this.stats = stats;
            this.render();
        },
        render: function() {
            this.$tableBody.empty();
            for(var a = 0; a < this.stats.length; a++) {
                this.$tableBody.append(this.getTableRow(this.stats[a]));
            }

        },
        getTableRow: function(stat) {
            return "
"+stat.name+"	"+stat.value+"
";
        }
    };

    var workerTable = {
        $tableBody: $("#workerTableBody"),
        init: function(workers) {
            this.workers = workers;
            this.render();
        },
        render: function() {
            this.$tableBody.empty();
            for(var a = 0; a < this.workers.length; a++) {
                this.$tableBody.append(this.getTableRow(this.workers[a]));
            }

        },
        getTableRow: function(worker) {
            console.log(worker.lastRequestTime)
            var timeSinceCommunication = Math.round(100*((new Date() - new Date(worker.lastRequestTime)) / (1000*60))) / 100;
            return "
"+worker.workerID+"	"+timeSinceCommunication+" min
";
        }
    };
    workerTable.init(getWorkers());

    var throughput = getThroughput();
    var users = getNumActiveUsers();
    var averageUsersPerGame = 4;
    statTable.init([
        {name: "Throughput", value: throughput},
        {name: "Estimated time/game/user (Avg users/game = 4)", value: ((24*60*users)/(throughput*averageUsersPerGame)).toFixed(2) + " min"},
        {name: "Active Users", value: getNumActiveUsers()},
        {name: "Total Submissions", value: getNumSubmissions()}
    ]);
})
<commit_msg>Force status page to parse times as UTC.<commit_after>$(function() {
    var statTable = {
        $tableBody: $("#statTableBody"),
        init: function(stats) {
            this.stats = stats;
            this.render();
        },
        render: function() {
            this.$tableBody.empty();
            for(var a = 0; a < this.stats.length; a++) {
                this.$tableBody.append(this.getTableRow(this.stats[a]));
            }

        },
        getTableRow: function(stat) {
            return "
"+stat.name+"	"+stat.value+"
";
        }
    };

    var workerTable = {
        $tableBody: $("#workerTableBody"),
        init: function(workers) {
            this.workers = workers;
            this.render();
        },
        render: function() {
            this.$tableBody.empty();
            for(var a = 0; a < this.workers.length; a++) {
                this.$tableBody.append(this.getTableRow(this.workers[a]));
            }

        },
        getTableRow: function(worker) {
            console.log(worker.lastRequestTime)
            var timeSinceCommunication = Math.round(100*((new Date() - new Date(worker.lastRequestTime+"Z")) / (1000*60))) / 100;
            return "
"+worker.workerID+"	"+timeSinceCommunication+" min
";
        }
    };
    workerTable.init(getWorkers());

    var throughput = getThroughput();
    var users = getNumActiveUsers();
    var averageUsersPerGame = 4;
    statTable.init([
        {name: "Throughput", value: throughput},
        {name: "Estimated time/game/user (Avg users/game = 4)", value: ((24*60*users)/(throughput*averageUsersPerGame)).toFixed(2) + " min"},
        {name: "Active Users", value: getNumActiveUsers()},
        {name: "Total Submissions", value: getNumSubmissions()}
    ]);
})
<|endoftext|>


<commit_before>// ==UserScript==
// @name         Duolingo - Lesson Review
// @description  This script allows you to go back and review all the different challenges in a lesson.
// @match        *://www.duolingo.com/*
// @author       HodofHod
// @namespace    HodofHod
// @version      0.1.1
// ==/UserScript==

//Beware all who enter here. This code may be hideous and worse.
//I am not responsible for any damage done to your eyes, or the ears of those around you.

//TODO: Inject a stylesheet and use classes instead of .css()
//      Maybe get really fancy, and hijack Session and SessionView, and switch lessons with .set({positon,x}) and .render()
//          Needs work. Doesn't save grading. Replays wrong audio.

function inject() { //Inject the script into the document
	var script;
	for (var i = 0; i < arguments.length; i++) {
		if (typeof (arguments[i]) === 'function') {
			script = document.createElement('script');
			script.type = 'text/javascript';
			script.textContent = '(' + arguments[i].toString() + ')(jQuery)';
			document.head.appendChild(script);
		}
	}
}

inject(init);

function init(){
    console.log('Duolingo Lesson Review');
    var origNext         = duo.SessionView.prototype.next,
        origRendered     = duo.SessionView.prototype.rendered,
        origGraded       = duo.SessionView.prototype.graded,
        origShowFailView = duo.SessionView.prototype.showFailView,
        origShowEndView  = duo.SessionView.prototype.showEndView,
        origTimesUp      = duo.TimedSessionView.prototype.timesUp,
        origPushState    = window.history.pushState;

    if (/^\/practice|skill|word_practice\/.+/.test(window.location.pathname)){ //for the first time the script is loaded, check if we're already on a page.
        main();
    }
    window.history.pushState = function checkPage(a, b, c){  //Hijack the window's pushState so we know whenever duolingo navigates to a new page.
        /^\/practice|skill|word_practice\/.+/.test(c) ? main() : cleanup();
        return origPushState.call(this, a, b, c);
    };

    function cleanup(){
        $(document).off('.hh'); //unbind any handlers from previous lessons.
        $.extend(duo.SessionView.prototype, {
            next: origNext,
            rendered: origRendered,
            graded: origGraded,
            showFailView: origShowFailView,
            showEndView: origShowEndView
        });
        duo.TimedSessionView.prototype.timesUp = origTimesUp;
    }

    function main(){
        console.log('main');
        cleanup();
        add_arrows();

        var lessons = {},
            cur_lesson_id = 1,
            selected_lesson_id = cur_lesson_id,
            finished = false,
            failed = false,
            header, last_lesson_id,
            waiting_for_discussion_load = false,
            redesign = duo.user.get("ab_options").site_redesign_experiment ;

        function save_lesson(save_id){
            var app_class = $('#app').prop('class');
            lessons[save_id] = redesign ? [$('.player-container>footer, .player-main').clone(), $('#discussion-modal-container').clone(), $('#app').prop('class')]
                                        : [$('#app>div:not(.player-header)').clone(), $('#app').prop('class')];
        }

        function replace_lesson(replace_id){
            console.log('cur: ' + cur_lesson_id + ', old id: ' + selected_lesson_id + ', new id ' + replace_id);
            if (selected_lesson_id === replace_id){ return false; } //don't replace yourself with yourself.
            if (selected_lesson_id === cur_lesson_id || selected_lesson_id === 'end'){//if switching away from cur_lesson
                lessons[cur_lesson_id] = redesign ? [$('.player-container>footer, .player-main, #end-carousel').detach(), $('#discussion-modal-container').detach(), $('#app').prop('class')]
                                                  : [$('#app>div:not(.player-header)').detach(), $('#app').prop('class')];
            }else if (lessons[replace_id] === undefined){
                return false;
            }else{
                redesign ? $('.player-container>footer, .player-main, #end-carousel, .discussion-modal-container').remove()
                		 : $('#app>div:not(.player-header)').remove();
            }

            $(redesign?'.player-container':'#app').append(lessons[replace_id][0]);
            redesign && $('body').append(lessons[replace_id][1]);
            $('#app').prop('class', lessons[replace_id][redesign+1]);//tricky trick
            bind_discussion_toggle();//TODO: Remove the other?

            $('.token-wrapper:has(.non-space)').hover(function(){
                var a = $(this).outerWidth(),
                    b = $(this).find('.hint-table').outerWidth(),
                    c = (b / 2) - (a / 2);
                $(this).css('position','relative').find('.hint-table').toggle().css({left: -1*c+'px', top: '15px'});
            });

            //Disable all controls except for discuss
            if (replace_id !== cur_lesson_id){//switching not to cur
                $('#next_button, #continue_button, #show-report-options, #discussion-modal textarea').attr('disabled', 'disabled');
                $('#submit_button, #skip_button, #review_button, .twipsy\
                   #home-button, #fix_mistakes_button, #controls .tooltip').remove();

                var resume_button = $('<button id="resume_button" class="btn success large right" tabindex="20">Resume</button>');
                $('#next_button, #continue_button, #retry-button').after(resume_button).remove();

                if (finished && !failed){
                    $(redesign?'.player-container':'#app').prepend(header);
                }
            }else if (finished && !failed){//if switching to end of successful lesson, remove header.
                $('.player-header').detach();
            }else{ $('.twipsy').hide(); }

            selected_lesson_id = replace_id;
            select_cell(selected_lesson_id);
            activate_arrows();
        }

        function select_cell(cell_num){
            $('li[id^=element-]').find('.inner').andSelf().css({'box-shadow': '', 'border-right-width': '1px'});
            $('li#element-'+cell_num).find('.inner')
                                     .andSelf().css({'box-shadow': '1px 1px 3px black inset',
                                                     'border-right-width': '0px'});
            //TODO: Move out of select_cell(), only needs to run once at the beginning
            $('li[id^=element-]:first-child').css({'-webkit-border-radius': '9px 0 0 9px',
                                                  'border-radius': '9px 0 0 9px'});
            $('li[id^=element-]:last-child').css({'-webkit-border-radius': '0 9px 9px 0',
                                                  'border-radius': '0 9px 9px 0'});
        }

        //Hijack the rendered() function (it runs after each problem is rendered)
        duo.SessionView.prototype.rendered = function newRendered(){
            console.log('render');
            if ($('#prev-arrow, #next-arrow').length !== 2){
                add_arrows();
            }
            select_cell(selected_lesson_id);
            activate_arrows();
            return origRendered.apply(this, arguments);
        };

        //Hijack the function that switches lessons.
        duo.SessionView.prototype.next = function newNext(){
            if ($('#discussion-toggle').size() && !$("#discussion-modal").size()){
                waiting_for_discussion_load = true;
                console.log('wait for discussions to finish loading');
            } else {
                cur_lesson_id = (this.model.get('position') + 1); //0-indexed
                save_lesson(cur_lesson_id);
                cur_lesson_id += 1;
                selected_lesson_id = cur_lesson_id;
                return origNext.apply(this, arguments);
            }
        };

        duo.SessionView.prototype.graded = function(){
            var solution = this.model.getSubmittedSolution();
            origGraded.apply(this, arguments);
            if (solution.get('incorrect') && !solution.get('try-again')){
                $('li#element-' + cur_lesson_id + '>.inner').andSelf()
                    .css('background-image', '-webkit-linear-gradient(top, #EE6969, #FF0000)')
                    .css('background-image', '-moz-linear-gradient(center top , #EE6969, #FF0000)')
                    .css(redesign ? {'border': '1px solid #950000', 'border-left':'none'} : {});
            }
        }
        function bind_discussion_toggle(){
            $('#discussion-toggle').on('click', function(e){
                e.stopImmediatePropagation();
                $('#discussion-modal').modal('show');
                $('.close-modal-background, .modal-backdrop, .player-discussion>.close').on('click', function(){
                    $('#discussion-modal').modal('hide');
                });
            });
        }

        //Load the discussions so they're saved by the cloning.
        document.body.addEventListener('DOMNodeInserted', function (e) {
            if (redesign ? $(e.target).has('#discussion-toggle').length && e.target.id !== 'controls'
                           : e.target.id === 'discussion-modal-container'){
                $('').appendTo("head");
                $('#discussion-modal-container').hide();
                console.log('load discussions');
                $('#discussion-toggle').click();
                bind_discussion_toggle();
                document.body.addEventListener('DOMNodeInserted', function wait() {
                    if  ($('.modal-backdrop.in').length){
                        $('#discussion-modal').modal('toggle')
                        $('#discussion-modal-container').show();

                        $('.modal-backdrop.in, #modalcss').remove();
                        if (waiting_for_discussion_load === true){
                            waiting_for_discussion_load = false;
                            $('#next_button, #continue_button').click();
                        }
                        document.body.removeEventListener('DOMNodeInserted', wait);
                    }
                });
            }else if (finished && $(e.target).has('.session-end-footer').length){
                finish();
            }
        });

        $(document).on('click.hh', 'li[id^=element-]', function(){
            var clicked_id = parseInt(this.id.replace('element-', ''), 10);
            if (lessons[clicked_id] !== undefined){
                if (failed){ console.log('fail click'); $('#review_button').click(); }
                replace_lesson(clicked_id);
            }
        });

        $(document).on('click.hh', '#resume_button', function(){
            replace_lesson(cur_lesson_id);
            //TODO: See if this is necessary after the redesign.
            if (finished && ($('#end-carousel .left').length > 1 || !$('#end-carousel .active').length)){
                $('#end-carousel .item').removeClass('active next left');
                $('#end-carousel .item:eq(' +$('.dots .active').data('slide')+ ')').addClass('active')
                $(".carousel").carousel("pause")
            }
        });

        function finish(){
            var button = $('<button id="review_button" class="btn large btn-lg btn-standard right" style="margin:0 10px 0 0;">Review</button>'),
                loc = failed ? '#controls>' + (redesign ? '.col-right' : '.row>.right')
                             : (redesign ? '.session-end-footer' : 'div.buttons');
            failed ? $(loc).append(button) : $(loc).prepend(button);//Redesign CAN both be prepend
            !failed && redesign ? button.css({position:'absolute', left:'40px'})
                                : button.css('float','left');
            finished = true;
            last_lesson_id = cur_lesson_id;
            cur_lesson_id = 'end';
            selected_lesson_id = 'end';
            select_cell();//none
        }

        duo.SessionView.prototype.showFailView = function(){
            if ($('#discussion-toggle').size() && !$("#discussion-modal").size()){
                console.log('wait for discussions to finish loading');
                waiting_for_discussion_load = true;//TODO
            }
            save_lesson(cur_lesson_id);
            r = origShowFailView.apply(this, arguments);
            failed = true;
            finish();
            $('.close-fail').hide();
            add_arrows();
            return r;
        };

        duo.SessionView.prototype.showEndView = function(){
            //Timed out lessons don't need this. Timeouts will set finished to true earlier.
            cur_lesson_id -= !finished; //newNext() increments on the last one too, adjust for that.
            header = $('.player-header').detach();//TODO: Improve?
            origShowEndView.apply(this, arguments);
            finished = true; //TODO FIX THIS ONCE THE MIGRATION TO THE REDESIGN IS COMPLETE.
            //finish(); end view won't fully load by here. Instead, I'm adding an else if to the DOMNodeInserted binding
        };

        duo.TimedSessionView.prototype.timesUp = function(){
            save_lesson(cur_lesson_id);
            finished = true;
            origTimesUp.apply(this, arguments);
        }

        $(document).on('click.hh', '#review_button', function(){
            if (failed){
                save_lesson('end');
            }
            replace_lesson(last_lesson_id);
        });

        $(document).on('click.hh', '#prev-arrow, #next-arrow', function(){
            lesson_id = (this.id === 'prev-arrow') ? selected_lesson_id-1 : selected_lesson_id+1;
            if (selected_lesson_id === 'end'){
                $('#review_button').click();
            }else if (!lessons[lesson_id] && cur_lesson_id === 'end'){
                replace_lesson('end');
            }else{
                replace_lesson(lesson_id);
            }
        });

        function add_arrows(){
            $('#prev-arrow, #next-arrow').remove();//precaution
            arrow = $('').css({
                background: 'url("//d7mj4aqfscim2.cloudfront.net/images/sprite_mv_082bd900117422dec137f596afcc1708.png") no-repeat',
                width: '24px', height: '18px', float: 'left', 'pointer-events':'none', 'background-position': '-323px -130px'
            });

            arrow.clone().attr('id', 'prev-arrow').css({margin: redesign ? '31px 0 0 -15px' : '22px -30px 0 5px',
                     transform: 'rotate(-90deg)',
                     '-webkit-transform': 'rotate(-90deg)'
            }).prependTo('#progress-bar');

            arrow.clone().attr('id', 'next-arrow').css({margin: redesign ? '31px 0 0 0' : '22px 0 0 4px',
                     transform: 'rotate(90deg)',
                     '-webkit-transform': 'rotate(90deg)'
            }).appendTo('#progress-bar');

            activate_arrows();
        }

        function activate_arrows(){
            selected_lesson_id > 1 || selected_lesson_id === 'end' ? activate($('#prev-arrow')) : deactivate($('#prev-arrow'));
            selected_lesson_id !== cur_lesson_id ? activate($('#next-arrow')) : deactivate($('#next-arrow'));
            function activate($arrow){
                $arrow.css({'background-position':'-323px -178px',cursor:'pointer','pointer-events':''});
            }
            function deactivate($arrow){
                $arrow.css({'background-position':'-323px -130px',cursor:'initial','pointer-events':'none'});
            }
        }
    }
}
<commit_msg>Hide endview instead of removing it. Fixes animateGraph errors<commit_after>// ==UserScript==
// @name         Duolingo - Lesson Review
// @description  This script allows you to go back and review all the different challenges in a lesson.
// @match        *://www.duolingo.com/*
// @author       HodofHod
// @namespace    HodofHod
// @version      0.1.2
// ==/UserScript==

//Beware all who enter here. This code may be hideous and worse.
//I am not responsible for any damage done to your eyes, or the ears of those around you.

//TODO: Inject a stylesheet and use classes instead of .css()
//      Maybe get really fancy, and hijack Session and SessionView, and switch lessons with .set({positon,x}) and .render()
//          Needs work. Doesn't save grading. Replays wrong audio.

function inject() { //Inject the script into the document
	var script;
	for (var i = 0; i < arguments.length; i++) {
		if (typeof (arguments[i]) === 'function') {
			script = document.createElement('script');
			script.type = 'text/javascript';
			script.textContent = '(' + arguments[i].toString() + ')(jQuery)';
			document.head.appendChild(script);
		}
	}
}

inject(init);

function init(){
    console.log('Duolingo Lesson Review');
    var origNext         = duo.SessionView.prototype.next,
        origRendered     = duo.SessionView.prototype.rendered,
        origGraded       = duo.SessionView.prototype.graded,
        origShowFailView = duo.SessionView.prototype.showFailView,
        origShowEndView  = duo.SessionView.prototype.showEndView,
        origTimesUp      = duo.TimedSessionView.prototype.timesUp,
        origPushState    = window.history.pushState;

    if (/^\/practice|skill|word_practice\/.+/.test(window.location.pathname)){ //for the first time the script is loaded, check if we're already on a page.
        main();
    }
    window.history.pushState = function checkPage(a, b, c){  //Hijack the window's pushState so we know whenever duolingo navigates to a new page.
        /^\/practice|skill|word_practice\/.+/.test(c) ? main() : cleanup();
        return origPushState.call(this, a, b, c);
    };

    function cleanup(){
        $(document).off('.hh'); //unbind any handlers from previous lessons.
        $.extend(duo.SessionView.prototype, {
            next: origNext,
            rendered: origRendered,
            graded: origGraded,
            showFailView: origShowFailView,
            showEndView: origShowEndView
        });
        duo.TimedSessionView.prototype.timesUp = origTimesUp;
    }

    function main(){
        console.log('main');
        cleanup();
        add_arrows();

        var lessons = {},
            cur_lesson_id = 1,
            selected_lesson_id = cur_lesson_id,
            finished = false,
            failed = false,
            header, last_lesson_id,
            waiting_for_discussion_load = false,
            redesign = duo.user.get("ab_options").site_redesign_experiment ;

        function save_lesson(save_id){
            var app_class = $('#app').prop('class');
            lessons[save_id] = redesign ? [$('.player-container>footer, .player-main').clone(), $('#discussion-modal-container').clone(), $('#app').prop('class')]
                                        : [$('#app>div:not(.player-header)').clone(), $('#app').prop('class')];
        }

        function replace_lesson(replace_id){
            console.log('cur: ' + cur_lesson_id + ', old id: ' + selected_lesson_id + ', new id ' + replace_id);
            if (selected_lesson_id === replace_id){ return false; } //don't replace yourself with yourself.
            if (selected_lesson_id === cur_lesson_id || selected_lesson_id === 'end'){//if switching away from cur_lesson
                lessons[cur_lesson_id] = redesign ? [$('.player-container>footer, .player-main, #end-carousel').hide(), $('#discussion-modal-container').hide(), $('#app').prop('class')]
                                                  : [$('#app>div:not(.player-header)').detach(), $('#app').prop('class')];
            }else if (lessons[replace_id] === undefined){
                return false;
            }else{
                redesign ? $('#controls, .player-main, .discussion-modal-container').remove()
                		 : $('#app>div:not(.player-header)').remove();
            }

            $(redesign?'.player-container':'#app').append(lessons[replace_id][0].show());//.show() is for redesign success end view.
            redesign && $('body').append(lessons[replace_id][1]);
            $('#app').prop('class', lessons[replace_id][redesign+1]);//tricky trick
            bind_discussion_toggle();//TODO: Remove the other?

            $('.token-wrapper:has(.non-space)').hover(function(){
                var a = $(this).outerWidth(),
                    b = $(this).find('.hint-table').outerWidth(),
                    c = (b / 2) - (a / 2);
                $(this).css('position','relative').find('.hint-table').toggle().css({left: -1*c+'px', top: '15px'});
            });

            //Disable all controls except for discuss
            if (replace_id !== cur_lesson_id){//switching not to cur
                $('#next_button, #continue_button, #show-report-options, #discussion-modal textarea').attr('disabled', 'disabled');
                $('#submit_button, #skip_button, .twipsy\
                   #home-button, #fix_mistakes_button, #controls .tooltip').remove();
                $('.hint-table').hide();
                var resume_button = $('<button id="resume_button" class="btn success large right" tabindex="20">Resume</button>');
                $('#next_button, #continue_button, #retry-button').after(resume_button).remove();

                if (finished && !failed){
                    $(redesign?'.player-container':'#app').prepend(header);
                }
            }else if (finished && !failed){//if switching to end of successful lesson, remove header.
                $('.player-header').detach();
            }else{ $('.twipsy').hide(); }

            selected_lesson_id = replace_id;
            select_cell(selected_lesson_id);
        }

        function select_cell(cell_num){
            //TODO: For redesign: add the box-shadow to .inner only.
            //       Inherit b-color on .nothing, and reset on .done (red uses b-image, so it won't reset that);
            $('li[id^=element-]').find('.inner').andSelf().css({'box-shadow': '', 'border-right-width': '1px'});
            $('li#element-'+cell_num).find('.inner')
                                     .andSelf().css({'box-shadow': '1px 1px 3px black inset',
                                                     'border-right-width': '0px'});
            $('li[id^=element-]:first-child').css({'-webkit-border-radius': '9px 0 0 9px',
                                                  'border-radius': '9px 0 0 9px'});
            $('li[id^=element-]:last-child').css({'-webkit-border-radius': '0 9px 9px 0',
                                                  'border-radius': '0 9px 9px 0'});
            activate_arrows();
        }

        //Hijack the rendered() function (it runs after each problem is rendered)
        duo.SessionView.prototype.rendered = function newRendered(){
            console.log('render');
            if ($('#prev-arrow, #next-arrow').length !== 2){
                add_arrows();
            }
            select_cell(selected_lesson_id);
            return origRendered.apply(this, arguments);
        };

        //Hijack the function that switches lessons.
        duo.SessionView.prototype.next = function newNext(){
            if ($('#discussion-toggle').size() && !$("#discussion-modal").size()){
                waiting_for_discussion_load = true;
                console.log('wait for discussions to finish loading');
            } else {
                cur_lesson_id = (this.model.get('position') + 1); //0-indexed
                save_lesson(cur_lesson_id);
                cur_lesson_id += 1;
                selected_lesson_id = cur_lesson_id;
                return origNext.apply(this, arguments);
            }
        };

        duo.SessionView.prototype.graded = function(){
            var solution = this.model.getSubmittedSolution();
            origGraded.apply(this, arguments);
            if (solution.get('incorrect') && !solution.get('try-again')){
                $('li#element-' + cur_lesson_id + '>.inner').andSelf()
                    .css('background-image', '-webkit-linear-gradient(top, #EE6969, #FF0000)')
                    .css('background-image', '-moz-linear-gradient(center top , #EE6969, #FF0000)')
                    .css(redesign ? {'border': '1px solid #950000', 'border-left':'none'} : {});
            }
        }
        function bind_discussion_toggle(){
            $('#discussion-toggle').on('click', function(e){
                e.stopImmediatePropagation();
                $('#discussion-modal').modal('show');
                $('.close-modal-background, .modal-backdrop, .player-discussion>.close').on('click', function(){
                    $('#discussion-modal').modal('hide');
                });
            });
        }

        //Load the discussions so they're saved by the cloning.
        document.body.addEventListener('DOMNodeInserted', function (e) {
            if (redesign ? $(e.target).has('#discussion-toggle').length && e.target.id !== 'controls'
                           : e.target.id === 'discussion-modal-container'){
                $('').appendTo("head");
                $('#discussion-modal-container').hide();
                console.log('load discussions');
                $('#discussion-toggle').click();
                bind_discussion_toggle();
                document.body.addEventListener('DOMNodeInserted', function wait() {
                    if  ($('.modal-backdrop.in').length){
                        $('#discussion-modal').modal('toggle')
                        $('#discussion-modal-container').show();

                        $('.modal-backdrop.in, #modalcss').remove();
                        if (waiting_for_discussion_load === true){
                            waiting_for_discussion_load = false;
                            $('#next_button, #continue_button').click();
                        }
                        document.body.removeEventListener('DOMNodeInserted', wait);
                    }
                });
            }else if (finished && $(e.target).has('.session-end-footer').length){
                finish();
            }
        });

        $(document).on('click.hh', 'li[id^=element-]', function(){
            var clicked_id = parseInt(this.id.replace('element-', ''), 10);
            if (lessons[clicked_id] !== undefined){
                if (failed){ console.log('fail click'); $('#review_button').click(); }
                replace_lesson(clicked_id);
            }
        });

        $(document).on('click.hh', '#resume_button', function(){
            replace_lesson(cur_lesson_id);
            //TODO: See if this is necessary after the redesign.
            if (finished && ($('#end-carousel .left').length > 1 || !$('#end-carousel .active').length)){
                $('#end-carousel .item').removeClass('active next left');
                $('#end-carousel .item:eq(' +$('.dots .active').data('slide')+ ')').addClass('active')
                $(".carousel").carousel("pause")
            }
        });

        function finish(){
            var button = $('<button id="review_button" class="btn large btn-lg btn-standard right" style="margin:0 10px 0 0;">Review</button>'),
                loc = failed ? '#controls>' + (redesign ? '.col-right' : '.row>.right')
                             : (redesign ? '.session-end-footer' : 'div.buttons');
            failed ? $(loc).append(button) : $(loc).prepend(button);//Redesign CAN both be prepend
            !failed && redesign ? button.css({position:'absolute', left:'40px'})
                                : button.css('float','left');
            finished = true;
            last_lesson_id = cur_lesson_id;
            cur_lesson_id = 'end';
            selected_lesson_id = 'end';
            select_cell();//none
        }

        duo.SessionView.prototype.showFailView = function(){
            if ($('#discussion-toggle').size() && !$("#discussion-modal").size()){
                console.log('wait for discussions to finish loading');
                waiting_for_discussion_load = true;//TODO
            }
            save_lesson(cur_lesson_id);
            r = origShowFailView.apply(this, arguments);
            failed = true;
            finish();
            $('.close-fail').hide();
            add_arrows();
            return r;
        };

        duo.SessionView.prototype.showEndView = function(){
            //Timed out lessons don't need this. Timeouts will set finished to true earlier.
            cur_lesson_id -= !finished; //newNext() increments on the last one too, adjust for that.
            header = $('.player-header').detach();//TODO: Improve?
            origShowEndView.apply(this, arguments);
            finished = true; //TODO FIX THIS ONCE THE MIGRATION TO THE REDESIGN IS COMPLETE.
            //finish(); end view won't fully load by here. Instead, I'm adding an else if to the DOMNodeInserted binding
        };

        duo.TimedSessionView.prototype.timesUp = function(){
            save_lesson(cur_lesson_id);
            finished = true;
            origTimesUp.apply(this, arguments);
        }

        $(document).on('click.hh', '#review_button', function(){
            if (failed){
                save_lesson('end');
            }
            replace_lesson(last_lesson_id);
        });

        $(document).on('click.hh', '#prev-arrow, #next-arrow', function(){
            lesson_id = (this.id === 'prev-arrow') ? selected_lesson_id-1 : selected_lesson_id+1;
            if (selected_lesson_id === 'end'){
                $('#review_button').click();
            }else if (!lessons[lesson_id] && cur_lesson_id === 'end'){
                replace_lesson('end');
            }else{
                replace_lesson(lesson_id);
            }
        });

        function add_arrows(){
            $('#prev-arrow, #next-arrow').remove();//precaution
            arrow = $('').css({
                background: 'url("//d7mj4aqfscim2.cloudfront.net/images/sprite_mv_082bd900117422dec137f596afcc1708.png") no-repeat',
                width: '24px', height: '18px', float: 'left', 'pointer-events':'none', 'background-position': '-323px -130px'
            });

            arrow.clone().attr('id', 'prev-arrow').css({margin: redesign ? '31px 0 0 -15px' : '22px -30px 0 5px',
                     transform: 'rotate(-90deg)',
                     '-webkit-transform': 'rotate(-90deg)'
            }).prependTo('#progress-bar');

            arrow.clone().attr('id', 'next-arrow').css({margin: redesign ? '31px 0 0 0' : '22px 0 0 4px',
                     transform: 'rotate(90deg)',
                     '-webkit-transform': 'rotate(90deg)'
            }).appendTo('#progress-bar');

            activate_arrows();
        }

        function activate_arrows(){
            selected_lesson_id > 1 || selected_lesson_id === 'end' ? activate($('#prev-arrow')) : deactivate($('#prev-arrow'));
            selected_lesson_id !== cur_lesson_id ? activate($('#next-arrow')) : deactivate($('#next-arrow'));
            function activate($arrow){
                $arrow.css({'background-position':'-323px -178px',cursor:'pointer','pointer-events':''});
            }
            function deactivate($arrow){
                $arrow.css({'background-position':'-323px -130px',cursor:'initial','pointer-events':'none'});
            }
        }
    }
}
<|endoftext|>


<commit_before>/*
 *  // Theme selector
 *  // Select your favorite code coloring
 */

define(["require"], function(require) {
    "use strict";

    var themes = {
        Default: "./themes/theme_default.css",
        _3024_Dark : "./themes/base16-3024-dark.css",
        _3024_Light : "./themes/base16-3024-light.css",
        Apathy_Dark : "./themes/base16-apathy-dark.css",
        Apathy_Light : "./themes/base16-apathy-light.css",
        Ashes_Dark : "./themes/base16-ashes-dark.css",
        Ashes_Light : "./themes/base16-ashes-light.css",
        Atelierdune_Dark : "./themes/base16-atelierdune-dark.css",
        Atelierdune_Light : "./themes/base16-atelierdune-light.css",
        Atelierforest_Dark : "./themes/base16-atelierforest-dark.css",
        Atelierforest_Light : "./themes/base16-atelierforest-light.css",
        Atelierheath_Dark : "./themes/base16-atelierheath-dark.css",
        Atelierheath_Light : "./themes/base16-atelierheath-light.css",
        Atelierlakeside_Dark : "./themes/base16-atelierlakeside-dark.css",
        Atelierlakeside_Light : "./themes/base16-atelierlakeside-light.css",
        Atelierseaside_Dark : "./themes/base16-atelierseaside-dark.css",
        Atelierseaside_Light : "./themes/base16-atelierseaside-light.css",
        Bespin_Dark : "./themes/base16-bespin-dark.css",
        Bespin_Light : "./themes/base16-bespin-light.css",
        Brewer_Dark : "./themes/base16-brewer-dark.css",
        Brewer_Light : "./themes/base16-brewer-light.css",
        Bright_Dark : "./themes/base16-bright-dark.css",
        Bright_Light : "./themes/base16-bright-light.css",
        Chalk_Dark : "./themes/base16-chalk-dark.css",
        Chalk_Light : "./themes/base16-chalk-light.css",
        Codeschool_Dark : "./themes/base16-codeschool-dark.css",
        Codeschool_Light : "./themes/base16-codeschool-light.css",
        Colors_Dark : "./themes/base16-colors-dark.css",
        Colors_Light : "./themes/base16-colors-light.css",
        Default_Dark : "./themes/base16-default-dark.css",
        Default_Light : "./themes/base16-default-light.css",
        Eighties_Dark : "./themes/base16-eighties-dark.css",
        Eighties_Light : "./themes/base16-eighties-light.css",
        Embers_Dark : "./themes/base16-embers-dark.css",
        Embers_Light : "./themes/base16-embers-light.css",
        Flat_Dark : "./themes/base16-flat-dark.css",
        Flat_Light : "./themes/base16-flat-light.css",
        Google_Dark : "./themes/base16-google-dark.css",
        Google_Light : "./themes/base16-google-light.css",
        Grayscale_Dark : "./themes/base16-grayscale-dark.css",
        Grayscale_Light : "./themes/base16-grayscale-light.css",
        Greenscreen_Dark : "./themes/base16-greenscreen-dark.css",
        Greenscreen_Light : "./themes/base16-greenscreen-light.css",
        Harmonic16_Dark : "./themes/base16-harmonic16-dark.css",
        Harmonic16_Light : "./themes/base16-harmonic16-light.css",
        Hopscotch_Dark : "./themes/base16-hopscotch-dark.css",
        Hopscotch_Light : "./themes/base16-hopscotch-light.css",
        Isotope_Dark : "./themes/base16-isotope-dark.css",
        Isotope_Light : "./themes/base16-isotope-light.css",
        Londontube_Dark : "./themes/base16-londontube-dark.css",
        Londontube_Light : "./themes/base16-londontube-light.css",
        Marrakesh_Dark : "./themes/base16-marrakesh-dark.css",
        Marrakesh_Light : "./themes/base16-marrakesh-light.css",
        Mocha_Dark : "./themes/base16-mocha-dark.css",
        Mocha_Light : "./themes/base16-mocha-light.css",
        Monokai_Dark : "./themes/base16-monokai-dark.css",
        Monokai_Light : "./themes/base16-monokai-light.css",
        Ocean_Dark : "./themes/base16-ocean-dark.css",
        Ocean_Light : "./themes/base16-ocean-light.css",
        Paraiso_Dark : "./themes/base16-paraiso-dark.css",
        Paraiso_Light : "./themes/base16-paraiso-light.css",
        Pop_Dark : "./themes/base16-pop-dark.css",
        Pop_Light : "./themes/base16-pop-light.css",
        Railscasts_Dark : "./themes/base16-railscasts-dark.css",
        Railscasts_Light : "./themes/base16-railscasts-light.css",
        Shapeshifter_Dark : "./themes/base16-shapeshifter-dark.css",
        Shapeshifter_Light : "./themes/base16-shapeshifter-light.css",
        Solarized_Dark : "./themes/base16-solarized-dark.css",
        Solarized_Light : "./themes/base16-solarized-light.css",
        Summerfruit_Dark : "./themes/base16-summerfruit-dark.css",
        Summerfruit_Light : "./themes/base16-summerfruit-light.css",
        Tomorrow_Dark : "./themes/base16-tomorrow-dark.css",
        Tomorrow_Light : "./themes/base16-tomorrow-light.css",
        Twilight_Dark : "./themes/base16-twilight-dark.css",
        Twilight_Light : "./themes/base16-twilight-light.css",
    };

    function add_to_toolbar(current_theme) {

        var ipython_toolbar = $(IPython.toolbar.element),
        	label = $('<span/>').addClass("navbar-text permissions-list").text('Select a theme:'),
        	select = $('<select/>').attr('id', 'permissions-select').attr('class', 'permissions-list form-control select-xs');

        // Add label to the toolbar
        ipython_toolbar.append(label).append(select);

        // Add themes to the selector
        for (var key in themes){
            select.append($('<option/>').attr('value', key).text(key));
        }

        // If actually a theme, select it
        if (current_theme){
            select.val(current_theme);
        }

        // Add an action when value is changed
        select.change( function(){
            theme_toggle($(this).val());
        });

    }

    function load_css(theme) {

        // Create a link element to attach the styles
        var link = document.createElement("link");
        link.type = "text/css";
        link.rel = "stylesheet";
        link.href = require.toUrl(themes[theme]);
        link.id = theme + "-css";
        document.getElementsByTagName("head")[0].appendChild(link);
    }

    function unload_css(theme) {

        // Select the theme to unload and remove the link node
        var css = document.getElementById(theme + "-css");
        css.parentNode.removeChild(css);
    }

    function theme_toggle(new_theme) {

        var current_theme = window.localStorage.getItem('nb-theme');

        // Check if there is a theme actually loaded
        if (current_theme) {
            unload_css(current_theme);
        }

		load_css(new_theme);
        window.localStorage.setItem('nb-theme', new_theme);
    }

    function load_theme_selector() {

        var current_theme = window.localStorage.getItem('nb-theme');

        add_to_toolbar(current_theme);

        if (current_theme) {
            load_css(current_theme);
        }

    }

    return {
        load_ipython_extension: load_theme_selector
    };

});
<commit_msg>change the toolbar message<commit_after>/*
 *  // Theme selector
 *  // Select your favorite code coloring
 */

define(["require"], function(require) {
    "use strict";

    var themes = {
        Default: "./themes/theme_default.css",
        _3024_Dark : "./themes/base16-3024-dark.css",
        _3024_Light : "./themes/base16-3024-light.css",
        Apathy_Dark : "./themes/base16-apathy-dark.css",
        Apathy_Light : "./themes/base16-apathy-light.css",
        Ashes_Dark : "./themes/base16-ashes-dark.css",
        Ashes_Light : "./themes/base16-ashes-light.css",
        Atelierdune_Dark : "./themes/base16-atelierdune-dark.css",
        Atelierdune_Light : "./themes/base16-atelierdune-light.css",
        Atelierforest_Dark : "./themes/base16-atelierforest-dark.css",
        Atelierforest_Light : "./themes/base16-atelierforest-light.css",
        Atelierheath_Dark : "./themes/base16-atelierheath-dark.css",
        Atelierheath_Light : "./themes/base16-atelierheath-light.css",
        Atelierlakeside_Dark : "./themes/base16-atelierlakeside-dark.css",
        Atelierlakeside_Light : "./themes/base16-atelierlakeside-light.css",
        Atelierseaside_Dark : "./themes/base16-atelierseaside-dark.css",
        Atelierseaside_Light : "./themes/base16-atelierseaside-light.css",
        Bespin_Dark : "./themes/base16-bespin-dark.css",
        Bespin_Light : "./themes/base16-bespin-light.css",
        Brewer_Dark : "./themes/base16-brewer-dark.css",
        Brewer_Light : "./themes/base16-brewer-light.css",
        Bright_Dark : "./themes/base16-bright-dark.css",
        Bright_Light : "./themes/base16-bright-light.css",
        Chalk_Dark : "./themes/base16-chalk-dark.css",
        Chalk_Light : "./themes/base16-chalk-light.css",
        Codeschool_Dark : "./themes/base16-codeschool-dark.css",
        Codeschool_Light : "./themes/base16-codeschool-light.css",
        Colors_Dark : "./themes/base16-colors-dark.css",
        Colors_Light : "./themes/base16-colors-light.css",
        Default_Dark : "./themes/base16-default-dark.css",
        Default_Light : "./themes/base16-default-light.css",
        Eighties_Dark : "./themes/base16-eighties-dark.css",
        Eighties_Light : "./themes/base16-eighties-light.css",
        Embers_Dark : "./themes/base16-embers-dark.css",
        Embers_Light : "./themes/base16-embers-light.css",
        Flat_Dark : "./themes/base16-flat-dark.css",
        Flat_Light : "./themes/base16-flat-light.css",
        Google_Dark : "./themes/base16-google-dark.css",
        Google_Light : "./themes/base16-google-light.css",
        Grayscale_Dark : "./themes/base16-grayscale-dark.css",
        Grayscale_Light : "./themes/base16-grayscale-light.css",
        Greenscreen_Dark : "./themes/base16-greenscreen-dark.css",
        Greenscreen_Light : "./themes/base16-greenscreen-light.css",
        Harmonic16_Dark : "./themes/base16-harmonic16-dark.css",
        Harmonic16_Light : "./themes/base16-harmonic16-light.css",
        Hopscotch_Dark : "./themes/base16-hopscotch-dark.css",
        Hopscotch_Light : "./themes/base16-hopscotch-light.css",
        Isotope_Dark : "./themes/base16-isotope-dark.css",
        Isotope_Light : "./themes/base16-isotope-light.css",
        Londontube_Dark : "./themes/base16-londontube-dark.css",
        Londontube_Light : "./themes/base16-londontube-light.css",
        Marrakesh_Dark : "./themes/base16-marrakesh-dark.css",
        Marrakesh_Light : "./themes/base16-marrakesh-light.css",
        Mocha_Dark : "./themes/base16-mocha-dark.css",
        Mocha_Light : "./themes/base16-mocha-light.css",
        Monokai_Dark : "./themes/base16-monokai-dark.css",
        Monokai_Light : "./themes/base16-monokai-light.css",
        Ocean_Dark : "./themes/base16-ocean-dark.css",
        Ocean_Light : "./themes/base16-ocean-light.css",
        Paraiso_Dark : "./themes/base16-paraiso-dark.css",
        Paraiso_Light : "./themes/base16-paraiso-light.css",
        Pop_Dark : "./themes/base16-pop-dark.css",
        Pop_Light : "./themes/base16-pop-light.css",
        Railscasts_Dark : "./themes/base16-railscasts-dark.css",
        Railscasts_Light : "./themes/base16-railscasts-light.css",
        Shapeshifter_Dark : "./themes/base16-shapeshifter-dark.css",
        Shapeshifter_Light : "./themes/base16-shapeshifter-light.css",
        Solarized_Dark : "./themes/base16-solarized-dark.css",
        Solarized_Light : "./themes/base16-solarized-light.css",
        Summerfruit_Dark : "./themes/base16-summerfruit-dark.css",
        Summerfruit_Light : "./themes/base16-summerfruit-light.css",
        Tomorrow_Dark : "./themes/base16-tomorrow-dark.css",
        Tomorrow_Light : "./themes/base16-tomorrow-light.css",
        Twilight_Dark : "./themes/base16-twilight-dark.css",
        Twilight_Light : "./themes/base16-twilight-light.css",
    };

    function add_to_toolbar(current_theme) {

        var ipython_toolbar = $(IPython.toolbar.element),
        	label = $('<span/>').addClass("navbar-text permissions-list").text('Theme:'),
        	select = $('<select/>').attr('id', 'permissions-select').attr('class', 'permissions-list form-control select-xs');

        // Add label to the toolbar
        ipython_toolbar.append(label).append(select);

        // Add themes to the selector
        for (var key in themes){
            select.append($('<option/>').attr('value', key).text(key));
        }

        // If actually a theme, select it
        if (current_theme){
            select.val(current_theme);
        }

        // Add an action when value is changed
        select.change( function(){
            theme_toggle($(this).val());
        });

    }

    function load_css(theme) {

        // Create a link element to attach the styles
        var link = document.createElement("link");
        link.type = "text/css";
        link.rel = "stylesheet";
        link.href = require.toUrl(themes[theme]);
        link.id = theme + "-css";
        document.getElementsByTagName("head")[0].appendChild(link);
    }

    function unload_css(theme) {

        // Select the theme to unload and remove the link node
        var css = document.getElementById(theme + "-css");
        css.parentNode.removeChild(css);
    }

    function theme_toggle(new_theme) {

        var current_theme = window.localStorage.getItem('nb-theme');

        // Check if there is a theme actually loaded
        if (current_theme) {
            unload_css(current_theme);
        }

		load_css(new_theme);
        window.localStorage.setItem('nb-theme', new_theme);
    }

    function load_theme_selector() {

        var current_theme = window.localStorage.getItem('nb-theme');

        add_to_toolbar(current_theme);

        if (current_theme) {
            load_css(current_theme);
        }

    }

    return {
        load_ipython_extension: load_theme_selector
    };

});
<|endoftext|>


<commit_before>function Bowling (frames) {
  this.frames = new Frames();
  this.FRAME_COUNT_LIMIT = 10;
  this.STRIKE = 10;
  this._isFirstBowlOfFrame = true;
}
Bowling.prototype.toggleFirstBowlOfGame = function (value) {
  this._isFirstBowlOfFrame = this._isFirstBowlOfFrame ? false : true;
};
Bowling.prototype.randomNumberOfPins = function () {
  this.previousNum = ( this.STRIKE - this.frames._frames.slice(-1).pop() );
  if (this._isFirstBowlOfFrame) {
    return Math.floor( Math.random () * ( this.FRAME_COUNT_LIMIT - 0 + 1)) + 0;
  } else {
    return Math.floor( Math.random () * ( this.previousNum - 0 + 1)) + 0;
  }
};
Bowling.prototype.finalScore = function () {
  this.frameTotal = 0;

  for( var i in this.frames._frames )
  { this.frameTotal += this.frames._frames[i]; }

  this.frameTotal += this.frames._bonusPoints;
  return this.frameTotal;
};
Bowling.prototype.bowl = function (number) {
  if(this.frames._frameCounter == this.FRAME_COUNT_LIMIT) throw Error('Game over!!');
  this.frames.setIsStrike(false);
  var pins = number || this.randomNumberOfPins();

  if (this.frames._bonusCounter >= 1) this.frames.applyBonus(pins);

  this.toggleFirstBowlOfGame();

  if (pins === this.STRIKE) this.frames.strike();
  if (pins !== this.STRIKE) {
    this.applyPinsToFrame(pins);
    this.frames.spareChecker(pins);
  }
  return pins;
};
Bowling.prototype.applyPinsToFrame = function (pins) {
  this.frames.setFrames(pins);
  this.frames.calculateFrameCount();
  this.frames._currentFrame.push(pins);
};
Bowling.prototype.resetPins = function () {
  this.frames.resetPins();
  this._isFirstBowlOfFrame = true;
};
<commit_msg>Resolved bug in random number generator<commit_after>function Bowling (frames) {
  this.frames = new Frames();
  this.FRAME_COUNT_LIMIT = 10;
  this.STRIKE = 10;
  this._isFirstBowlOfFrame = true;
}
Bowling.prototype.toggleFirstBowlOfGame = function (value) {
  this._isFirstBowlOfFrame = this._isFirstBowlOfFrame ? false : true;
};
Bowling.prototype.randomNumberOfPins = function () {
  this.previousNum = ( this.STRIKE - this.frames._frames.slice(-1).pop() );
  if (this._isFirstBowlOfFrame) {
    return Math.floor( Math.random () * ( this.FRAME_COUNT_LIMIT - 0 + 1)) + 0;
  } else {
    return Math.floor( Math.random () * ( this.previousNum - 0 + 1)) + 0;
  }
};
Bowling.prototype.finalScore = function () {
  this.frameTotal = 0;

  for( var i in this.frames._frames )
  { this.frameTotal += this.frames._frames[i]; }

  this.frameTotal += this.frames._bonusPoints;
  return this.frameTotal;
};
Bowling.prototype.bowl = function (number) {
  if(this.frames._frameCounter == this.FRAME_COUNT_LIMIT) throw Error('Game over!!');
  this.frames.setIsStrike(false);
  var pins = number || this.randomNumberOfPins();

  if (this.frames._bonusCounter >= 1) this.frames.applyBonus(pins);

  this.toggleFirstBowlOfGame();

  if (pins === this.STRIKE) {
    this.frames.strike();
    this._isFirstBowlOfFrame = true;
  } else if (pins !== this.STRIKE) {
    this.applyPinsToFrame(pins);
    this.frames.spareChecker(pins);
  }
  return pins;
};
Bowling.prototype.applyPinsToFrame = function (pins) {
  this.frames.setFrames(pins);
  this.frames.calculateFrameCount();
  this.frames._currentFrame.push(pins);
};
Bowling.prototype.resetPins = function () {
  this.frames.resetPins();
  this._isFirstBowlOfFrame = true;
};
<|endoftext|>