<commit_before>enyo.kind({
	name: "moon.CalendarDate",
	kind: "enyo.Button",
	classes: "moon-calendar-date enyo-unselectable",
	spotlight: true,
	published: {
		value: null,
		color: 0,
	},
	colorChanged: function(inOld) {
		if (this.color) {
			this.addClass("moon-calendar-date-shadow");
		} else {
			this.removeClass("moon-calendar-date-shadow");
		}
	},
	valueChanged: function() {
		this.setContent(this.value.getDate());
	},
});

enyo.kind({
	name: "moon.CalendarWeek",
	classes: "moon-calendar-week",
	published: {
		days: [],
		colors: [],
	},
	create: function() {
		this.inherited(arguments);
		this.setupLayout();
	},
	setupLayout: function() {
		for (var i = 0; i < 7; i++) {
			this.createComponent({kind: "moon.CalendarDate"});
		}
	},
	fillDate: function(days, colors) {
		this.days = days;
		this.colors = colors;

		for (var i = 0; i < this.days.length; i++) {
			var value = this.days[i],
				color = this.colors[i];
			this.controls[i].setValue(new Date(value.getFullYear(), value.getMonth(), value.getDate()));
			this.controls[i].setColor(color);
		}
	}
});

enyo.kind({
	name: "moon.Calendar",
	classes: "moon-calendar",
	events: {
		/**
			Fires when the date changes.

			_inEvent.name_ contains the name of this control.
			_inEvent.value_ contains the current Date object (standard JS Date object).
		*/
		onChange: ""
	},
	handlers: {
		ontap: "doTap", //*onChange events coming from consituent controls (simplePicker)
		onChange: "updateCalendar"
	},
	published: {
		//* Text to be displayed in the _currentValue_ control if no item is currently selected.
		noneText: "",
		/**
			Current locale used for formatting. Can be set after control
			creation, in which case the control will be updated to reflect the
			new value.
		*/
		locale: "en_us",
		/**
			The current Date object. When a Date object is passed to _setValue_,
			the control is updated to reflect the new value. _getValue_ returns
			a Date object.
		*/
		value: null,
		/**
			The maximum number of weeks to display in a screen.
			If this value over 9, it may show dates of 2 month later.
			(it is unexpected input, makes err)
		*/
		maxWeeks: 6,
		months: ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"],
		//days: ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],
		dateArray: [],
		colorArray: []
	},
	components: [
		{name: "simplePicker", kind: "moon.SimplePicker", classes: "moon-calendar-simplepicmoon-calendar-block"},
		{name: "dates", kind: "enyo.Group", classes: "moon-calendar-dates"}
	],
	create: function() {
		this.inherited(arguments);
		if (enyo.g11n) {
			this.locale = enyo.g11n.currentLocale().getLocale();
		}
		this.initDefaults();
	//	this.noneTextChanged();
	},
	initDefaults: function() {
		//Attempt to use the g11n lib (ie assume it is loaded)
		if (enyo.g11n) {
			this._tf = new enyo.g11n.Fmts({locale:this.locale});
		}

		this.value = this.value || new Date();
		this.setupSimplePicker();
		this.$.simplePicker.setSelectedIndex(this.value.getMonth());
		this.setupLayout();
		this.valueChanged();
	},
	/**
		Set simplePicker with months
		The contents will be filled with from JAN to DEC
	*/
	setupSimplePicker: function() {
		var months = this.months;
		/*Todo: Follwing statement violates encapsulation -david.um */
		this.$.simplePicker.$.buttonLeft.addClass("picker-button");
		this.$.simplePicker.$.client.addClass("picker-content");
		this.$.simplePicker.$.buttonRight.addClass("picker-button");
		for (var i = 0; i < 12; i++) {
			this.$.simplePicker.createComponent(
				{content: months[i]}
			)
		}
	},
	/**
		Set a layout of calendar.
		The content of it is not prepared at this time.
	*/
	setupLayout: function() {
		for (var i = 0; i < this.maxWeeks; i++) {
			var days = [];
			this.$.dates.createComponent(
				{kind: "moon.CalendarWeek", days: days}
			)
		}
	},
	/**
		Set the first week of this month.
		Before the first day of this month, some days from previous month will fill calendar
	*/
	setupPrevMonth: function() {
		var value = this.value;
		var dt = new Date(value.getFullYear(), value.getMonth(), value.getDate());
		dt.setDate(0);
		var thisYear = dt.getFullYear(),
			daysOfPrevMonth = dt.getDate(),
			dayOfLastDate = dt.getDay(),
			prevMonth = dt.getMonth();
		var firstDateOfWeek = daysOfPrevMonth - dayOfLastDate;
		if (dayOfLastDate != 0) {
			for (var i = firstDateOfWeek; i <= daysOfPrevMonth; i++) {
				this.dateArray.push(new Date(thisYear, prevMonth, i));
				this.colorArray.push(1);
			}
		}
	},
	/**
		Set the last week of this month.
		After the last day of this month, some days from next month will fill calendar
	*/
	setupNextMonth: function(monthLength) {
		var value = this.value;
		var dt = new Date(value.getFullYear(), value.getMonth(), value.getDate());
		dt.setMonth(dt.getMonth() + 1);

		var thisYear = dt.getFullYear(),
			nextMonth = dt.getMonth(),
			thisDate = dt.getDate();
		var offset = this.maxWeeks * 7 - this.dateArray.length + 1;
		for (var i = 1; i < offset; i++) {
			this.dateArray.push(new Date(thisYear, nextMonth, i));
			this.colorArray.push(1);
		}
	},
	setupCalendar: function(ordering) {
		//* Make empty
		this.dateArray = [];
		this.colorArray = [];

		this.setupPrevMonth();

		var thisYear = this.value.getFullYear(),
			thisMonth = this.value.getMonth();
		var	monthLength = this.monthLength(thisYear, thisMonth);
		for (var i = 1; i <= monthLength; i++) {
			this.dateArray.push(new Date(thisYear, thisMonth, i));
			this.colorArray.push(0);
		}

		this.setupNextMonth(monthLength);
	},
	fillDate: function() {
		var calendarWeeks =this.$.dates.getControls();
		for (var i = 0; i < this.dateArray.length / 7; i++) {
			var days = [],
				colors = [];
			for (var j = 0; j < 7; j++) {
				days.push(this.dateArray[i * 7 + j]);
				colors.push(this.colorArray[i * 7 + j]);
			}
			calendarWeeks[i].fillDate(days, colors);
		}
	},
	parseDate: function(ordering) {
	},
	/**
		When value of DatePicker is changed, it will update Calendar
	*/
	updateCalendar: function(inSender, inEvent) {
		//* Avoid onChange events coming from itself
		if (inEvent && inEvent.originator == this || inEvent.originator.kind == "Selection") {
			return;
		}
		var value = this.value;
		var year = value.getFullYear(),
			month = this.$.simplePicker.getSelectedIndex();
		//* Determine whether calender need to redraw or not
		if (month != this.value.getMonth()) {
			this.setValue(new Date(value.getFullYear(), month, value.getDate()));
		} else {
			this.value.setYear(year);
			this.value.setMonth(month);
			this.value.setDate(value.getDate());
		}
		return true;
	},
	monthLength: function(inYear, inMonth) {
		// determine number of days in a particular month/year
		return 32 - new Date(inYear, inMonth, 32).getDate();
	},
	/**
		Change value of simplePicker with selected CalendarDate.
	*/
	doTap: function(inSender, inEvent) {
		if (inEvent.originator.kind == "moon.CalendarDate") {
			var newValue = inEvent.originator.value,
				oldValue = this.getValue();

			if (newValue.getFullYear() > oldValue.getFullYear()) {
				this.$.simplePicker.setSelectedIndex(0);
			} else if (newValue.getFullYear() < oldValue.getFullYear()) {
				this.$.simplePicker.setSelectedIndex(11);
			} else if (newValue.getMonth() > oldValue.getMonth()) {
				this.$.simplePicker.next();
			} else if (newValue.getMonth() < oldValue.getMonth()) {
				this.$.simplePicker.previous();
			}
		}
		return true;
	},
	valueChanged: function(inOld) {
		this.setupCalendar();
		this.fillDate();
		this.$.dates.render();
	},
	localeChanged: function() {
		this.refresh();
	},
	refresh: function(){
		this.destroyClientControls();
		this.initDefaults();
		this.render();
	}
});<commit_msg>GF-2156: Remove public block.<commit_after>enyo.kind({
	name: "moon.CalendarDate",
	kind: "enyo.Button",
	classes: "moon-calendar-date enyo-unselectable",
	spotlight: true,
	published: {
		value: null,
		color: 0,
	},

	colorChanged: function(inOld) {
		if (this.color) {
			this.addClass("moon-calendar-date-shadow");
		} else {
			this.removeClass("moon-calendar-date-shadow");
		}
	},

	valueChanged: function() {
		this.setContent(this.value.getDate());
	},
});

enyo.kind({
	name: "moon.CalendarWeek",
	classes: "moon-calendar-week",
	days: [],
	colors: [],

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

	setupLayout: function() {
		for (var i = 0; i < 7; i++) {
			this.createComponent({kind: "moon.CalendarDate"});
		}
	},

	fillDate: function(days, colors) {
		this.days = days;
		this.colors = colors;

		for (var i = 0; i < this.days.length; i++) {
			var value = this.days[i],
				color = this.colors[i];
			this.controls[i].setValue(new Date(value.getFullYear(), value.getMonth(), value.getDate()));
			this.controls[i].setColor(color);
		}
	}
});

enyo.kind({
	name: "moon.Calendar",
	classes: "moon-calendar",
	events: {
		/**
			Fires when the date changes.

			_inEvent.name_ contains the name of this control.
			_inEvent.value_ contains the current Date object (standard JS Date object).
		*/
		onChange: ""
	},
	handlers: {
		ontap: "doTap", //*onChange events coming from consituent controls (simplePicker)
		onChange: "updateCalendar"
	},
	published: {
		//* Text to be displayed in the _currentValue_ control if no item is currently selected.
		noneText: "",
		/**
			Current locale used for formatting. Can be set after control
			creation, in which case the control will be updated to reflect the
			new value.
		*/
		locale: "en_us",
		/**
			The current Date object. When a Date object is passed to _setValue_,
			the control is updated to reflect the new value. _getValue_ returns
			a Date object.
		*/
		value: null,
		/**
			The maximum number of weeks to display in a screen.
			If this value over 9, it may show dates of 2 month later.
			(it is unexpected input, makes err)
		*/
		maxWeeks: 6,
		months: ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"],
		//days: ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],
		dateArray: [],
		colorArray: []
	},
	components: [
		{name: "simplePicker", kind: "moon.SimplePicker", classes: "moon-calendar-simplepicmoon-calendar-block"},
		{name: "dates", kind: "enyo.Group", classes: "moon-calendar-dates"}
	],
	create: function() {
		this.inherited(arguments);
		if (enyo.g11n) {
			this.locale = enyo.g11n.currentLocale().getLocale();
		}
		this.initDefaults();
	//	this.noneTextChanged();
	},
	initDefaults: function() {
		//Attempt to use the g11n lib (ie assume it is loaded)
		if (enyo.g11n) {
			this._tf = new enyo.g11n.Fmts({locale:this.locale});
		}

		this.value = this.value || new Date();
		this.setupSimplePicker();
		this.$.simplePicker.setSelectedIndex(this.value.getMonth());
		this.setupLayout();
		this.valueChanged();
	},
	/**
		Set simplePicker with months
		The contents will be filled with from JAN to DEC
	*/
	setupSimplePicker: function() {
		var months = this.months;
		/*Todo: Follwing statement violates encapsulation -david.um */
		this.$.simplePicker.$.buttonLeft.addClass("picker-button");
		this.$.simplePicker.$.client.addClass("picker-content");
		this.$.simplePicker.$.buttonRight.addClass("picker-button");
		for (var i = 0; i < 12; i++) {
			this.$.simplePicker.createComponent(
				{content: months[i]}
			)
		}
	},
	/**
		Set a layout of calendar.
		The content of it is not prepared at this time.
	*/
	setupLayout: function() {
		for (var i = 0; i < this.maxWeeks; i++) {
			var days = [];
			this.$.dates.createComponent(
				{kind: "moon.CalendarWeek", days: days}
			)
		}
	},
	/**
		Set the first week of this month.
		Before the first day of this month, some days from previous month will fill calendar
	*/
	setupPrevMonth: function() {
		var value = this.value;
		var dt = new Date(value.getFullYear(), value.getMonth(), value.getDate());
		dt.setDate(0);
		var thisYear = dt.getFullYear(),
			daysOfPrevMonth = dt.getDate(),
			dayOfLastDate = dt.getDay(),
			prevMonth = dt.getMonth();
		var firstDateOfWeek = daysOfPrevMonth - dayOfLastDate;
		if (dayOfLastDate != 0) {
			for (var i = firstDateOfWeek; i <= daysOfPrevMonth; i++) {
				this.dateArray.push(new Date(thisYear, prevMonth, i));
				this.colorArray.push(1);
			}
		}
	},
	/**
		Set the last week of this month.
		After the last day of this month, some days from next month will fill calendar
	*/
	setupNextMonth: function(monthLength) {
		var value = this.value;
		var dt = new Date(value.getFullYear(), value.getMonth(), value.getDate());
		dt.setMonth(dt.getMonth() + 1);

		var thisYear = dt.getFullYear(),
			nextMonth = dt.getMonth(),
			thisDate = dt.getDate();
		var offset = this.maxWeeks * 7 - this.dateArray.length + 1;
		for (var i = 1; i < offset; i++) {
			this.dateArray.push(new Date(thisYear, nextMonth, i));
			this.colorArray.push(1);
		}
	},
	setupCalendar: function(ordering) {
		//* Make empty
		this.dateArray = [];
		this.colorArray = [];

		this.setupPrevMonth();

		var thisYear = this.value.getFullYear(),
			thisMonth = this.value.getMonth();
		var	monthLength = this.monthLength(thisYear, thisMonth);
		for (var i = 1; i <= monthLength; i++) {
			this.dateArray.push(new Date(thisYear, thisMonth, i));
			this.colorArray.push(0);
		}

		this.setupNextMonth(monthLength);
	},
	fillDate: function() {
		var calendarWeeks =this.$.dates.getControls();
		for (var i = 0; i < this.dateArray.length / 7; i++) {
			var days = [],
				colors = [];
			for (var j = 0; j < 7; j++) {
				days.push(this.dateArray[i * 7 + j]);
				colors.push(this.colorArray[i * 7 + j]);
			}
			calendarWeeks[i].fillDate(days, colors);
		}
	},
	parseDate: function(ordering) {
	},
	/**
		When value of DatePicker is changed, it will update Calendar
	*/
	updateCalendar: function(inSender, inEvent) {
		//* Avoid onChange events coming from itself
		if (inEvent && inEvent.originator == this || inEvent.originator.kind == "Selection") {
			return;
		}
		var value = this.value;
		var year = value.getFullYear(),
			month = this.$.simplePicker.getSelectedIndex();
		//* Determine whether calender need to redraw or not
		if (month != this.value.getMonth()) {
			this.setValue(new Date(value.getFullYear(), month, value.getDate()));
		} else {
			this.value.setYear(year);
			this.value.setMonth(month);
			this.value.setDate(value.getDate());
		}
		return true;
	},
	monthLength: function(inYear, inMonth) {
		// determine number of days in a particular month/year
		return 32 - new Date(inYear, inMonth, 32).getDate();
	},
	/**
		Change value of simplePicker with selected CalendarDate.
	*/
	doTap: function(inSender, inEvent) {
		if (inEvent.originator.kind == "moon.CalendarDate") {
			var newValue = inEvent.originator.value,
				oldValue = this.getValue();

			if (newValue.getFullYear() > oldValue.getFullYear()) {
				this.$.simplePicker.setSelectedIndex(0);
			} else if (newValue.getFullYear() < oldValue.getFullYear()) {
				this.$.simplePicker.setSelectedIndex(11);
			} else if (newValue.getMonth() > oldValue.getMonth()) {
				this.$.simplePicker.next();
			} else if (newValue.getMonth() < oldValue.getMonth()) {
				this.$.simplePicker.previous();
			}
		}
		return true;
	},
	valueChanged: function(inOld) {
		this.setupCalendar();
		this.fillDate();
		this.$.dates.render();
	},
	localeChanged: function() {
		this.refresh();
	},
	refresh: function(){
		this.destroyClientControls();
		this.initDefaults();
		this.render();
	}
});<|endoftext|>


<commit_before>/* Copyright 2012-2013 Trans Lunar Designs, Inc. */
// Globals are a cheat plain and simple. I get confused with the different namespaces and calling back and forth between classes
// there's a way to do it with parent or window.TopWatch, but this is a little easier
var dialRef = {};
var topWatchRef = {};
var dialLabel = "";
var watchLabel = "";
enyo.kind({
	name: "TopWatch",
	kind: "FittableRows",
	classes: "app enyo-fit",
	components: [
		{name: "slidingPane", kind: "Panels", fit: true, arrangerKind: "CollapsingArranger", animate: true, components: [
			{name: "leftPanel", style: "width: 100%;", fixedWidth: true, draggable: true, animate: true, components: [
				{kind:"onyx.MoreToolbar", ontap: "closePanel", components: [
					{kind: "onyx.Grabber", noStretch: 'true', ontap: "closePanel"}, {content: "Splits"},
					{kind: "onyx.IconButton", src: "img/QuestionMark.png", ontap: "openPopup", popup: "popupHelp", style: "margin-left: 150px;"}
				]},
				{kind: "TopWatchDial"}
			]},
			{name: "rightPanel", style: "width: 30%;", fixedWidth: false, draggable: true, animate: true, components: [
				{kind:"onyx.MoreToolbar", name:"rightToolbar", ontap: "openPanel", components: [
					{kind: "onyx.Grabber", noStretch: 'true', ontap: "openPanel"},
					{content: "Timer"},
					{kind: "onyx.IconButton", src: "img/QuestionMark.png", ontap: "openPopup", popup: "popupHelp", style: "margin-left: 145px;"}
				]},
				{kind: "List", name: "splitList", layoutKind: "FittableRowsLayout", style: "margin-top:55px;", classes: "onyx enyo-fit", touch: true, count: 1, onSetupItem: "setupItem", item: "item1", components: [
					{name: "item1", classes: "panels-sample-sliding-item", style: "margin-left:20px;font-size:26px;"}
				]}
			]}
		]},
		{kind: onyx.MoreToolbar,
			name: "ButtonToolbar",
			layoutKind: "FittableRowsLayout",
			classes: "onyx",
			style: "height: 50px;",
			components: [
				{kind: "onyx.Button", name: "startSplitButton", content: "Start", ontap: "startSplitTimer"},
				// Not happy with button choices, needed to combine button functions to save on handset realestate
				// Not working properly{kind: "onyx.Button", content: "Reset", ontap: "resetTimer"},
				{kind: "onyx.Button", name: "stopResetButton", content: "Reset", ontap: "stopReset", style: "margin-left: 145px;"}
			]
		},
		{kind: "PopupDialog", name: "HelpPopup"},
		{kind: onyx.Popup,
			name: "popupHelp",
			centered: true,
			style: "text-align: center; padding: 10px; background: #C9C9C9;width: 350px;",
			components: [
				{
					kind: "Image",
					src: "img/LogoColor_162.png",
				},
				{kind: "Button",
					content: "Email Support@TransLunarDesigns.com",
					ontap: "buttonEmailTap",
				},
				{name: "message", style: "font-size: 26px; padding: 6px; text-align: center;color:black;", content:"Enyo 2 Demonstration App"},
				{kind: "onyx.Button",
						content: "Project Blog & Code",
						ontap: "openBlog",
				},
				{kind: "onyx.Button",
					style: "margin-left: 20px;",
					content: "Cancel",
					ontap: "buttontapCancelHelp",
				}
			]
		}
	],
	published: {
		// Data list
		splitTimeData: [{id:"", value:"Splits"}]
	},
	rendered: function() {
		this.inherited(arguments);
		topWatchRef = this;
	},
	startSplitTimer: function() {
		if (dialRef.timerRunning === false) {
			dialRef.startTimer();
			this.$.startSplitButton.setContent("Split");
			this.$.stopResetButton.setContent("Stop");
		} else {
			dialRef.splitTimer();
		}
	},
	addSplit: function(record) {
		topWatchRef.splitTimeData.push(record);
		//topWatchRef.$.splitList.renderRow(topWatchRef.splitTimeData.length-1);
		topWatchRef.$.splitList.reset();
	},
	getNextId: function() {
		return topWatchRef.padStr(topWatchRef.splitTimeData.length, " ", 4);
	},
	stopReset: function() {
		if (dialRef.timerRunning === false) {
			topWatchRef.splitTimeData = [{id:"", value:"Splits"}];
			// refresh list row
			topWatchRef.$.splitList.reset();
			// Why twice?
			topWatchRef.$.splitList.reset();
			// Commenting out the RESET for now, funky behavior: If running, need to press reset twice, once to stop the timer and once to clear the dial, if stopped, reset won't clear the dial
			dialRef.resetTimer();
			// refresh list row
			topWatchRef.clearSplits();
			dialRef.resetTimer();
			dialRef.$.timerLayer.destroyClientControls();
		} else {
			dialRef.stopTimer();
			this.$.startSplitButton.setContent("Start");
			this.$.stopResetButton.setContent("Reset");
		}
	},
	closePanel: function() {
		var index = this.$.slidingPane.setIndex(1);
	},
	openPanel: function() {
		var index = this.$.slidingPane.setIndex(0);
	},
	displayTime: function(timeStr) {
		topWatchRef.splitTimeData[0].value = "Time: " + timeStr;
		topWatchRef.$.splitList.reset();
	},
	setupItem: function(inSender, inEvent) {
		inSender.count = this.splitTimeData.length;
		var inIndex = inEvent.index;
		if (inIndex < this.splitTimeData.length) {
			if (inIndex < 0) return false;
			var record = this.splitTimeData[inIndex];
			if (record.id.length > 0) {
				this.$[inSender.item].setContent(record.id + ": " + record.value);
			} else {
				this.$[inSender.item].setContent(record.value);
			}
			return true;
		}
	},
	openPopup: function(inSender) {
		var p = this.$[inSender.popup];
		if (p) {
			p.show();
		}
	},
	buttonEmailTap: function() {
		window.open("mailto:Support@TransLunarDesigns.com?subject=Question/Suggestion");
		this.$.popupHelp.hide();
	},
	buttontapCancelHelp: function() {
		this.$.popupHelp.hide();
	},
	buttonClick: function() {
		this.$.openAppService.call({
			id: 'com.palm.app.email',
			params: {
				summary: "Top Watch question/comment",
				text: "",
				recipients: [{
					type: "email",
					role: 1,
					value: "support@translunardesigns.com",
					contactDisplay: "Trans Lunar Designs"
				}]
			}
		});
	},
	// popup helper
	pop: function(inSender) {
		this.popMessage(inSender.message);
	},
    popMessage: function(message) {
        this.$.HelpPopup.show();
		this.$.HelpPopup.setMessage(message);
    },
	padStr: function(stringVal, padChar, length) {
		var retStr = padChar + stringVal;
		return retStr.substring(stringVal.length - length);
	},
	openBlog: function() {
		window.open("http://pcimino.blog.com/enyo/")
	}
});<commit_msg>Fixed spacing issues<commit_after>/* Copyright 2012-2013 Trans Lunar Designs, Inc. */
// Globals are a cheat plain and simple. I get confused with the different namespaces and calling back and forth between classes
// there's a way to do it with parent or window.TopWatch, but this is a little easier
var dialRef = {};
var topWatchRef = {};
var dialLabel = "";
var watchLabel = "";
enyo.kind({
	name: "TopWatch",
	kind: "FittableRows",
	classes: "app enyo-fit",
	components: [
		{name: "slidingPane", kind: "Panels", fit: true, arrangerKind: "CollapsingArranger", animate: true, components: [
			{name: "leftPanel", style: "width: 100%;", fixedWidth: true, draggable: true, animate: true, components: [
				{kind:"onyx.MoreToolbar", ontap: "closePanel", components: [
					{kind: "onyx.Grabber", noStretch: 'true', ontap: "closePanel"}, {content: "Splits"},
					{kind: "onyx.IconButton", src: "img/QuestionMark.png", ontap: "openPopup", popup: "popupHelp", style: "margin-left: 150px;"}
				]},
				{kind: "TopWatchDial"}
			]},
			{name: "rightPanel", style: "width: 30%;", fixedWidth: false, draggable: true, animate: true, components: [
				{kind:"onyx.MoreToolbar", name:"rightToolbar", ontap: "openPanel", components: [
					{kind: "onyx.Grabber", noStretch: 'true', ontap: "openPanel"},
					{content: "Timer"},
					{kind: "onyx.IconButton", src: "img/QuestionMark.png", ontap: "openPopup", popup: "popupHelp", style: "margin-left: 145px;"}
				]},
				{kind: "List", name: "splitList", layoutKind: "FittableRowsLayout", style: "margin-top:55px;", classes: "onyx enyo-fit", touch: true, count: 1, onSetupItem: "setupItem", item: "item1", components: [
					{name: "item1", classes: "panels-sample-sliding-item", style: "margin-left:20px;font-size:26px;"}
				]}
			]}
		]},
		{kind: onyx.MoreToolbar,
			name: "ButtonToolbar",
			layoutKind: "FittableRowsLayout",
			classes: "onyx",
			style: "height: 50px;",
			components: [
				{kind: "onyx.Button", name: "startSplitButton", content: "Start", ontap: "startSplitTimer"},
				// Not happy with button choices, needed to combine button functions to save on handset realestate
				// Not working properly{kind: "onyx.Button", content: "Reset", ontap: "resetTimer"},
				{kind: "onyx.Button", name: "stopResetButton", content: "Reset", ontap: "stopReset", style: "margin-left: 145px;"}
			]
		},
		{kind: "PopupDialog", name: "HelpPopup"},
		{kind: onyx.Popup,
			name: "popupHelp",
			centered: true,
			style: "text-align: center; padding: 10px; background: #C9C9C9;width: 350px;",
			components: [
				{
					kind: "Image",
					src: "img/LogoColor_162.png",
				},
				{kind: "Button",
					content: "Email Support@TransLunarDesigns.com",
					ontap: "buttonEmailTap",
				},
				{name: "message", style: "font-size: 26px; padding: 6px; text-align: center;color:black;", content:"Enyo 2 Demonstration App"},
				{kind: "onyx.Button",
						content: "Project Blog & Code",
						ontap: "openBlog",
				},
				{kind: "onyx.Button",
					style: "margin-left: 20px;",
					content: "Cancel",
					ontap: "buttontapCancelHelp",
				}
			]
		}
	],
	published: {
		// Data list
		splitTimeData: [{id:"", value:"Splits"}]
	},
	rendered: function() {
		this.inherited(arguments);
		topWatchRef = this;
	},
	startSplitTimer: function() {
		if (dialRef.timerRunning === false) {
			dialRef.startTimer();
			this.$.startSplitButton.setContent("Split");
			this.$.stopResetButton.setContent("Stop");
		} else {
			dialRef.splitTimer();
		}
	},
	addSplit: function(record) {
		topWatchRef.splitTimeData.push(record);
		//topWatchRef.$.splitList.renderRow(topWatchRef.splitTimeData.length-1);
		topWatchRef.$.splitList.reset();
	},
	getNextId: function() {
		return topWatchRef.padStr(topWatchRef.splitTimeData.length, " ", 4);
	},
	stopReset: function() {
		if (dialRef.timerRunning === false) {
			topWatchRef.splitTimeData = [{id:"", value:"Splits"}];
			// refresh list row
			topWatchRef.$.splitList.reset();
			// Why twice?
			topWatchRef.$.splitList.reset();
			// Commenting out the RESET for now, funky behavior: If running, need to press reset twice, once to stop the timer and once to clear the dial, if stopped, reset won't clear the dial
			dialRef.resetTimer();
			dialRef.resetTimer();
			dialRef.$.timerLayer.destroyClientControls();
			//dialRef.setupCanvasSize();
		} else {
			dialRef.stopTimer();
			this.$.startSplitButton.setContent("Start");
			this.$.stopResetButton.setContent("Reset");
		}
	},
	closePanel: function() {
		var index = this.$.slidingPane.setIndex(1);
	},
	openPanel: function() {
		var index = this.$.slidingPane.setIndex(0);
	},
	displayTime: function(timeStr) {
		topWatchRef.splitTimeData[0].value = "Time: " + timeStr;
		topWatchRef.$.splitList.reset();
	},
	setupItem: function(inSender, inEvent) {
		inSender.count = this.splitTimeData.length;
		var inIndex = inEvent.index;
		if (inIndex < this.splitTimeData.length) {
			if (inIndex < 0) return false;
			var record = this.splitTimeData[inIndex];
			if (record.id.length > 0) {
				this.$[inSender.item].setContent(record.id + ": " + record.value);
			} else {
				this.$[inSender.item].setContent(record.value);
			}
			return true;
		}
	},
	openPopup: function(inSender) {
		var p = this.$[inSender.popup];
		if (p) {
			p.show();
		}
	},
	buttonEmailTap: function() {
		window.open("mailto:Support@TransLunarDesigns.com?subject=Question/Suggestion");
		this.$.popupHelp.hide();
	},
	buttontapCancelHelp: function() {
		this.$.popupHelp.hide();
	},
	buttonClick: function() {
		this.$.openAppService.call({
			id: 'com.palm.app.email',
			params: {
				summary: "Top Watch question/comment",
				text: "",
				recipients: [{
					type: "email",
					role: 1,
					value: "support@translunardesigns.com",
					contactDisplay: "Trans Lunar Designs"
				}]
			}
		});
	},
	// popup helper
	pop: function(inSender) {
		this.popMessage(inSender.message);
	},
    popMessage: function(message) {
        this.$.HelpPopup.show();
		this.$.HelpPopup.setMessage(message);
    },
	padStr: function(stringVal, padChar, length) {
		var retStr = padChar + stringVal;
		return retStr.substring(stringVal.length - length);
	},
	openBlog: function() {
		window.open("http://pcimino.blog.com/enyo/")
	}
});<|endoftext|>


<commit_before>'use strict';

var net = require('net'),
    Q = require('q');

function send (message, serverPort, timeout) {
    var deferred = Q.defer(),
        socket = net.createConnection({ port: serverPort }, function () { socket.write(message); });

    if (!serverPort) {
        throw Error('you forgot to pass the port again');
    }

    socket.once('error', deferred.reject);
    socket.once('data', deferred.resolve);

    if (timeout) {
        setTimeout(function () { deferred.resolve(''); }, timeout);
    }

    return deferred.promise;
}

function fireAndForget (message, serverPort) {
    var deferred = Q.defer(),
        socket = net.createConnection({ port: serverPort }, function () { socket.write(message); });

    // Attempt to avoid race conditions where the subsequent test code
    // gets ahead of the server's ability to record the request
    setTimeout(deferred.resolve, 150);
}

module.exports = {
    send: send,
    fireAndForget: fireAndForget
};
<commit_msg>fixed bug - forgot to return promise<commit_after>'use strict';

var net = require('net'),
    Q = require('q');

function send (message, serverPort, timeout) {
    var deferred = Q.defer(),
        socket = net.createConnection({ port: serverPort }, function () { socket.write(message); });

    if (!serverPort) {
        throw Error('you forgot to pass the port again');
    }

    socket.once('error', deferred.reject);
    socket.once('data', deferred.resolve);

    if (timeout) {
        setTimeout(function () { deferred.resolve(''); }, timeout);
    }

    return deferred.promise;
}

function fireAndForget (message, serverPort) {
    var deferred = Q.defer(),
        socket = net.createConnection({ port: serverPort }, function () { socket.write(message); });

    // Attempt to avoid race conditions where the subsequent test code
    // gets ahead of the server's ability to record the request
    setTimeout(deferred.resolve, 150);
    return deferred.promise;
}

module.exports = {
    send: send,
    fireAndForget: fireAndForget
};
<|endoftext|>


<commit_before>module('lively.ide.codeeditor.MorphicOverlay').requires('lively.morphic.Core', 'lively.morphic.TextCore', 'lively.ide.CodeEditor').toRun(function() {

lively.morphic.Morph.subclass("lively.ide.CodeEditor.MorphicOverlay",
"settings", {

  style: {
    fill: Global.Color.rgba(33,33,33,.2),
    borderWidth: 0
  },

  labelStyle: {
    handStyle: 'pointer',
    fixedWidth: true, fixedHeight: true,
    textColor: Global.Color.white,
    fill: Global.Color.rgb(120,120,120),
    clipMode: "hidden",
    padding: Global.Rectangle.inset(10,0, 5, 0),
    fontSize: lively.morphic.CodeEditor.prototype.style.fontSize - 2,
    selectable: false, allowInput: false
  },

  doNotSerialize: ["documentStartAnchor", "documentEndAnchor"]
},
"initializing", {

  initialize: function($super, spec) {
    $super(null, lively.rect(0,0,100,100));

    this.spec = lively.lang.obj.merge({
      alignLabel: "line-end",
      fitLabel: true
    }, spec);

    this.state = {
      value: null,
      node: null
    }

    this.disableEvents();
    this.label = this.makeLabel();
  },

  onLoad: function($super) {
    if (this.owner && this.owner.isCodeEditor) {
      this.ensureAnchors(this.owner, this.getRange(this.owner));
    }
  },

  makeLabel: function() {
    var label = lively.morphic.Text.makeLabel("");
    label.applyStyle(this.labelStyle);
    label.name = "label";
    label.addScript(function onClick(evt) {
      return this.owner.onLabelClick(evt);
    });
    label.enableEvents();
    return this.addMorph(label);
  },

  ensureAnchors: function(codeEditor, range) {
    var self = this;
    var Anchor = lively.ide.ace.require("ace/anchor").Anchor;
    if (this.documentStartAnchor) {
      this.documentStartAnchor.setPosition(range.start.row, range.start.column);
    } else {
      this.documentStartAnchor = new Anchor(codeEditor.getDocument(), range.start.row, range.start.column);
      this.documentStartAnchor.on("change", function(change) { self.onAnchorChange(codeEditor); });

    }

    if (this.documentEndAnchor) {
      this.documentEndAnchor.setPosition(range.end.row, range.end.column+1);
    } else {
      this.documentEndAnchor = new Anchor(codeEditor.getDocument(), range.end.row, range.end.column+1);
      this.documentEndAnchor.on("change", function(change) { self.onAnchorChange(codeEditor); });
    }
  },

  cleanupAnchors : function() {
    if (this.documentStartAnchor) {
      this.documentStartAnchor.removeAllListeners("change");
      this.documentStartAnchor.detach();
      this.documentStartAnchor = null;
    }
    if (this.documentEndAnchor) {
      this.documentEndAnchor.removeAllListeners("change");
      this.documentEndAnchor.detach();
      this.documentEndAnchor = null;
    }
  }

},
"layouting", {

  getRange: function(codeEditor) {
    var bounds = this.globalBounds(),
        topLeft = bounds.topLeft(),
        bottomRight = bounds.bottomRight(),
        r = codeEditor.aceEditor.renderer,
        start = r.pixelToScreenCoordinates(topLeft.x, topLeft.y),
        end = r.pixelToScreenCoordinates(bottomRight.x, bottomRight.y-1);
    return lively.ide.ace.require("ace/range").Range.fromPoints(start, end);
  },

  getLine: function(codeEditor) {
    return this.getRange(codeEditor).start.row;
  },

  alignWithAnchor: function(codeEditor) {
    if (!this.documentStartAnchor) {
      this.ensureAnchors(codeEditor, this.getRange(codeEditor));
    }
    var bounds = lively.rect(
      codeEditor.posToMorphicPos(this.documentStartAnchor.getPosition(), "topLeft"),
      codeEditor.posToMorphicPos(this.documentEndAnchor.getPosition(), "bottomLeft"))
    this.setBounds(bounds);
    this.alignLabel(codeEditor);
  },

  realign: function(codeEditor) {
    this.alignWithAnchor(codeEditor);
  },

  fitLabel: function(thenDo) {
    this.label.applyStyle({extent: pt(10,10), fixedWidth: false, fixedHeight: false})
    this.label.fit();
    this.label.fitThenDo(function() {
      this.label.applyStyle({fixedWidth: true, fixedHeight: true});
      this.label.setExtent(this.label.getExtent().withY(this.getExtent().y));
      thenDo && thenDo();
    }.bind(this));
  },

  alignLabel: function(codeEditor) {
    switch (this.spec.alignLabel) {
      case 'line-end': this.alignLabelAtLineEnd(codeEditor); break;
      case 'marker-end': this.alignLabelAtMarkerEnd(); break;
    }
  },

  alignLabelAtMarkerEnd: function() {
    this.label.align(
      this.label.bounds().topLeft(),
      this.innerBounds().topRight());
    this.cachedBounds = null;
  },

  alignLabelAtLineEnd: function(codeEditor) {
    var markerRange = this.getRange(codeEditor),
        col = codeEditor.getSession().getLine(markerRange.start.row).length,
        pos = codeEditor.posToMorphicPos({row: markerRange.start.row, column: col}, "topRight"),
        localPos = this.getTransform().inverse().transformPoint(pos);
    this.label.align(this.label.bounds().topLeft(), localPos);
    this.cachedBounds = null;
  },

  setAtRange: function(codeEditor, range) {
    if (this.owner !== codeEditor) codeEditor.addMorph(this);
    this.setBounds(codeEditor.rangeToMorphicBounds(range));
    this.ensureAnchors(codeEditor, range);
  },

  setLabelAtRange: function(codeEditor, range) {
    if (this.owner !== codeEditor) codeEditor.addMorph(this);
    var bounds = this.getTransform().inverse()
      .transformRectToRect(codeEditor.rangeToMorphicBounds(range))
    this.label.setBounds(bounds);
  }

},
"updating", {

  setLabelString: function(codeEditor, string, thenDo) {
    var needsRender = false;

    if (this.label.textString !== string) {
      this.label.textString = string;
      needsRender = true;
    }

    var fontSize = codeEditor.getFontSize() - 4;
    if (this.label.getFontSize() !== fontSize) {
      this.label.setFontSize(fontSize);
      needsRender = true;
    }

    this.alignLabel(codeEditor);
    if (needsRender && this.spec.fitLabel) this.fitLabel(thenDo);
    else thenDo && thenDo();
  },

  setLabelStringAtNode: function(codeEditor, node, value, stringifiedValue) {
    // this.setVisible(false);
    var range = codeEditor.astNodeRange(node);

    this.state.node = node;
    this.setAtRange(codeEditor, range);
    // this.alignWithAstNode(codeEditor, node);

    var text = "=> " + stringifiedValue;
    this.setLabelString(codeEditor, text);
  },

  setHighlighted: function(bool) {
    this.label.applyStyle({
      textColor: bool ? Global.Color.orange : Global.Color.white
    });
  },

},
"events", {

  onAnchorChange: function(codeEditor, change) {
    this.alignWithAnchor(codeEditor);
  },

  onLabelClick: function(evt) {
    var val = this.state.value;
    lively.lang.fun.debounceNamed(this.id+"click-inspect", 20, function() {
      Global.inspect(val);
    })();
    return evt.stop(); true;
  }

},
"removal", {

  remove: function($super) {
    this.cleanupAnchors();
    return $super();
  }
});

lively.morphic.CodeEditor.addMethods({

  morphicOverlayCreate: function(spec) {
    var overlay = new lively.ide.CodeEditor.MorphicOverlay(spec);
    if (!this.morphicOverlays) this.morphicOverlays = [];
    this.morphicOverlays.push(overlay);
    return overlay;
  },

  morphicOverlaysRemoveAll: function() {
    this.morphicOverlays.invoke("remove");
    this.morphicOverlays.length = 0;
  },

  morphicOverlaysRemove: function(overlay) {
    overlay.remove();
    this.morphicOverlays = this.morphicOverlays.without(overlay);
  },

  morphicOverlaysOnAfterRender: function(evt) {
    // this.subscribeToEditorEvents()
    var self = this;
     self.morphicOverlays && lively.lang.fun.debounceNamed(this.id+"-afterrender", 20, function() {
      self.morphicOverlays.invoke("realign", self);
    })();
  },

  morphicOverlaysOnAfterScroll: function(evt) {
    var self = this;
    self.morphicOverlays && self.morphicOverlays.invoke("realign", self);
  },

  morphicOverlaysSubscribeToEditorEvents: function() {
    // this.subscribeToEditorEvents();
    var doNotSerialize = this.hasOwnProperty("doNotSerialize") ?
      this.doNotSerialize : (this.doNotSerialize = []);
    doNotSerialize.push("_morphicOverlaysOnAfterRender", "_morphicOverlaysOnAfterScroll");
    this.withAceDo(function(ed) {
      if (this._morphicOverlaysOnAfterRender)
        ed.renderer.off("afterRender", this._morphicOverlaysOnAfterRender);
      this._morphicOverlaysOnAfterRender = this.morphicOverlaysOnAfterRender.bind(this);
      ed.renderer.on("afterRender", this._morphicOverlaysOnAfterRender);
      if (this._morphicOverlaysOnAfterScroll)
        ed.session.off("changeScrollTop", this._morphicOverlaysOnAfterScroll);
      this._morphicOverlaysOnAfterScroll = this.morphicOverlaysOnAfterScroll.bind(this);
      ed.session.on("changeScrollTop", this._morphicOverlaysOnAfterScroll);
    })
  }

});

}) // end of module
<commit_msg>codeeditor morphic overlay: fix positioning when scrolled<commit_after>module('lively.ide.codeeditor.MorphicOverlay').requires('lively.morphic.Core', 'lively.morphic.TextCore', 'lively.ide.CodeEditor').toRun(function() {

lively.morphic.Morph.subclass("lively.ide.CodeEditor.MorphicOverlay",
"settings", {

  style: {
    fill: Global.Color.rgba(33,33,33,.2),
    borderWidth: 0
  },

  labelStyle: {
    handStyle: 'pointer',
    fixedWidth: true, fixedHeight: true,
    textColor: Global.Color.white,
    fill: Global.Color.rgb(120,120,120),
    clipMode: "hidden",
    padding: Global.Rectangle.inset(10,0, 5, 0),
    fontSize: lively.morphic.CodeEditor.prototype.style.fontSize - 2,
    selectable: false, allowInput: false
  },

  doNotSerialize: ["documentStartAnchor", "documentEndAnchor"]
},
"initializing", {

  initialize: function($super, spec) {
    $super(null, lively.rect(0,0,100,100));

    this.spec = lively.lang.obj.merge({
      alignLabel: "line-end",
      fitLabel: true
    }, spec);

    this.state = {
      value: null,
      node: null
    }

    this.disableEvents();
    this.label = this.makeLabel();
  },

  onrestore: function($super) {
    var self = this, o = this.owner;
    if (o && o.isCodeEditor) {
      o.withAceDo(function() {
        self.ensureAnchors(o, self.getRange(o));
      });
    }
  },

  makeLabel: function() {
    var label = lively.morphic.Text.makeLabel("");
    label.applyStyle(this.labelStyle);
    label.name = "label";
    label.addScript(function onClick(evt) {
      return this.owner.onLabelClick(evt);
    });
    label.enableEvents();
    return this.addMorph(label);
  },

  ensureAnchors: function(codeEditor, range) {
    var self = this;
    var Anchor = lively.ide.ace.require("ace/anchor").Anchor;
    if (this.documentStartAnchor) {
      this.documentStartAnchor.setPosition(range.start.row, range.start.column);
    } else {
      this.documentStartAnchor = new Anchor(codeEditor.getDocument(), range.start.row, range.start.column);
      this.documentStartAnchor.on("change", function(change) { self.onAnchorChange(codeEditor); });
    }

    if (this.documentEndAnchor) {
      this.documentEndAnchor.setPosition(range.end.row, range.end.column+1);
    } else {
      this.documentEndAnchor = new Anchor(codeEditor.getDocument(), range.end.row, range.end.column+1);
      this.documentEndAnchor.on("change", function(change) { self.onAnchorChange(codeEditor); });
    }
  },

  cleanupAnchors : function() {
    if (this.documentStartAnchor) {
      this.documentStartAnchor.removeAllListeners("change");
      this.documentStartAnchor.detach();
      this.documentStartAnchor = null;
    }
    if (this.documentEndAnchor) {
      this.documentEndAnchor.removeAllListeners("change");
      this.documentEndAnchor.detach();
      this.documentEndAnchor = null;
    }
  }

},
"layouting", {

  getRange: function(codeEditor) {
    var bounds = this.globalBounds(),
        // internally ace computes positions relative to viewport. We need to
        // offset that:
        bodyRect = document.body.getBoundingClientRect(),
        topLeft = bounds.topLeft().addXY(bodyRect.left, bodyRect.top),
        bottomRight = bounds.bottomRight().addXY(bodyRect.left, bodyRect.top),
        r = codeEditor.aceEditor.renderer,
        conf = r.layerConfig,
        start = r.pixelToScreenCoordinates(topLeft.x-conf.characterWidth, topLeft.y),
        end = r.pixelToScreenCoordinates(bottomRight.x, bottomRight.y-(conf.lineHeight-1));
    return codeEditor.createRange(start, end);
  },

  getLine: function(codeEditor) {
    return this.getRange(codeEditor).start.row;
  },

  alignWithAnchor: function(codeEditor) {
    if (!this.documentStartAnchor) {
      this.ensureAnchors(codeEditor, this.getRange(codeEditor));
    }
    var bounds = lively.rect(
      codeEditor.posToMorphicPos(this.documentStartAnchor.getPosition(), "topLeft"),
      codeEditor.posToMorphicPos(this.documentEndAnchor.getPosition(), "bottomLeft"))
    this.setBounds(bounds);
    this.alignLabel(codeEditor);
  },

  realign: function(codeEditor) {
    this.alignWithAnchor(codeEditor);
  },

  fitLabel: function(thenDo) {
    this.label.applyStyle({extent: pt(10,10), fixedWidth: false, fixedHeight: false})
    this.label.fit();
    this.label.fitThenDo(function() {
      this.label.applyStyle({fixedWidth: true, fixedHeight: true});
      this.label.setExtent(this.label.getExtent().withY(this.getExtent().y));
      thenDo && thenDo();
    }.bind(this));
  },

  alignLabel: function(codeEditor) {
    switch (this.spec.alignLabel) {
      case 'line-end': this.alignLabelAtLineEnd(codeEditor); break;
      case 'marker-end': this.alignLabelAtMarkerEnd(); break;
    }
  },

  alignLabelAtMarkerEnd: function() {
    this.label.align(
      this.label.bounds().topLeft(),
      this.innerBounds().topRight());
    this.cachedBounds = null;
  },

  alignLabelAtLineEnd: function(codeEditor) {
    var markerRange = this.getRange(codeEditor),
        col = codeEditor.getSession().getLine(markerRange.start.row).length,
        pos = codeEditor.posToMorphicPos({row: markerRange.start.row, column: col}, "topRight"),
        localPos = this.getTransform().inverse().transformPoint(pos);
    this.label.align(this.label.bounds().topLeft(), localPos);
    this.cachedBounds = null;
  },

  setAtRange: function(codeEditor, range) {
    if (this.owner !== codeEditor) codeEditor.addMorph(this);
    this.setBounds(codeEditor.rangeToMorphicBounds(range));
    this.ensureAnchors(codeEditor, range);
  },

  setLabelAtRange: function(codeEditor, range) {
    if (this.owner !== codeEditor) codeEditor.addMorph(this);
    var bounds = this.getTransform().inverse()
      .transformRectToRect(codeEditor.rangeToMorphicBounds(range))
    this.label.setBounds(bounds);
  }

},
"updating", {

  setLabelString: function(codeEditor, string, thenDo) {
    var needsRender = false;

    if (this.label.textString !== string) {
      this.label.textString = string;
      needsRender = true;
    }

    var fontSize = codeEditor.getFontSize() - 4;
    if (this.label.getFontSize() !== fontSize) {
      this.label.setFontSize(fontSize);
      needsRender = true;
    }

    this.alignLabel(codeEditor);
    if (needsRender && this.spec.fitLabel) this.fitLabel(thenDo);
    else thenDo && thenDo();
  },

  setLabelStringAtNode: function(codeEditor, node, value, stringifiedValue) {
    // this.setVisible(false);
    var range = codeEditor.astNodeRange(node);

    this.state.node = node;
    this.setAtRange(codeEditor, range);
    // this.alignWithAstNode(codeEditor, node);

    var text = "=> " + stringifiedValue;
    this.setLabelString(codeEditor, text);
  },

  setHighlighted: function(bool) {
    this.label.applyStyle({
      textColor: bool ? Global.Color.orange : Global.Color.white
    });
  },

},
"events", {

  onAnchorChange: function(codeEditor, change) {
    this.alignWithAnchor(codeEditor);
  },

  onLabelClick: function(evt) {
    var val = this.state.value;
    lively.lang.fun.debounceNamed(this.id+"click-inspect", 20, function() {
      Global.inspect(val);
    })();
    return evt.stop(); true;
  }

},
"removal", {

  remove: function($super) {
    this.cleanupAnchors();
    return $super();
  }
});

lively.morphic.CodeEditor.addMethods({

  morphicOverlayCreate: function(spec) {
    var overlay = new lively.ide.CodeEditor.MorphicOverlay(spec);
    if (!this.morphicOverlays) this.morphicOverlays = [];
    this.morphicOverlays.push(overlay);
    return overlay;
  },

  morphicOverlaysRemoveAll: function() {
    this.morphicOverlays.invoke("remove");
    this.morphicOverlays.length = 0;
  },

  morphicOverlaysRemove: function(overlay) {
    overlay.remove();
    this.morphicOverlays = this.morphicOverlays.without(overlay);
  },

  morphicOverlaysOnAfterRender: function(evt) {
    // this.subscribeToEditorEvents()
    var self = this;
     self.morphicOverlays && lively.lang.fun.debounceNamed(this.id+"-afterrender", 20, function() {
      self.morphicOverlays.invoke("realign", self);
    })();
  },

  morphicOverlaysOnAfterScroll: function(evt) {
    var self = this;
    self.morphicOverlays && self.morphicOverlays.invoke("realign", self);
  },

  morphicOverlaysSubscribeToEditorEvents: function() {
    // this.subscribeToEditorEvents();
    var doNotSerialize = this.hasOwnProperty("doNotSerialize") ?
      this.doNotSerialize : (this.doNotSerialize = []);
    doNotSerialize.push("_morphicOverlaysOnAfterRender", "_morphicOverlaysOnAfterScroll");
    this.withAceDo(function(ed) {
      if (this._morphicOverlaysOnAfterRender)
        ed.renderer.off("afterRender", this._morphicOverlaysOnAfterRender);
      this._morphicOverlaysOnAfterRender = this.morphicOverlaysOnAfterRender.bind(this);
      ed.renderer.on("afterRender", this._morphicOverlaysOnAfterRender);
      if (this._morphicOverlaysOnAfterScroll)
        ed.session.off("changeScrollTop", this._morphicOverlaysOnAfterScroll);
      this._morphicOverlaysOnAfterScroll = this.morphicOverlaysOnAfterScroll.bind(this);
      ed.session.on("changeScrollTop", this._morphicOverlaysOnAfterScroll);
    })
  }

});

}) // end of module
<|endoftext|>


<commit_before>var RiotControl = {
  _stores: [],
  _debug: false,
  addStore: function(store) {
    this._stores.push(store);
  },
  reset: function() {
    this._stores = [];
  },
  debug: function(setting) {
    this._debug = Boolean(setting);
  }
};

['on','one','off','trigger'].forEach(function(api){
  RiotControl[api] = function() {
    var args = [].slice.call(arguments);
    this._stores.forEach(function(el){
      if (RiotControl._debug) {
        console.log(api + ' ->', el, args);
      }
      el[api].apply(el, args);
    });
  };
});

if (typeof(module) !== 'undefined') module.exports = RiotControl;
<commit_msg>renaming<commit_after>var RiotControl = {
  _subscribers: [],
  _debug: false,
  subscribe: function(subscriber) {
    this._subscribers.push(subscriber);
  },
  reset: function() {
    this._subscribers = [];
  },
  debug: function(setting) {
    this._debug = Boolean(setting);
  }
};

['on','one','off','trigger'].forEach(function(api){
  RiotControl[api] = function() {
    var args = [].slice.call(arguments);
    this._subscribers.forEach(function(el){
      if (RiotControl._debug) {
        console.log(api + ' ->', el, args);
      }
      el[api].apply(el, args);
    });
  };
});

if (typeof(module) !== 'undefined') module.exports = RiotControl;
<|endoftext|>


<commit_before>(function() {

	"use strict";

	var pageFactory = modules.PoeticRivals.factories.page,
		jqWindow = $(window),
		jqBody = $('.body'),
		utils = modules.Utils,
		once = utils.once,
		debounce = utils.debounce;

	pageFactory.SubmitCommentaryForm = function(indexId, jqTemplateClassName, apiUrl, newModelCallback, formId, afterModelRenderCallback, indexPage) {

		var page = this,
			jqForm = $('#' + formId),
			jqFormSubmitButton = $('#' + formId + ' input[type="submit"]');

		pageFactory.Index.call(page, indexId, jqTemplateClassName, apiUrl, newModelCallback);
		pageFactory.Error.call(page);

		var setEventListeners = function() {
			jqForm.on("submit", page.onSubmit);
			jqFormSubmitButton.removeAttr("data-disable-with");
		};

		var jqTemplate = once(function() {
			return $($("." + page.jqTemplateClassName)[0]).clone();
		});

		var onSubmit = function(event) {
			event.preventDefault();
			page.data = $(this).serialize();
			page.postCommentary();
		};

		var onSubmitError = function(errorJqXHR) {
			console.log(errorJqXHR);
			console.log(errorJqXHR.responseJSON);
			page.onError(errorJqXHR, page.onRecordNotFound, page.onRecordNotProcessed);
		};

		var postCommentary = debounce(function() {
			$.ajax(
				{
					url: page.apiUrl,
					method: "POST",
					data: page.data,
					dataType: "json",
					success: page.onPost,
					error: page.onSubmitError
				}
			);
		}, 5000, true);

		var onPost = function(modelJSON) {
			var model = newModelCallback(modelJSON, page.indexId, page.jqTemplate().clone());
			model.updateJqTemplate();
			model.render();
			if (page.afterModelRender) {
				page.afterModelRender(model);
			}
			page.indexPage.excludedIds += "," + model.id;
			$('div.field_with_errors').children().unwrap();
			// jqFormSubmitButton.prop("disabled", false);
		};

		var onRecordNotProcessed = function(error, errorJqXHR, recordNotFoundCallback, self) {
			$('#' + page.formId + ' label').wrap('

');
			$('#' + page.formId + ' textarea').wrap('

');
		};

		var onRecordNotFound = function(error, errorJqXHR, self, recordNotProcessedCallback) {
			console.log("Status %s: %s", error.status, error.title);
			console.log("This should not be possible on this page.");
		};

		page.indexId = indexId;
		page.jqTemplateClassName = jqTemplateClassName;
		page.apiUrl = apiUrl;
		page.newModelCallback = newModelCallback;
		page.formId = formId;
		if (typeof(afterModelRenderCallback) === "function") {
			page.afterModelRender = afterModelRenderCallback;
		}
		page.indexPage = indexPage;
		page.setEventListeners = setEventListeners;
		page.jqTemplate = jqTemplate;
		page.onSubmit = onSubmit;
		page.onSubmitError = onSubmitError;
		page.postCommentary = postCommentary;
		page.onPost = onPost;
		page.onRecordNotProcessed = onRecordNotProcessed;
		page.onRecordNotFound = onRecordNotFound;
	}

})();<commit_msg>page.SubmitCommentaryForm: successful submission now clears textarea<commit_after>(function() {

	"use strict";

	var pageFactory = modules.PoeticRivals.factories.page,
		jqWindow = $(window),
		jqBody = $('.body'),
		utils = modules.Utils,
		once = utils.once,
		debounce = utils.debounce;

	pageFactory.SubmitCommentaryForm = function(indexId, jqTemplateClassName, apiUrl, newModelCallback, formId, afterModelRenderCallback, indexPage) {

		var page = this,
			jqForm = $('#' + formId),
			jqFormSubmitButton = $('#' + formId + ' input[type="submit"]');

		pageFactory.Index.call(page, indexId, jqTemplateClassName, apiUrl, newModelCallback);
		pageFactory.Error.call(page);

		var setEventListeners = function() {
			jqForm.on("submit", page.onSubmit);
			jqFormSubmitButton.removeAttr("data-disable-with");
		};

		var jqTemplate = once(function() {
			return $($("." + page.jqTemplateClassName)[0]).clone();
		});

		var onSubmit = function(event) {
			event.preventDefault();
			page.data = $(this).serialize();
			page.postCommentary();
		};

		var onSubmitError = function(errorJqXHR) {
			console.log(errorJqXHR);
			console.log(errorJqXHR.responseJSON);
			page.onError(errorJqXHR, page.onRecordNotFound, page.onRecordNotProcessed);
		};

		var postCommentary = debounce(function() {
			$.ajax(
				{
					url: page.apiUrl,
					method: "POST",
					data: page.data,
					dataType: "json",
					success: page.onPost,
					error: page.onSubmitError
				}
			);
		}, 5000, true);

		var onPost = function(modelJSON) {
			var model = newModelCallback(modelJSON, page.indexId, page.jqTemplate().clone());
			model.updateJqTemplate();
			model.render();
			if (page.afterModelRender) {
				page.afterModelRender(model);
			}
			page.indexPage.excludedIds += "," + model.id;
			$('div.field_with_errors').children().unwrap();
			$('#' + page.formId + ' textarea').val("");
			// jqFormSubmitButton.prop("disabled", false);
		};

		var onRecordNotProcessed = function(error, errorJqXHR, recordNotFoundCallback, self) {
			$('#' + page.formId + ' label').wrap('

');
			$('#' + page.formId + ' textarea').wrap('

');
		};

		var onRecordNotFound = function(error, errorJqXHR, self, recordNotProcessedCallback) {
			console.log("Status %s: %s", error.status, error.title);
			console.log("This should not be possible on this page.");
		};

		page.indexId = indexId;
		page.jqTemplateClassName = jqTemplateClassName;
		page.apiUrl = apiUrl;
		page.newModelCallback = newModelCallback;
		page.formId = formId;
		if (typeof(afterModelRenderCallback) === "function") {
			page.afterModelRender = afterModelRenderCallback;
		}
		page.indexPage = indexPage;
		page.setEventListeners = setEventListeners;
		page.jqTemplate = jqTemplate;
		page.onSubmit = onSubmit;
		page.onSubmitError = onSubmitError;
		page.postCommentary = postCommentary;
		page.onPost = onPost;
		page.onRecordNotProcessed = onRecordNotProcessed;
		page.onRecordNotFound = onRecordNotFound;
	}

})();<|endoftext|>


<commit_before>/* global WeatherProvider */

/* Magic Mirror
 * Module: Weather
 *
 * By Michael Teeuw https://michaelteeuw.nl
 * MIT Licensed.
 */
Module.register("weather", {
	// Default module config.
	defaults: {
		weatherProvider: "openweathermap",
		roundTemp: false,
		type: "current", // current, forecast, daily (equivalent to forecast), hourly (only with OpenWeatherMap /onecall endpoint)
		units: config.units,
		useKmh: false,
		tempUnits: config.units,
		windUnits: config.units,
		updateInterval: 10 * 60 * 1000, // every 10 minutes
		animationSpeed: 1000,
		timeFormat: config.timeFormat,
		showPeriod: true,
		showPeriodUpper: false,
		showWindDirection: true,
		showWindDirectionAsArrow: false,
		useBeaufort: true,
		lang: config.language,
		showHumidity: false,
		showSun: true,
		degreeLabel: false,
		decimalSymbol: ".",
		showIndoorTemperature: false,
		showIndoorHumidity: false,
		maxNumberOfDays: 5,
		maxEntries: 5,
		fade: true,
		fadePoint: 0.25, // Start on 1/4th of the list.
		initialLoadDelay: 0, // 0 seconds delay
		appendLocationNameToHeader: true,
		calendarClass: "calendar",
		tableClass: "small",
		onlyTemp: false,
		showPrecipitationAmount: false,
		colored: false,
		showFeelsLike: true
	},

	// Module properties.
	weatherProvider: null,

	// Define required scripts.
	getStyles: function () {
		return ["font-awesome.css", "weather-icons.css", "weather.css"];
	},

	// Return the scripts that are necessary for the weather module.
	getScripts: function () {
		return ["moment.js", "weatherprovider.js", "weatherobject.js", "suncalc.js", this.file("providers/" + this.config.weatherProvider.toLowerCase() + ".js")];
	},

	// Override getHeader method.
	getHeader: function () {
		if (this.config.appendLocationNameToHeader && this.weatherProvider) {
			if (this.data.header) return this.data.header + " " + this.weatherProvider.fetchedLocation();
			else return this.weatherProvider.fetchedLocation();
		}

		return this.data.header ? this.data.header : "";
	},

	// Start the weather module.
	start: function () {
		moment.locale(this.config.lang);

		// Initialize the weather provider.
		this.weatherProvider = WeatherProvider.initialize(this.config.weatherProvider, this);

		// Let the weather provider know we are starting.
		this.weatherProvider.start();

		// Add custom filters
		this.addFilters();

		// Schedule the first update.
		this.scheduleUpdate(this.config.initialLoadDelay);
	},

	// Override notification handler.
	notificationReceived: function (notification, payload, sender) {
		if (notification === "CALENDAR_EVENTS") {
			var senderClasses = sender.data.classes.toLowerCase().split(" ");
			if (senderClasses.indexOf(this.config.calendarClass.toLowerCase()) !== -1) {
				this.firstEvent = false;

				for (var e in payload) {
					var event = payload[e];
					if (event.location || event.geo) {
						this.firstEvent = event;
						//Log.log("First upcoming event with location: ", event);
						break;
					}
				}
			}
		} else if (notification === "INDOOR_TEMPERATURE") {
			this.indoorTemperature = this.roundValue(payload);
			this.updateDom(300);
		} else if (notification === "INDOOR_HUMIDITY") {
			this.indoorHumidity = this.roundValue(payload);
			this.updateDom(300);
		}
	},

	// Select the template depending on the display type.
	getTemplate: function () {
		switch (this.config.type.toLowerCase()) {
			case "current":
				return `current.njk`;
			case "hourly":
				return `hourly.njk`;
			case "daily":
			case "forecast":
			//Make the invalid values use the "Loading..." from forecast
			default:
				return `forecast.njk`;
		}
	},

	// Add all the data to the template.
	getTemplateData: function () {
		return {
			config: this.config,
			current: this.weatherProvider.currentWeather(),
			forecast: this.weatherProvider.weatherForecast(),
			hourly: this.weatherProvider.weatherHourly(),
			indoor: {
				humidity: this.indoorHumidity,
				temperature: this.indoorTemperature
			}
		};
	},

	// What to do when the weather provider has new information available?
	updateAvailable: function () {
		Log.log("New weather information available.");
		this.updateDom(0);
		this.scheduleUpdate();

		if (this.weatherProvider.currentWeather()) {
			this.sendNotification("CURRENTWEATHER_TYPE", { type: this.weatherProvider.currentWeather().weatherType.replace("-", "_") });
		}
	},

	scheduleUpdate: function (delay = null) {
		var nextLoad = this.config.updateInterval;
		if (delay !== null && delay >= 0) {
			nextLoad = delay;
		}

		setTimeout(() => {
			switch (this.config.type.toLowerCase()) {
				case "current":
					this.weatherProvider.fetchCurrentWeather();
					break;
				case "hourly":
					this.weatherProvider.fetchWeatherHourly();
					break;
				case "daily":
				case "forecast":
					this.weatherProvider.fetchWeatherForecast();
					break;
				default:
					Log.error(`Invalid type ${this.config.type} configured (must be one of 'current', 'hourly', 'daily' or 'forecast')`);
			}
		}, nextLoad);
	},

	roundValue: function (temperature) {
		var decimals = this.config.roundTemp ? 0 : 1;
		var roundValue = parseFloat(temperature).toFixed(decimals);
		return roundValue === "-0" ? 0 : roundValue;
	},

	addFilters() {
		this.nunjucksEnvironment().addFilter(
			"formatTime",
			function (date) {
				date = moment(date);

				if (this.config.timeFormat !== 24) {
					if (this.config.showPeriod) {
						if (this.config.showPeriodUpper) {
							return date.format("h:mm A");
						} else {
							return date.format("h:mm a");
						}
					} else {
						return date.format("h:mm");
					}
				}

				return date.format("HH:mm");
			}.bind(this)
		);

		this.nunjucksEnvironment().addFilter(
			"unit",
			function (value, type) {
				if (type === "temperature") {
					if (this.config.tempUnits === "metric" || this.config.tempUnits === "imperial") {
						value += "°";
					}
					if (this.config.degreeLabel) {
						if (this.config.tempUnits === "metric") {
							value += "C";
						} else if (this.config.tempUnits === "imperial") {
							value += "F";
						} else {
							value += "K";
						}
					}
				} else if (type === "precip") {
					if (value === null || isNaN(value) || value === 0 || value.toFixed(2) === "0.00") {
						value = "";
					} else {
						if (this.config.weatherProvider === "ukmetoffice" || this.config.weatherProvider === "ukmetofficedatahub") {
							value += "%";
						} else {
							value = `${value.toFixed(2)} ${this.config.units === "imperial" ? "in" : "mm"}`;
						}
					}
				} else if (type === "humidity") {
					value += "%";
				}

				return value;
			}.bind(this)
		);

		this.nunjucksEnvironment().addFilter(
			"roundValue",
			function (value) {
				return this.roundValue(value);
			}.bind(this)
		);

		this.nunjucksEnvironment().addFilter(
			"decimalSymbol",
			function (value) {
				return value.toString().replace(/\./g, this.config.decimalSymbol);
			}.bind(this)
		);

		this.nunjucksEnvironment().addFilter(
			"calcNumSteps",
			function (forecast) {
				return Math.min(forecast.length, this.config.maxNumberOfDays);
			}.bind(this)
		);

		this.nunjucksEnvironment().addFilter(
			"calcNumEntries",
			function (dataArray) {
				return Math.min(dataArray.length, this.config.maxEntries);
			}.bind(this)
		);

		this.nunjucksEnvironment().addFilter(
			"opacity",
			function (currentStep, numSteps) {
				if (this.config.fade && this.config.fadePoint < 1) {
					if (this.config.fadePoint < 0) {
						this.config.fadePoint = 0;
					}
					var startingPoint = numSteps * this.config.fadePoint;
					var numFadesteps = numSteps - startingPoint;
					if (currentStep >= startingPoint) {
						return 1 - (currentStep - startingPoint) / numFadesteps;
					} else {
						return 1;
					}
				} else {
					return 1;
				}
			}.bind(this)
		);
	}
});
<commit_msg>Fixing code style issue with no return before default<commit_after>/* global WeatherProvider */

/* Magic Mirror
 * Module: Weather
 *
 * By Michael Teeuw https://michaelteeuw.nl
 * MIT Licensed.
 */
Module.register("weather", {
	// Default module config.
	defaults: {
		weatherProvider: "openweathermap",
		roundTemp: false,
		type: "current", // current, forecast, daily (equivalent to forecast), hourly (only with OpenWeatherMap /onecall endpoint)
		units: config.units,
		useKmh: false,
		tempUnits: config.units,
		windUnits: config.units,
		updateInterval: 10 * 60 * 1000, // every 10 minutes
		animationSpeed: 1000,
		timeFormat: config.timeFormat,
		showPeriod: true,
		showPeriodUpper: false,
		showWindDirection: true,
		showWindDirectionAsArrow: false,
		useBeaufort: true,
		lang: config.language,
		showHumidity: false,
		showSun: true,
		degreeLabel: false,
		decimalSymbol: ".",
		showIndoorTemperature: false,
		showIndoorHumidity: false,
		maxNumberOfDays: 5,
		maxEntries: 5,
		fade: true,
		fadePoint: 0.25, // Start on 1/4th of the list.
		initialLoadDelay: 0, // 0 seconds delay
		appendLocationNameToHeader: true,
		calendarClass: "calendar",
		tableClass: "small",
		onlyTemp: false,
		showPrecipitationAmount: false,
		colored: false,
		showFeelsLike: true
	},

	// Module properties.
	weatherProvider: null,

	// Define required scripts.
	getStyles: function () {
		return ["font-awesome.css", "weather-icons.css", "weather.css"];
	},

	// Return the scripts that are necessary for the weather module.
	getScripts: function () {
		return ["moment.js", "weatherprovider.js", "weatherobject.js", "suncalc.js", this.file("providers/" + this.config.weatherProvider.toLowerCase() + ".js")];
	},

	// Override getHeader method.
	getHeader: function () {
		if (this.config.appendLocationNameToHeader && this.weatherProvider) {
			if (this.data.header) return this.data.header + " " + this.weatherProvider.fetchedLocation();
			else return this.weatherProvider.fetchedLocation();
		}

		return this.data.header ? this.data.header : "";
	},

	// Start the weather module.
	start: function () {
		moment.locale(this.config.lang);

		// Initialize the weather provider.
		this.weatherProvider = WeatherProvider.initialize(this.config.weatherProvider, this);

		// Let the weather provider know we are starting.
		this.weatherProvider.start();

		// Add custom filters
		this.addFilters();

		// Schedule the first update.
		this.scheduleUpdate(this.config.initialLoadDelay);
	},

	// Override notification handler.
	notificationReceived: function (notification, payload, sender) {
		if (notification === "CALENDAR_EVENTS") {
			var senderClasses = sender.data.classes.toLowerCase().split(" ");
			if (senderClasses.indexOf(this.config.calendarClass.toLowerCase()) !== -1) {
				this.firstEvent = false;

				for (var e in payload) {
					var event = payload[e];
					if (event.location || event.geo) {
						this.firstEvent = event;
						//Log.log("First upcoming event with location: ", event);
						break;
					}
				}
			}
		} else if (notification === "INDOOR_TEMPERATURE") {
			this.indoorTemperature = this.roundValue(payload);
			this.updateDom(300);
		} else if (notification === "INDOOR_HUMIDITY") {
			this.indoorHumidity = this.roundValue(payload);
			this.updateDom(300);
		}
	},

	// Select the template depending on the display type.
	getTemplate: function () {
		switch (this.config.type.toLowerCase()) {
			case "current":
				return `current.njk`;
			case "hourly":
				return `hourly.njk`;
			case "daily":
			case "forecast":
				return `forecast.njk`;
			//Make the invalid values use the "Loading..." from forecast
			default:
				return `forecast.njk`;
		}
	},

	// Add all the data to the template.
	getTemplateData: function () {
		return {
			config: this.config,
			current: this.weatherProvider.currentWeather(),
			forecast: this.weatherProvider.weatherForecast(),
			hourly: this.weatherProvider.weatherHourly(),
			indoor: {
				humidity: this.indoorHumidity,
				temperature: this.indoorTemperature
			}
		};
	},

	// What to do when the weather provider has new information available?
	updateAvailable: function () {
		Log.log("New weather information available.");
		this.updateDom(0);
		this.scheduleUpdate();

		if (this.weatherProvider.currentWeather()) {
			this.sendNotification("CURRENTWEATHER_TYPE", { type: this.weatherProvider.currentWeather().weatherType.replace("-", "_") });
		}
	},

	scheduleUpdate: function (delay = null) {
		var nextLoad = this.config.updateInterval;
		if (delay !== null && delay >= 0) {
			nextLoad = delay;
		}

		setTimeout(() => {
			switch (this.config.type.toLowerCase()) {
				case "current":
					this.weatherProvider.fetchCurrentWeather();
					break;
				case "hourly":
					this.weatherProvider.fetchWeatherHourly();
					break;
				case "daily":
				case "forecast":
					this.weatherProvider.fetchWeatherForecast();
					break;
				default:
					Log.error(`Invalid type ${this.config.type} configured (must be one of 'current', 'hourly', 'daily' or 'forecast')`);
			}
		}, nextLoad);
	},

	roundValue: function (temperature) {
		var decimals = this.config.roundTemp ? 0 : 1;
		var roundValue = parseFloat(temperature).toFixed(decimals);
		return roundValue === "-0" ? 0 : roundValue;
	},

	addFilters() {
		this.nunjucksEnvironment().addFilter(
			"formatTime",
			function (date) {
				date = moment(date);

				if (this.config.timeFormat !== 24) {
					if (this.config.showPeriod) {
						if (this.config.showPeriodUpper) {
							return date.format("h:mm A");
						} else {
							return date.format("h:mm a");
						}
					} else {
						return date.format("h:mm");
					}
				}

				return date.format("HH:mm");
			}.bind(this)
		);

		this.nunjucksEnvironment().addFilter(
			"unit",
			function (value, type) {
				if (type === "temperature") {
					if (this.config.tempUnits === "metric" || this.config.tempUnits === "imperial") {
						value += "°";
					}
					if (this.config.degreeLabel) {
						if (this.config.tempUnits === "metric") {
							value += "C";
						} else if (this.config.tempUnits === "imperial") {
							value += "F";
						} else {
							value += "K";
						}
					}
				} else if (type === "precip") {
					if (value === null || isNaN(value) || value === 0 || value.toFixed(2) === "0.00") {
						value = "";
					} else {
						if (this.config.weatherProvider === "ukmetoffice" || this.config.weatherProvider === "ukmetofficedatahub") {
							value += "%";
						} else {
							value = `${value.toFixed(2)} ${this.config.units === "imperial" ? "in" : "mm"}`;
						}
					}
				} else if (type === "humidity") {
					value += "%";
				}

				return value;
			}.bind(this)
		);

		this.nunjucksEnvironment().addFilter(
			"roundValue",
			function (value) {
				return this.roundValue(value);
			}.bind(this)
		);

		this.nunjucksEnvironment().addFilter(
			"decimalSymbol",
			function (value) {
				return value.toString().replace(/\./g, this.config.decimalSymbol);
			}.bind(this)
		);

		this.nunjucksEnvironment().addFilter(
			"calcNumSteps",
			function (forecast) {
				return Math.min(forecast.length, this.config.maxNumberOfDays);
			}.bind(this)
		);

		this.nunjucksEnvironment().addFilter(
			"calcNumEntries",
			function (dataArray) {
				return Math.min(dataArray.length, this.config.maxEntries);
			}.bind(this)
		);

		this.nunjucksEnvironment().addFilter(
			"opacity",
			function (currentStep, numSteps) {
				if (this.config.fade && this.config.fadePoint < 1) {
					if (this.config.fadePoint < 0) {
						this.config.fadePoint = 0;
					}
					var startingPoint = numSteps * this.config.fadePoint;
					var numFadesteps = numSteps - startingPoint;
					if (currentStep >= startingPoint) {
						return 1 - (currentStep - startingPoint) / numFadesteps;
					} else {
						return 1;
					}
				} else {
					return 1;
				}
			}.bind(this)
		);
	}
});
<|endoftext|>


<commit_before>function Calendar() {

	this.proj = "";
	this.team = null;

	//holds the selected month & year
	this.date = new Date();

	this.logs = new Array();	//will hold complete month of log entries
	this.logdays = new Array();	//will hold max of one log entry (the last) for each day in month

	//event signals
	this._signals = new Array();
}

var MONTHS = new Array("January", "February", "March", "April", "May", "June",
	"July", "August","September", "October", "November", "December");

Calendar.prototype.init = function() {
	this.logs = new Array();
	this.logdays = new Array();

	// set the date so that we draw it with the correct days offset
	this.date.setDate(1);

	//do html
	this.drawCal();
	//try ajax
	this.getDates();
	//setup events

	map( disconnect, this._signals );
	this._signals = [];

	this._signals.push( connect("cal-prev-month",
				    'onclick',
				    bind(this.changeMonth, this, -1) ) );
	this._signals.push( connect("cal-next-month",
				    'onclick',
				    bind(this.changeMonth, this, +1) ) );
}

Calendar.prototype.drawCal = function() {

	//Set month header
	$("cal-header").innerHTML = MONTHS[this.date.getMonth()]+" "+this.date.getFullYear();

	//reset row, cell and day variables
	var td = 0;
	var tr = 0;
	var day = 1;

	//clear all cells from calendar
	for(tr=0; tr < 6; tr++) {
		replaceChildNodes("cal-row-"+tr);
	}

	//insert grey cells so we start on the correct day of the week
	tr = 0;
	for(td= 0; td < 7; td++) {
		if(td < this.date.getDay()) {
			appendChildNodes($("cal-row-"+tr), TD({'class':'null'}, ""));
		} else {
			appendChildNodes($("cal-row-"+tr), TD({'id' : 'cal'+day}, day));
			day++;
		}
	}

	//now generate the rest of the cells in rows of 7 cells
	for(tr=1; tr < 6; tr++) {
		while(td < (7*(tr+1))) {
			if(day <= this.dinm() ) {
				appendChildNodes($("cal-row-"+tr), TD({'id' : 'cal'+day}, day));
				day++;
			} else {
				//appendChildNodes($("cal-row-"+tr), TD(null, " "));
			}
			td++;
		}
	}

	//highlight today's date (bold text only) if we are showing current month and current year
	if( ( this.date.getMonth() == (new Date()).getMonth() ) && (this.date.getFullYear() == (new Date()).getFullYear() ) )
		setStyle("cal"+(new Date()).getDate(), {"font-weight" : "bold", "border" : "1px solid #eee"});

	//clears date/revision select box
	replaceChildNodes("cal-revs",
		OPTION({"value" : 'HEAD'}, "HEAD - the most recent version"),
		OPTION({"value" : -1, "selected" : "selected"}, "Select a date")
	);
}

//convert date string in log array into jscript date
Calendar.prototype.extract = function(datetime) {
	var parts = datetime.split("/");
	return new Date(parts[0], parts[1], parts[2], parts[3], parts[4], parts[5]);
}

//return the number of days in the week
Calendar.prototype.dinm = function() {
	return 32 - new Date(this.date.getFullYear(), this.date.getMonth(), 32).getDate();
}

//ajax handler for receiving logs from server
Calendar.prototype._receiveDates = function(nodes) {

	if(nodes.log.length > 0) {
		//convert string representation of date to javascript date object
		this.logs = map(function(x) {
			var jsdate = new Date(x.time * 1000);
			return { "date" : jsdate,
				 "message" : x.message,
				 "rev" : x.hash,
				 "author" : x.author};
		}, nodes.log);

		this.processDates();
		this.updateCal();
	}
	else {
		this.logs = [];
		this.logdays = [];
		return;
	}
}

//ajax handler for failed requests
Calendar.prototype._errorReceiveDates = function() {
	logDebug("Error retrieving calendar dates");
}

//get month of logs messages from server
Calendar.prototype.getDates = function() {
	IDE_backend_request("proj/log", {team: this.team,
	                                 project: this.proj},
	                                 bind(this._receiveDates, this),
	                                 bind(this._errorReceiveDates, this));
}

//create a new array with one log entry per date (the last one from that day of that month)
Calendar.prototype.processDates = function() {

	//blank array
	this.logdays = new Array();

	//get array of days with corresponding log entries
	for(var z=0; z < this.logs.length; z++) {
		var now = this.logs[z].date.getDate();
		if( this.logs[z].date.getMonth() == this.date.getMonth()	// is in the month on display
		 && this.logs[z].date.getYear() == this.date.getYear()	// is in the year on display
		 && findValue(this.logdays, now) < 0) {
			this.logdays.push(now);
		}
	}
}

//use logdays to bring to life the cells on the Calendar which relate to log entries
Calendar.prototype.updateCal = function() {
	for(var i=0; i < this.logdays.length; i++) {
		setNodeAttribute($("cal"+this.logdays[i]), "class", "td-log");
		connect($("cal"+this.logdays[i]),
			'onclick',
			bind(this.change_day, this, this.logdays[i]) );
		setNodeAttribute($("cal"+this.logdays[i]), "title", "Click to see revisions for this day");
	}
}

Calendar.prototype.changeMonth = function(dir) {
	this.date.setMonth(this.date.getMonth() + dir);
	replaceChildNodes("cal-revs",
		OPTION({"value" : 'HEAD'}, "HEAD - the most recent version"),
		OPTION({"value" : -1, "selected" : "selected"}, "Select a date")
	);
	this.init();
}

Calendar.prototype.change_day = function(target) {
	//set this.date's day to the current date (for message in drop-down)
	this.date.setDate(target);
	//alert user to select a revision
	replaceChildNodes("cal-revs",
		OPTION({"value" : 'HEAD'}, "HEAD - the most recent version"),
		OPTION({"value" : -1, "selected" : "selected"}, "Select a revision for "+this.date.getDate()+" "+MONTHS[this.date.getMonth()])
	);

	//clear the boxes from around all dates
	for (var i=1; i<=this.dinm(); i++)
		setStyle("cal"+i, {"border-color" : "#eee"});

	//but a box around the selected day
	setStyle("cal"+target, {"border-color" : "#000"});

	//get logs for target date
	for(var i = 0; i < this.logs.length; i++) {
		if(this.logs[i].date.getDate() == target) {
			appendChildNodes("cal-revs", OPTION({ "value" : this.logs[i].rev},
							    IDE_hash_shrink(this.logs[i].rev) + " " +
							    this.logs[i].author+": "+
							    this.logs[i].message.slice(0, 20)+" ("+
							    this.logs[i].date.getHours()+":"+
							    this.logs[i].date.getMinutes()+")"));
		}
	}

	disconnectAll("cal-revs");
	connect("cal-revs", 'onchange', bind(this._load_new_rev, this) );

	projpage.hide_filelist();
	status_msg("Please select a revision", LEVEL_OK);
	$("cal-revs").className = "hilight"
	setTimeout(function() {
			$("cal-revs").className = "normal"
		},500);
	setTimeout(function() {
			$("cal-revs").className = "hilight"
		},1000);
	setTimeout(function() {
			$("cal-revs").className = "normal"
		},1500);
}

Calendar.prototype._load_new_rev = function() {
	var target = $("cal-revs").value;

	// Check that it's not a special value
	if( !(target < 0) )
		this._load_rev( target );
	if(target == 'HEAD')
		this.init();
}

Calendar.prototype._load_rev = function(rev) {
	projpage.flist.change_rev(rev);
	status_msg("Now showing project at revision: "+rev, LEVEL_OK);
}

Calendar.prototype.change_proj = function(project, team) {
	this.proj = project;
	this.team = team;
	this.date = new Date();

	this.init();
}
<commit_msg>Reset the calendar to the current month on selecting HEAD<commit_after>function Calendar() {

	this.proj = "";
	this.team = null;

	//holds the selected month & year
	this.date = new Date();

	this.logs = new Array();	//will hold complete month of log entries
	this.logdays = new Array();	//will hold max of one log entry (the last) for each day in month

	//event signals
	this._signals = new Array();
}

var MONTHS = new Array("January", "February", "March", "April", "May", "June",
	"July", "August","September", "October", "November", "December");

Calendar.prototype.init = function() {
	this.logs = new Array();
	this.logdays = new Array();

	// set the date so that we draw it with the correct days offset
	this.date.setDate(1);

	//do html
	this.drawCal();
	//try ajax
	this.getDates();
	//setup events

	map( disconnect, this._signals );
	this._signals = [];

	this._signals.push( connect("cal-prev-month",
				    'onclick',
				    bind(this.changeMonth, this, -1) ) );
	this._signals.push( connect("cal-next-month",
				    'onclick',
				    bind(this.changeMonth, this, +1) ) );
}

Calendar.prototype.drawCal = function() {

	//Set month header
	$("cal-header").innerHTML = MONTHS[this.date.getMonth()]+" "+this.date.getFullYear();

	//reset row, cell and day variables
	var td = 0;
	var tr = 0;
	var day = 1;

	//clear all cells from calendar
	for(tr=0; tr < 6; tr++) {
		replaceChildNodes("cal-row-"+tr);
	}

	//insert grey cells so we start on the correct day of the week
	tr = 0;
	for(td= 0; td < 7; td++) {
		if(td < this.date.getDay()) {
			appendChildNodes($("cal-row-"+tr), TD({'class':'null'}, ""));
		} else {
			appendChildNodes($("cal-row-"+tr), TD({'id' : 'cal'+day}, day));
			day++;
		}
	}

	//now generate the rest of the cells in rows of 7 cells
	for(tr=1; tr < 6; tr++) {
		while(td < (7*(tr+1))) {
			if(day <= this.dinm() ) {
				appendChildNodes($("cal-row-"+tr), TD({'id' : 'cal'+day}, day));
				day++;
			} else {
				//appendChildNodes($("cal-row-"+tr), TD(null, " "));
			}
			td++;
		}
	}

	//highlight today's date (bold text only) if we are showing current month and current year
	if( ( this.date.getMonth() == (new Date()).getMonth() ) && (this.date.getFullYear() == (new Date()).getFullYear() ) )
		setStyle("cal"+(new Date()).getDate(), {"font-weight" : "bold", "border" : "1px solid #eee"});

	//clears date/revision select box
	replaceChildNodes("cal-revs",
		OPTION({"value" : 'HEAD'}, "HEAD - the most recent version"),
		OPTION({"value" : -1, "selected" : "selected"}, "Select a date")
	);
}

//convert date string in log array into jscript date
Calendar.prototype.extract = function(datetime) {
	var parts = datetime.split("/");
	return new Date(parts[0], parts[1], parts[2], parts[3], parts[4], parts[5]);
}

//return the number of days in the week
Calendar.prototype.dinm = function() {
	return 32 - new Date(this.date.getFullYear(), this.date.getMonth(), 32).getDate();
}

//ajax handler for receiving logs from server
Calendar.prototype._receiveDates = function(nodes) {

	if(nodes.log.length > 0) {
		//convert string representation of date to javascript date object
		this.logs = map(function(x) {
			var jsdate = new Date(x.time * 1000);
			return { "date" : jsdate,
				 "message" : x.message,
				 "rev" : x.hash,
				 "author" : x.author};
		}, nodes.log);

		this.processDates();
		this.updateCal();
	}
	else {
		this.logs = [];
		this.logdays = [];
		return;
	}
}

//ajax handler for failed requests
Calendar.prototype._errorReceiveDates = function() {
	logDebug("Error retrieving calendar dates");
}

//get month of logs messages from server
Calendar.prototype.getDates = function() {
	IDE_backend_request("proj/log", {team: this.team,
	                                 project: this.proj},
	                                 bind(this._receiveDates, this),
	                                 bind(this._errorReceiveDates, this));
}

//create a new array with one log entry per date (the last one from that day of that month)
Calendar.prototype.processDates = function() {

	//blank array
	this.logdays = new Array();

	//get array of days with corresponding log entries
	for(var z=0; z < this.logs.length; z++) {
		var now = this.logs[z].date.getDate();
		if( this.logs[z].date.getMonth() == this.date.getMonth()	// is in the month on display
		 && this.logs[z].date.getYear() == this.date.getYear()	// is in the year on display
		 && findValue(this.logdays, now) < 0) {
			this.logdays.push(now);
		}
	}
}

//use logdays to bring to life the cells on the Calendar which relate to log entries
Calendar.prototype.updateCal = function() {
	for(var i=0; i < this.logdays.length; i++) {
		setNodeAttribute($("cal"+this.logdays[i]), "class", "td-log");
		connect($("cal"+this.logdays[i]),
			'onclick',
			bind(this.change_day, this, this.logdays[i]) );
		setNodeAttribute($("cal"+this.logdays[i]), "title", "Click to see revisions for this day");
	}
}

Calendar.prototype.changeMonth = function(dir) {
	this.date.setMonth(this.date.getMonth() + dir);
	replaceChildNodes("cal-revs",
		OPTION({"value" : 'HEAD'}, "HEAD - the most recent version"),
		OPTION({"value" : -1, "selected" : "selected"}, "Select a date")
	);
	this.init();
}

Calendar.prototype.change_day = function(target) {
	//set this.date's day to the current date (for message in drop-down)
	this.date.setDate(target);
	//alert user to select a revision
	replaceChildNodes("cal-revs",
		OPTION({"value" : 'HEAD'}, "HEAD - the most recent version"),
		OPTION({"value" : -1, "selected" : "selected"}, "Select a revision for "+this.date.getDate()+" "+MONTHS[this.date.getMonth()])
	);

	//clear the boxes from around all dates
	for (var i=1; i<=this.dinm(); i++)
		setStyle("cal"+i, {"border-color" : "#eee"});

	//but a box around the selected day
	setStyle("cal"+target, {"border-color" : "#000"});

	//get logs for target date
	for(var i = 0; i < this.logs.length; i++) {
		if(this.logs[i].date.getDate() == target) {
			appendChildNodes("cal-revs", OPTION({ "value" : this.logs[i].rev},
							    IDE_hash_shrink(this.logs[i].rev) + " " +
							    this.logs[i].author+": "+
							    this.logs[i].message.slice(0, 20)+" ("+
							    this.logs[i].date.getHours()+":"+
							    this.logs[i].date.getMinutes()+")"));
		}
	}

	disconnectAll("cal-revs");
	connect("cal-revs", 'onchange', bind(this._load_new_rev, this) );

	projpage.hide_filelist();
	status_msg("Please select a revision", LEVEL_OK);
	$("cal-revs").className = "hilight"
	setTimeout(function() {
			$("cal-revs").className = "normal"
		},500);
	setTimeout(function() {
			$("cal-revs").className = "hilight"
		},1000);
	setTimeout(function() {
			$("cal-revs").className = "normal"
		},1500);
}

Calendar.prototype._load_new_rev = function() {
	var target = $("cal-revs").value;

	// Check that it's not a special value
	if( !(target < 0) )
		this._load_rev( target );
	if(target == 'HEAD')
	{
		this.date = new Date();
		this.init();
	}
}

Calendar.prototype._load_rev = function(rev) {
	projpage.flist.change_rev(rev);
	status_msg("Now showing project at revision: "+rev, LEVEL_OK);
}

Calendar.prototype.change_proj = function(project, team) {
	this.proj = project;
	this.team = team;
	this.date = new Date();

	this.init();
}
<|endoftext|>


<commit_before>function Checkout() {
	// handle on the applet
	this._applet = null;

	// hold status message for the page
	this._prompt = null;

	// keep track of whether object is initialised
	this._inited = false;

	// keep trac of whether java works here or not,
	// default to whether the browser claims to support java
	this._java_works = navigator.javaEnabled();

	// store a copy of our instance!
	Checkout.Instance = this;
}

Checkout.GetInstance = function() {
	if(Checkout.Instance == null) {
		Checkout.Instance = new Checkout();
	}
	return Checkout.Instance;
}

Checkout.prototype.init = function() {
	if(this._inited == true) {
		return;
	}

	logDebug("Checkout: Initializing");

	// If Java works, and the user wants it then load the applet
	if (this._use_java()) {
		this._applet = createDOM('applet',
			{ archive: 'applet/build/checkout.jar',
				 code: 'org.studentrobotics.ide.checkout.CheckoutApplet',
				   id: 'checkout-applet',
				 name: 'checkout-applet',
				width: '128',
			   height: '128'
			});
		appendChildNodes('applet', this._applet);
	}

	/* remember that we are initialised */
	this._inited = true;
}

// If Java works and the user wants it
Checkout.prototype._use_java = function() {
	return this._java_works && user.get_setting('export.usejava');
}

Checkout.prototype._basic = function(url, successCallback, errorCallback) {
	var handle = window.open(url, "Source Checkout");
	if (handle == null) {
		window.location = url;
	}
	successCallback();
}

Checkout.prototype._getLocation = function() {
	var protocolhost = location.protocol + "//" + location.hostname;

	if (location.port != 80) {
		protocolhost += ":" + location.port;
	}

	return protocolhost;
}

Checkout.prototype._java = function(url, successCallback, errorCallback) {
	var xhr = new XMLHttpRequest();
	var retcode = this._applet.writeZip(this._getLocation() + "/" + url);
	//if downloading worked
	if (retcode == 0) {
		successCallBack();
	} else {
		// negative response code means that java is not going to work ever
		if (retcode < 0) {
			this._java_works = false;
		}

		//use the file dialogue download method
		this._basic(url, successCallback, errorCallback);
	}
}

Checkout.prototype._download = function(successCallback, errorCallback, nodes) {
	var url = nodes.url;
	if (this._use_java() && this._applet != null) {
		this._java(url, successCallback, errorCallback);
	} else {
		this._basic(url, successCallback, errorCallback);
	}
}

Checkout.prototype.checkout = function(team, project, successCallback, errorCallback) {
	// get URL
	IDE_backend_request("proj/co", {team: team, project: project},
	                    bind(this._download, this, successCallback, errorCallback),
	                    errorCallback);
}
<commit_msg>whitespace fix<commit_after>function Checkout() {
	// handle on the applet
	this._applet = null;

	// hold status message for the page
	this._prompt = null;

	// keep track of whether object is initialised
	this._inited = false;

	// keep trac of whether java works here or not,
	// default to whether the browser claims to support java
	this._java_works = navigator.javaEnabled();

	// store a copy of our instance!
	Checkout.Instance = this;
}

Checkout.GetInstance = function() {
	if(Checkout.Instance == null) {
		Checkout.Instance = new Checkout();
	}
	return Checkout.Instance;
}

Checkout.prototype.init = function() {
	if(this._inited == true) {
		return;
	}

	logDebug("Checkout: Initializing");

	// If Java works, and the user wants it then load the applet
	if (this._use_java()) {
		this._applet = createDOM('applet',
			{ archive: 'applet/build/checkout.jar',
			     code: 'org.studentrobotics.ide.checkout.CheckoutApplet',
			       id: 'checkout-applet',
			     name: 'checkout-applet',
			    width: '128',
			   height: '128'
			});
		appendChildNodes('applet', this._applet);
	}

	/* remember that we are initialised */
	this._inited = true;
}

// If Java works and the user wants it
Checkout.prototype._use_java = function() {
	return this._java_works && user.get_setting('export.usejava');
}

Checkout.prototype._basic = function(url, successCallback, errorCallback) {
	var handle = window.open(url, "Source Checkout");
	if (handle == null) {
		window.location = url;
	}
	successCallback();
}

Checkout.prototype._getLocation = function() {
	var protocolhost = location.protocol + "//" + location.hostname;

	if (location.port != 80) {
		protocolhost += ":" + location.port;
	}

	return protocolhost;
}

Checkout.prototype._java = function(url, successCallback, errorCallback) {
	var xhr = new XMLHttpRequest();
	var retcode = this._applet.writeZip(this._getLocation() + "/" + url);
	//if downloading worked
	if (retcode == 0) {
		successCallBack();
	} else {
		// negative response code means that java is not going to work ever
		if (retcode < 0) {
			this._java_works = false;
		}

		//use the file dialogue download method
		this._basic(url, successCallback, errorCallback);
	}
}

Checkout.prototype._download = function(successCallback, errorCallback, nodes) {
	var url = nodes.url;
	if (this._use_java() && this._applet != null) {
		this._java(url, successCallback, errorCallback);
	} else {
		this._basic(url, successCallback, errorCallback);
	}
}

Checkout.prototype.checkout = function(team, project, successCallback, errorCallback) {
	// get URL
	IDE_backend_request("proj/co", {team: team, project: project},
	                    bind(this._download, this, successCallback, errorCallback),
	                    errorCallback);
}
<|endoftext|>


<commit_before>var CrossfadeSample = {playing:false};

var sourceArray;
var firstIndex = 0;

CrossfadeSample.init = function() {
  // Create three sources.
  this.ctl1 = createSource(BUFFERS.type1);
  this.ctl2 = createSource(BUFFERS.type2);
  this.ctl3 = createSource(BUFFERS.type3);
  this.ctl4 = createSource(BUFFERS.type4);
  sourceArray = [this.ctl1,this.ctl2,this.ctl3,this.ctl4];
  // Mute the second source.
  for (var i = 0; i < sourceArray.length; i++) {
    sourceArray[i].gainNode.gain.value = 0;
  }
  sourceArray[firstIndex].gainNode.gain.value = 100;

  function createSource(buffer) {
    var source = context.createBufferSource();
    var gainNode = context.createGain ? context.createGain() : context.createGainNode();
    source.buffer = buffer;
    // Turn on looping
    source.loop = true;
    // Connect source to gain.
    source.connect(gainNode);
    // Connect gain to destination.
    gainNode.connect(context.destination);

    return {
      source: source,
      gainNode: gainNode
    };
  }

}

CrossfadeSample.play = function() {
  // Start playback in a loop
  if (!sourceArray[firstIndex].source.start) {
    for (var i = 0; i < sourceArray.length; i++) {
      sourceArray[i].source.noteOn(0);
    }
  } else {
    for (var i = 0; i < sourceArray.length; i++) {
      sourceArray[i].source.start(0);
    }
  }

};

CrossfadeSample.stop = function() {
  if (!sourceArray[firstIndex].source.stop) {
    for (var i = 0; i < sourceArray.length; i++) {
      sourceArray[i].source.noteOff(0);
    }
  } else {
    for (var i = 0; i < sourceArray.length; i++) {
      sourceArray[i].source.stop(0);
    }
  }
};

// Fades between 0 (all source 1) and 1 (all source 2)
CrossfadeSample.crossfade = function(num) {
  var x = 0;
  //var x = parseInt(element.value) / parseInt(element.max);

  // Use an equal-power crossfading curve:
  var gain1 = Math.cos(x * 0.5*Math.PI);
  var gain2 = Math.cos((1.0 - x) * 0.5*Math.PI);

  for (var i = 0; i < sourceArray.length; i++) {
    sourceArray[i].gainNode.gain.value = gain2;
  }
  sourceArray[num].gainNode.gain.value = gain1;
};

CrossfadeSample.toggle = function() {
  this.playing ? this.stop() : this.play();
  this.playing = !this.playing;
};
<commit_msg>とりあえず全部歌つき<commit_after>var CrossfadeSample = {playing:false};

var sourceArray;
var firstIndex = 0;

CrossfadeSample.init = function() {
  // Create three sources.
  this.ctl1 = createSource(BUFFERS.type1);
  this.ctl2 = createSource(BUFFERS.type1);
  this.ctl3 = createSource(BUFFERS.type1);
  this.ctl4 = createSource(BUFFERS.type4);
  sourceArray = [this.ctl1,this.ctl2,this.ctl3,this.ctl4];
  // Mute the second source.
  for (var i = 0; i < sourceArray.length; i++) {
    sourceArray[i].gainNode.gain.value = 0;
  }
  sourceArray[firstIndex].gainNode.gain.value = 100;

  function createSource(buffer) {
    var source = context.createBufferSource();
    var gainNode = context.createGain ? context.createGain() : context.createGainNode();
    source.buffer = buffer;
    // Turn on looping
    source.loop = true;
    // Connect source to gain.
    source.connect(gainNode);
    // Connect gain to destination.
    gainNode.connect(context.destination);

    return {
      source: source,
      gainNode: gainNode
    };
  }

}

CrossfadeSample.play = function() {
  // Start playback in a loop
  if (!sourceArray[firstIndex].source.start) {
    for (var i = 0; i < sourceArray.length; i++) {
      sourceArray[i].source.noteOn(0);
    }
  } else {
    for (var i = 0; i < sourceArray.length; i++) {
      sourceArray[i].source.start(0);
    }
  }

};

CrossfadeSample.stop = function() {
  if (!sourceArray[firstIndex].source.stop) {
    for (var i = 0; i < sourceArray.length; i++) {
      sourceArray[i].source.noteOff(0);
    }
  } else {
    for (var i = 0; i < sourceArray.length; i++) {
      sourceArray[i].source.stop(0);
    }
  }
};

// Fades between 0 (all source 1) and 1 (all source 2)
CrossfadeSample.crossfade = function(num) {
  var x = 0;
  //var x = parseInt(element.value) / parseInt(element.max);

  // Use an equal-power crossfading curve:
  var gain1 = Math.cos(x * 0.5*Math.PI);
  var gain2 = Math.cos((1.0 - x) * 0.5*Math.PI);

  for (var i = 0; i < sourceArray.length; i++) {
    sourceArray[i].gainNode.gain.value = gain2;
  }
  sourceArray[num].gainNode.gain.value = gain1;
};

CrossfadeSample.toggle = function() {
  this.playing ? this.stop() : this.play();
  this.playing = !this.playing;
};
<|endoftext|>