<commit_before>import gulp from "gulp";
import cp from "child_process";
import gutil from "gulp-util";
import postcss from "gulp-postcss";
import cssImport from "postcss-import";
import cssnext from "postcss-cssnext";
import BrowserSync from "browser-sync";
import webpack from "webpack";
import webpackConfig from "./webpack.conf";
import svgstore from "gulp-svgstore";
import svgmin from "gulp-svgmin";
import inject from "gulp-inject";
import replace from "gulp-replace";
import cssnano from "cssnano";

const browserSync = BrowserSync.create();
const hugoBin = `./bin/hugo.${process.platform === "windows" ? "exe" : process.platform}`;
const defaultArgs = ["-d", "../dist", "-s", "site"];

gulp.task("hugo", (cb) => buildSite(cb));
gulp.task("hugo-preview", (cb) => buildSite(cb, ["--buildDrafts", "--buildFuture"]));

gulp.task("cms", () => {
  const match = process.env.REPOSITORY_URL ? process.env.REPOSITORY_URL : cp.execSync("git remote -v", {encoding: "utf-8"});
  let repo = null;
  match.replace(/github.com:(\S+)(\.git)?/, (_, m) => {
    repo = m.replace(/\.git$/, "");
  });
  gulp.src("./src/cms/*")
    .pipe(replace("<% GITHUB_REPOSITORY %>", repo))
    .pipe(gulp.dest("./dist/admin"))
    .pipe(browserSync.stream());
});

gulp.task("build", ["css", "js", "hugo", "cms"]);
gulp.task("build-preview", ["css", "js", "hugo-preview"]);

gulp.task("css", () => (
  gulp.src("./src/css/*.css")
    .pipe(postcss([
      cssImport({from: "./src/css/main.css"}),
      cssnext(),
      cssnano(),
    ]))
    .pipe(gulp.dest("./dist/css"))
    .pipe(browserSync.stream())
));

gulp.task("js", (cb) => {
  const myConfig = Object.assign({}, webpackConfig);

  webpack(myConfig, (err, stats) => {
    if (err) throw new gutil.PluginError("webpack", err);
    gutil.log("[webpack]", stats.toString({
      colors: true,
      progress: true
    }));
    browserSync.reload();
    cb();
  });
});

gulp.task("svg", () => {
  const svgs = gulp
    .src("site/static/img/icons/*.svg")
    .pipe(svgmin())
    .pipe(svgstore({inlineSvg: true}));

  function fileContents(filePath, file) {
    return file.contents.toString();
  }

  return gulp
    .src("site/layouts/partials/svg.html")
    .pipe(inject(svgs, {transform: fileContents}))
    .pipe(gulp.dest("site/layouts/partials/"));
});

gulp.task("server", ["hugo", "css", "js", "svg", "cms"], () => {
  browserSync.init({
    server: {
      baseDir: "./dist"
    }
  });
  gulp.watch("./src/js/**/*.js", ["js"]);
  gulp.watch("./src/css/**/*.css", ["css"]);
  gulp.watch("./src/cms/*", ["cms"]);
  gulp.watch("./site/static/img/icons/*.svg", ["svg"]);
  gulp.watch("./site/**/*", ["hugo"]);
});

function buildSite(cb, options) {
  const args = options ? defaultArgs.concat(options) : defaultArgs;

  return cp.spawn(hugoBin, args, {stdio: "inherit"}).on("close", (code) => {
    if (code === 0) {
      browserSync.reload("notify:false");
      cb();
    } else {
      browserSync.notify("Hugo build failed :(");
      cb("Hugo build failed");
    }
  });
}
<commit_msg>Fix Windows detection in gulpfile<commit_after>import gulp from "gulp";
import cp from "child_process";
import gutil from "gulp-util";
import postcss from "gulp-postcss";
import cssImport from "postcss-import";
import cssnext from "postcss-cssnext";
import BrowserSync from "browser-sync";
import webpack from "webpack";
import webpackConfig from "./webpack.conf";
import svgstore from "gulp-svgstore";
import svgmin from "gulp-svgmin";
import inject from "gulp-inject";
import replace from "gulp-replace";
import cssnano from "cssnano";

const browserSync = BrowserSync.create();
const hugoBin = `./bin/hugo.${process.platform === "win32" ? "exe" : process.platform}`;
const defaultArgs = ["-d", "../dist", "-s", "site"];

gulp.task("hugo", (cb) => buildSite(cb));
gulp.task("hugo-preview", (cb) => buildSite(cb, ["--buildDrafts", "--buildFuture"]));

gulp.task("cms", () => {
  const match = process.env.REPOSITORY_URL ? process.env.REPOSITORY_URL : cp.execSync("git remote -v", {encoding: "utf-8"});
  let repo = null;
  match.replace(/github.com:(\S+)(\.git)?/, (_, m) => {
    repo = m.replace(/\.git$/, "");
  });
  gulp.src("./src/cms/*")
    .pipe(replace("<% GITHUB_REPOSITORY %>", repo))
    .pipe(gulp.dest("./dist/admin"))
    .pipe(browserSync.stream());
});

gulp.task("build", ["css", "js", "hugo", "cms"]);
gulp.task("build-preview", ["css", "js", "hugo-preview"]);

gulp.task("css", () => (
  gulp.src("./src/css/*.css")
    .pipe(postcss([
      cssImport({from: "./src/css/main.css"}),
      cssnext(),
      cssnano(),
    ]))
    .pipe(gulp.dest("./dist/css"))
    .pipe(browserSync.stream())
));

gulp.task("js", (cb) => {
  const myConfig = Object.assign({}, webpackConfig);

  webpack(myConfig, (err, stats) => {
    if (err) throw new gutil.PluginError("webpack", err);
    gutil.log("[webpack]", stats.toString({
      colors: true,
      progress: true
    }));
    browserSync.reload();
    cb();
  });
});

gulp.task("svg", () => {
  const svgs = gulp
    .src("site/static/img/icons/*.svg")
    .pipe(svgmin())
    .pipe(svgstore({inlineSvg: true}));

  function fileContents(filePath, file) {
    return file.contents.toString();
  }

  return gulp
    .src("site/layouts/partials/svg.html")
    .pipe(inject(svgs, {transform: fileContents}))
    .pipe(gulp.dest("site/layouts/partials/"));
});

gulp.task("server", ["hugo", "css", "js", "svg", "cms"], () => {
  browserSync.init({
    server: {
      baseDir: "./dist"
    }
  });
  gulp.watch("./src/js/**/*.js", ["js"]);
  gulp.watch("./src/css/**/*.css", ["css"]);
  gulp.watch("./src/cms/*", ["cms"]);
  gulp.watch("./site/static/img/icons/*.svg", ["svg"]);
  gulp.watch("./site/**/*", ["hugo"]);
});

function buildSite(cb, options) {
  const args = options ? defaultArgs.concat(options) : defaultArgs;

  return cp.spawn(hugoBin, args, {stdio: "inherit"}).on("close", (code) => {
    if (code === 0) {
      browserSync.reload("notify:false");
      cb();
    } else {
      browserSync.notify("Hugo build failed :(");
      cb("Hugo build failed");
    }
  });
}
<|endoftext|>


<commit_before>/*
	-------------------------------------
	MIDI.Player : 0.3
	-------------------------------------
	https://github.com/mudcube/MIDI.js
	-------------------------------------
	#jasmid
	-------------------------------------
*/

if (typeof (MIDI) === "undefined") var MIDI = {};
if (typeof (MIDI.Player) === "undefined") MIDI.Player = {};

(function() { "use strict";

var root = MIDI.Player;
root.callback = undefined; // your custom callback goes here!
root.currentTime = 0;
root.endTime = 0;
root.restart = 0;
root.playing = false;
root.timeWarp = 1;

//
root.start =
root.resume = function () {
	if (root.currentTime < -1) root.currentTime = -1;
	startAudio(root.currentTime);
};

root.pause = function () {
	var tmp = root.restart;
	stopAudio();
	root.restart = tmp;
};

root.stop = function () {
	stopAudio();
	root.restart = 0;
	root.currentTime = 0;
};

root.addListener = function(callback) {
	onMidiEvent = callback;
};

root.removeListener = function() {
	onMidiEvent = undefined;
};

root.clearAnimation = function() {
	if (root.interval)  {
		window.clearInterval(root.interval);
	}
};

root.setAnimation = function(config) {
	var callback = (typeof(config) === "function") ? config : config.callback;
	var interval = config.interval || 30;
	var currentTime = 0;
	var tOurTime = 0;
	var tTheirTime = 0;
	//
	root.clearAnimation();
	root.interval = window.setInterval(function () {
		if (root.endTime === 0) return;
		if (root.playing) {
			currentTime = (tTheirTime === root.currentTime) ? tOurTime - (new Date).getTime() : 0;
			if (root.currentTime === 0) {
				currentTime = 0;
			} else {
				currentTime = root.currentTime - currentTime;
			}
			if (tTheirTime !== root.currentTime) {
				tOurTime = (new Date).getTime();
				tTheirTime = root.currentTime;
			}
		} else { // paused
			currentTime = root.currentTime;
		}
		var endTime = root.endTime;
		var percent = currentTime / endTime;
		var total = currentTime / 1000;
		var minutes = total / 60;
		var seconds = total - (minutes * 60);
		var t1 = minutes * 60 + seconds;
		var t2 = (endTime / 1000);
		if (t2 - t1 < -1) return;
		callback({
			now: t1,
			end: t2,
			events: noteRegistrar
		});
	}, interval);
};

// helpers

root.loadMidiFile = function() { // reads midi into javascript array of events
	root.replayer = new Replayer(MidiFile(root.currentData), root.timeWarp);
	root.data = root.replayer.getData();
	root.endTime = getLength();
};

root.loadFile = function (file, callback) {
	root.stop();
	if (file.indexOf("base64,") !== -1) {
		var data = window.atob(file.split(",")[1]);
		root.currentData = data;
		root.loadMidiFile();
		if (callback) callback(data);
		return;
	}
	///
	var fetch = new XMLHttpRequest();
	fetch.open('GET', file);
	fetch.overrideMimeType("text/plain; charset=x-user-defined");
	fetch.onreadystatechange = function () {
		if (this.readyState === 4 && this.status === 200) {
			var t = this.responseText || "";
			var ff = [];
			var mx = t.length;
			var scc = String.fromCharCode;
			for (var z = 0; z < mx; z++) {
				ff[z] = scc(t.charCodeAt(z) & 255);
			}
			var data = ff.join("");
			root.currentData = data;
			root.loadMidiFile();
			if (callback) callback(data);
		}
	};
	fetch.send();
};

// Playing the audio

var eventQueue = []; // hold events to be triggered
var queuedTime; //
var startTime = 0; // to measure time elapse
var noteRegistrar = {}; // get event for requested note
var onMidiEvent = undefined; // listener callback
var scheduleTracking = function (channel, note, currentTime, offset, message, velocity) {
	var interval = window.setTimeout(function () {
		var data = {
			channel: channel,
			note: note,
			now: currentTime,
			end: root.endTime,
			message: message,
			velocity: velocity
		};
		//
		if (message === 128) {
			delete noteRegistrar[note];
		} else {
			noteRegistrar[note] = data;
		}
		if (onMidiEvent) {
			onMidiEvent(data);
		}
		root.currentTime = currentTime;
		if (root.currentTime === queuedTime && queuedTime < root.endTime) { // grab next sequence
			startAudio(queuedTime, true);
		}
	}, currentTime - offset);
	return interval;
};

var getContext = function() {
	if (MIDI.lang === 'WebAudioAPI') {
		return MIDI.Player.ctx;
	} else if (!root.ctx) {
		root.ctx = { currentTime: 0 };
	}
	return root.ctx;
};

var getLength = function() {
	var data =  root.data;
	var length = data.length;
	var totalTime = 0.5;
	for (var n = 0; n < length; n++) {
		totalTime += data[n][1];
	}
	return totalTime;
};

var startAudio = function (currentTime, fromCache) {
	if (!root.replayer) return;
	if (!fromCache) {
		if (typeof (currentTime) === "undefined") currentTime = root.restart;
		if (root.playing) stopAudio();
		root.playing = true;
		root.data = root.replayer.getData();
		root.endTime = getLength();
	}
	var note;
	var offset = 0;
	var messages = 0;
	var data = root.data;
	var ctx = getContext();
	var length = data.length;
	//
	queuedTime = 0.5;
	startTime = ctx.currentTime;
	//
	for (var n = 0; n < length && messages < 100; n++) {
		queuedTime += data[n][1];
		if (queuedTime < currentTime) {
			offset = queuedTime;
			continue;
		}
		currentTime = queuedTime - offset;
		var event = data[n][0].event;
		if (event.type !== "channel") continue;
		var channel = event.channel;
		switch (event.subtype) {
			case 'noteOn':
				if (MIDI.channels[channel].mute) break;
				note = event.noteNumber - (root.MIDIOffset || 0);
				eventQueue.push({
					event: event,
					source: MIDI.noteOn(channel, event.noteNumber, event.velocity, currentTime / 1000 + ctx.currentTime),
					interval: scheduleTracking(channel, note, queuedTime, offset, 144, event.velocity)
				});
				messages ++;
				break;
			case 'noteOff':
				if (MIDI.channels[channel].mute) break;
				note = event.noteNumber - (root.MIDIOffset || 0);
				eventQueue.push({
					event: event,
					source: MIDI.noteOff(channel, event.noteNumber, currentTime / 1000 + ctx.currentTime),
					interval: scheduleTracking(channel, note, queuedTime, offset, 128)
				});
				break;
			default:
				break;
		}
	}
};

var stopAudio = function () {
	var ctx = getContext();
	root.playing = false;
	root.restart += (ctx.currentTime - startTime) * 1000;
	// stop the audio, and intervals
	while (eventQueue.length) {
		var o = eventQueue.pop();
		window.clearInterval(o.interval);
		if (!o.source) continue; // is not webaudio
		if (typeof(o.source) === "number") {
			window.clearTimeout(o.source);
		} else { // webaudio
			o.source.disconnect(0);
		}
	}
	// run callback to cancel any notes still playing
	for (var key in noteRegistrar) {
		var o = noteRegistrar[key]
		if (noteRegistrar[key].message === 144 && onMidiEvent) {
			onMidiEvent({
				channel: o.channel,
				note: o.note,
				now: o.now,
				end: o.end,
				message: 128,
				velocity: o.velocity
			});
		}
	}
	// reset noteRegistrar
	noteRegistrar = {};
};

})();<commit_msg>- increased queue length to avoid bug with overloaded queue<commit_after>/*
	-------------------------------------
	MIDI.Player : 0.3
	-------------------------------------
	https://github.com/mudcube/MIDI.js
	-------------------------------------
	#jasmid
	-------------------------------------
*/

if (typeof (MIDI) === "undefined") var MIDI = {};
if (typeof (MIDI.Player) === "undefined") MIDI.Player = {};

(function() { "use strict";

var root = MIDI.Player;
root.callback = undefined; // your custom callback goes here!
root.currentTime = 0;
root.endTime = 0;
root.restart = 0;
root.playing = false;
root.timeWarp = 1;

//
root.start =
root.resume = function () {
	if (root.currentTime < -1) root.currentTime = -1;
	startAudio(root.currentTime);
};

root.pause = function () {
	var tmp = root.restart;
	stopAudio();
	root.restart = tmp;
};

root.stop = function () {
	stopAudio();
	root.restart = 0;
	root.currentTime = 0;
};

root.addListener = function(callback) {
	onMidiEvent = callback;
};

root.removeListener = function() {
	onMidiEvent = undefined;
};

root.clearAnimation = function() {
	if (root.interval)  {
		window.clearInterval(root.interval);
	}
};

root.setAnimation = function(config) {
	var callback = (typeof(config) === "function") ? config : config.callback;
	var interval = config.interval || 30;
	var currentTime = 0;
	var tOurTime = 0;
	var tTheirTime = 0;
	//
	root.clearAnimation();
	root.interval = window.setInterval(function () {
		if (root.endTime === 0) return;
		if (root.playing) {
			currentTime = (tTheirTime === root.currentTime) ? tOurTime - (new Date).getTime() : 0;
			if (root.currentTime === 0) {
				currentTime = 0;
			} else {
				currentTime = root.currentTime - currentTime;
			}
			if (tTheirTime !== root.currentTime) {
				tOurTime = (new Date).getTime();
				tTheirTime = root.currentTime;
			}
		} else { // paused
			currentTime = root.currentTime;
		}
		var endTime = root.endTime;
		var percent = currentTime / endTime;
		var total = currentTime / 1000;
		var minutes = total / 60;
		var seconds = total - (minutes * 60);
		var t1 = minutes * 60 + seconds;
		var t2 = (endTime / 1000);
		if (t2 - t1 < -1) return;
		callback({
			now: t1,
			end: t2,
			events: noteRegistrar
		});
	}, interval);
};

// helpers

root.loadMidiFile = function() { // reads midi into javascript array of events
	root.replayer = new Replayer(MidiFile(root.currentData), root.timeWarp);
	root.data = root.replayer.getData();
	root.endTime = getLength();
};

root.loadFile = function (file, callback) {
	root.stop();
	if (file.indexOf("base64,") !== -1) {
		var data = window.atob(file.split(",")[1]);
		root.currentData = data;
		root.loadMidiFile();
		if (callback) callback(data);
		return;
	}
	///
	var fetch = new XMLHttpRequest();
	fetch.open('GET', file);
	fetch.overrideMimeType("text/plain; charset=x-user-defined");
	fetch.onreadystatechange = function () {
		if (this.readyState === 4 && this.status === 200) {
			var t = this.responseText || "";
			var ff = [];
			var mx = t.length;
			var scc = String.fromCharCode;
			for (var z = 0; z < mx; z++) {
				ff[z] = scc(t.charCodeAt(z) & 255);
			}
			var data = ff.join("");
			root.currentData = data;
			root.loadMidiFile();
			if (callback) callback(data);
		}
	};
	fetch.send();
};

// Playing the audio

var eventQueue = []; // hold events to be triggered
var queuedTime; //
var startTime = 0; // to measure time elapse
var noteRegistrar = {}; // get event for requested note
var onMidiEvent = undefined; // listener callback
var scheduleTracking = function (channel, note, currentTime, offset, message, velocity) {
	var interval = window.setTimeout(function () {
		var data = {
			channel: channel,
			note: note,
			now: currentTime,
			end: root.endTime,
			message: message,
			velocity: velocity
		};
		//
		if (message === 128) {
			delete noteRegistrar[note];
		} else {
			noteRegistrar[note] = data;
		}
		if (onMidiEvent) {
			onMidiEvent(data);
		}
		root.currentTime = currentTime;
		if (root.currentTime === queuedTime && queuedTime < root.endTime) { // grab next sequence
			startAudio(queuedTime, true);
		}
	}, currentTime - offset);
	return interval;
};

var getContext = function() {
	if (MIDI.lang === 'WebAudioAPI') {
		return MIDI.Player.ctx;
	} else if (!root.ctx) {
		root.ctx = { currentTime: 0 };
	}
	return root.ctx;
};

var getLength = function() {
	var data =  root.data;
	var length = data.length;
	var totalTime = 0.5;
	for (var n = 0; n < length; n++) {
		totalTime += data[n][1];
	}
	return totalTime;
};

var startAudio = function (currentTime, fromCache) {
	if (!root.replayer) return;
	if (!fromCache) {
		if (typeof (currentTime) === "undefined") currentTime = root.restart;
		if (root.playing) stopAudio();
		root.playing = true;
		root.data = root.replayer.getData();
		root.endTime = getLength();
	}
	var note;
	var offset = 0;
	var messages = 0;
	var data = root.data;
	var ctx = getContext();
	var length = data.length;
	//
	queuedTime = 0.5;
	startTime = ctx.currentTime;
	//
	for (var n = 0; n < length && messages < 20000; n++) {
		queuedTime += data[n][1];
		if (queuedTime < currentTime) {
			offset = queuedTime;
			continue;
		}
		currentTime = queuedTime - offset;
		var event = data[n][0].event;
		if (event.type !== "channel") continue;
		var channel = event.channel;
		switch (event.subtype) {
			case 'noteOn':
				if (MIDI.channels[channel].mute) break;
				note = event.noteNumber - (root.MIDIOffset || 0);
				eventQueue.push({
					event: event,
					source: MIDI.noteOn(channel, event.noteNumber, event.velocity, currentTime / 1000 + ctx.currentTime),
					interval: scheduleTracking(channel, note, queuedTime, offset, 144, event.velocity)
				});
				messages ++;
				break;
			case 'noteOff':
				if (MIDI.channels[channel].mute) break;
				note = event.noteNumber - (root.MIDIOffset || 0);
				eventQueue.push({
					event: event,
					source: MIDI.noteOff(channel, event.noteNumber, currentTime / 1000 + ctx.currentTime),
					interval: scheduleTracking(channel, note, queuedTime, offset, 128)
				});
				break;
			default:
				break;
		}
	}
};

var stopAudio = function () {
	var ctx = getContext();
	root.playing = false;
	root.restart += (ctx.currentTime - startTime) * 1000;
	// stop the audio, and intervals
	while (eventQueue.length) {
		var o = eventQueue.pop();
		window.clearInterval(o.interval);
		if (!o.source) continue; // is not webaudio
		if (typeof(o.source) === "number") {
			window.clearTimeout(o.source);
		} else { // webaudio
			o.source.disconnect(0);
		}
	}
	// run callback to cancel any notes still playing
	for (var key in noteRegistrar) {
		var o = noteRegistrar[key]
		if (noteRegistrar[key].message === 144 && onMidiEvent) {
			onMidiEvent({
				channel: o.channel,
				note: o.note,
				now: o.now,
				end: o.end,
				message: 128,
				velocity: o.velocity
			});
		}
	}
	// reset noteRegistrar
	noteRegistrar = {};
};

})();<|endoftext|>


<commit_before>//= require turbolinks
//= require ./mootools-core-1.5.0-full-compat.js
//= require ./mootools-more-1.5.0.js
//= require ./mootools_ujs
//= require_tree ./classes/

// Turbolinks bugs out on popState if you add own pushState events, so we cancel it
Turbolinks.pagesCached(0);

var initHelper = function(callback){
	var scopedCallback = function(){
		callback(document.body);
	};
	document.addEventListener('page:load', scopedCallback);
	window.addEvent('domready', scopedCallback);
	window.addEvent('platformUpdate', callback);
	window.addEvent('quickEditFormInject', callback);
};

(function(){
	var stackIndexCounter = 0;
	var lang = document.html.get('lang');
	Locale.use(lang = (lang === 'en') ? 'en-US' : lang = lang+'-'+lang.toUpperCase());

	var ajaxNote = new Ajaxify();
	document.addEventListener('page:fetch', function(){
		ajaxNote.loading();
	});

	var editStack = new QuickEditStack({
		permanentQuickEditEvents: {
			startRequest: function(){
				var linkElem = this.linkElem;
				var rowElem = this.linkElem.getParent('tr');
				if (rowElem) {
					linkElem = rowElem;
				}
				linkElem.addClass('live_edit');
			},
			closed: function(){
				var linkElem = this.linkElem;
				var rowElem = this.linkElem.getParent('tr');
				if (rowElem) {
					linkElem = rowElem;
				}
				linkElem.addClass('animate');
				setTimeout(function(){
					linkElem.removeClass('live_edit');
				});
				setTimeout(function(){
					linkElem.removeClass('animate');
				}, 600);
			}
		}
	});

	var triggerPlatformPagination = function(href, platform, callback){
		window.history.pushState({ turbolinks: true, url: href }, '', href);
		ajaxNote.loading();
		new Request.HTML({
			method: 'get',
			url: href,
			onFailure: function(){
				ajaxNote.failure();
			},
			onSuccess: function(a, b, html){
				platform.innerHTML = html;
				if (callback) {
					callback.call();
				}
				window.fireEvent('platformUpdate', [platform.getParent()]);
			}
		}).send();
	};

	var updateElementsAfterQuickEditSuccess = function(eventNames, linkElem, json){
		var parent = linkElem.getParent('.quick_edit_block');
		var entryTemplate = parent.getElement('.quick_edit_template');
		var newEntryInjectArea = parent.getElement('.quick_edit_inject');
		var relation = parent.getElement('.relation');
		var entry = linkElem.getParent('.quick_edit_entry');
		if ( ! entry) {
			entry = parent.getElement('.quick_edit_active');
		}

		if (json) {
			var parsedTemplate = entryTemplate.innerHTML.replace(new RegExp('%7Bobject_id%7D', 'g'), '{object_id}').substitute(json)
		}

		if (eventNames.contains('successAndAdd')) {
			if (newEntryInjectArea && entryTemplate) {
				newEntryInjectArea.appendHTML(parsedTemplate);
				if (newEntryInjectArea) {
					newEntryInjectArea.fireEvent('quickEditEntryAdded');
				}
			}

			if (relation) {
				if (relation.getPrevious('.empty')) {
					relation.getPrevious('.empty').addClass('hide');
				}
				if (relation.hasClass('has_one') || relation.hasClass('embeds_one')) {
					relation.getNext('.js_add_field').addClass('hide');
				}
			}
		}
		if (eventNames.contains('successAndChange')) {
			if (entry) {
				entry.innerHTML = parsedTemplate;
			}
		}
		if (eventNames.contains('successAndRemove')) {
			if (entry) {
				entry.dispose();
			}
			if (newEntryInjectArea) {
				newEntryInjectArea.fireEvent('quickEditEntryRemoved');
			}

		}
	};

	initHelper(function(mainScope){

		var areaSelect = mainScope.getElement('#area_select');
		if (areaSelect) {
			areaSelect.addEvent('change', function(){
				location.href = this.value;
			});
		}

		var quickEditArray = [];
		var quickEditOptions;

		ajaxNote.setup();

		var jsForm = new FormHelper();
		mainScope.getElements('.js_bhf_form').each(function(form){
			jsForm.setup(form);
		});

		var sharedQuickEditOptions = {
			onFailure: function(){
				ajaxNote.failure();
			},
			onStartRequest: function(form){
				ajaxNote.loading();
			},
			onFormInjected: function(form){
				scrollContent();
				ajaxNote.success();
			},
			onSave: function(eventNames, linkElem, json){
				updateElementsAfterQuickEditSuccess(eventNames, linkElem, json);
				ajaxNote.success();
			},
			onBeforeSubmit: function(){
				ajaxNote.loading();
				jsForm.wysiwyg.each(function(editor){
					editor.saveContent();
				});
			}
		};

		var platforms = mainScope.getElements('.platform');
		var mainForm = mainScope.getElementById('main_form');

		mainScope.getElements('.quick_edit_select').addEvent('change', function(e){
			var parent = this.getParent('.quick_edit_block');
			var optionElem = this.options[this.selectedIndex];
			var editElem = parent.getElement('.js_edit_field');
			if (editElem) {
				editElem.href = optionElem.get('data-edit');
			}
			var deleteElem = parent.getElement('.js_delete');
			if (deleteElem) {
				deleteElem.href = optionElem.get('data-delete');
			}
			this.getElements('.quick_edit_active').removeClass('quick_edit_active');
			optionElem.addClass('quick_edit_active');
		}).addEvent('quickEditEntryAdded', function(){
			this.selectedIndex = this.options.length - 1;
			this.fireEvent('change');
		}).addEvent('quickEditEntryRemoved', function(){
			this.selectedIndex = 0;
			this.fireEvent('change');
		}).fireEvent('change');

		mainScope.addEvent('click:relay(.js_delete)', function(e){
			e.target.addEvents({
				'ajax:success': function(html){
					updateElementsAfterQuickEditSuccess(['successAndRemove'], e.target);
				},
				'ajax:failure': function(html){
					alert(Locale.get('Notifications.failure'));
				}
			});
		});

		if (platforms.length) {
			quickEditOptions = Object.merge({
				onSuccessAndNext: function(json){
					var tr = this.linkElem;
					var qe;
					var nextTr = tr.getNext('tr');

					if (nextTr) {
						editStack.removeAllStacks();
						editStack.addEditBrick(quickEditOptions, nextTr.getElement('a'), nextTr);
					}
					else {
						var platform = tr.getParent('.platform');
						var loadMore = platform.getElement('.load_more');
						if (loadMore) {
							trIndex = tr.getParent('tbody').getElements('tr').indexOf(tr);
							triggerPlatformPagination(loadMore.get('href'), platform, function(){
								platform.getElements('tbody tr').each(function(newTr, index){
									if (trIndex === index) {
										nextTr = newTr.getNext('tr');

										editStack.removeAllStacks();
										editStack.addEditBrick(quickEditOptions, nextTr.getElement('a'), nextTr);
									}
								});
							});
						}
						else {
							nextTr = platform.getElements('tbody tr')[0];

							editStack.removeAllStacks();
							editStack.addEditBrick(quickEditOptions, nextTr.getElement('a'), nextTr);
						}
					}
				}
			}, sharedQuickEditOptions);

			platforms.each(function(p){
				new PlatformHelper(p, {
					onPaginationStart: function(link){
						triggerPlatformPagination(link.get('href'), link.getParent('.platform'));
					},
					onQuickEditStart: function(link){
						editStack.removeAllStacks();
						editStack.addEditBrick(quickEditOptions, link, link.getParent('tr'));
					},
					onSearch: function(){
						ajaxNote.loading();
					},
					onSearchFailure: function(){
						ajaxNote.failure();
					},
					onSearchSuccess: function(request){
						window.fireEvent('platformUpdate', [p.getParent()]);
						// TODO: remove the mootools hack for request.url don't
						window.history.pushState({ turbolinks: true, url: request.url }, '', request.url);
					}
				});
			});
		}
		else if (mainForm) {
			quickEditOptions = Object.merge({
				onSuccessAndNext: function(json){
					var a = this.linkElem;
					var li = a.getParent('li');
					if ( ! li) {
						this.close();
						return;
					}
					var holder = li.getNext('li');
					if ( ! holder) {
						holder = li.getParent('ul');
					}

					editStack.removeAllStacks();
					editStack.addEditBrick(quickEditOptions, holder.getElement('a'));
				}
			}, sharedQuickEditOptions);

			mainForm.addEvent('click:relay(.quick_edit)', function(e){
				e.preventDefault();
				editStack.removeAllStacks();
				editStack.addEditBrick(quickEditOptions, this);
			});
		}
		else if (mainScope.hasClass('quick_edit_holder')) {
			quickEditOptions = Object.merge({
				onClosed: function(){
					editStack.removeStack();
				},
				hideNext: true
			}, sharedQuickEditOptions);

			mainScope.addEvent('click:relay(.quick_edit)', function(e){
				e.preventDefault();
				editStack.addStack();
				editStack.addEditBrick(quickEditOptions, this);
			});
		}

		var scrollContent = function(){
			quickEditArray.each(function(quickEdit){
				var innerForm = quickEdit.holder.getElement('form');
				if ( ! innerForm) { return; }
				var scroll = document.body.scrollTop - 83;
				if (scroll + innerForm.getSize().y > document.body.clientHeight) { return; }
				quickEdit.holder.setStyle('padding-top', scroll);
			});
		};
		// window.onscroll = scrollContent;

		mainScope.getElements('.js_sortable').each(function(sortableElems){
			new Sortables(sortableElems, {
				handle: '.handle',
				onStart: function(element, clone){
					element.addClass('dragged');
				},
				onComplete: function(element){
					element.removeClass('dragged');
					new Request({
						method: 'put',
						url: sortableElems.get('data-sort-url')
					}).send({data: {order: this.serialize()}});
				}
			});
		});

		var fm = $('flash_massages');
		if (fm) {
			fm.removeClass.delay(10000, fm, 'show');
		}

		mainScope.getElements('.initial_referral').each(function(elem){
			setTimeout(function(){
				elem.removeClass('live_edit');
				setTimeout(function(){
					elem.removeClass('animate');
				}, 600);
			}, 500);
		});

		ajaxNote.success();
	});
})();
<commit_msg>"bhfDomChunkReady" js event added<commit_after>//= require turbolinks
//= require ./mootools-core-1.5.0-full-compat.js
//= require ./mootools-more-1.5.0.js
//= require ./mootools_ujs
//= require_tree ./classes/

// Turbolinks bugs out on popState if you add own pushState events, so we cancel it
Turbolinks.pagesCached(0);

(function(){
	var stackIndexCounter = 0;
	var lang = document.html.get('lang');
	Locale.use(lang = (lang === 'en') ? 'en-US' : lang = lang+'-'+lang.toUpperCase());

	var ajaxNote = new Ajaxify();
	document.addEventListener('page:fetch', function(){
		ajaxNote.loading();
	});

	var editStack = new QuickEditStack({
		permanentQuickEditEvents: {
			startRequest: function(){
				var linkElem = this.linkElem;
				var rowElem = this.linkElem.getParent('tr');
				if (rowElem) {
					linkElem = rowElem;
				}
				linkElem.addClass('live_edit');
			},
			closed: function(){
				var linkElem = this.linkElem;
				var rowElem = this.linkElem.getParent('tr');
				if (rowElem) {
					linkElem = rowElem;
				}
				linkElem.addClass('animate');
				setTimeout(function(){
					linkElem.removeClass('live_edit');
				});
				setTimeout(function(){
					linkElem.removeClass('animate');
				}, 600);
			}
		}
	});

	var triggerPlatformPagination = function(href, platform, callback){
		window.history.pushState({ turbolinks: true, url: href }, '', href);
		ajaxNote.loading();
		new Request.HTML({
			method: 'get',
			url: href,
			onFailure: function(){
				ajaxNote.failure();
			},
			onSuccess: function(a, b, html){
				platform.innerHTML = html;
				if (callback) {
					callback.call();
				}
				window.fireEvent('platformUpdate', [platform.getParent()]);
			}
		}).send();
	};

	var updateElementsAfterQuickEditSuccess = function(eventNames, linkElem, json){
		var parent = linkElem.getParent('.quick_edit_block');
		var entryTemplate = parent.getElement('.quick_edit_template');
		var newEntryInjectArea = parent.getElement('.quick_edit_inject');
		var relation = parent.getElement('.relation');
		var entry = linkElem.getParent('.quick_edit_entry');
		if ( ! entry) {
			entry = parent.getElement('.quick_edit_active');
		}

		if (json) {
			var parsedTemplate = entryTemplate.innerHTML.replace(new RegExp('%7Bobject_id%7D', 'g'), '{object_id}').substitute(json)
		}

		if (eventNames.contains('successAndAdd')) {
			if (newEntryInjectArea && entryTemplate) {
				newEntryInjectArea.appendHTML(parsedTemplate);
				if (newEntryInjectArea) {
					newEntryInjectArea.fireEvent('quickEditEntryAdded');
				}
			}

			if (relation) {
				if (relation.getPrevious('.empty')) {
					relation.getPrevious('.empty').addClass('hide');
				}
				if (relation.hasClass('has_one') || relation.hasClass('embeds_one')) {
					relation.getNext('.js_add_field').addClass('hide');
				}
			}
		}
		if (eventNames.contains('successAndChange')) {
			if (entry) {
				entry.innerHTML = parsedTemplate;
			}
		}
		if (eventNames.contains('successAndRemove')) {
			if (entry) {
				entry.dispose();
			}
			if (newEntryInjectArea) {
				newEntryInjectArea.fireEvent('quickEditEntryRemoved');
			}

		}
	};

	window.addEvent('bhfDomChunkReady', function(mainScope){

		var areaSelect = mainScope.getElement('#area_select');
		if (areaSelect) {
			areaSelect.addEvent('change', function(){
				location.href = this.value;
			});
		}

		var quickEditArray = [];
		var quickEditOptions;

		ajaxNote.setup();

		var jsForm = new FormHelper();
		mainScope.getElements('.js_bhf_form').each(function(form){
			jsForm.setup(form);
		});

		var sharedQuickEditOptions = {
			onFailure: function(){
				ajaxNote.failure();
			},
			onStartRequest: function(form){
				ajaxNote.loading();
			},
			onFormInjected: function(form){
				scrollContent();
				ajaxNote.success();
			},
			onSave: function(eventNames, linkElem, json){
				updateElementsAfterQuickEditSuccess(eventNames, linkElem, json);
				ajaxNote.success();
			},
			onBeforeSubmit: function(){
				ajaxNote.loading();
				jsForm.wysiwyg.each(function(editor){
					editor.saveContent();
				});
			}
		};

		var platforms = mainScope.getElements('.platform');
		var mainForm = mainScope.getElementById('main_form');

		mainScope.getElements('.quick_edit_select').addEvent('change', function(e){
			var parent = this.getParent('.quick_edit_block');
			var optionElem = this.options[this.selectedIndex];
			var editElem = parent.getElement('.js_edit_field');
			if (editElem) {
				editElem.href = optionElem.get('data-edit');
			}
			var deleteElem = parent.getElement('.js_delete');
			if (deleteElem) {
				deleteElem.href = optionElem.get('data-delete');
			}
			this.getElements('.quick_edit_active').removeClass('quick_edit_active');
			optionElem.addClass('quick_edit_active');
		}).addEvent('quickEditEntryAdded', function(){
			this.selectedIndex = this.options.length - 1;
			this.fireEvent('change');
		}).addEvent('quickEditEntryRemoved', function(){
			this.selectedIndex = 0;
			this.fireEvent('change');
		}).fireEvent('change');

		mainScope.addEvent('click:relay(.js_delete)', function(e){
			e.target.addEvents({
				'ajax:success': function(html){
					updateElementsAfterQuickEditSuccess(['successAndRemove'], e.target);
				},
				'ajax:failure': function(html){
					alert(Locale.get('Notifications.failure'));
				}
			});
		});

		if (platforms.length) {
			quickEditOptions = Object.merge({
				onSuccessAndNext: function(json){
					var tr = this.linkElem;
					var qe;
					var nextTr = tr.getNext('tr');

					if (nextTr) {
						editStack.removeAllStacks();
						editStack.addEditBrick(quickEditOptions, nextTr.getElement('a'), nextTr);
					}
					else {
						var platform = tr.getParent('.platform');
						var loadMore = platform.getElement('.load_more');
						if (loadMore) {
							trIndex = tr.getParent('tbody').getElements('tr').indexOf(tr);
							triggerPlatformPagination(loadMore.get('href'), platform, function(){
								platform.getElements('tbody tr').each(function(newTr, index){
									if (trIndex === index) {
										nextTr = newTr.getNext('tr');

										editStack.removeAllStacks();
										editStack.addEditBrick(quickEditOptions, nextTr.getElement('a'), nextTr);
									}
								});
							});
						}
						else {
							nextTr = platform.getElements('tbody tr')[0];

							editStack.removeAllStacks();
							editStack.addEditBrick(quickEditOptions, nextTr.getElement('a'), nextTr);
						}
					}
				}
			}, sharedQuickEditOptions);

			platforms.each(function(p){
				new PlatformHelper(p, {
					onPaginationStart: function(link){
						triggerPlatformPagination(link.get('href'), link.getParent('.platform'));
					},
					onQuickEditStart: function(link){
						editStack.removeAllStacks();
						editStack.addEditBrick(quickEditOptions, link, link.getParent('tr'));
					},
					onSearch: function(){
						ajaxNote.loading();
					},
					onSearchFailure: function(){
						ajaxNote.failure();
					},
					onSearchSuccess: function(request){
						window.fireEvent('platformUpdate', [p.getParent()]);
						// TODO: remove the mootools hack for request.url don't
						window.history.pushState({ turbolinks: true, url: request.url }, '', request.url);
					}
				});
			});
		}
		else if (mainForm) {
			quickEditOptions = Object.merge({
				onSuccessAndNext: function(json){
					var a = this.linkElem;
					var li = a.getParent('li');
					if ( ! li) {
						this.close();
						return;
					}
					var holder = li.getNext('li');
					if ( ! holder) {
						holder = li.getParent('ul');
					}

					editStack.removeAllStacks();
					editStack.addEditBrick(quickEditOptions, holder.getElement('a'));
				}
			}, sharedQuickEditOptions);

			mainForm.addEvent('click:relay(.quick_edit)', function(e){
				e.preventDefault();
				editStack.removeAllStacks();
				editStack.addEditBrick(quickEditOptions, this);
			});
		}
		else if (mainScope.hasClass('quick_edit_holder')) {
			quickEditOptions = Object.merge({
				onClosed: function(){
					editStack.removeStack();
				},
				hideNext: true
			}, sharedQuickEditOptions);

			mainScope.addEvent('click:relay(.quick_edit)', function(e){
				e.preventDefault();
				editStack.addStack();
				editStack.addEditBrick(quickEditOptions, this);
			});
		}

		var scrollContent = function(){
			quickEditArray.each(function(quickEdit){
				var innerForm = quickEdit.holder.getElement('form');
				if ( ! innerForm) { return; }
				var scroll = document.body.scrollTop - 83;
				if (scroll + innerForm.getSize().y > document.body.clientHeight) { return; }
				quickEdit.holder.setStyle('padding-top', scroll);
			});
		};
		// window.onscroll = scrollContent;

		mainScope.getElements('.js_sortable').each(function(sortableElems){
			new Sortables(sortableElems, {
				handle: '.handle',
				onStart: function(element, clone){
					element.addClass('dragged');
				},
				onComplete: function(element){
					element.removeClass('dragged');
					new Request({
						method: 'put',
						url: sortableElems.get('data-sort-url')
					}).send({data: {order: this.serialize()}});
				}
			});
		});

		var fm = $('flash_massages');
		if (fm) {
			fm.removeClass.delay(10000, fm, 'show');
		}

		mainScope.getElements('.initial_referral').each(function(elem){
			setTimeout(function(){
				elem.removeClass('live_edit');
				setTimeout(function(){
					elem.removeClass('animate');
				}, 600);
			}, 500);
		});

		ajaxNote.success();
	});

	var bodyCallback = function(){
		window.fireEvent('bhfDomChunkReady', [document.body]);
	};
	var scopeCallback = function(scope){
		window.fireEvent('bhfDomChunkReady', [scope]);
	};
	document.addEventListener('page:load', bodyCallback);
	window.addEvent('domready', bodyCallback);
	window.addEvent('platformUpdate', scopeCallback);
	window.addEvent('quickEditFormInject', scopeCallback);
})();
<|endoftext|>


<commit_before>// Copyright 2002-2013, University of Colorado Boulder

/**
 * PropertySet facilitates creation and use of multiple named Property instances.  There are still several API design issues in question, but this
 * class is ready for use.
 *
 * A PropertySet is a set of Property instances that provides support for:
 * -Easily creating several properties using an object literal (hash)
 * -Resetting them as a group
 * -Set multiple values at once, using propertySet.set({x:100,y:200,name:'alice'});
 * -Support for derived properties, which appear with the same interface as basic properties
 * -Convenient toString that prints e.g., PropertySet{name:'larry',age:101,kids:['alice','bob']}
 * -Wiring up to listen to multiple properties simultaneously
 * -Add properties after the PropertySet is created?  Don't forget to add to the key list as well.
 * -Remove properties that were added using addProperty or the constructor
 *
 * Sample usage:
 * var p = new PropertySet( {name: 'larry', age: 100, kids: ['alice', 'bob']} );
 * p.nameProperty.link( function( n ) {console.log( 'hello ' + n );} );
 * p.name = 'jensen';
 * p.age = 101;//Happy Birthday!
 * console.log( p );
 * p.reset();
 * console.log( p );
 * p.set({name:'clark',age:102,kids:['alice','bob','charlie']});
 *
 * How would this be done without PropertySet (for comparison)?
 * //Normally would be created in a class but that is omitted here for brevity.
 * var p ={name: new Property('larry'), age: new Property('age'), kids: new Property(['alice','bob'])}
 * p.reset = function(){
 *   this.name.reset();
 *   this.age.reset();
 *   this.kids.reset();
 * }
 * p.name.set('clark');
 * p.age.set('102');
 * p.kids.set(['alice','bob','charlie']);
 *
 * Note: If a subclass ever substitutes a property like this: person.ageProperty = new Property(person.age), then it would break the getter/setter
 * @author Sam Reid
 */

define( function( require ) {
  'use strict';

  var Property = require( 'AXON/Property' );
  var DerivedProperty = require( 'AXON/DerivedProperty' );
  var Events = require( 'AXON/Events' );
  var axon = require( 'AXON/axon' );
  var inherit = require( 'PHET_CORE/inherit' );

  /**
   * @class PropertySet
   * @constructor
   * @param values an object hash with the initial values for the properties
   */
  axon.PropertySet = function PropertySet( values ) {
    var propertySet = this;

    Events.call( this );

    //Keep track of the keys so we know which to reset
    this.keys = [];

    Object.getOwnPropertyNames( values ).forEach( function( value ) {
      propertySet.addProperty( value, values[value] );
    } );

    this.eventListeners = {};
  };

  return inherit( Events, axon.PropertySet, {

    /**
     * Adds a new property to this PropertySet
     *
     * @param {String} name
     * @param value
     */
    addProperty: function( name, value ) {
      this[name + 'Property'] = new Property( value );
      this.addGetterAndSetter( name );
      this.keys.push( name );
    },

    /**
     * Remove any property (whether a derived property or not) that was added to this PropertySet
     * @param name
     */
    removeProperty: function( name ) {

      //Remove from the keys (only for non-derived properties)
      var index = this.keys.indexOf( name );
      if ( index !== -1 ) {
        this.keys.splice( index, 1 );
      }

      //Unregister the Property instance from the PropertySet
      delete this[name + 'Property'];

      //Unregister the getter/setter, if they exist
      delete this[name];
    },

    //Add a getter and setter using ES5 get/set syntax, similar to https://gist.github.com/dandean/1292057, same as in github/Atlas
    addGetterAndSetter: function( name ) {
      var property = this[name + 'Property'];

      Object.defineProperty( this, name, {

        // Getter proxies to Model#get()...
        get: function() { return property.get();},

        // Setter proxies to Model#set(attributes)
        set: function( value ) { property.set( value );},

        // Make it configurable and enumerable so it's easy to override...
        configurable: true,
        enumerable: true
      } );
    },

    addGetter: function( name ) {
      var property = this[name + 'Property'];

      Object.defineProperty( this, name, {

        get: function() { return property.get();},

        // Make it configurable and enumerable so it's easy to override...
        configurable: true,
        enumerable: true
      } );
    },

    //Resets all of the properties associated with this PropertySet
    reset: function() {
      var propertySet = this;
      this.keys.forEach( function( key ) {
        propertySet[key + 'Property'].reset();
      } );
    },

    /**
     * Creates a DerivedProperty from the given dependency names and derivation.
     * @param dependencyNames {Array<String>}
     * @param derivation {Function}
     * @returns {DerivedProperty}
     */
    toDerivedProperty: function( dependencyNames, derivation ) {
      var propertySet = this;
      var dependencies = dependencyNames.map( function( dependency ) {
        return propertySet[dependency + 'Property'];
      } );
      return new DerivedProperty( dependencies, derivation );
    },

    addDerivedProperty: function( name, dependencyNames, derivation ) {
      this[name + 'Property'] = this.toDerivedProperty( dependencyNames, derivation );
      this.addGetter( name );
    },

    /**
     * Set all of the values specified in the object hash
     * Allows you to use this form:
     * puller.set( {x: knot.x, y: knot.y, knot: knot} );
     *
     * instead of this:
     * puller.x.value = knot.x;
     * puller.y.value = knot.y;
     * puller.knot.value = knot;
     *
     * Throws an error if you try to set a value for which there is no property.
     */
    set: function( values ) {
      var propertySet = this;
      Object.getOwnPropertyNames( values ).forEach( function( val ) {
        if ( typeof(propertySet[val + 'Property'] === 'Property') ) {
          propertySet[val + 'Property'].set( values[val] );
        }
        else {
          throw new Error( 'property not found: ' + val );
        }
      } );
    },

    /**
     * Add a listener to zero or more properties in this PropertySet, useful when you have an update function
     * that relies on several properties.  Similar to DerivedProperty.
     * Discussion result: Let's use 'multilink' for now, and in the future we may change it to link.
     * @param dependencyNames {Array<String>} the list of dependencies to use
     * @param listener {Function} the listener to call back, with signature matching the dependency names
     */
    multilink: function( dependencyNames, listener ) {
      return this.toDerivedProperty( dependencyNames, listener );
    },

    /**
     * Removes the multilinked listener from this PropertySet.
     * Same as calling detach() on the handle (which happens to be a DerivedProperty instance)
     * @param derivedProperty
     */
    unmultilink: function( derivedProperty ) {
      derivedProperty.detach();
    },

    toString: function() {
      var text = 'PropertySet{';
      var propertySet = this;
      for ( var i = 0; i < this.keys.length; i++ ) {
        var key = this.keys[i];
        text = text + key + ':' + propertySet[key].toString();
        if ( i < this.keys.length - 1 ) {
          text = text + ',';
        }
      }
      return text + '}';
    },

    /**
     * Link to a property by name, see https://github.com/phetsims/axon/issues/16
     * @param {string} propertyName the name of the property to link to
     * @param {function }observer the callback to link to the property
     */
    link: function( propertyName, observer ) {
      this[propertyName + 'Property'].link( observer );
    },

    /**
     * Get a property by name, see https://github.com/phetsims/axon/issues/16
     * @param {string} propertyName the name of the property to get
     */
    property: function( propertyName ) {
      return this[propertyName + 'Property'];
    },

    /**
     * Link an attribute to a property by name
     * @param {string} propertyName the property to link to
     * @param {object} object the object for which the attribute will be set
     * @param {string} attributeName the name of the attribute to set on the object
     */
    linkAttribute: function( propertyName, object, attributeName ) {
      this.property( propertyName ).linkAttribute( object, attributeName );
    }
  } );
} );<commit_msg>Added PropertySet.get, see #19<commit_after>// Copyright 2002-2013, University of Colorado Boulder

/**
 * PropertySet facilitates creation and use of multiple named Property instances.  There are still several API design issues in question, but this
 * class is ready for use.
 *
 * A PropertySet is a set of Property instances that provides support for:
 * -Easily creating several properties using an object literal (hash)
 * -Resetting them as a group
 * -Set multiple values at once, using propertySet.set({x:100,y:200,name:'alice'});
 * -Support for derived properties, which appear with the same interface as basic properties
 * -Convenient toString that prints e.g., PropertySet{name:'larry',age:101,kids:['alice','bob']}
 * -Wiring up to listen to multiple properties simultaneously
 * -Add properties after the PropertySet is created?  Don't forget to add to the key list as well.
 * -Remove properties that were added using addProperty or the constructor
 *
 * Sample usage:
 * var p = new PropertySet( {name: 'larry', age: 100, kids: ['alice', 'bob']} );
 * p.nameProperty.link( function( n ) {console.log( 'hello ' + n );} );
 * p.name = 'jensen';
 * p.age = 101;//Happy Birthday!
 * console.log( p );
 * p.reset();
 * console.log( p );
 * p.set({name:'clark',age:102,kids:['alice','bob','charlie']});
 *
 * How would this be done without PropertySet (for comparison)?
 * //Normally would be created in a class but that is omitted here for brevity.
 * var p ={name: new Property('larry'), age: new Property('age'), kids: new Property(['alice','bob'])}
 * p.reset = function(){
 *   this.name.reset();
 *   this.age.reset();
 *   this.kids.reset();
 * }
 * p.name.set('clark');
 * p.age.set('102');
 * p.kids.set(['alice','bob','charlie']);
 *
 * Note: If a subclass ever substitutes a property like this: person.ageProperty = new Property(person.age), then it would break the getter/setter
 * @author Sam Reid
 */

define( function( require ) {
  'use strict';

  var Property = require( 'AXON/Property' );
  var DerivedProperty = require( 'AXON/DerivedProperty' );
  var Events = require( 'AXON/Events' );
  var axon = require( 'AXON/axon' );
  var inherit = require( 'PHET_CORE/inherit' );

  /**
   * @class PropertySet
   * @constructor
   * @param values an object hash with the initial values for the properties
   */
  axon.PropertySet = function PropertySet( values ) {
    var propertySet = this;

    Events.call( this );

    //Keep track of the keys so we know which to reset
    this.keys = [];

    Object.getOwnPropertyNames( values ).forEach( function( value ) {
      propertySet.addProperty( value, values[value] );
    } );

    this.eventListeners = {};
  };

  return inherit( Events, axon.PropertySet, {

    /**
     * Adds a new property to this PropertySet
     *
     * @param {String} name
     * @param value
     */
    addProperty: function( name, value ) {
      this[name + 'Property'] = new Property( value );
      this.addGetterAndSetter( name );
      this.keys.push( name );
    },

    /**
     * Remove any property (whether a derived property or not) that was added to this PropertySet
     * @param name
     */
    removeProperty: function( name ) {

      //Remove from the keys (only for non-derived properties)
      var index = this.keys.indexOf( name );
      if ( index !== -1 ) {
        this.keys.splice( index, 1 );
      }

      //Unregister the Property instance from the PropertySet
      delete this[name + 'Property'];

      //Unregister the getter/setter, if they exist
      delete this[name];
    },

    //Add a getter and setter using ES5 get/set syntax, similar to https://gist.github.com/dandean/1292057, same as in github/Atlas
    addGetterAndSetter: function( name ) {
      var property = this[name + 'Property'];

      Object.defineProperty( this, name, {

        // Getter proxies to Model#get()...
        get: function() { return property.get();},

        // Setter proxies to Model#set(attributes)
        set: function( value ) { property.set( value );},

        // Make it configurable and enumerable so it's easy to override...
        configurable: true,
        enumerable: true
      } );
    },

    addGetter: function( name ) {
      var property = this[name + 'Property'];

      Object.defineProperty( this, name, {

        get: function() { return property.get();},

        // Make it configurable and enumerable so it's easy to override...
        configurable: true,
        enumerable: true
      } );
    },

    //Resets all of the properties associated with this PropertySet
    reset: function() {
      var propertySet = this;
      this.keys.forEach( function( key ) {
        propertySet[key + 'Property'].reset();
      } );
    },

    /**
     * Creates a DerivedProperty from the given dependency names and derivation.
     * @param dependencyNames {Array<String>}
     * @param derivation {Function}
     * @returns {DerivedProperty}
     */
    toDerivedProperty: function( dependencyNames, derivation ) {
      var propertySet = this;
      var dependencies = dependencyNames.map( function( dependency ) {
        return propertySet[dependency + 'Property'];
      } );
      return new DerivedProperty( dependencies, derivation );
    },

    addDerivedProperty: function( name, dependencyNames, derivation ) {
      this[name + 'Property'] = this.toDerivedProperty( dependencyNames, derivation );
      this.addGetter( name );
    },

    /**
     * Set all of the values specified in the object hash
     * Allows you to use this form:
     * puller.set( {x: knot.x, y: knot.y, knot: knot} );
     *
     * instead of this:
     * puller.x.value = knot.x;
     * puller.y.value = knot.y;
     * puller.knot.value = knot;
     *
     * Throws an error if you try to set a value for which there is no property.
     */
    set: function( values ) {
      var propertySet = this;
      Object.getOwnPropertyNames( values ).forEach( function( val ) {
        if ( typeof(propertySet[val + 'Property'] === 'Property') ) {
          propertySet[val + 'Property'].set( values[val] );
        }
        else {
          throw new Error( 'property not found: ' + val );
        }
      } );
    },

    /**
     * Get a JS object literal with all the current values of the properties in this property set, say for serialization.  See `set`
     * TODO: this works well for numbers, strings, booleans.  How to handle complex state values such as Vector2 or nested Property?  Maybe that must be up to the client code.
     * TODO: This was named 'get' to mirror the 'set' method above, but I'm concerned this will make them difficult to find/replace and may confuse with real getters & setters.  Maybe setState/getState would be better?
     */
    get: function() {
      var state = {};
      for ( var i = 0; i < this.keys.length; i++ ) {
        var key = this.keys[i];
        state[key] = this.property( key ).value;
      }
      return state;
    },

    /**
     * Add a listener to zero or more properties in this PropertySet, useful when you have an update function
     * that relies on several properties.  Similar to DerivedProperty.
     * Discussion result: Let's use 'multilink' for now, and in the future we may change it to link.
     * @param dependencyNames {Array<String>} the list of dependencies to use
     * @param listener {Function} the listener to call back, with signature matching the dependency names
     */
    multilink: function( dependencyNames, listener ) {
      return this.toDerivedProperty( dependencyNames, listener );
    },

    /**
     * Removes the multilinked listener from this PropertySet.
     * Same as calling detach() on the handle (which happens to be a DerivedProperty instance)
     * @param derivedProperty
     */
    unmultilink: function( derivedProperty ) {
      derivedProperty.detach();
    },

    toString: function() {
      var text = 'PropertySet{';
      var propertySet = this;
      for ( var i = 0; i < this.keys.length; i++ ) {
        var key = this.keys[i];
        text = text + key + ':' + propertySet[key].toString();
        if ( i < this.keys.length - 1 ) {
          text = text + ',';
        }
      }
      return text + '}';
    },

    /**
     * Link to a property by name, see https://github.com/phetsims/axon/issues/16
     * @param {string} propertyName the name of the property to link to
     * @param {function }observer the callback to link to the property
     */
    link: function( propertyName, observer ) {
      this[propertyName + 'Property'].link( observer );
    },

    /**
     * Get a property by name, see https://github.com/phetsims/axon/issues/16
     * @param {string} propertyName the name of the property to get
     */
    property: function( propertyName ) {
      return this[propertyName + 'Property'];
    },

    /**
     * Link an attribute to a property by name
     * @param {string} propertyName the property to link to
     * @param {object} object the object for which the attribute will be set
     * @param {string} attributeName the name of the attribute to set on the object
     */
    linkAttribute: function( propertyName, object, attributeName ) {
      this.property( propertyName ).linkAttribute( object, attributeName );
    }
  } );
} );<|endoftext|>


<commit_before>import gulp from "gulp";
import cp from "child_process";
import gutil from "gulp-util";
import BrowserSync from "browser-sync";
import webpack from "webpack";
import webpackConfig from "./webpack.conf";

const browserSync = BrowserSync.create();
const hugoBin = "hugo";
const defaultArgs = ["-d", "../dist", "-s", "site", "-v"];

gulp.task("hugo", (cb) => buildSite(cb));
gulp.task("hugo-preview", (cb) => buildSite(cb, ["--buildDrafts", "--buildFuture"]));

gulp.task("build", ["js", "hugo"]);
gulp.task("build-preview", ["js", "hugo-preview"]);

gulp.task("js", (cb) => {
  const myConfig = Object.assign({}, webpackConfig);

  webpack(myConfig, (err, stats) => {
    if (err) throw new gutil.PluginError("webpack", err);
    gutil.log("[webpack]", stats.toString({
      colors: true,
      progress: true
    }));
    browserSync.reload();
    cb();
  });
});

gulp.task("server", ["hugo", "js"], () => {
  browserSync.init({
    server: {
      baseDir: "./dist"
    }
  });
  gulp.watch("./src/js/**/*.js", ["js"]);
  gulp.watch("./site/**/*", ["hugo"]);
});

function buildSite(cb, options) {
  const args = options ? defaultArgs.concat(options) : defaultArgs;

  return cp.spawn(hugoBin, args, {stdio: "inherit"}).on("close", (code) => {
    if (code === 0) {
      browserSync.reload();
      cb();
    } else {
      browserSync.notify("Hugo build failed :(");
      cb("Hugo build failed");
    }
  });
}
<commit_msg>Simplify hugo build and improve output<commit_after>import gulp from "gulp";
import cp from "child_process";
import gutil from "gulp-util";
import BrowserSync from "browser-sync";
import webpack from "webpack";
import webpackConfig from "./webpack.conf";

const browserSync = BrowserSync.create();

gulp.task("hugo", (cb) => buildSite(cb));
gulp.task("hugo-preview", (cb) => buildSite(cb, "--buildDrafts --buildFuture"));

gulp.task("build", ["js", "hugo"]);
gulp.task("build-preview", ["js", "hugo-preview"]);

gulp.task("js", (cb) => {
  const myConfig = Object.assign({}, webpackConfig);

  webpack(myConfig, (err, stats) => {
    if (err) throw new gutil.PluginError("webpack", err);
    gutil.log("Webpack output:");
    gutil.log(stats.toString({
      colors: true,
      progress: true
    }));
    browserSync.reload();
    cb();
  });
});

gulp.task("server", ["hugo", "js"], () => {
  browserSync.init({
    server: {
      baseDir: "./dist"
    }
  });
  gulp.watch("./src/js/**/*.js", ["js"]);
  gulp.watch("./site/**/*", ["hugo"]);
});

function buildSite(cb, extraArgs) {
  const command = `hugo -d ../dist -s site -b http://localhost:3001 --cleanDestinationDir ${extraArgs || ""}`.trim();
  gutil.log("COMMAND", command);

  return cp.exec(command, (err, stdin, stderr) => {
    if (err) {
      browserSync.notify("Hugo build failed :(");
      gutil.log("Hugo output:");
      gutil.log(stdin);
      gutil.log(stderr);
      cb();
    } else {
      browserSync.reload();
      cb();
    }
  });
}
<|endoftext|>


<commit_before>CKEDITOR.editorConfig = function( config ) {
    // Url para upload
    config.filebrowserImageUploadUrl = "/ckeditor/pictures";

    // Para resolver o problema do token perdido após o upload
    var csrf_token = $('meta[name=csrf-token]').attr('content'),
        csrf_param = $('meta[name=csrf-param]').attr('content');

    if (csrf_param !== undefined && csrf_token !== undefined) {
        config.filebrowserImageUploadUrl += "?" + csrf_param + "=" + encodeURIComponent(csrf_token)
    }

    // Todo: cogitar outra maneira que nao envolvar remover botoes desnecessarios do insert
    config.removeButtons = 'Flash,HorizontalRule,Smiley,SpecialChar,PageBreak,Iframe';

    config.toolbarGroups = [
        { name: 'clipboard',   groups: [ 'clipboard', 'undo' ] },
        { name: 'editing',     groups: [ 'find', 'selection', 'spellchecker' ] },
        { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
        { name: 'paragraph',   groups: [ 'list', 'indent', 'blocks', 'align' ] },
        { name: 'styles' },
        { name: 'tools' },
        { name: 'insert' },
    ];

    config.extraPlugins = 'citacao';
    config.allowedContent = true;

    config.toolbar_mini = [
        ['Bold', 'Italic', 'Underline', 'Subscript', 'Superscript', '-', 'RemoveFormat'],
        ['Maximize']
    ];

    config.toolbar_readonly = [
        ['Find', 'Maximize']
    ];

    config.language = 'pt-br';
};
<commit_msg>Configurações da barra de botões do editor<commit_after>CKEDITOR.editorConfig = function(config) {
    // Url para upload
    config.filebrowserImageUploadUrl = "/ckeditor/pictures";

    // Para resolver o problema do token perdido após o upload
    var csrf_token = $('meta[name=csrf-token]').attr('content'),
        csrf_param = $('meta[name=csrf-param]').attr('content');

    if (csrf_param !== undefined && csrf_token !== undefined) {
        config.filebrowserImageUploadUrl += "?" + csrf_param + "=" + encodeURIComponent(csrf_token)
    }

    // Plugin de Citacao
    config.extraPlugins = 'citacao';
    config.allowedContent = true;

    // Configuracao de auto-resize
    config.autoGrow_maxHeight = 600;

    // Configuracao do Colar do Word
    config.pasteFromWordNumberedHeadingToList = true;
    config.pasteFromWordPromptCleanup = true;
    config.pasteFromWordRemoveFontStyles = true;
    config.pasteFromWordRemoveStyles = true;

    // Remover botoes que nao vao ser utilizados
    config.removeButtons = 'Flash,HorizontalRule,Smiley,SpecialChar,PageBreak,Iframe,CreateDiv,Styles,Font,FontSize';

    config.toolbarGroups = [
        { name: 'styles' },
        { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
        { name: 'paragraph',   groups: [ 'list', 'indent', 'blocks', 'align' ] },
        { name: 'insert' },
        '/',
        { name: 'clipboard',   groups: [ 'clipboard', 'undo' ] },
        { name: 'editing',     groups: [ 'find', 'selection', 'spellchecker' ] },
        { name: 'tools' },
    ];

    config.toolbar_mini = [
        ['Bold', 'Italic', 'Underline', 'Subscript', 'Superscript', '-', 'RemoveFormat'],
        ['Maximize']
    ];

    config.toolbar_readonly = [
        ['Find', 'Maximize']
    ];

    config.language = 'pt-br';
};
<|endoftext|>


<commit_before>'use strict';

/*@ngInject*/
function TreeChooser($timeout) {
  require('./treeChooser.css');

  var angular = require('angular');

  return {
    bindToController: true,
    controller: 'treeChooserController',
    controllerAs: 'vm',
    require: ['ngModel'],
    scope: {
      /**
       * Tree data structure
       * @type {Array.<Object>}
       */
      treeData: '=treeChooser',

      /**
       * Property that contains unique ID
       * @type {string}
       */
      idProperty: '@',

      /**
       * Property that contains label
       * @todo alternately support template
       * @type {string}
       */
      labelProperty: '@',

      /**
       * Property that contains children array
       * @type {string}
       */
      childrenProperty: '@',

      /**
       * Deselect all descendants
       * @type {boolean}
       */
      deselectsChildren: '=?',

      /**
       * Function to determine if item is disabled
       * @type {Function}
       */
      disableNode: '=?',

      /**
       * Function to determine if item is filtered
       * @type {Function}
       */
      filterNode: '=?',

      /**
       * Show list and expand all nodes after specified length
       * @type {number}
       */
      filterAutoShowLength: '=?',

      /**
       * Enable multiselection
       * @type {boolean}
       */
      multiselect: '=?',

      /**
       * ngDisabled pass through
       * @type {boolean}
       */
      ngDisabled: '=?',

      /**
       * ngPlaceholder pass through
       * @type {boolean}
       */
      ngPlaceholder: '=?',

      /**
       * Only allow selection of leaf nodes
       * @type {boolean}
       */
      onlyLeaves: '=?',

      /**
       * Restrict model to members of tree data structure
       * @type {boolean}
       */
      restrictModel: '=?',

      /**
       * Select all descendants
       * @type {boolean}
       */
      selectsChildren: '=?',

      /**
       * Enable pills
       * @type {boolean}
       */
      enablePills: '=?',

      /**
       * Just use the ID as the model value?
       * @type {boolean}
       */
      modelAsId: '=?'
    },
    template: require('./treeChooser.html'),
    link: function (scope, element) {
      // @todo clean up query selectors to not rely on classes
      var input = angular.element(element[0].querySelector('.treeChooser-input input'));
      input.on('click', function (event) {
        event.stopPropagation();
      });
      var list = angular.element(element[0].querySelector('.treeChooser-list'));
      list.on('click', function (event) {
        event.stopPropagation();
      });
      scope.focusInput = function () {
        $timeout(function () {
          input[0].focus();
        });
      };
      scope.focusList = function () {
        $timeout(function () {
          list[0].focus();
        });
      };

      scope.getListStyles = function () {
        return {
          top: input[0].parentNode.offsetHeight + 'px',
          width: input[0].parentNode.offsetWidth + 'px'
        };
      };

      scope.scrollActive = function () {
        $timeout(function () {
          var active = element[0].querySelector('.treeChooser-active');
          list[0].scrollTop = active.offsetTop - 12; // @todo this should be about font size
        });
      };
    }
  };
}

module.exports = TreeChooser;
<commit_msg>Remove hardcoded offset for active scroll<commit_after>'use strict';

/*@ngInject*/
function TreeChooser($timeout) {
  require('./treeChooser.css');

  var angular = require('angular');

  return {
    bindToController: true,
    controller: 'treeChooserController',
    controllerAs: 'vm',
    require: ['ngModel'],
    scope: {
      /**
       * Tree data structure
       * @type {Array.<Object>}
       */
      treeData: '=treeChooser',

      /**
       * Property that contains unique ID
       * @type {string}
       */
      idProperty: '@',

      /**
       * Property that contains label
       * @todo alternately support template
       * @type {string}
       */
      labelProperty: '@',

      /**
       * Property that contains children array
       * @type {string}
       */
      childrenProperty: '@',

      /**
       * Deselect all descendants
       * @type {boolean}
       */
      deselectsChildren: '=?',

      /**
       * Function to determine if item is disabled
       * @type {Function}
       */
      disableNode: '=?',

      /**
       * Function to determine if item is filtered
       * @type {Function}
       */
      filterNode: '=?',

      /**
       * Show list and expand all nodes after specified length
       * @type {number}
       */
      filterAutoShowLength: '=?',

      /**
       * Enable multiselection
       * @type {boolean}
       */
      multiselect: '=?',

      /**
       * ngDisabled pass through
       * @type {boolean}
       */
      ngDisabled: '=?',

      /**
       * ngPlaceholder pass through
       * @type {boolean}
       */
      ngPlaceholder: '=?',

      /**
       * Only allow selection of leaf nodes
       * @type {boolean}
       */
      onlyLeaves: '=?',

      /**
       * Restrict model to members of tree data structure
       * @type {boolean}
       */
      restrictModel: '=?',

      /**
       * Select all descendants
       * @type {boolean}
       */
      selectsChildren: '=?',

      /**
       * Enable pills
       * @type {boolean}
       */
      enablePills: '=?',

      /**
       * Just use the ID as the model value?
       * @type {boolean}
       */
      modelAsId: '=?'
    },
    template: require('./treeChooser.html'),
    link: function (scope, element) {
      // @todo clean up query selectors to not rely on classes
      var input = angular.element(element[0].querySelector('.treeChooser-input input'));
      input.on('click', function (event) {
        event.stopPropagation();
      });
      var list = angular.element(element[0].querySelector('.treeChooser-list'));
      list.on('click', function (event) {
        event.stopPropagation();
      });
      scope.focusInput = function () {
        $timeout(function () {
          input[0].focus();
        });
      };
      scope.focusList = function () {
        $timeout(function () {
          list[0].focus();
        });
      };

      scope.getListStyles = function () {
        return {
          top: input[0].parentNode.offsetHeight + 'px',
          width: input[0].parentNode.offsetWidth + 'px'
        };
      };

      scope.scrollActive = function () {
        $timeout(function () {
          var active = element[0].querySelector('.treeChooser-active .treeChooser-label');
          list[0].scrollTop = active.offsetTop;
        });
      };
    }
  };
}

module.exports = TreeChooser;
<|endoftext|>


<commit_before>import {READ_BREWSESSION_STARTED, READ_BREWSESSION_SUCCEEDED, READ_BREWSESSION_FAILED,
        BREWSESSION_STARTSTOP_STARTED, BREWSESSION_STARTSTOP_SUCCEEDED, BREWSESSION_STARTSTOP_FAILED,
        READ_BREWSESSION_DATA_STARTED, READ_BREWSESSION_DATA_SUCCEEDED, READ_BREWSESSION_DATA_FAILED,
        UPDATE_BREWSESSIONSTATUS_FIELD} from '../constants/actionTypes';
import objectAssign from 'object-assign';
import initialState from './initialState';

export default function brewSessionStatusReducer(state = initialState.brewSessionStatus, action) {
  let newState;

  switch (action.type) {
      case READ_BREWSESSION_STARTED:
        return state;

      case READ_BREWSESSION_SUCCEEDED:
        newState = objectAssign({}, state);
        newState.isBrewSessionRunning = action.status.isBrewSessionRunning;
        if (newState.isBrewSessionRunning) {
          newState.sessionName = action.status.sessionName;
          newState.mashTemp = action.status.mashTemp;
          newState.mashHoldTime = action.status.mashHoldTime;
        }

        return newState;

      case READ_BREWSESSION_FAILED:
        newState = objectAssign({}, state);
        newState.isBrewSessionRunning = false;
        // TODO: set some kind of error message to return and show
        return newState;

      case BREWSESSION_STARTSTOP_STARTED:
        return state;

      case BREWSESSION_STARTSTOP_SUCCEEDED:
        // newState = objectAssign({}, state);
        // if (action.status.action == 'start') {
        //   newState.isBrewSessionRunning = false;
        // }
        // else {
        //   newState.isBrewSessionRunning = true;
        // }
        // return newState;

        // We're already updating the status on a timer anyway.
        // Not sure we need to do anything here.
        return state;

      case BREWSESSION_STARTSTOP_FAILED:
        // TODO: set some kind of error message to return and show
        console.log('BREWSESSION_STARTSTOP_FAILED ERROR');
        return state;

      case READ_BREWSESSION_DATA_STARTED:
        return state;

      case READ_BREWSESSION_DATA_SUCCEEDED:
        newState = objectAssign({}, state);
        newState.data = action.data;
        console.log(newState.data);
        return newState;

        case READ_BREWSESSION_DATA_FAILED:
          // TODO: set some kind of error message to return and show
          console.log('READ_BREWSESSION_DATA_FAILED ERROR');
          return state;

        case UPDATE_BREWSESSIONSTATUS_FIELD:
          newState = objectAssign({}, state);
          newState[action.fieldName] = action.value;
          return newState;

    default:
      return state;
  }

}<commit_msg>round temp for display.<commit_after>import {READ_BREWSESSION_STARTED, READ_BREWSESSION_SUCCEEDED, READ_BREWSESSION_FAILED,
        BREWSESSION_STARTSTOP_STARTED, BREWSESSION_STARTSTOP_SUCCEEDED, BREWSESSION_STARTSTOP_FAILED,
        READ_BREWSESSION_DATA_STARTED, READ_BREWSESSION_DATA_SUCCEEDED, READ_BREWSESSION_DATA_FAILED,
        UPDATE_BREWSESSIONSTATUS_FIELD} from '../constants/actionTypes';
import objectAssign from 'object-assign';
import initialState from './initialState';

export default function brewSessionStatusReducer(state = initialState.brewSessionStatus, action) {
  let newState;

  switch (action.type) {
      case READ_BREWSESSION_STARTED:
        return state;

      case READ_BREWSESSION_SUCCEEDED:
        newState = objectAssign({}, state);
        newState.isBrewSessionRunning = action.status.isBrewSessionRunning;
        if (newState.isBrewSessionRunning) {
          newState.sessionName = action.status.sessionName;
          newState.mashTemp = Math.round(Number(action.status.mashTemp * 9/5 + 32).toFixed(2));
          newState.mashHoldTime = action.status.mashHoldTime;
        }

        return newState;

      case READ_BREWSESSION_FAILED:
        newState = objectAssign({}, state);
        newState.isBrewSessionRunning = false;
        // TODO: set some kind of error message to return and show
        return newState;

      case BREWSESSION_STARTSTOP_STARTED:
        return state;

      case BREWSESSION_STARTSTOP_SUCCEEDED:
        // newState = objectAssign({}, state);
        // if (action.status.action == 'start') {
        //   newState.isBrewSessionRunning = false;
        // }
        // else {
        //   newState.isBrewSessionRunning = true;
        // }
        // return newState;

        // We're already updating the status on a timer anyway.
        // Not sure we need to do anything here.
        return state;

      case BREWSESSION_STARTSTOP_FAILED:
        // TODO: set some kind of error message to return and show
        console.log('BREWSESSION_STARTSTOP_FAILED ERROR');
        return state;

      case READ_BREWSESSION_DATA_STARTED:
        return state;

      case READ_BREWSESSION_DATA_SUCCEEDED:
        newState = objectAssign({}, state);
        newState.data = action.data;
        console.log(newState.data);
        return newState;

        case READ_BREWSESSION_DATA_FAILED:
          // TODO: set some kind of error message to return and show
          console.log('READ_BREWSESSION_DATA_FAILED ERROR');
          return state;

        case UPDATE_BREWSESSIONSTATUS_FIELD:
          newState = objectAssign({}, state);
          newState[action.fieldName] = action.value;
          return newState;

    default:
      return state;
  }

}<|endoftext|>


<commit_before>/**
 * Wait before the DOM has been loaded before initializing the Ubuntu UI layer
 */
function getKB(a) {
 return (a * 1000) / 1024;
}

function getMB(a) {
 return (a * Math.pow(1000, 2)) / Math.pow(1024, 2);
}

function getGB(a) {
 return (a * Math.pow(1000, 3)) / Math.pow(1024, 3);
}

function getTB(a) {
 return (a * Math.pow(1000, 4)) / Math.pow(1024, 4);
}

function getPB(a) {
 return (a * Math.pow(1000, 5)) / Math.pow(1024, 5);
}

function getEB(a) {
 return (a * Math.pow(1000, 6)) / Math.pow(1024, 6);
}

function getZB(a) {
 return (a * Math.pow(1000, 7)) / Math.pow(1024, 7);
}

function getYB(a) {
 return (a * Math.pow(1000, 8)) / Math.pow(1024, 8);
}

jQuery(document).ready(function () {
    var UI = new UbuntuUI();
    UI.init();

    UI.button('calc').click(function (event) {
       event.preventDefault();
       var size = jQuery('#size').val(), denomination = jQuery('#denominations option:selected').text();

        if (denomination === 'KB') {
            jQuery('#result').val(getKB(size));
        } else if (denomination === 'MB') {
            jQuery('#result').val(getMB(size));
        } else if (denomination === 'GB') {
            jQuery('#result').val(getGB(size));
        } else if (denomination === 'TB') {
            jQuery('#result').val(getTB(size));
        } else if (denomination === 'PB') {
            jQuery('#result').val(getPB(size));
        } else if (denomination === 'EB') {
            jQuery('#result').val(getEB(size));
        } else if (denomination === 'ZB') {
            jQuery('#result').val(getZB(size));
        } else if (denomination === 'YB') {
            jQuery('#result').val(getYB(size));
        }
    });
});
<commit_msg>have calculations rounded to two places.<commit_after>/**
 * Wait before the DOM has been loaded before initializing the Ubuntu UI layer
 */
function getKB(a) {
 return (a * 1000) / 1024;
}

function getMB(a) {
 return (a * Math.pow(1000, 2)) / Math.pow(1024, 2);
}

function getGB(a) {
 return (a * Math.pow(1000, 3)) / Math.pow(1024, 3);
}

function getTB(a) {
 return (a * Math.pow(1000, 4)) / Math.pow(1024, 4);
}

function getPB(a) {
 return (a * Math.pow(1000, 5)) / Math.pow(1024, 5);
}

function getEB(a) {
 return (a * Math.pow(1000, 6)) / Math.pow(1024, 6);
}

function getZB(a) {
 return (a * Math.pow(1000, 7)) / Math.pow(1024, 7);
}

function getYB(a) {
 return (a * Math.pow(1000, 8)) / Math.pow(1024, 8);
}

jQuery(document).ready(function () {
    var UI = new UbuntuUI();
    UI.init();

    UI.button('calc').click(function (event) {
       event.preventDefault();
       var size = jQuery('#size').val(), denomination = jQuery('#denominations option:selected').text();

        if (denomination === 'KB') {
            jQuery('#result').val(getKB(size).toFixed(2));
        } else if (denomination === 'MB') {
            jQuery('#result').val(getMB(size).toFixed(2));
        } else if (denomination === 'GB') {
            jQuery('#result').val(getGB(size).toFixed(2));
        } else if (denomination === 'TB') {
            jQuery('#result').val(getTB(size).toFixed(2));
        } else if (denomination === 'PB') {
            jQuery('#result').val(getPB(size).toFixed(2));
        } else if (denomination === 'EB') {
            jQuery('#result').val(getEB(size).toFixed(2));
        } else if (denomination === 'ZB') {
            jQuery('#result').val(getZB(size).toFixed(2));
        } else if (denomination === 'YB') {
            jQuery('#result').val(getYB(size).toFixed(2));
        }
    });
});
<|endoftext|>


<commit_before>// Copyright 2013-2020, University of Colorado Boulder
/**
 * Singleton which launches a PhET Simulation, after preloading resources such as images or dynamic modules.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */

import Random from '../../dot/js/Random.js';
import arrayRemove from '../../phet-core/js/arrayRemove.js';
import Tandem from '../../tandem/js/Tandem.js';
import checkNamespaces from './checkNamespaces.js';
import joist from './joist.js';

// See below for dynamic imports, which must be locked.
let phetioEngine = null; // {null|PhetioEngine}

// Dynamic imports must be started after SimLauncher is ready to process locks
const initializeDynamicImports = () => {

  const unlockBrand = SimLauncher.createLock( { name: 'brand' } );
  import( /* webpackMode: "eager" */ `../../brand/${phet.chipper.brand}/js/Brand.js`).then( module => unlockBrand() );

  if ( Tandem.PHET_IO_ENABLED ) {
    const unlockPhetioEngine = SimLauncher.createLock( { name: 'phetioEngine' } );
    import( /* webpackMode: "eager" */ '../../phet-io/js/phetioEngine.js').then( module => {
      phetioEngine = module.default;
      unlockPhetioEngine();
    } );
  }
};

const SimLauncher = {

  // @private - Locks waiting to be resolved before we can move to the next phase of the launch sequence
  pendingLocks: [],

  // @private - Marked as true when there are no more locks and we try to proceed.  Helps protect against new locks being created after they should be.
  launchBegan: false,

  // @private - Marked as true when SimLauncher has finished its work cycle and control is given over to the simulation to finish initialization.
  launchComplete: false,

  // @private - {function} The callback which should be invoked on launch.
  callback: null,

  /**
   * Launch the Sim by preloading the images and calling the callback.
   *
   * @param callback the callback function which should create and start the sim, given that the images are loaded
   * @public - to be called by main()s everywhere
   */
  launch: function( callback ) {
    assert && assert( !window.phet.launchCalled, 'Tried to launch twice' );

    this.callback = callback;

    //Signify that the SimLauncher was called, see https://github.com/phetsims/joist/issues/142
    window.phet.joist.launchCalled = true;

    // Check namespaces if assertions are enabled, see https://github.com/phetsims/joist/issues/307.
    assert && checkNamespaces();
  },

  proceedIfReady: function() {

    assert && assert( !this.launchComplete, 'cannot proceed if already launched' );

    if ( this.pendingLocks.length === 0 ) {

      this.launchBegan = true;

      window.phet.joist.launchSimulation = () => {

        // once launchSimulation has been called, the wrapper is ready to receive messages because any listeners it
        // wants have been set up by now.
        if ( Tandem.PHET_IO_ENABLED ) {
          phetioEngine.onCrossFrameListenersReady();
        }

        // Provide a global Random that is easy to use and seedable from phet-io for playback
        // phet-io configuration happens after SimLauncher.launch is called and before phet.joist.launchSimulation is called
        phet.joist.random = new Random( { staticSeed: true } );

        // Instantiate the sim and show it.
        this.callback();
      };

      // PhET-iO simulations support an initialization phase (before the sim launches)
      if ( Tandem.PHET_IO_ENABLED ) {
        phetioEngine.initialize(); // calls back to window.phet.joist.launchSimulation
      }

      if ( phet.chipper.queryParameters.postMessageOnReady ) {
        window.parent && window.parent.postMessage( JSON.stringify( {
          type: 'ready',
          url: window.location.href
        } ), '*' );
      }

      if ( ( Tandem.PHET_IO_ENABLED && !phet.preloads.phetio.queryParameters.phetioStandalone ) ||
           phet.chipper.queryParameters.playbackMode ) {

        // Wait for phet-io to finish adding listeners. It will direct the launch from there.
      }
      else {
        this.launchComplete = true;
        window.phet.joist.launchSimulation();
      }
    }
  },

  /**
   * Creates a lock, which returns a callback that needs to be run before the launch sequence will continue to the
   * next phase.
   * @public
   *
   * @returns {function}
   */
  createLock( object ) {
    assert && assert( !this.launchBegan, 'Cannot create more locks after launch began' );
    this.pendingLocks.push( object );
    return () => {
      assert && assert( this.pendingLocks.indexOf( object ) >= 0, 'invalid lock' );
      arrayRemove( this.pendingLocks, object );
      this.proceedIfReady();
    };
  }
};

// Dynamic imports must be started after SimLauncher is ready to process locks
initializeDynamicImports();

joist.register( 'SimLauncher', SimLauncher );

export default SimLauncher;<commit_msg>Allow images to be loaded in qunit tests, see https://github.com/phetsims/tasks/issues/1035<commit_after>// Copyright 2013-2020, University of Colorado Boulder
/**
 * Singleton which launches a PhET Simulation, after preloading resources such as images or dynamic modules.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */

import Random from '../../dot/js/Random.js';
import arrayRemove from '../../phet-core/js/arrayRemove.js';
import Tandem from '../../tandem/js/Tandem.js';
import checkNamespaces from './checkNamespaces.js';
import joist from './joist.js';

// See below for dynamic imports, which must be locked.
let phetioEngine = null; // {null|PhetioEngine}

// Dynamic imports must be started after SimLauncher is ready to process locks
const initializeDynamicImports = () => {

  const unlockBrand = SimLauncher.createLock( { name: 'brand' } );
  import( /* webpackMode: "eager" */ `../../brand/${phet.chipper.brand}/js/Brand.js`).then( module => unlockBrand() );

  if ( Tandem.PHET_IO_ENABLED ) {
    const unlockPhetioEngine = SimLauncher.createLock( { name: 'phetioEngine' } );
    import( /* webpackMode: "eager" */ '../../phet-io/js/phetioEngine.js').then( module => {
      phetioEngine = module.default;
      unlockPhetioEngine();
    } );
  }
};

const SimLauncher = {

  // @private - Locks waiting to be resolved before we can move to the next phase of the launch sequence
  pendingLocks: [],

  // @private - Marked as true when there are no more locks and we try to proceed.  Helps protect against new locks being created after they should be.
  launchBegan: false,

  // @private - Marked as true when SimLauncher has finished its work cycle and control is given over to the simulation to finish initialization.
  launchComplete: false,

  // @private - {function} The callback which should be invoked on launch.
  callback: null,

  /**
   * Launch the Sim by preloading the images and calling the callback.
   *
   * @param callback the callback function which should create and start the sim, given that the images are loaded
   * @public - to be called by main()s everywhere
   */
  launch: function( callback ) {
    assert && assert( !window.phet.launchCalled, 'Tried to launch twice' );

    this.callback = callback;

    //Signify that the SimLauncher was called, see https://github.com/phetsims/joist/issues/142
    window.phet.joist.launchCalled = true;

    // Check namespaces if assertions are enabled, see https://github.com/phetsims/joist/issues/307.
    assert && checkNamespaces();
  },

  proceedIfReady: function() {

    assert && assert( !this.launchComplete, 'cannot proceed if already launched' );

    if ( this.pendingLocks.length === 0 && this.callback ) {

      this.launchBegan = true;

      window.phet.joist.launchSimulation = () => {

        // once launchSimulation has been called, the wrapper is ready to receive messages because any listeners it
        // wants have been set up by now.
        if ( Tandem.PHET_IO_ENABLED ) {
          phetioEngine.onCrossFrameListenersReady();
        }

        // Provide a global Random that is easy to use and seedable from phet-io for playback
        // phet-io configuration happens after SimLauncher.launch is called and before phet.joist.launchSimulation is called
        phet.joist.random = new Random( { staticSeed: true } );

        // Instantiate the sim and show it.
        this.callback();
      };

      // PhET-iO simulations support an initialization phase (before the sim launches)
      if ( Tandem.PHET_IO_ENABLED ) {
        phetioEngine.initialize(); // calls back to window.phet.joist.launchSimulation
      }

      if ( phet.chipper.queryParameters.postMessageOnReady ) {
        window.parent && window.parent.postMessage( JSON.stringify( {
          type: 'ready',
          url: window.location.href
        } ), '*' );
      }

      if ( ( Tandem.PHET_IO_ENABLED && !phet.preloads.phetio.queryParameters.phetioStandalone ) ||
           phet.chipper.queryParameters.playbackMode ) {

        // Wait for phet-io to finish adding listeners. It will direct the launch from there.
      }
      else {
        this.launchComplete = true;
        window.phet.joist.launchSimulation();
      }
    }
  },

  /**
   * Creates a lock, which returns a callback that needs to be run before the launch sequence will continue to the
   * next phase.
   * @public
   *
   * @returns {function}
   */
  createLock( object ) {
    assert && assert( !this.launchBegan, 'Cannot create more locks after launch began' );
    this.pendingLocks.push( object );
    return () => {
      assert && assert( this.pendingLocks.indexOf( object ) >= 0, 'invalid lock' );
      arrayRemove( this.pendingLocks, object );
      this.proceedIfReady();
    };
  }
};

// Dynamic imports must be started after SimLauncher is ready to process locks
initializeDynamicImports();

joist.register( 'SimLauncher', SimLauncher );

export default SimLauncher;<|endoftext|>


<commit_before>import browserify from 'browserify';
import connect from 'gulp-connect';
import gulp from 'gulp';
import path from 'path';
import stylus from 'gulp-stylus';
import uglify from 'gulp-uglify';
import source from 'vinyl-source-stream';
import deploy from 'gulp-gh-pages';
import babelify from "babelify";
import buffer from 'vinyl-buffer';
import gulpif from 'gulp-if';

const DEBUG = (process.env.NODE_ENV === 'development');

const vendorModules = [
  'react', 'react-dom', 'redux', 'react-redux', 'immutable'
];

gulp.task('build', [
  'stylus', 'assets', 'browserify-vendor', 'browserify-app'
]);

gulp.task('browserify-vendor', () => {
  return commonBrowserify('vendor.js', browserify({
    debug: DEBUG
  }).require(vendorModules));
});

gulp.task('browserify-app', () => {
  return commonBrowserify('index.js', browserify({
    entries: ['./src/index.js'],
    debug: DEBUG,
    fullPaths: true
  }).external(vendorModules));
});

function commonBrowserify(sourceName, b) {
  return b
    .transform("babelify", {presets: ["es2015", "react"]})
    .bundle()
    .pipe(source(sourceName))
    .pipe(buffer())
    .pipe(gulpif(!DEBUG, uglify()))
    .pipe(gulp.dest('./dist'))
    .pipe(connect.reload());
}

gulp.task('stylus', () => {
  return gulp.src('./src/**/*.styl')
    .pipe(stylus())
    .pipe(gulp.dest('./dist'))
    .pipe(connect.reload());
});

gulp.task('assets', () => {
  return gulp.src([
      './src/manifest.webapp',
      './src/**/*.png',
      './src/**/*.html'
    ])
    .pipe(gulp.dest('./dist'))
    .pipe(connect.reload());
});

gulp.task('connect', () => {
  connect.server({
    root: 'dist',
    livereload: true,
    port: 3001
  });
});

gulp.task('watch', () => {
  gulp.watch('./src/**/*', ['browserify-app', 'stylus', 'assets']);
  gulp.watch('./package.json', ['browserify-vendor']);
});

gulp.task('deploy', () => {
  gulp.src('./dist/**/*')
    .pipe(deploy({}));
});

gulp.task('server', ['build', 'connect', 'watch']);

gulp.task('default', ['server']);
<commit_msg>Only browserify with fullPaths while in DEBUG mode<commit_after>import browserify from 'browserify';
import connect from 'gulp-connect';
import gulp from 'gulp';
import path from 'path';
import stylus from 'gulp-stylus';
import uglify from 'gulp-uglify';
import source from 'vinyl-source-stream';
import deploy from 'gulp-gh-pages';
import babelify from "babelify";
import buffer from 'vinyl-buffer';
import gulpif from 'gulp-if';

const DEBUG = (process.env.NODE_ENV === 'development');

const vendorModules = [
  'react', 'react-dom', 'redux', 'react-redux', 'immutable'
];

gulp.task('build', [
  'stylus', 'assets', 'browserify-vendor', 'browserify-app'
]);

gulp.task('browserify-vendor', () => {
  return commonBrowserify('vendor.js', browserify({
    debug: DEBUG
  }).require(vendorModules));
});

gulp.task('browserify-app', () => {
  return commonBrowserify('index.js', browserify({
    entries: ['./src/index.js'],
    debug: DEBUG,
    fullPaths: DEBUG
  }).external(vendorModules));
});

function commonBrowserify(sourceName, b) {
  return b
    .transform("babelify", {presets: ["es2015", "react"]})
    .bundle()
    .pipe(source(sourceName))
    .pipe(buffer())
    .pipe(gulpif(!DEBUG, uglify()))
    .pipe(gulp.dest('./dist'))
    .pipe(connect.reload());
}

gulp.task('stylus', () => {
  return gulp.src('./src/**/*.styl')
    .pipe(stylus())
    .pipe(gulp.dest('./dist'))
    .pipe(connect.reload());
});

gulp.task('assets', () => {
  return gulp.src([
      './src/manifest.webapp',
      './src/**/*.png',
      './src/**/*.html'
    ])
    .pipe(gulp.dest('./dist'))
    .pipe(connect.reload());
});

gulp.task('connect', () => {
  connect.server({
    root: 'dist',
    livereload: true,
    port: 3001
  });
});

gulp.task('watch', () => {
  gulp.watch('./src/**/*', ['browserify-app', 'stylus', 'assets']);
  gulp.watch('./package.json', ['browserify-vendor']);
});

gulp.task('deploy', () => {
  gulp.src('./dist/**/*')
    .pipe(deploy({}));
});

gulp.task('server', ['build', 'connect', 'watch']);

gulp.task('default', ['server']);
<|endoftext|>