<commit_before>enyo.kind({
	name: "App",
	kind: enyo.VFlexBox,
	published: {
		filename: "test.md"
	},
	components: [
		{kind: "EditorPanel", flex: 1,
			lazy: false,
			onLinkClick: "linkClick"
		},
		{kind: "AppMenu", lazy: false, components: [
			{caption: $L("Documents"), lazy: false, name:"docsMenu", components: [
				{caption: $L("Create New..."), onclick: "sendNew", className: "subtleitem"}
			]},
			{caption: $L("Share"), components: [
				{caption: $L("Dropbox"), onclick: "doDropbox"},
				{caption: $L("Email"), onclick: "doEmail"},
				{caption: $L("Print"), name:"print", onclick: "doPrint"}
			]},
			{caption: $L("Help"), components: [
				{caption: $L("Syntax"), onclick: "doSyntax"},
				{caption: $L("FAQ"), onclick: "doFAQ"},
				{caption: $L("Report a Bug"), onclick: "doBug"}
			]},
			]
		},
		{kind: "Scrim", name:"taboutscrim", layoutKind: "VFlexLayout", align:"center", pack:"center", style:"background-color: transparent; opacity: 1;", components: [
			{kind: "Image", src:"images/icon256.png", style: "opacity: 0.0;"}
		]},
		{kind: enyo.ApplicationEvents,
			onWindowDeactivated: "sleep",
			onWindowActivated: "wakeup",
			onUnload: "close"
		},
		{kind: "FileIO",
			onOpened: "handleOpened",
			onSaved: "handleSaved",
			onLogin: "handleLoginResult",
			onDirRead: "handleLoadFiles"
		},
		{name:"Demotext", kind:"Demotext" },
	],

	/* NEUE DATEI */

	sendNew: function(inSender, inResponse) {
		enyo.windows.openWindow("index.html", "", {wasLaunchedBy: window.name, action:"doNew"});
	},

	doNew: function() {
		this.$.fileIO.createNew();
	},

	/* DATEI ÖFFNEN */

	doLoadFiles: function(inSender, inEvent) {
		this.$.fileIO.listFiles();
	},

	handleLoadFiles: function(inSender, inResponse) {
		this.$.docsMenu.destroyControls();

		this.$.docsMenu.createComponent({
			caption: $L("Create New..."),
			onclick: "sendNew",
			owner: this, // this part is important as the owner is the one who listens for the events
			kind: "AppMenuItem", // you might not need this. Might be that components are automatically turned into AppMenuItems
			className: "subtleitem"
		});

		for(var i = 0; i < inResponse.length; i++) {
			this.$.docsMenu.createComponent({
				caption: inResponse[i].caption,
				onclick: "sendOpen",
				owner: this, // this part is important as the owner is the one who listens for the events
				kind: "AppMenuItem" // you might not need this. Might be that components are automatically turned into AppMenuItems
			});
		}
		this.$.docsMenu.render();
		this.$.appMenu.render();
	},

	sendOpen: function(inSender, inEvent) {
		var windows = enyo.windows.getWindows();

		for(i in windows) {
			if(enyo.windows.fetchWindow(windows[i].window.name).rootKind.getFilename() == inSender.caption + ".md") {
				enyo.windows.activate(undefined, windows[i].window.name);
				return;
			}
		}
		enyo.windows.openWindow("index.html", "", {wasLaunchedBy: window.name, action:"doOpen", filename: inSender.caption + ".md"});
	},

	doOpen: function(inFilename) {
		this.$.fileIO.readFile(inFilename);
	},

	handleOpened: function(inSender, inResponse) {
		if(!inResponse.err) {
			this.$.editorPanel.setContent(inResponse.content, inResponse.filename);
			setInterval(enyo.hitch(this, "doSave"),5000);
		}
		else {
			this.$.editorPanel.setActive(false);
		}
	},

	/* SPEICHERN */

	doSave: function(inSender, inEvent) {
		this.$.fileIO.saveFile(this.$.editorPanel.getContent());
	},

	handleSaved: function(inSender, inResponse) {
	},

	/* SYNC */

	doDropbox: function(inSender, inEvent) {
		this.$.fileIO.syncFile();
	},

	linkClick: function(inSender, inUrl, inAnchor) {
		if(inAnchor == "create")
			this.sendNew();
	},

	ready: function() {
		enyo.keyboard.setManualMode(true);
	},

	rendered: function() {
		this.$.editorPanel.render();
		if(enyo.windowParams) {
			if(enyo.windowParams.action) {
				enyo.keyboard.show();
				if(enyo.windowParams.action == "doOpen") {
					console.log("oeffne datei");
					this.doOpen(enyo.windowParams.filename);
				}
				if(enyo.windowParams.action == "doNew") {	// das muss irgendwie in rendered, ohne alles zu zerschmeissen
					console.log("neue datei");
					this.doNew();
				}
			}
			else {
				var lastfile = enyo.getCookie("lastfile") || "";
				if(lastfile == "") {
					enyo.keyboard.hide();
					this.$.editorPanel.setContent(this.$.Demotext.text, "");
					//this.$.editorPanel.setActive(false);
				}
				else {
					enyo.keyboard.show();
					this.doOpen(lastfile);
				}
			}
		}
		console.log(lastfile);
		//setInterval(enyo.hitch(this, "doSave"),5000);
		setInterval(enyo.hitch(this, "doLoadFiles"),15000);
		this.doLoadFiles();
	},

	/* BORING EVENTS */
	sleep: function() {
		//if(this.position == "down")
		//	this.$.top.node.style.height = enyo.fetchControlSize(this).h + "px";
		this.$.taboutscrim.show();
	},

	wakeup: function() {
		//this.$.top.node.style.height = (enyo.fetchControlSize(this).h - 55 - enyo.keyboard.height) + "px";
		this.$.taboutscrim.hide();
	},

	close: function() {
		this.$.fileIO.saveFile(this.$.editorPanel.getContent());
		enyo.setCookie("lastfile", this.$.fileIO.getFilename());
	},

	doPrint: function() {
		this.$.editorPanel.printDocument();
	},

	doEmail: function() {
		if(this.$.fileIO.getFilename() == "")
			return;
		var r = new enyo.PalmService();
		r.service = "palm://com.palm.applicationManager/";
		r.method = "open";
		r.call({id: "com.palm.app.email",
			params: {
				text:"See attachment", summary: new enyo.g11n.Template($L("Typewriter Document \"#{name}\"")).evaluate({name: this.$.fileIO.getFilename().basename(".md") }), attachments: [{fullPath: "file:///media/internal/Typewriter/" + this.$.fileIO.getFilename()}]
			}
		});
	},

	doSyntax: function(inSender) {
		var r = new enyo.PalmService();
		r.service = "palm://com.palm.applicationManager/";
		r.method = "open";
		r.call({target: "http://www.typewriterwebos.com/markdown/" + enyo.g11n.currentLocale() + "/"});
	},

	doFAQ: function(inSender) {
		var r = new enyo.PalmService();
		r.service = "palm://com.palm.applicationManager/";
		r.method = "open";
		r.call({target: "http://www.typewriterwebos.com/faq/" + enyo.g11n.currentLocale() + "/"});
	},

	doBug: function(inSender) {
		var r = new enyo.PalmService();
		r.service = "palm://com.palm.applicationManager/";
		r.method = "open";
		r.call({target: "http://www.typewriterwebos.com/report/" + enyo.g11n.currentLocale() + "/?version=" + enyo.fetchAppInfo().version + "&id=" + enyo.fetchAppInfo().id});
	},

	getFilename: function() {
		return this.$.fileIO.getFilename();
	}
})
<commit_msg>Sync einstellen wenn App im Hintergrund<commit_after>enyo.kind({
	name: "App",
	kind: enyo.VFlexBox,
	published: {
		filename: "test.md"
	},
	components: [
		{kind: "EditorPanel", flex: 1,
			lazy: false,
			onLinkClick: "linkClick"
		},
		{kind: "AppMenu", lazy: false, components: [
			{caption: $L("Documents"), lazy: false, name:"docsMenu", components: [
				{caption: $L("Create New..."), onclick: "sendNew", className: "subtleitem"}
			]},
			{caption: $L("Share"), components: [
				{caption: $L("Dropbox"), onclick: "doDropbox"},
				{caption: $L("Email"), onclick: "doEmail"},
				{caption: $L("Print"), name:"print", onclick: "doPrint"}
			]},
			{caption: $L("Help"), components: [
				{caption: $L("Syntax"), onclick: "doSyntax"},
				{caption: $L("FAQ"), onclick: "doFAQ"},
				{caption: $L("Report a Bug"), onclick: "doBug"}
			]},
			]
		},
		{kind: "Scrim", name:"taboutscrim", layoutKind: "VFlexLayout", align:"center", pack:"center", style:"background-color: transparent; opacity: 1;", components: [
			{kind: "Image", src:"images/icon256.png", style: "opacity: 0.0;"}
		]},
		{kind: enyo.ApplicationEvents,
			onWindowDeactivated: "sleep",
			onWindowActivated: "wakeup",
			onUnload: "close"
		},
		{kind: "FileIO",
			onOpened: "handleOpened",
			onSaved: "handleSaved",
			onLogin: "handleLoginResult",
			onDirRead: "handleLoadFiles"
		},
		{name:"Demotext", kind:"Demotext" },
	],

	/* NEUE DATEI */

	sendNew: function(inSender, inResponse) {
		enyo.windows.openWindow("index.html", "", {wasLaunchedBy: window.name, action:"doNew"});
	},

	doNew: function() {
		this.$.fileIO.createNew();
	},

	/* DATEI ÖFFNEN */

	doLoadFiles: function(inSender, inEvent) {
		this.$.fileIO.listFiles();
	},

	handleLoadFiles: function(inSender, inResponse) {
		this.$.docsMenu.destroyControls();

		this.$.docsMenu.createComponent({
			caption: $L("Create New..."),
			onclick: "sendNew",
			owner: this, // this part is important as the owner is the one who listens for the events
			kind: "AppMenuItem", // you might not need this. Might be that components are automatically turned into AppMenuItems
			className: "subtleitem"
		});

		for(var i = 0; i < inResponse.length; i++) {
			this.$.docsMenu.createComponent({
				caption: inResponse[i].caption,
				onclick: "sendOpen",
				owner: this, // this part is important as the owner is the one who listens for the events
				kind: "AppMenuItem" // you might not need this. Might be that components are automatically turned into AppMenuItems
			});
		}
		this.$.docsMenu.render();
		this.$.appMenu.render();
	},

	sendOpen: function(inSender, inEvent) {
		var windows = enyo.windows.getWindows();

		for(i in windows) {
			if(enyo.windows.fetchWindow(windows[i].window.name).rootKind.getFilename() == inSender.caption + ".md") {
				enyo.windows.activate(undefined, windows[i].window.name);
				return;
			}
		}
		enyo.windows.openWindow("index.html", "", {wasLaunchedBy: window.name, action:"doOpen", filename: inSender.caption + ".md"});
	},

	doOpen: function(inFilename) {
		this.$.fileIO.readFile(inFilename);
	},

	handleOpened: function(inSender, inResponse) {
		if(!inResponse.err) {
			this.$.editorPanel.setContent(inResponse.content, inResponse.filename);
			setInterval(enyo.hitch(this, "doSave"),5000);
		}
		else {
			this.$.editorPanel.setActive(false);
		}
	},

	/* SPEICHERN */

	doSave: function(inSender, inEvent) {
		this.$.fileIO.saveFile(this.$.editorPanel.getContent());
	},

	handleSaved: function(inSender, inResponse) {
	},

	/* SYNC */

	doDropbox: function(inSender, inEvent) {
		this.$.fileIO.syncFile();
	},

	linkClick: function(inSender, inUrl, inAnchor) {
		if(inAnchor == "create")
			this.sendNew();
	},

	ready: function() {
		enyo.keyboard.setManualMode(true);
	},

	rendered: function() {
		this.$.editorPanel.render();
		if(enyo.windowParams) {
			if(enyo.windowParams.action) {
				enyo.keyboard.show();
				if(enyo.windowParams.action == "doOpen") {
					console.log("oeffne datei");
					this.doOpen(enyo.windowParams.filename);
				}
				if(enyo.windowParams.action == "doNew") {	// das muss irgendwie in rendered, ohne alles zu zerschmeissen
					console.log("neue datei");
					this.doNew();
				}
			}
			else {
				var lastfile = enyo.getCookie("lastfile") || "";
				if(lastfile == "") {
					enyo.keyboard.hide();
					this.$.editorPanel.setContent(this.$.Demotext.text, "");
					//this.$.editorPanel.setActive(false);
				}
				else {
					enyo.keyboard.show();
					this.doOpen(lastfile);
				}
			}
		}
		console.log(lastfile);
		//setInterval(enyo.hitch(this, "doSave"),5000);
		setInterval(enyo.hitch(this, "doLoadFiles"),15000);
		this.doLoadFiles();
	},

	/* BORING EVENTS */
	sleep: function() {
		//if(this.position == "down")
		//	this.$.top.node.style.height = enyo.fetchControlSize(this).h + "px";
		this.$.taboutscrim.show();
		this.$.editorPanel.clearSchedule();
	},

	wakeup: function() {
		//this.$.top.node.style.height = (enyo.fetchControlSize(this).h - 55 - enyo.keyboard.height) + "px";
		this.$.taboutscrim.hide();
		this.$.editorPanel.setSchedule();
	},

	close: function() {
		this.$.fileIO.saveFile(this.$.editorPanel.getContent());
		enyo.setCookie("lastfile", this.$.fileIO.getFilename());
	},

	doPrint: function() {
		this.$.editorPanel.printDocument();
	},

	doEmail: function() {
		if(this.$.fileIO.getFilename() == "")
			return;
		var r = new enyo.PalmService();
		r.service = "palm://com.palm.applicationManager/";
		r.method = "open";
		r.call({id: "com.palm.app.email",
			params: {
				text:"See attachment", summary: new enyo.g11n.Template($L("Typewriter Document \"#{name}\"")).evaluate({name: this.$.fileIO.getFilename().basename(".md") }), attachments: [{fullPath: "file:///media/internal/Typewriter/" + this.$.fileIO.getFilename()}]
			}
		});
	},

	doSyntax: function(inSender) {
		var r = new enyo.PalmService();
		r.service = "palm://com.palm.applicationManager/";
		r.method = "open";
		r.call({target: "http://www.typewriterwebos.com/markdown/" + enyo.g11n.currentLocale() + "/"});
	},

	doFAQ: function(inSender) {
		var r = new enyo.PalmService();
		r.service = "palm://com.palm.applicationManager/";
		r.method = "open";
		r.call({target: "http://www.typewriterwebos.com/faq/" + enyo.g11n.currentLocale() + "/"});
	},

	doBug: function(inSender) {
		var r = new enyo.PalmService();
		r.service = "palm://com.palm.applicationManager/";
		r.method = "open";
		r.call({target: "http://www.typewriterwebos.com/report/" + enyo.g11n.currentLocale() + "/?version=" + enyo.fetchAppInfo().version + "&id=" + enyo.fetchAppInfo().id});
	},

	getFilename: function() {
		return this.$.fileIO.getFilename();
	}
})
<|endoftext|>


<commit_before>/* Author: Brandon Layton
 *
 * JSData-core.js
 *
 *
 */

//non-conflict
(function($){

	this.Pies = [];

	function Pie(ele){
		var element = ele;
		element.prepend("<canvas class='data-pie-canvas' width='"+element.width()+"' height='"+element.height()+"'></canvas>");

		//Time to do some defaulting
		if(!element.attr("data-pie-show-text"))    element.attr("data-pie-show-text","true");
		if(!element.attr("data-pie-hover-sticky")) element.attr("data-pie-hover-sticky","false");

		var radiusFactor = 3; //just used instead of a hard-coded number so you can edit (shouldn't be any less than 2 though)
		var radiusHoverEnlarge = 4;

		//this function is extremely similar to Draw
		//Excluding the drawing...
		//Trying to do collision detection with data that
		//Isn't readily available that also falls into portions
		//of a circle.
		element.mousemove(function( event ){
			var x = event.pageX - element.offset().left,
				y = event.pageY - element.offset().top ;
			var pie = element.find(".data-pie-canvas");
			var w = pie.attr("width"), h = pie.attr("height"),
				r = (w > h ? w : h)/radiusFactor;
			var total = 0,
				points = [],
			    curAngle = 0;
			//The distance from the center
			var dX = x - w/2,
				dY = h/2 - y;
			//If the squared distance is bigger than the squared radius then it is not even in the circle
			if((dX*dX + dY*dY) > r*r){
				if(element.attr("data-pie-hover-sticky")=="false"){//since attributes are strings
					element.attr("data-hovered",-1);
				}
				return;
			}
			//Grab data
			element.find(".data-point").each(function(){
				var val = parseInt($(this).attr("data-val"),10);
				total += val;
				points.push(val);
			});
			//see if the point is in a certain segment
			//If already in the circle, then we can make some assumptions about the point
			//Since we are looking at it from a counter clockwise perspective.
			//If the angle to the clicking point is less than the current angle, then it is within that segment
			for(var p in points){
				var perc 	= points[p]/total,
					theta	= Math.PI*2*perc,
					angleTo = curAngle + theta;

				var fi = Math.atan2(dY,dX);
				if(fi < 0) fi += Math.PI * 2;
				//Flip it so that it is counter clockwise
				fi = -(fi - Math.PI * 2);
				if(fi <= angleTo && fi >= curAngle){
					element.attr("data-hovered",p);
					return;
				}

				curAngle = angleTo;
			}
		});

		//Draws the pie
		function Draw(){
			var god = element;
			var pie = god.find(".data-pie-canvas");
			var piec= pie.get(0).getContext("2d");
			var total = 0,
				points = [],
			    curAngle = 0,
			    colors = [];
			var w = pie.attr("width"), h = pie.attr("height"),
				r = (w > h ? w : h)/radiusFactor;
			var hoveredAngleStart = -1, hoveredAngleEnd = -1;
			var hoveredIndex = parseInt(god.attr("data-hovered"),10);

			piec.imageSmoothingEnabled = true;

			//grab the data points
			god.find(".data-point").each(function(){
				var val = parseInt($(this).attr("data-val"),10);
				total += val;
				points.push(val);
				colors.push($(this).css("color"));
			});
			piec.clearRect(0,0,w,h); //clear canvas
			piec.strokeStyle = "#222";
			piec.lineWidth = 2;
			//plot the data points
			for(var p in points){
				piec.fillStyle = colors[p]; //set the color
				piec.beginPath(); //start the path

				var perc = points[p]/total; //find the percentage
				var angleTo = curAngle + Math.PI*2*perc; //find the angle we need to move to
				piec.moveTo(w/2,h/2); //move to the center of the circle
				piec.arc(w/2,h/2,r,curAngle,angleTo); //arc the path from the angle we are at to the angle we need to be
				piec.fill(); //fill the path
				if(hoveredIndex == p){
					hoveredAngleStart = curAngle;
					hoveredAngleEnd   = angleTo;
				}
				piec.lineTo(w/2,h/2);
				piec.stroke();

				curAngle = angleTo; //shift over our current angle
			}

			if(hoveredAngleStart != -1 && hoveredAngleEnd != -1){
				piec.fillStyle = colors[hoveredIndex]; //set the color
				piec.beginPath(); //start the path
				var perc = points[hoveredIndex]/total; //find the percentage

				piec.moveTo(w/2,h/2);
				piec.arc(w/2,h/2,r+radiusHoverEnlarge,hoveredAngleStart,hoveredAngleEnd);
				piec.lineTo(w/2,h/2);
				piec.fill();

				piec.strokeStyle = "#222";
				piec.lineWidth = 3;
				piec.stroke();

				if(god.attr("data-pie-show-text") != "false")
				{
					//Text
					piec.font = "14px Arial Bold";
					piec.fillStyle = "#111";
					//the middle + the mid way point between the angles, then compensate for the text's size
					//the r/2 brings the text closer to the middle of the circle
					var textX = w/2 + (r/2)*Math.cos(hoveredAngleStart + (hoveredAngleEnd - hoveredAngleStart)/2) - 30,
						textY = h/2 + (r/2)*Math.sin(hoveredAngleStart + (hoveredAngleEnd - hoveredAngleStart)/2) + 16;
					piec.fillText(points[hoveredIndex] + " (" + parseFloat(perc*100).toFixed(2) + "%)",
						 textX,
						 textY);
				}
			}
		};

		Draw(); //initially draw the pie graph
		UpdateInterval = setInterval(Draw, 25);
	};
	//Override function to create the pie initializer
	$.fn.pie = function(){
		Pies.push(new Pie(this));
		return this;//must return the object so it can have chained functions
	};

}(jQuery));
<commit_msg>Code to make Pie look nicer + COMMENTS<commit_after>/* Author: Brandon Layton
 *
 * JSData-core.js
 *
 *
 */

//non-conflict
(function($){

	this.Pies = [];

	function Pie(ele){
		var element = ele;
		element.prepend("<canvas class='data-pie-canvas' width='"+element.width()+"' height='"+element.height()+"'></canvas>");

		//Time to do some defaulting
		if(!element.attr("data-pie-show-text"))    element.attr("data-pie-show-text","true");
		if(!element.attr("data-pie-hover-sticky")) element.attr("data-pie-hover-sticky","false");

		var radiusFactor = 3; //just used instead of a hard-coded number so you can edit (shouldn't be any less than 2 though)
		var radiusHoverEnlarge = 4;

		//this function is extremely similar to Draw
		//Excluding the drawing...
		//Trying to do collision detection with data that
		//Isn't readily available that also falls into portions
		//of a circle.
		element.mousemove(function( event ){
			var x = event.pageX - element.offset().left,
				y = event.pageY - element.offset().top ;
			var pie = element.find(".data-pie-canvas");
			var w = pie.attr("width"), h = pie.attr("height"),
				r = (w > h ? w : h)/radiusFactor;
			var total = 0,
				points = [],
			    curAngle = 0;
			//The distance from the center
			var dX = x - w/2,
				dY = h/2 - y;
			//If the squared distance is bigger than the squared radius then it is not even in the circle
			if((dX*dX + dY*dY) > r*r){
				if(element.attr("data-pie-hover-sticky")=="false"){//since attributes are strings
					element.attr("data-hovered",-1);
				}
				return;
			}
			//Grab data
			element.find(".data-point").each(function(){
				var val = parseInt($(this).attr("data-val"),10);
				total += val;
				points.push(val);
			});
			//see if the point is in a certain segment
			//If already in the circle, then we can make some assumptions about the point
			//Since we are looking at it from a counter clockwise perspective.
			//If the angle to the clicking point is less than the current angle, then it is within that segment
			for(var p in points){
				var perc 	= points[p]/total,
					theta	= Math.PI*2*perc,
					angleTo = curAngle + theta;

				var fi = Math.atan2(dY,dX);//angle of our vector relative to the x-axis
				if(fi < 0) fi += Math.PI * 2;//shift everything into the domain where 2pi>x>0
				fi = -(fi - Math.PI * 2);//Flip it so that it is counter clockwise (normal it's CW)
				if(fi <= angleTo && fi >= curAngle){
					element.attr("data-hovered",p);//set our data
					return;
				}

				curAngle = angleTo;
			}
		});

		//Draws the pie
		function Draw(){
			var god = element;
			var pie = god.find(".data-pie-canvas");
			var piec= pie.get(0).getContext("2d");
			var total = 0,
				points = [],
			    curAngle = 0,
			    colors = [];
			var w = pie.attr("width"), h = pie.attr("height"),
				r = (w > h ? w : h)/radiusFactor;
			var hoveredAngleStart = -1, hoveredAngleEnd = -1;
			var hoveredIndex = parseInt(god.attr("data-hovered"),10);

			//Context initializing
			piec.imageSmoothingEnabled = true;
			piec.lineCap     = "round";
			piec.strokeStyle = "#222";
			piec.lineWidth   = 2;
			piec.clearRect(0,0,w,h); //clear canvas

			//grab the data points
			god.find(".data-point").each(function(){
				var val = parseInt($(this).attr("data-val"),10);
				total += val;
				points.push(val);
				colors.push($(this).css("color"));
			});

			//plot the data points
			for(var p in points){
				piec.fillStyle = colors[p]; //set the color

				var perc = points[p]/total; //find the percentage
				var angleTo = curAngle + Math.PI*2*perc; //find the angle we need to move to

				piec.beginPath(); //start the path
				piec.moveTo(w/2,h/2); //move to the center of the circle
				piec.arc(w/2,h/2,r,curAngle,angleTo); //arc the path from the angle we are at to the angle we need to be
				piec.fill(); //fill the path
				if(hoveredIndex == p){
					hoveredAngleStart = curAngle;
					hoveredAngleEnd   = angleTo;
				}
				piec.lineTo(w/2,h/2);
				piec.stroke();//stroke the arc as well as fill it

				curAngle = angleTo; //shift over our current angle
			}

			if(hoveredAngleStart != -1 && hoveredAngleEnd != -1){
				piec.fillStyle = colors[hoveredIndex]; //set the color
				piec.beginPath(); //start the path
				var perc = points[hoveredIndex]/total; //find the percentage

				piec.moveTo(w/2,h/2);
				piec.arc(w/2,h/2,r+radiusHoverEnlarge,hoveredAngleStart,hoveredAngleEnd);
				piec.lineTo(w/2,h/2);
				piec.fill();

				piec.stroke();

				if(god.attr("data-pie-show-text") != "false")
				{
					//Text
					piec.font = "14px Arial Bold";
					piec.fillStyle = "#111";
					var text = points[hoveredIndex] + " (" + parseFloat(perc*100).toFixed(2) + "%)";
					var textSize = piec.measureText(text);
					//the middle + the mid way point between the angles, then compensate for the text's size
					//the r/2 brings the text closer to the middle of the circle
					var textX = w/2 + (r/2)*Math.cos(hoveredAngleStart + (hoveredAngleEnd - hoveredAngleStart)/2) - textSize.width/2,
						textY = h/2 + (r/2)*Math.sin(hoveredAngleStart + (hoveredAngleEnd - hoveredAngleStart)/2) + 20;
					console.log(textX + "," + textY);
					piec.fillText(text, textX, textY);
				}
			}
		};

		Draw(); //initially draw the pie graph
		UpdateInterval = setInterval(Draw, 25);
	};
	//Override function to create the pie initializer
	$.fn.pie = function(){
		Pies.push(new Pie(this));
		return this;//must return the object so it can have chained functions
	};

}(jQuery));
<|endoftext|>


<commit_before>const config = require('../config');
var db = config.get('database');
db.connection.filename = __dirname + db.connection.filename;
const knex = require('knex')(db); // knex ha bisogno del path completo
const bookshelf = require('bookshelf')(knex);
module.exports = bookshelf;
<commit_msg>Delete index.js<commit_after><|endoftext|>


<commit_before>var m = require('mithril');
var $ = require('jquery');
var $osf = require('js/osfHelpers');
var waterbutler = require('js/waterbutler');

var util = require('./util.js');

// Helper for filtering
function TRUTHY(item) {
    return !!item; //Force cast to a bool
}

var model = {
    revisions: [],
    loaded: m.prop(false),
    errorMessage: undefined,
    hasUser: false,
    hasDate: false,
    selectedRevision: 0
};

var FileRevisionsTable = {
    controller: function(file, node, enableEditing, canEdit) {
        var self = {};
        self.node = node;
        self.file = file;
        self.canEdit = canEdit;
        self.enableEditing = enableEditing;
        self.baseUrl = (window.location.href).split('?')[0];

        model.hasDate = self.file.provider !== 'dataverse';

        self.reload = function() {
            model.loaded(false);
            m.redraw();
            $.ajax({
                dataType: 'json',
                async: true,
                url: self.file.urls.revisions,
                beforeSend: $osf.setXHRAuthorization
            }).done(function(response) {
                m.startComputation();
                var urlParmas = $osf.urlParams();
                model.revisions = response.data.map(function(rev, index) {
                    rev = FileRevisionsTable.postProcessRevision(self.file, self.node, rev, index);
                    if (urlParmas[rev.versionIdentifier] === rev.version) {
                        model.selectedRevision = index;
                    }
                    return rev;
                });
                model.loaded(true);
                // Can only edit the latest version of a file
                if (model.selectedRevision === 0) {
                    self.enableEditing();
                }
                model.hasUser = model.revisions[0] && model.revisions[0].extra && model.revisions[0].extra.user;
                m.endComputation();
            }).fail(function(response) {
                m.startComputation();
                model.loaded(true);
                model.errorMessage = response.responseJSON ?
                    response.responseJSON.message || 'Unable to fetch versions' :
                    'Unable to fetch versions';
                m.endComputation();

                // model.errorMessage(err);

                if (self.file.provider === 'figshare') {
                    // Hack for Figshare
                    // only figshare will error on a revisions request
                    // so dont allow downloads and set a fake current version
                    $.ajax({
                        method: 'GET',
                        url: self.file.urls.metadata,
                        beforeSend: $osf.setXHRAuthorization
                    }).done(function(resp) {
                        self.canEdit(self.canEdit() && resp.data.extra.canDelete);
                        m.redraw();
                    }).fail(function(xhr) {
                        self.canEdit(false);
                        m.redraw();
                    });
                }
            });
        };

        self.getTableHead = function() {
            return m('thead', [
                m('tr', [
                    m('th', 'Version ID'),
                    model.hasDate ? m('th', 'Date') : false,
                    model.hasUser ? m('th', 'User') : false,
                    m('th[colspan=2]', 'Download'),
                ].filter(TRUTHY))
            ]);
        };

        self.makeTableRow = function(revision, index) {
            var isSelected = index === model.selectedRevision;

            return m('tr' + (isSelected ? '.active' : ''), [
                m('td',  isSelected ? revision.displayVersion :
                  m('a', {href: parseInt(revision.displayVersion) === model.revisions.length ? self.baseUrl : revision.osfViewUrl}, revision.displayVersion)
                ),
                model.hasDate ? m('td', revision.displayDate) : false,
                model.hasUser ?
                    m('td', revision.extra.user.url ?
                            m('a', {href: revision.extra.user.url}, revision.extra.user.name) :
                            revision.extra.user.name
                    ) : false,
                m('td', revision.extra.downloads > -1 ? m('.badge', revision.extra.downloads) : ''),
                m('td',
                    m('a.btn.btn-primary.btn-sm.file-download', {
                        href: revision.osfDownloadUrl,
                        onclick: function() {
                            window.location = revision.waterbutlerDownloadUrl;
                            return false;
                        }
                    }, m('i.fa.fa-download'))
                ),
            ].filter(TRUTHY));
        };

        if (!model.loaded()) {
            self.reload();
        }
        $(document).on('fileviewpage:reload', self.reload);
        return self;
    },
    view: function(ctrl) {
        return m('#revisionsPanel.panel.panel-default', [
                m('.panel-heading.clearfix', m('h3.panel-title', 'Revisions')),
                m('.panel-body', {style:{'padding-right': '0','padding-left':'0', 'padding-bottom' : '0'}}, (function() {
                    if (!model.loaded()) {
                        return util.Spinner;
                    }
                    if (model.errorMessage) {
                        return m('.alert.alert-warning', {style:{margin: '10px'}}, model.errorMessage);
                    }

                    return m('table.table',{style:{'margin-bottom': '0'}}, [
                        ctrl.getTableHead(),
                        m('tbody', model.revisions.map(ctrl.makeTableRow))
                    ]);
                })())
            ]);
    },
    postProcessRevision: function(file, node, revision, index) {
        var options = {};
        var urlParams = $osf.urlParams();

        if (urlParams.branch !== undefined) {
            options.branch = urlParams.branch;
        }
        options[revision.versionIdentifier] = revision.version;

        revision.date = new $osf.FormattableDate(revision.modified);
        revision.displayDate = revision.date.local !== 'Invalid date' ?
            revision.date.local :
            revision.date;

        switch (file.provider) {
            // Note: Google Drive version identifiers often begin with the same sequence
            case 'googledrive':
                revision.displayVersion = revision.version.substring(revision.version.length - 8);
                break;
            // Note: Dataverse internal version names are ugly; Substitute our own
            case 'dataverse':
                var displayMap = {
                    'latest': 'Draft',
                    'latest-published': 'Published'
                };

                revision.displayVersion = revision.version in displayMap ?
                    displayMap[revision.version] : revision.version.substring(0, 8);
                break;
            default:
                revision.displayVersion = revision.version.substring(0, 8);
        }

        if (file.provider === 'osfstorage' && file.name && index !== 0) {
            var parts = file.name.split('.');
            if (parts.length === 1) {
                options.displayName = parts[0] + '-' + revision.modified;
            } else {
                options.displayName = parts.slice(0, parts.length - 1).join('') + '-' + revision.modified + '.' + parts[parts.length - 1];
            }
        }

        revision.osfViewUrl = '?' + $.param(options);
        revision.osfDownloadUrl = '?' + $.param($.extend({action: 'download'}, options));
        revision.waterbutlerDownloadUrl = waterbutler.buildDownloadUrl(file.path, file.provider, node.id, options);

        return revision;
    }
};

module.exports = FileRevisionsTable;
<commit_msg>Set table-layout as fixed for revision table<commit_after>var m = require('mithril');
var $ = require('jquery');
var $osf = require('js/osfHelpers');
var waterbutler = require('js/waterbutler');

var util = require('./util.js');

// Helper for filtering
function TRUTHY(item) {
    return !!item; //Force cast to a bool
}

var model = {
    revisions: [],
    loaded: m.prop(false),
    errorMessage: undefined,
    hasUser: false,
    hasDate: false,
    selectedRevision: 0
};

var FileRevisionsTable = {
    controller: function(file, node, enableEditing, canEdit) {
        var self = {};
        self.node = node;
        self.file = file;
        self.canEdit = canEdit;
        self.enableEditing = enableEditing;
        self.baseUrl = (window.location.href).split('?')[0];

        model.hasDate = self.file.provider !== 'dataverse';

        self.reload = function() {
            model.loaded(false);
            m.redraw();
            $.ajax({
                dataType: 'json',
                async: true,
                url: self.file.urls.revisions,
                beforeSend: $osf.setXHRAuthorization
            }).done(function(response) {
                m.startComputation();
                var urlParmas = $osf.urlParams();
                model.revisions = response.data.map(function(rev, index) {
                    rev = FileRevisionsTable.postProcessRevision(self.file, self.node, rev, index);
                    if (urlParmas[rev.versionIdentifier] === rev.version) {
                        model.selectedRevision = index;
                    }
                    return rev;
                });
                model.loaded(true);
                // Can only edit the latest version of a file
                if (model.selectedRevision === 0) {
                    self.enableEditing();
                }
                model.hasUser = model.revisions[0] && model.revisions[0].extra && model.revisions[0].extra.user;
                m.endComputation();
            }).fail(function(response) {
                m.startComputation();
                model.loaded(true);
                model.errorMessage = response.responseJSON ?
                    response.responseJSON.message || 'Unable to fetch versions' :
                    'Unable to fetch versions';
                m.endComputation();

                // model.errorMessage(err);

                if (self.file.provider === 'figshare') {
                    // Hack for Figshare
                    // only figshare will error on a revisions request
                    // so dont allow downloads and set a fake current version
                    $.ajax({
                        method: 'GET',
                        url: self.file.urls.metadata,
                        beforeSend: $osf.setXHRAuthorization
                    }).done(function(resp) {
                        self.canEdit(self.canEdit() && resp.data.extra.canDelete);
                        m.redraw();
                    }).fail(function(xhr) {
                        self.canEdit(false);
                        m.redraw();
                    });
                }
            });
        };

        self.getTableHead = function() {
            return m('thead', [
                m('tr', [
                    m('th', 'Version ID'),
                    model.hasDate ? m('th', 'Date') : false,
                    model.hasUser ? m('th', 'User') : false,
                    m('th[colspan=2]', 'Download'),
                ].filter(TRUTHY))
            ]);
        };

        self.makeTableRow = function(revision, index) {
            var isSelected = index === model.selectedRevision;

            return m('tr' + (isSelected ? '.active' : ''), [
                m('td',  isSelected ? revision.displayVersion :
                  m('a', {href: parseInt(revision.displayVersion) === model.revisions.length ? self.baseUrl : revision.osfViewUrl}, revision.displayVersion)
                ),
                model.hasDate ? m('td', revision.displayDate) : false,
                model.hasUser ?
                    m('td', revision.extra.user.url ?
                            m('a', {href: revision.extra.user.url}, revision.extra.user.name) :
                            revision.extra.user.name
                    ) : false,
                m('td', revision.extra.downloads > -1 ? m('.badge', revision.extra.downloads) : ''),
                m('td',
                    m('a.btn.btn-primary.btn-sm.file-download', {
                        href: revision.osfDownloadUrl,
                        onclick: function() {
                            window.location = revision.waterbutlerDownloadUrl;
                            return false;
                        }
                    }, m('i.fa.fa-download'))
                ),
            ].filter(TRUTHY));
        };

        if (!model.loaded()) {
            self.reload();
        }
        $(document).on('fileviewpage:reload', self.reload);
        return self;
    },
    view: function(ctrl) {
        return m('#revisionsPanel.panel.panel-default', [
                m('.panel-heading.clearfix', m('h3.panel-title', 'Revisions')),
                m('.panel-body', {style:{'padding-right': '0','padding-left':'0', 'padding-bottom' : '0'}}, (function() {
                    if (!model.loaded()) {
                        return util.Spinner;
                    }
                    if (model.errorMessage) {
                        return m('.alert.alert-warning', {style:{margin: '10px'}}, model.errorMessage);
                    }

                    return m('table.table',{style: {'table-layout': 'fixed', 'margin-bottom': '0'}}, [
                        ctrl.getTableHead(),
                        m('tbody', model.revisions.map(ctrl.makeTableRow))
                    ]);
                })())
            ]);
    },
    postProcessRevision: function(file, node, revision, index) {
        var options = {};
        var urlParams = $osf.urlParams();

        if (urlParams.branch !== undefined) {
            options.branch = urlParams.branch;
        }
        options[revision.versionIdentifier] = revision.version;

        revision.date = new $osf.FormattableDate(revision.modified);
        revision.displayDate = revision.date.local !== 'Invalid date' ?
            revision.date.local :
            revision.date;

        switch (file.provider) {
            // Note: Google Drive version identifiers often begin with the same sequence
            case 'googledrive':
                revision.displayVersion = revision.version.substring(revision.version.length - 8);
                break;
            // Note: Dataverse internal version names are ugly; Substitute our own
            case 'dataverse':
                var displayMap = {
                    'latest': 'Draft',
                    'latest-published': 'Published'
                };

                revision.displayVersion = revision.version in displayMap ?
                    displayMap[revision.version] : revision.version.substring(0, 8);
                break;
            default:
                revision.displayVersion = revision.version.substring(0, 8);
        }

        if (file.provider === 'osfstorage' && file.name && index !== 0) {
            var parts = file.name.split('.');
            if (parts.length === 1) {
                options.displayName = parts[0] + '-' + revision.modified;
            } else {
                options.displayName = parts.slice(0, parts.length - 1).join('') + '-' + revision.modified + '.' + parts[parts.length - 1];
            }
        }

        revision.osfViewUrl = '?' + $.param(options);
        revision.osfDownloadUrl = '?' + $.param($.extend({action: 'download'}, options));
        revision.waterbutlerDownloadUrl = waterbutler.buildDownloadUrl(file.path, file.provider, node.id, options);

        return revision;
    }
};

module.exports = FileRevisionsTable;
<|endoftext|>


<commit_before>//  The OARN Relief Nursery Database
//  Copyright (C) 2015  Oregon Association of Relief Nurseries
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as
//  published by the Free Software Foundation, either version 3 of the
//  License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.

(function (enyo, scope) {

    enyo.kind({
        name: 'oarn.ClassroomAssignment',

        selectLoaded: false, // a flag to determine whether or not we have already retrieved select data

        published: {
            token: '',

            /**
             * When the state has changed but not yet saved, this is set to true.
             * It is used to alert parent controls that we have unsaved changes here.
             *
             * @type {Boolean}
             * @public
             */
            dirty: false,

            username: 'none',
            selectedFamilyID: 0,
            organizationAccessList: null,

            selectedOrganization: null,
            currentOrgReadOnly: false,
            currentOrgReadWrite: false,
            currentOrgAdmin: false,

            selectedPersonID: -1,
            selectedPersonItem: null //model: person_id, first_name, last_name, gender, birth_date, is_child
        },

        components: [
            {name: 'scheduleRepeaterDisplay', kind: 'oarn.RepeaterDisplay'},

            {kind: 'onyx.Groupbox', style: 'padding-top: 5px;', components: [
                {kind: 'onyx.GroupboxHeader', style: 'wdith: 500px;', content: 'Assign to Class'},
                {tag: 'table', components: [
                    {tag: 'tr', components: [
                        {tag: 'td', components: [
                            {tag: 'label', classes: 'oarn-control oarn-groupbox-control', content: 'Classroom:'}
                        ]},
                        {tag: 'td', components: [
                            {name: 'selectClassroom', kind: 'oarn.DataSelect', onchange: 'classroomChanged'},
                        ]},
                        {tag: 'td', components: [
                            {tag: 'label', classes: 'oarn-control oarn-groupbox-control', content: 'Class Schedule:'}
                        ]},
                        {tag: 'td', components: [
                            {name: 'selectSchedule', kind: 'oarn.DataSelect'},
                        ]}
                    ]},
                    {tag: 'tr', components:[
                        {tag: 'td', components: [
                            {tag: 'label', classes: 'oarn-control oarn-groupbox-control', content: 'Begin Date:'}
                        ]},
                        {tag: 'td', attributes:[{'colspan':'3'}], components: [
                            {name: 'beginDate', kind: 'oarn.DatePicker', emptyIsValid: false}
                        ]}
                    ]},
                    {tag: 'tr', components:[
                        {tag: 'td', attributes:[{'colspan':'4'}], components: [
                            {kind: 'onyx.Button', content: 'Schedule Class', ontap: 'goSchedule'}
                        ]}
                    ]}
                ]}
            ]},
            {name: 'selectHelper', kind: 'oarn.SelectHelper'},
            {name: 'popupFactory', kind: 'oarn.PopupFactory'}
        ],

        events: {
            onAjaxError: '',
            onAjaxStarted: '',
            onAjaxFinished: ''
        },

        handlers: {
            onSelectListsAcquired: 'selectListsAcquiredHandler'
        },

        create: function () {
            this.inherited(arguments);
            this.initSelectHelper();
        },

        selectedPersonIDChanged: function (oldVal) {
            if (this.get('.selectedPersonID') > 0) {
                this.defineScheduleRepeaterDisplay();
            }
        },

        defineScheduleRepeaterDisplay: function () {
            this.$.scheduleRepeaterDisplay.set('.groupboxHeaderText', 'Class Schedule');
            this.$.scheduleRepeaterDisplay.set('.hasSimpleSelectButton', false);
            this.$.scheduleRepeaterDisplay.allowsNewRecords = false;

            this.$.scheduleRepeaterDisplay.selectEndpoints = [
                {
                    endpoint: 'api/v1/attendance/classrooms/',
                    name: 'classrooms',
                    parseWith: this.$.selectHelper.parseClassroom
                },
                {
                    endpoint: 'api/v1/attendance/class-schedules/',
                    name: 'class_schedules',
                    parseWith: this.$.selectHelper.parseClassSchedule
                }
            ];

            this.$.scheduleRepeaterDisplay.staticPostFields = [
                {fieldName: 'person', value: this.get('.selectedPersonID')}
            ];

            this.$.scheduleRepeaterDisplay.fields = [
                {
                    fieldName: 'person_class_schedule_id',
                    postBodyOnly: true,
                    primaryKey: true
                },
                {
                    fieldName: 'classroom',
                    fieldType: 'DataSelect',
                    dataSelectName: 'classrooms',
                    headerText: 'Classroom',
                    readOnly: true,
                    fieldWidth: 100
                },
                {
                    fieldName: 'class_schedule',
                    fieldType: 'DataSelect',
                    dataSelectName: 'class_schedules',
                    headerText: 'Class',
                    readOnly: true,
                    fieldWidth: 100
                },
                {
                    fieldName: 'begin_date',
                    fieldType: 'DatePicker',
                    headerText: 'Begin Date',
                    fieldWidth: 125,
                    emptyIsValid: false
                },
                {
                    fieldName: 'end_date',
                    fieldType: 'DatePicker',
                    headerText: 'End Date',
                    fieldWidth: 125,
                    emptyIsValid: true
                },
                {
                    fieldName: 'sunday',
                    fieldType: 'Checkbox',
                    headerText: 'Sun',
                    labelText: 'Sunday',
                    fieldWidth: 30,
                },
                {
                    fieldName: 'monday',
                    fieldType: 'Checkbox',
                    headerText: 'Mon',
                    labelText: 'Monday',
                    fieldWidth: 30,
                },
                {
                    fieldName: 'tuesday',
                    fieldType: 'Checkbox',
                    headerText: 'Tues',
                    labelText: 'Tuesday',
                    fieldWidth: 30,
                },
                {
                    fieldName: 'wednesday',
                    fieldType: 'Checkbox',
                    headerText: 'Wed',
                    labelText: 'Wednesday',
                    fieldWidth: 30,
                },
                {
                    fieldName: 'thursday',
                    fieldType: 'Checkbox',
                    headerText: 'Thur',
                    labelText: 'Thursday',
                    fieldWidth: 30,
                },
                {
                    fieldName: 'friday',
                    fieldType: 'Checkbox',
                    headerText: 'Fri',
                    labelText: 'Friday',
                    fieldWidth: 30,
                },
                {
                    fieldName: 'saturday',
                    fieldType: 'Checkbox',
                    headerText: 'Sat',
                    labelText: 'Saturday',
                    fieldWidth: 30
                }
            ];

            this.$.scheduleRepeaterDisplay.endpoint = 'api/v1/attendance/person-class-schedules/?person_id=' +
                this.get('.selectedPersonID');
            this.$.scheduleRepeaterDisplay.patchEndpoint = 'api/v1/attendance/person-class-schedules/';
            this.$.scheduleRepeaterDisplay.deleteEndpoint = 'api/v1/attendance/person-class-schedules/';

            this.$.scheduleRepeaterDisplay.set('maxWidth', 800);

            this.$.scheduleRepeaterDisplay.show();
            this.$.scheduleRepeaterDisplay.createRepeater();

            this.set('.scheduleRepeaterDisplayInitialized', true);
        },

        initSelectHelper: function () {
            if (!this.get('.selectLoaded')) {
                this.$.selectHelper.endpoints = [
                    {
                        endpoint: 'api/v1/attendance/classrooms/',
                        name: 'classrooms',
                        parseWith: this.$.selectHelper.parseClassroom
                    },
                    {
                        endpoint: 'api/v1/attendance/class-schedules/',
                        name: 'class_schedules',
                        parseWith: this.$.selectHelper.parseClassSchedule
                    }
                ];

                if (!this.get('.selectLoaded')) {
                    this.$.selectHelper.loadSelectData();
                }
            }
        },

        selectListsAcquiredHandler: function (inSender, inEvent) {
            this.set('.selectLoaded', true);
            // We retrieved the whole list of class schedules. We need to break them up now into separate
            // arrays for each classroom:

            for (var i=0; i < this.$.selectHelper.optionsLists['class_schedules_options_list'].length; i++) {
                var classroom = this.$.selectHelper.optionsLists['class_schedules_options_list'][i].classroom;
                this['schedule_options_' + classroom] = [];
            }

            for (var i=0; i < this.$.selectHelper.optionsLists['class_schedules_options_list'].length; i++) {
                var classroom = this.$.selectHelper.optionsLists['class_schedules_options_list'][i].classroom;

                // If there isn't an array yet for this schedule, create it:
                if (this.get('schedule_options_' + classroom) == undefined) {
                    this.set('schedule_options_' + classroom, []);
                }

                // Add the current value to the array:
                this['schedule_options_' + classroom].push({
                    value: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].value,
                    display_text: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].display_text,
                    sunday: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].sunday,
                    monday: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].monday,
                    tuesday: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].tuesday,
                    wednesday: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].wednesday,
                    thursday: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].thursday,
                    friday: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].friday,
                    saturday: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].saturday
                });
            }

            this.$.selectClassroom.options_list.empty();
            this.$.selectClassroom.options_list.add(this.$.selectHelper.optionsLists['classrooms_options_list']);

            this.$.selectSchedule.options_list.empty();
            this.$.selectSchedule.options_list.add(
                this.get('schedule_options_' + this.$.selectClassroom.getValue())
            );
        },

        classroomChanged: function (inSender, inEvent) {
            this.$.selectSchedule.options_list.empty();
            this.$.selectSchedule.options_list.add(
                this.get('schedule_options_' + this.$.selectClassroom.getValue())
            );
        },

        goSchedule: function (inSender, inEvent) {
            if (this.$.beginDate.getValue() == null || this.$.beginDate.getValue() == "") {
                this.$.popupFactory.showInfo('Missing Required Data', 'The begin date is required.');
                return;
            }

            var classroom = this.$.selectClassroom.getValue();
            for (var i=0; i < this['schedule_options_' + classroom].length; i++) {
                if (this['schedule_options_' + classroom][i].value == this.$.selectSchedule.getValue()) {
                    var sunday = this['schedule_options_' + classroom][i].sunday;
                    var monday = this['schedule_options_' + classroom][i].monday;
                    var tuesday = this['schedule_options_' + classroom][i].tuesday;
                    var wednesday = this['schedule_options_' + classroom][i].wednesday;
                    var thursday = this['schedule_options_' + classroom][i].thursday;
                    var friday = this['schedule_options_' + classroom][i].friday;
                    var saturday = this['schedule_options_' + classroom][i].saturday;
                }
            }

            var postBody = {};
            postBody['person'] = this.get('.selectedPersonID');
            enyo.log('selectedPersonID:' + this.get('.selectedPersonID'));

            var beginDate = null;
            if (!Number.isNaN(this.$.beginDate.getValue())) {
                var testDate = new Date(
                    this.$.beginDate.getValue()
                ).toISOString();
                beginDate = moment(testDate).format('YYYY-MM-DD');
            }
            else {
                this.$.popupFactory.showInfo('Invalid Date', 'The begin date does not appear to be valid.');
                return;
            }

            postBody['class_schedule'] = this.$.selectSchedule.getValue();
            postBody['begin_date'] = beginDate;
            postBody['sunday'] = sunday;
            postBody['monday'] = monday;
            postBody['tuesday'] = tuesday;
            postBody['wednesday'] = wednesday;
            postBody['thursday'] = thursday;
            postBody['friday'] = friday;
            postBody['saturday'] = saturday;

            this.api = new oarn.API();
            this.set('.api.token', this.get('.token'));
            this.set('.api.method', 'POST');
            var endpoint = 'api/v1/attendance/person-class-schedules/';
            var ajax = this.api.getAjaxObject(endpoint);
            ajax.postBody = postBody;

            this.doAjaxStarted();
            ajax.go();
            ajax.response(enyo.bindSafely(this, 'postResponse'));
            ajax.error(enyo.bindSafely(this, 'processError'));
        },

        processError: function (inSender, inResponse) {
            this.doAjaxFinished(); // let a parent control turn off a spinner, etc.

            var status = inSender.xhrResponse.status;
            var detail = JSON.parse(inSender.xhrResponse.body);

            var detail_msg = '';
            for (var prop in detail) {
                if (detail.hasOwnProperty(prop)) {
                    detail_msg = prop + ': ' + detail[prop] + '
';
                }
            }

            this.$.popupFactory.showInfo('Database Communication Error', 'An error occurred while trying to ' +
                ' communicate with the server. ' +
                'Please provide the following information to your database administrator: ' +
                '

' + 'status: ' + status + '
' + detail_msg);

            this.set('.xhrResponse', inSender.xhrResponse);
            return true;
        },

        postResponse: function (inRequest, inResponse) {
            this.doAjaxFinished(); // let a parent control turn off a spinner, etc.
            this.$.scheduleRepeaterDisplay.refreshData();
        }
    });

})(enyo, this);<commit_msg>Removed a stray debugging console log command.<commit_after>//  The OARN Relief Nursery Database
//  Copyright (C) 2015  Oregon Association of Relief Nurseries
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as
//  published by the Free Software Foundation, either version 3 of the
//  License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.

(function (enyo, scope) {

    enyo.kind({
        name: 'oarn.ClassroomAssignment',

        selectLoaded: false, // a flag to determine whether or not we have already retrieved select data

        published: {
            token: '',

            /**
             * When the state has changed but not yet saved, this is set to true.
             * It is used to alert parent controls that we have unsaved changes here.
             *
             * @type {Boolean}
             * @public
             */
            dirty: false,

            username: 'none',
            selectedFamilyID: 0,
            organizationAccessList: null,

            selectedOrganization: null,
            currentOrgReadOnly: false,
            currentOrgReadWrite: false,
            currentOrgAdmin: false,

            selectedPersonID: -1,
            selectedPersonItem: null //model: person_id, first_name, last_name, gender, birth_date, is_child
        },

        components: [
            {name: 'scheduleRepeaterDisplay', kind: 'oarn.RepeaterDisplay'},

            {kind: 'onyx.Groupbox', style: 'padding-top: 5px;', components: [
                {kind: 'onyx.GroupboxHeader', style: 'wdith: 500px;', content: 'Assign to Class'},
                {tag: 'table', components: [
                    {tag: 'tr', components: [
                        {tag: 'td', components: [
                            {tag: 'label', classes: 'oarn-control oarn-groupbox-control', content: 'Classroom:'}
                        ]},
                        {tag: 'td', components: [
                            {name: 'selectClassroom', kind: 'oarn.DataSelect', onchange: 'classroomChanged'},
                        ]},
                        {tag: 'td', components: [
                            {tag: 'label', classes: 'oarn-control oarn-groupbox-control', content: 'Class Schedule:'}
                        ]},
                        {tag: 'td', components: [
                            {name: 'selectSchedule', kind: 'oarn.DataSelect'},
                        ]}
                    ]},
                    {tag: 'tr', components:[
                        {tag: 'td', components: [
                            {tag: 'label', classes: 'oarn-control oarn-groupbox-control', content: 'Begin Date:'}
                        ]},
                        {tag: 'td', attributes:[{'colspan':'3'}], components: [
                            {name: 'beginDate', kind: 'oarn.DatePicker', emptyIsValid: false}
                        ]}
                    ]},
                    {tag: 'tr', components:[
                        {tag: 'td', attributes:[{'colspan':'4'}], components: [
                            {kind: 'onyx.Button', content: 'Schedule Class', ontap: 'goSchedule'}
                        ]}
                    ]}
                ]}
            ]},
            {name: 'selectHelper', kind: 'oarn.SelectHelper'},
            {name: 'popupFactory', kind: 'oarn.PopupFactory'}
        ],

        events: {
            onAjaxError: '',
            onAjaxStarted: '',
            onAjaxFinished: ''
        },

        handlers: {
            onSelectListsAcquired: 'selectListsAcquiredHandler'
        },

        create: function () {
            this.inherited(arguments);
            this.initSelectHelper();
        },

        selectedPersonIDChanged: function (oldVal) {
            if (this.get('.selectedPersonID') > 0) {
                this.defineScheduleRepeaterDisplay();
            }
        },

        defineScheduleRepeaterDisplay: function () {
            this.$.scheduleRepeaterDisplay.set('.groupboxHeaderText', 'Class Schedule');
            this.$.scheduleRepeaterDisplay.set('.hasSimpleSelectButton', false);
            this.$.scheduleRepeaterDisplay.allowsNewRecords = false;

            this.$.scheduleRepeaterDisplay.selectEndpoints = [
                {
                    endpoint: 'api/v1/attendance/classrooms/',
                    name: 'classrooms',
                    parseWith: this.$.selectHelper.parseClassroom
                },
                {
                    endpoint: 'api/v1/attendance/class-schedules/',
                    name: 'class_schedules',
                    parseWith: this.$.selectHelper.parseClassSchedule
                }
            ];

            this.$.scheduleRepeaterDisplay.staticPostFields = [
                {fieldName: 'person', value: this.get('.selectedPersonID')}
            ];

            this.$.scheduleRepeaterDisplay.fields = [
                {
                    fieldName: 'person_class_schedule_id',
                    postBodyOnly: true,
                    primaryKey: true
                },
                {
                    fieldName: 'classroom',
                    fieldType: 'DataSelect',
                    dataSelectName: 'classrooms',
                    headerText: 'Classroom',
                    readOnly: true,
                    fieldWidth: 100
                },
                {
                    fieldName: 'class_schedule',
                    fieldType: 'DataSelect',
                    dataSelectName: 'class_schedules',
                    headerText: 'Class',
                    readOnly: true,
                    fieldWidth: 100
                },
                {
                    fieldName: 'begin_date',
                    fieldType: 'DatePicker',
                    headerText: 'Begin Date',
                    fieldWidth: 125,
                    emptyIsValid: false
                },
                {
                    fieldName: 'end_date',
                    fieldType: 'DatePicker',
                    headerText: 'End Date',
                    fieldWidth: 125,
                    emptyIsValid: true
                },
                {
                    fieldName: 'sunday',
                    fieldType: 'Checkbox',
                    headerText: 'Sun',
                    labelText: 'Sunday',
                    fieldWidth: 30,
                },
                {
                    fieldName: 'monday',
                    fieldType: 'Checkbox',
                    headerText: 'Mon',
                    labelText: 'Monday',
                    fieldWidth: 30,
                },
                {
                    fieldName: 'tuesday',
                    fieldType: 'Checkbox',
                    headerText: 'Tues',
                    labelText: 'Tuesday',
                    fieldWidth: 30,
                },
                {
                    fieldName: 'wednesday',
                    fieldType: 'Checkbox',
                    headerText: 'Wed',
                    labelText: 'Wednesday',
                    fieldWidth: 30,
                },
                {
                    fieldName: 'thursday',
                    fieldType: 'Checkbox',
                    headerText: 'Thur',
                    labelText: 'Thursday',
                    fieldWidth: 30,
                },
                {
                    fieldName: 'friday',
                    fieldType: 'Checkbox',
                    headerText: 'Fri',
                    labelText: 'Friday',
                    fieldWidth: 30,
                },
                {
                    fieldName: 'saturday',
                    fieldType: 'Checkbox',
                    headerText: 'Sat',
                    labelText: 'Saturday',
                    fieldWidth: 30
                }
            ];

            this.$.scheduleRepeaterDisplay.endpoint = 'api/v1/attendance/person-class-schedules/?person_id=' +
                this.get('.selectedPersonID');
            this.$.scheduleRepeaterDisplay.patchEndpoint = 'api/v1/attendance/person-class-schedules/';
            this.$.scheduleRepeaterDisplay.deleteEndpoint = 'api/v1/attendance/person-class-schedules/';

            this.$.scheduleRepeaterDisplay.set('maxWidth', 800);

            this.$.scheduleRepeaterDisplay.show();
            this.$.scheduleRepeaterDisplay.createRepeater();

            this.set('.scheduleRepeaterDisplayInitialized', true);
        },

        initSelectHelper: function () {
            if (!this.get('.selectLoaded')) {
                this.$.selectHelper.endpoints = [
                    {
                        endpoint: 'api/v1/attendance/classrooms/',
                        name: 'classrooms',
                        parseWith: this.$.selectHelper.parseClassroom
                    },
                    {
                        endpoint: 'api/v1/attendance/class-schedules/',
                        name: 'class_schedules',
                        parseWith: this.$.selectHelper.parseClassSchedule
                    }
                ];

                if (!this.get('.selectLoaded')) {
                    this.$.selectHelper.loadSelectData();
                }
            }
        },

        selectListsAcquiredHandler: function (inSender, inEvent) {
            this.set('.selectLoaded', true);
            // We retrieved the whole list of class schedules. We need to break them up now into separate
            // arrays for each classroom:

            for (var i=0; i < this.$.selectHelper.optionsLists['class_schedules_options_list'].length; i++) {
                var classroom = this.$.selectHelper.optionsLists['class_schedules_options_list'][i].classroom;
                this['schedule_options_' + classroom] = [];
            }

            for (var i=0; i < this.$.selectHelper.optionsLists['class_schedules_options_list'].length; i++) {
                var classroom = this.$.selectHelper.optionsLists['class_schedules_options_list'][i].classroom;

                // If there isn't an array yet for this schedule, create it:
                if (this.get('schedule_options_' + classroom) == undefined) {
                    this.set('schedule_options_' + classroom, []);
                }

                // Add the current value to the array:
                this['schedule_options_' + classroom].push({
                    value: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].value,
                    display_text: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].display_text,
                    sunday: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].sunday,
                    monday: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].monday,
                    tuesday: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].tuesday,
                    wednesday: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].wednesday,
                    thursday: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].thursday,
                    friday: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].friday,
                    saturday: this.$.selectHelper.optionsLists['class_schedules_options_list'][i].saturday
                });
            }

            this.$.selectClassroom.options_list.empty();
            this.$.selectClassroom.options_list.add(this.$.selectHelper.optionsLists['classrooms_options_list']);

            this.$.selectSchedule.options_list.empty();
            this.$.selectSchedule.options_list.add(
                this.get('schedule_options_' + this.$.selectClassroom.getValue())
            );
        },

        classroomChanged: function (inSender, inEvent) {
            this.$.selectSchedule.options_list.empty();
            this.$.selectSchedule.options_list.add(
                this.get('schedule_options_' + this.$.selectClassroom.getValue())
            );
        },

        goSchedule: function (inSender, inEvent) {
            if (this.$.beginDate.getValue() == null || this.$.beginDate.getValue() == "") {
                this.$.popupFactory.showInfo('Missing Required Data', 'The begin date is required.');
                return;
            }

            var classroom = this.$.selectClassroom.getValue();
            for (var i=0; i < this['schedule_options_' + classroom].length; i++) {
                if (this['schedule_options_' + classroom][i].value == this.$.selectSchedule.getValue()) {
                    var sunday = this['schedule_options_' + classroom][i].sunday;
                    var monday = this['schedule_options_' + classroom][i].monday;
                    var tuesday = this['schedule_options_' + classroom][i].tuesday;
                    var wednesday = this['schedule_options_' + classroom][i].wednesday;
                    var thursday = this['schedule_options_' + classroom][i].thursday;
                    var friday = this['schedule_options_' + classroom][i].friday;
                    var saturday = this['schedule_options_' + classroom][i].saturday;
                }
            }

            var postBody = {};
            postBody['person'] = this.get('.selectedPersonID');

            var beginDate = null;
            if (!Number.isNaN(this.$.beginDate.getValue())) {
                var testDate = new Date(
                    this.$.beginDate.getValue()
                ).toISOString();
                beginDate = moment(testDate).format('YYYY-MM-DD');
            }
            else {
                this.$.popupFactory.showInfo('Invalid Date', 'The begin date does not appear to be valid.');
                return;
            }

            postBody['class_schedule'] = this.$.selectSchedule.getValue();
            postBody['begin_date'] = beginDate;
            postBody['sunday'] = sunday;
            postBody['monday'] = monday;
            postBody['tuesday'] = tuesday;
            postBody['wednesday'] = wednesday;
            postBody['thursday'] = thursday;
            postBody['friday'] = friday;
            postBody['saturday'] = saturday;

            this.api = new oarn.API();
            this.set('.api.token', this.get('.token'));
            this.set('.api.method', 'POST');
            var endpoint = 'api/v1/attendance/person-class-schedules/';
            var ajax = this.api.getAjaxObject(endpoint);
            ajax.postBody = postBody;

            this.doAjaxStarted();
            ajax.go();
            ajax.response(enyo.bindSafely(this, 'postResponse'));
            ajax.error(enyo.bindSafely(this, 'processError'));
        },

        processError: function (inSender, inResponse) {
            this.doAjaxFinished(); // let a parent control turn off a spinner, etc.

            var status = inSender.xhrResponse.status;
            var detail = JSON.parse(inSender.xhrResponse.body);

            var detail_msg = '';
            for (var prop in detail) {
                if (detail.hasOwnProperty(prop)) {
                    detail_msg = prop + ': ' + detail[prop] + '
';
                }
            }

            this.$.popupFactory.showInfo('Database Communication Error', 'An error occurred while trying to ' +
                ' communicate with the server. ' +
                'Please provide the following information to your database administrator: ' +
                '

' + 'status: ' + status + '
' + detail_msg);

            this.set('.xhrResponse', inSender.xhrResponse);
            return true;
        },

        postResponse: function (inRequest, inResponse) {
            this.doAjaxFinished(); // let a parent control turn off a spinner, etc.
            this.$.scheduleRepeaterDisplay.refreshData();
        }
    });

})(enyo, this);<|endoftext|>


<commit_before><commit_msg>starting point<commit_after>
// For this challenge, you'll focus on the JavaScript that would take a user's input and
// turn it into output. You need to find a way to capture input from the form. You then
// want to output that input to the console using console.log.
//
// This is a tough problem, so tackle it as a group, practicing breaking down baby steps.
// Youll need the Event reference on MDN to find the correct event to listen for and how to
// make it do your bidding (instead of its default behavior).
//
// When turning in this assignment, make sure you put your scripts.js code in the repo,
// but also put the result of the output as a comment in your WIP Issue. Just for good
// measure, drop a few of those comments and be sure to use code fences!
// -------------------------------------------------------------------------------------

// need to grab input from input boxes and selections from the drop down menus and
// print them to the console when the "send your data" button at the bottom is pushed.
//
// will start with getting it to work on one input field then refactor for the whole page.

// setup an even listener that grabs the input from the "first name" box and log it
// to the console.
var firstName = document.getElementById("first_name"); // gets the first name input box
var lastName = document.getElementById("last_name"); //gets the last name input box
var email = document.getElementById("email"); //gets the email input box
var country = document.getElementById("country"); //yep...gets the counrty input box
var bio = document.getElementById("bio");//i'm seeing a pattern here
var phone = document.getElementById("phone"); //gets phone number input box
var affiliations = document.getElementById("affiliations"); //affiliations input box
var occupation = document.getElementById("occupation"); //occupation selection box
var catName = document.getElementById("cat_name"); //cat name input box
var gadget = document.getElementById("gagdet"); //favorite gadget input box
  //html code has an annoying typo...gadget box label, gagdet element id...lamo
var talent = document.getElementById("talent"); //type of talent selction box
var drink = document.getElementById("drink"); //favorite drink input box
var power = document.getElementById("power"); //special power input box
var weapon = document.getElementById("weapon"); //weapon of choice input box
var comments = document.getElementById("comments"); //comments input box
var submitButton = document.querySelector(".cbp-mc-submit"); //and last but not least...submit

//this pattern seems to be working but i want dump the inputs to the console when
//i click submit, not after each input -- my evil plan is to write the value of each
//input to a variable when that box/selection is changed. when the submit button is clicked
//i'll console.log all of the input and try to make it look pretty

//variables to capture the input of each field.
//i'll make them default to "no input given" or something similiar
var firstNameInput = "not provided"; //place holder for firs name value
var lastNameInput = "not provided";
var emailInput = "not provided";
var countryInput = "not selected"; //altered this one since its a selection vs inputs
var bioInput = "not provided";
var phoneInput = "not provided";
var affiliationsInput = "not provided";
var occupationInput = "not selected";
var catNameInput = "not provided";
var gadgetInput = "not provided";
var talentInput = "not selected";
var drinkInput = "not provided";
var powerInput = "not provided";
var weaponInput = "not provided";
var commentsInput = "not provided";

//setup event listeners for the input boxes to grab the inputs
firstName.addEventListener('change', function(){
  //console.log("changed the first name");  //tracer bullet, yo!
  //console.log("first name: ",firstName.value); //tracer bullet...thank you Google
  firstNameInput = firstName.value; //captures input of first name box
  //console.log("tracer", firstNameInput); //tracer bullet
});

lastName.addEventListener('change', function(){
  //console.log("changed the last name");  //tracer bullet
  //console.log("last name: ",lastName.value); //tracer bullet
  lastNameInput = lastName.value; //captures input of last name box
});

email.addEventListener('change', function(){
  // console.log("changed the email box"); // pew pew
  // console.log("email address: ",email.value); //more tracers
  emailInput = email.value; //captures email address
});

country.addEventListener('change', function(){
  //console.log("selected the country"); //tracers
  //console.log("country: ", country.value); //and traers
  countryInput = country.value; //captures country selction
})

bio.addEventListener('change', function(){
  //console.log("changed the bio box"); //more tracers
  //console.log("biography: ", bio.value); //and even more tracers
  bioInput = bio.value //captures biography input
});

phone.addEventListener('change', function(){
  phoneInput = phone.value; // captures the phone number input
});

affiliations.addEventListener('change', function(){
  affiliationsInput = affiliations.value; // captures the affiliations input
});

occupation.addEventListener('change', function(){
  occupationInput = occupation.value; //captures the occupation selection
});

catName.addEventListener('change', function(){
  catNameInput = catName.value; //captures the cat name selection
});

gadget.addEventListener('change', function(){
  gadgetInput = gadget.value; //captures the favorie gadget input
 });

talent.addEventListener('change', function(){
  talentInput = talent.value; //captures the talent selection
});

drink.addEventListener('change', function(){
  drinkInput = drink.value; //captures favorite drink input
});

power.addEventListener('change', function(){
  powerInput = power.value; //captures special power input
});

weapon.addEventListener('change', function(){
  weaponInput = weapon.value; //captures weapon of choice input
});

comments.addEventListener('change', function(){
  commentsInput = comments.value; //catpures the comment box input
});

//need to creat an eventlister for clicking the send your data button that
//logs all of the inputs to the console
submitButton.addEventListener('click', function(){
  //console.log("clicking the submit button") // tracer bullet for clicking submit
  //console.log(firstNameInput); //testing
  //console.log(firstName.value);//moar testing
    //the following lines print the input to the console when the submit button is clicked
  console.log("First Name: ", firstNameInput);
  console.log("Last Name: ", lastNameInput);
  console.log("Email Address: ", emailInput);
  console.log("Country: ", countryInput);
  console.log("Biography: ", bioInput);
  console.log("Phone Number: ", phoneInput);
  console.log("Affiliations: ", affiliationsInput);
  console.log("Occupation: ", occupationInput);
  console.log("Cat's Name: ", catNameInput);
  console.log("Favorite Gadget: ", gadgetInput);
  console.log("Type of Talent: ", talentInput);
  console.log("Favorite Drink: ", drinkInput);
  console.log("Special Power: ", powerInput);
  console.log("Weapon of Choice: ", weaponInput);
  console.log("Comments: ", commentsInput);
});
<|endoftext|>


<commit_before>'use strict';

const generateRuleTests = require('../../helpers/rule-test-harness');
const message = require('../../../lib/rules/lint-table-groups').message;

generateRuleTests({
  name: 'table-groups',

  config: true,

  good: [
    `

    {{#if foo}}

    {{/if}}

    `,
    `

    {{#unless foo}}

    {{/unless}}

    `,
    '

',
    '
{{! or this }}
',
    '

',
    '

Foo

',
    '
<colgroup><col style="background-color: red"></colgroup>
',
    '

Header

',
    '

Body

',
    '

Footer

',
    '
' +
      '
' +
      '
Header
' +
      '
' +
      '
' +
      '
Body
' +
      '
' +
      '
' +
      '
Footer
' +
      '
' +
      '
',
    '
' +
      '<colgroup>' +
      '<col style="background-color: red">' +
      '</colgroup>' +
      '
' +
      '
Body
' +
      '
' +
      '
',
    '
\n' + '
\n' + '
\n' + '
',
  ],

  bad: [
    {
      template: `

      {{#if foo}}
        {{else}}

      {{/if}}

      `,
      result: {
        message,
        moduleId: 'layout.hbs',
        source:
          '
\n      {{#if foo}}\n        {{else}}\n

\n      {{/if}}\n
',
        line: 2,
        column: 6,
      }
    },
    {
      template: `

      {{#unless foo}}

      {{/unless}}

      `,
      result: {
        message,
        moduleId: 'layout.hbs',
        source:
          '
\n      {{#unless foo}}\n
\n

\n
\n      {{/unless}}\n
',
        line: 2,
        column: 6,
      },
    },
    {
      template: `

      {{#if foo}}

      {{/if}}

      `,
      result: {
        message,
        moduleId: 'layout.hbs',
        source:
          '
\n      {{#if foo}}\n
\n

\n
\n      {{/if}}\n
',
        line: 2,
        column: 6,
      },
    },
    {
      template: `

      {{#unless foo}}
        {{some-component}}
      {{/unless}}

      `,
      result: {
        message,
        moduleId: 'layout.hbs',
        source:
          '
\n      {{#unless foo}}\n        {{some-component}}\n      {{/unless}}\n
',
        line: 2,
        column: 6,
      },
    },
    {
      template: '

Foo

',

      result: {
        message,
        moduleId: 'layout.hbs',
        source: '

Foo

',
        line: 1,
        column: 0,
      },
    },
    {
      template: '
{{some-component}}
',

      result: {
        message,
        moduleId: 'layout.hbs',
        source: '
{{some-component}}
',
        line: 1,
        column: 0,
      },
    },
    {
      template: '
{{#each foo as |bar|}}{{bar}}{{/each}}
',

      result: {
        message,
        moduleId: 'layout.hbs',
        source: '
{{#each foo as |bar|}}{{bar}}{{/each}}
',
        line: 1,
        column: 0,
      },
    },
    {
      template: '
' + '

' + '

Foo

' + '
',

      result: {
        message,
        moduleId: 'layout.hbs',
        source: '
' + '

' + '

Foo

' + '
',
        line: 1,
        column: 0,
      },
    },
    {
      template: '
 whitespace

',

      result: {
        message,
        moduleId: 'layout.hbs',
        source: '
 whitespace

',
        line: 1,
        column: 0,
      },
    },
  ],
});
<commit_msg>eslint fix<commit_after>'use strict';

const generateRuleTests = require('../../helpers/rule-test-harness');
const message = require('../../../lib/rules/lint-table-groups').message;

generateRuleTests({
  name: 'table-groups',

  config: true,

  good: [
    `

    {{#if foo}}

    {{/if}}

    `,
    `

    {{#unless foo}}

    {{/unless}}

    `,
    '

',
    '
{{! or this }}
',
    '

',
    '

Foo

',
    '
<colgroup><col style="background-color: red"></colgroup>
',
    '

Header

',
    '

Body

',
    '

Footer

',
    '
' +
      '
' +
      '
Header
' +
      '
' +
      '
' +
      '
Body
' +
      '
' +
      '
' +
      '
Footer
' +
      '
' +
      '
',
    '
' +
      '<colgroup>' +
      '<col style="background-color: red">' +
      '</colgroup>' +
      '
' +
      '
Body
' +
      '
' +
      '
',
    '
\n' + '
\n' + '
\n' + '
',
  ],

  bad: [
    {
      template: `

      {{#if foo}}
        {{else}}

      {{/if}}

      `,
      result: {
        message,
        moduleId: 'layout.hbs',
        source:
          '
\n      {{#if foo}}\n        {{else}}\n

\n      {{/if}}\n
',
        line: 2,
        column: 6,
      },
    },
    {
      template: `

      {{#unless foo}}

      {{/unless}}

      `,
      result: {
        message,
        moduleId: 'layout.hbs',
        source:
          '
\n      {{#unless foo}}\n
\n

\n
\n      {{/unless}}\n
',
        line: 2,
        column: 6,
      },
    },
    {
      template: `

      {{#if foo}}

      {{/if}}

      `,
      result: {
        message,
        moduleId: 'layout.hbs',
        source:
          '
\n      {{#if foo}}\n
\n

\n
\n      {{/if}}\n
',
        line: 2,
        column: 6,
      },
    },
    {
      template: `

      {{#unless foo}}
        {{some-component}}
      {{/unless}}

      `,
      result: {
        message,
        moduleId: 'layout.hbs',
        source:
          '
\n      {{#unless foo}}\n        {{some-component}}\n      {{/unless}}\n
',
        line: 2,
        column: 6,
      },
    },
    {
      template: '

Foo

',

      result: {
        message,
        moduleId: 'layout.hbs',
        source: '

Foo

',
        line: 1,
        column: 0,
      },
    },
    {
      template: '
{{some-component}}
',

      result: {
        message,
        moduleId: 'layout.hbs',
        source: '
{{some-component}}
',
        line: 1,
        column: 0,
      },
    },
    {
      template: '
{{#each foo as |bar|}}{{bar}}{{/each}}
',

      result: {
        message,
        moduleId: 'layout.hbs',
        source: '
{{#each foo as |bar|}}{{bar}}{{/each}}
',
        line: 1,
        column: 0,
      },
    },
    {
      template: '
' + '

' + '

Foo

' + '
',

      result: {
        message,
        moduleId: 'layout.hbs',
        source: '
' + '

' + '

Foo

' + '
',
        line: 1,
        column: 0,
      },
    },
    {
      template: '
 whitespace

',

      result: {
        message,
        moduleId: 'layout.hbs',
        source: '
 whitespace

',
        line: 1,
        column: 0,
      },
    },
  ],
});
<|endoftext|>


<commit_before>export { AsyncWorker_Proxy as Proxy };

import * as Pool from "../Pool.js";
import * as Recyclable from "../Recyclable.js";
import { PromiseResolveReject } from "./AsyncWorker_PromiseResolveReject.js";
import { PromiseResolveRejectMap } from "./AsyncWorker_PromiseResolveReject.js";

/**
 * Hold the worker and its related promise map. It is a wrapper of a neural network
 * web worker for handling and communicating easily.
 *
 * @member {number} workerId  The array index of this worker proxy.
 * @member {Worker} worker    The worker.
 *
 * @member {number} processingId_current
 *   The current processing id. Negative means no command has been sent. Every
 * postCommand_by_processingId() call will use a new id.
 *
 * @member {PromiseResolveRejectMap} thePromiseResolveRejectMap
 *   Every worker has a result pending promise map. The key of the map is processing
 * id. The value of the map is a PromiseResolveReject.
 *
 */
class AsyncWorker_Proxy extends Recyclable.Root {

  /**
   * Used as default AsyncWorker.Proxy provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "AsyncWorker.Proxy.Pool",
    AsyncWorker_Proxy, AsyncWorker_Proxy.setAsConstructor );

  /** */
  constructor() {
    super();
    AsyncWorker_Proxy.setAsConstructor_self.call( this );
  }

  /** @override */
  static setAsConstructor() {
    super.setAsConstructor();
    AsyncWorker_Proxy.setAsConstructor_self.call( this );
    return this;
  }

//!!! ...unfinished... (2022/09/11)
// should also mange processingId generating, worker creating,
// onmessage registering.
// provide postCommand() with/without processingId automatically.
//

  /** @override */
  static setAsConstructor_self() {

    // Q: What if processingId become too large (e.g. infinity)?
    // A: Because Number.MAX_SAFE_INTEGER is pretty large (at least, 2 ** 52 ),
    //    it is not so easy to become out of bounds.
    //
    this.processingId_current = -1;

    if ( this.thePromiseResolveRejectMap )
      this.thePromiseResolveRejectMap.clear();
    else
      this.thePromiseResolveRejectMap = new PromiseResolveRejectMap();
  }

  /** @override */
  disposeResources() {
    this.thePromiseResolveRejectMap.clear();

    this.processingId_current = undefined;

    super.disposeResources();
  }

  /**
   * Dispatch messages come from the owned web worker. Please register this method
   * as this WorkerProxy's Worker.onmessage.
   *
   * @param {AsyncWorker_Proxy} this
   *   The "this" should be binded to this AsyncWorker_Proxy object.
   */
  static onmessage_from_AsyncWorker_Body( e ) {

//!!! (2022/09/10 Remarked) no workerId
//     // e.data == { processingId, workerId, result }
//     let processingId = e.data.processingId;
//     let workerId = e.data.workerId;
//     let result = e.data.result;
//
//     if ( workerId != this.workerId )
//       return; // Ignore if wrong worker id.

    // ( e.data == { processingId, done, value } )
    let { processingId, done, value } = e.data;

    this.thePromiseResolveRejectMap.resolve_by_processingId_done_value(
      processingId, done, value );
  }

}
<commit_msg>createWorker<commit_after>export { AsyncWorker_Proxy as Proxy };

import * as Pool from "../Pool.js";
import * as Recyclable from "../Recyclable.js";
import { PromiseResolveReject } from "./AsyncWorker_PromiseResolveReject.js";
import { PromiseResolveRejectMap } from "./AsyncWorker_PromiseResolveReject.js";

/**
 * Hold the worker and its related promise map. It is a wrapper of a neural network
 * web worker for handling and communicating easily.
 *
 * @member {number} workerId  The array index of this worker proxy.
 * @member {Worker} worker    The worker.
 *
 * @member {number} processingId_current
 *   The current processing id. Negative means no command has been sent. Every
 * postCommand_by_processingId() call will use a new id.
 *
 * @member {PromiseResolveRejectMap} thePromiseResolveRejectMap
 *   Every worker has a result pending promise map. The key of the map is processing
 * id. The value of the map is a PromiseResolveReject.
 *
 */
class AsyncWorker_Proxy extends Recyclable.Root {

  /**
   * Used as default AsyncWorker.Proxy provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "AsyncWorker.Proxy.Pool",
    AsyncWorker_Proxy, AsyncWorker_Proxy.setAsConstructor );

  /** */
  constructor() {
    super();
    AsyncWorker_Proxy.setAsConstructor_self.call( this );
  }

  /** @override */
  static setAsConstructor() {
    super.setAsConstructor();
    AsyncWorker_Proxy.setAsConstructor_self.call( this );
    return this;
  }

//!!! ...unfinished... (2022/09/11)
// should also mange processingId generating, worker creating,
// onmessage registering.
// provide postCommand() with/without processingId automatically.
//

  /** @override */
  static setAsConstructor_self() {

    // Q: What if processingId become too large (e.g. infinity)?
    // A: Because Number.MAX_SAFE_INTEGER is pretty large (at least, 2 ** 52 ),
    //    it is not so easy to become out of bounds.
    //
    this.processingId_current = -1;

    if ( this.thePromiseResolveRejectMap )
      this.thePromiseResolveRejectMap.clear();
    else
      this.thePromiseResolveRejectMap = new PromiseResolveRejectMap();
  }

  /** @override */
  disposeResources() {
    this.thePromiseResolveRejectMap.clear();

    this.processingId_current = undefined;

    super.disposeResources();
  }

//!!! ...unfinished... (2022/09/11)
// worker.js url? options?
// called at setAsConstructor_self()?

  /**
   *
   */
  createWorker( workerId ) {
    this.workerId = workerId;

//!!! ...unfinished... (2022/08/24) Why not use "./NeuralWorker_Body.js"?
// The import.meta.url should extract the path (exclude file name)

    // Assume the main (i.e. body) javascript file of neural network web worker is
    // a sibling file (i.e. inside the same folder) of this module file.
    this.workerURL = new URL( "NeuralWorker_Body.js", import.meta.url );

    // Should not use "module" type worker, otherwise the worker can not use
    // importScripts() to load tensorflow.js library.
    //
    //this.workerOptions = { type: "module" }; // So that the worker script could use import statement.
    this.workerOptions = null;

    let worker = this.worker = new Worker( this.workerURL, this.workerOptions );

    // Register callback from the web worker.
    worker.onmessage = NeuralWorker_Proxy.onmessage_from_AsyncWorker_Body.bind( this );
  }

  /**
   * Dispatch messages come from the owned web worker. Please register this method
   * as this WorkerProxy's Worker.onmessage.
   *
   * @param {AsyncWorker_Proxy} this
   *   The "this" should be binded to this AsyncWorker_Proxy object.
   */
  static onmessage_from_AsyncWorker_Body( e ) {

//!!! (2022/09/10 Remarked) no workerId
//     // e.data == { processingId, workerId, result }
//     let processingId = e.data.processingId;
//     let workerId = e.data.workerId;
//     let result = e.data.result;
//
//     if ( workerId != this.workerId )
//       return; // Ignore if wrong worker id.

    // ( e.data == { processingId, done, value } )
    let { processingId, done, value } = e.data;

    this.thePromiseResolveRejectMap.resolve_by_processingId_done_value(
      processingId, done, value );
  }

}
<|endoftext|>