<commit_before>/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

'use strict';

var net = require('net');
var EE = require('events').EventEmitter;
var util = require('util');
var childProcess = require('child_process');
var bser = require('bser');

// We'll emit the responses to these when they get sent down to us
var unilateralTags = ['subscription', 'log'];

/**
 * @param options An object with the following optional keys:
 *   * 'watchmanBinaryPath' (string) Absolute path to the watchman binary.
 *     If not provided, the Client locates the binary using the PATH specified
 *     by the node child_process's default env.
 */
function Client(options) {
  var self = this;
  EE.call(this);

  this.watchmanBinaryPath = 'watchman';
  if (options && options.watchmanBinaryPath) {
    this.watchmanBinaryPath = options.watchmanBinaryPath.trim();
  };
  this.commands = [];
}
util.inherits(Client, EE);

module.exports.Client = Client;

// Try to send the next queued command, if any
Client.prototype.sendNextCommand = function() {
  if (this.currentCommand) {
    // There's a command pending response, don't send this new one yet
    return;
  }

  this.currentCommand = this.commands.shift();
  if (!this.currentCommand) {
    // No further commands are queued
    return;
  }

  this.socket.write(bser.dumpToBuffer(this.currentCommand.cmd));
}

Client.prototype.cancelCommands = function(why) {
  var error = new Error(why);

  // Steal all pending commands before we start cancellation, in
  // case something decides to schedule more commands
  var cmds = this.commands;
  this.commands = [];

  if (this.currentCommand) {
    cmds.unshift(this.currentCommand);
    this.currentCommand = null;
  }

  // Synthesize an error condition for any commands that were queued
  cmds.forEach(function(cmd) {
    cmd.cb(error);
  });
}

Client.prototype.connect = function() {
  var self = this;

  function makeSock(sockname) {
    // bunser will decode the watchman BSER protocol for us
    self.bunser = new bser.BunserBuf();
    // For each decoded line:
    self.bunser.on('value', function(obj) {
      // Figure out if this is a unliteral response or if it is the
      // response portion of a request-response sequence.  At the time
      // of writing, there are only two possible unilateral responses.
      var unilateral = false;
      for (var i = 0; i < unilateralTags.length; i++) {
        var tag = unilateralTags[i];
        if (tag in obj) {
          unilateral = tag;
        }
      }

      if (unilateral) {
        self.emit(unilateral, obj);
      } else if (self.currentCommand) {
        var cmd = self.currentCommand;
        self.currentCommand = null;
        if ('error' in obj) {
          var error = new Error(obj.error);
          error.watchmanResponse = obj;
          cmd.cb(error);
        } else {
          cmd.cb(null, obj);
        }
      }

      // See if we can dispatch the next queued command, if any
      self.sendNextCommand();
    });
    self.bunser.on('error', function(err) {
      self.emit('error', err);
    });

    self.socket = net.createConnection(sockname);
    self.socket.on('connect', function() {
      self.connecting = false;
      self.emit('connect');
      self.sendNextCommand();
    });
    self.socket.on('error', function(err) {
      self.connecting = false;
      self.emit('error', err);
    });
    self.socket.on('data', function(buf) {
      if (self.bunser) {
        self.bunser.append(buf);
      }
    });
    self.socket.on('end', function() {
      self.socket = null;
      self.bunser = null;
      self.cancelCommands('The watchman connection was closed');
      self.emit('end');
    });
  }

  // triggers will export the sock path to the environment.
  // If we're invoked in such a way, we can simply pick up the
  // definition from the environment and avoid having to fork off
  // a process to figure it out
  if (process.env.WATCHMAN_SOCK) {
    makeSock(process.env.WATCHMAN_SOCK);
    return;
  }

  // We need to ask the client binary where to find it.
  // This will cause the service to start for us if it isn't
  // already running.
  var args = ['--no-pretty', 'get-sockname'];

  // We use the more elaborate spawn rather than exec because there
  // are some error cases on Windows where process spawning can hang.
  // It is desirable to pipe stderr directly to stderr live so that
  // we can discover the problem.
  var proc = null;
  var spawnFailed = false;

  function spawnError(error) {
    if (spawnFailed) {
      // For ENOENT, proc 'close' will also trigger with a negative code,
      // let's suppress that second error.
      return;
    }
    spawnFailed = true;
    if (error.code === 'EACCES' || error.errno === 'EACCES') {
      error.message = 'The Watchman CLI is installed but cannot ' +
                      'be spawned because of a permission problem';
    } else if (error.code === 'ENOENT' || error.errno === 'ENOENT') {
      error.message = 'Watchman was not found in PATH.  See ' +
          'https://facebook.github.io/watchman/docs/install.html ' +
          'for installation instructions';
    }
    console.error('Watchman: ', error.message);
    self.emit('error', error);
  }

  try {
    proc = childProcess.spawn(this.watchmanBinaryPath, args, {
      stdio: ['ignore', 'pipe', 'pipe']
    });
  } catch (error) {
    spawnError(error);
    return;
  }

  var stdout = [];
  var stderr = [];
  proc.stdout.on('data', function(data) {
    stdout.push(data);
  });
  proc.stderr.on('data', function(data) {
    data = data.toString('utf8');
    stderr.push(data);
    console.error(data);
  });
  proc.on('error', function(error) {
    spawnError(error);
  });

  proc.on('close', function (code, signal) {
    if (code !== 0) {
      spawnError(new Error(
          self.watchmanBinaryPath + ' ' + args.join(' ') +
          ' returned with exit code=' + code + ', signal=' +
          signal + ', stderr= ' + stderr.join('')));
      return;
    }
    try {
      var obj = JSON.parse(stdout.join(''));
      if ('error' in obj) {
        var error = new Error(obj.error);
        error.watchmanResponse = obj;
        self.emit('error', error);
        return;
      }
      makeSock(obj.sockname);
    } catch (e) {
      self.emit('error', e);
    }
  });
}

Client.prototype.command = function(args, done) {
  done = done || function() {};

  // Queue up the command
  this.commands.push({cmd: args, cb: done});

  // Establish a connection if we don't already have one
  if (!this.socket) {
    if (!this.connecting) {
      this.connecting = true;
      this.connect();
      return;
    }
    return;
  }

  // If we're already connected and idle, try sending the command immediately
  this.sendNextCommand();
}

var cap_versions = {
    "cmd-watch-del-all": "3.1.1",
    "cmd-watch-project": "3.1",
    "relative_root": "3.3",
    "term-dirname": "3.1",
    "term-idirname": "3.1",
    "wildmatch": "3.7",
}

// Compares a vs b, returns < 0 if a < b, > 0 if b > b, 0 if a == b
function vers_compare(a, b) {
  a = a.split('.');
  b = b.split('.');
  for (var i = 0; i < 3; i++) {
    var d = parseInt(a[i] || '0') - parseInt(b[i] || '0');
    if (d != 0) {
      return d;
    }
  }
  return 0; // Equal
}

function have_cap(vers, name) {
  if (name in cap_versions) {
    return vers_compare(vers, cap_versions[name]) >= 0;
  }
  return false;
}

// This is a helper that we expose for testing purposes
Client.prototype._synthesizeCapabilityCheck = function(
    resp, optional, required) {
  resp.capabilities = {}
  var version = resp.version;
  optional.forEach(function (name) {
    resp.capabilities[name] = have_cap(version, name);
  });
  required.forEach(function (name) {
    var have = have_cap(version, name);
    resp.capabilities[name] = have;
    if (!have) {
      resp.error = 'client required capability `' + name +
                   '` is not supported by this server';
    }
  });
  return resp;
}

Client.prototype.capabilityCheck = function(caps, done) {
  var optional = caps.optional || [];
  var required = caps.required || [];
  var self = this;
  this.command(['version', {
      optional: optional,
      required: required
  }], function (error, resp) {
    if (error) {
      done(error);
      return;
    }
    if (!('capabilities' in resp)) {
      // Server doesn't support capabilities, so we need to
      // synthesize the results based on the version
      resp = self._synthesizeCapabilityCheck(resp, optional, required);
      if (resp.error) {
        error = new Error(resp.error);
        error.watchmanResponse = resp;
        done(error);
        return;
      }
    }
    done(null, resp);
  });
}

// Close the connection to the service
Client.prototype.end = function() {
  this.cancelCommands('The client was ended');
  if (this.socket) {
    this.socket.end();
    this.socket = null;
  }
  this.bunser = null;
}
<commit_msg>set `windowsHide: true` when spawning a process<commit_after>/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

'use strict';

var net = require('net');
var EE = require('events').EventEmitter;
var util = require('util');
var childProcess = require('child_process');
var bser = require('bser');

// We'll emit the responses to these when they get sent down to us
var unilateralTags = ['subscription', 'log'];

/**
 * @param options An object with the following optional keys:
 *   * 'watchmanBinaryPath' (string) Absolute path to the watchman binary.
 *     If not provided, the Client locates the binary using the PATH specified
 *     by the node child_process's default env.
 */
function Client(options) {
  var self = this;
  EE.call(this);

  this.watchmanBinaryPath = 'watchman';
  if (options && options.watchmanBinaryPath) {
    this.watchmanBinaryPath = options.watchmanBinaryPath.trim();
  };
  this.commands = [];
}
util.inherits(Client, EE);

module.exports.Client = Client;

// Try to send the next queued command, if any
Client.prototype.sendNextCommand = function() {
  if (this.currentCommand) {
    // There's a command pending response, don't send this new one yet
    return;
  }

  this.currentCommand = this.commands.shift();
  if (!this.currentCommand) {
    // No further commands are queued
    return;
  }

  this.socket.write(bser.dumpToBuffer(this.currentCommand.cmd));
}

Client.prototype.cancelCommands = function(why) {
  var error = new Error(why);

  // Steal all pending commands before we start cancellation, in
  // case something decides to schedule more commands
  var cmds = this.commands;
  this.commands = [];

  if (this.currentCommand) {
    cmds.unshift(this.currentCommand);
    this.currentCommand = null;
  }

  // Synthesize an error condition for any commands that were queued
  cmds.forEach(function(cmd) {
    cmd.cb(error);
  });
}

Client.prototype.connect = function() {
  var self = this;

  function makeSock(sockname) {
    // bunser will decode the watchman BSER protocol for us
    self.bunser = new bser.BunserBuf();
    // For each decoded line:
    self.bunser.on('value', function(obj) {
      // Figure out if this is a unliteral response or if it is the
      // response portion of a request-response sequence.  At the time
      // of writing, there are only two possible unilateral responses.
      var unilateral = false;
      for (var i = 0; i < unilateralTags.length; i++) {
        var tag = unilateralTags[i];
        if (tag in obj) {
          unilateral = tag;
        }
      }

      if (unilateral) {
        self.emit(unilateral, obj);
      } else if (self.currentCommand) {
        var cmd = self.currentCommand;
        self.currentCommand = null;
        if ('error' in obj) {
          var error = new Error(obj.error);
          error.watchmanResponse = obj;
          cmd.cb(error);
        } else {
          cmd.cb(null, obj);
        }
      }

      // See if we can dispatch the next queued command, if any
      self.sendNextCommand();
    });
    self.bunser.on('error', function(err) {
      self.emit('error', err);
    });

    self.socket = net.createConnection(sockname);
    self.socket.on('connect', function() {
      self.connecting = false;
      self.emit('connect');
      self.sendNextCommand();
    });
    self.socket.on('error', function(err) {
      self.connecting = false;
      self.emit('error', err);
    });
    self.socket.on('data', function(buf) {
      if (self.bunser) {
        self.bunser.append(buf);
      }
    });
    self.socket.on('end', function() {
      self.socket = null;
      self.bunser = null;
      self.cancelCommands('The watchman connection was closed');
      self.emit('end');
    });
  }

  // triggers will export the sock path to the environment.
  // If we're invoked in such a way, we can simply pick up the
  // definition from the environment and avoid having to fork off
  // a process to figure it out
  if (process.env.WATCHMAN_SOCK) {
    makeSock(process.env.WATCHMAN_SOCK);
    return;
  }

  // We need to ask the client binary where to find it.
  // This will cause the service to start for us if it isn't
  // already running.
  var args = ['--no-pretty', 'get-sockname'];

  // We use the more elaborate spawn rather than exec because there
  // are some error cases on Windows where process spawning can hang.
  // It is desirable to pipe stderr directly to stderr live so that
  // we can discover the problem.
  var proc = null;
  var spawnFailed = false;

  function spawnError(error) {
    if (spawnFailed) {
      // For ENOENT, proc 'close' will also trigger with a negative code,
      // let's suppress that second error.
      return;
    }
    spawnFailed = true;
    if (error.code === 'EACCES' || error.errno === 'EACCES') {
      error.message = 'The Watchman CLI is installed but cannot ' +
                      'be spawned because of a permission problem';
    } else if (error.code === 'ENOENT' || error.errno === 'ENOENT') {
      error.message = 'Watchman was not found in PATH.  See ' +
          'https://facebook.github.io/watchman/docs/install.html ' +
          'for installation instructions';
    }
    console.error('Watchman: ', error.message);
    self.emit('error', error);
  }

  try {
    proc = childProcess.spawn(this.watchmanBinaryPath, args, {
      stdio: ['ignore', 'pipe', 'pipe'],
      windowsHide: true
    });
  } catch (error) {
    spawnError(error);
    return;
  }

  var stdout = [];
  var stderr = [];
  proc.stdout.on('data', function(data) {
    stdout.push(data);
  });
  proc.stderr.on('data', function(data) {
    data = data.toString('utf8');
    stderr.push(data);
    console.error(data);
  });
  proc.on('error', function(error) {
    spawnError(error);
  });

  proc.on('close', function (code, signal) {
    if (code !== 0) {
      spawnError(new Error(
          self.watchmanBinaryPath + ' ' + args.join(' ') +
          ' returned with exit code=' + code + ', signal=' +
          signal + ', stderr= ' + stderr.join('')));
      return;
    }
    try {
      var obj = JSON.parse(stdout.join(''));
      if ('error' in obj) {
        var error = new Error(obj.error);
        error.watchmanResponse = obj;
        self.emit('error', error);
        return;
      }
      makeSock(obj.sockname);
    } catch (e) {
      self.emit('error', e);
    }
  });
}

Client.prototype.command = function(args, done) {
  done = done || function() {};

  // Queue up the command
  this.commands.push({cmd: args, cb: done});

  // Establish a connection if we don't already have one
  if (!this.socket) {
    if (!this.connecting) {
      this.connecting = true;
      this.connect();
      return;
    }
    return;
  }

  // If we're already connected and idle, try sending the command immediately
  this.sendNextCommand();
}

var cap_versions = {
    "cmd-watch-del-all": "3.1.1",
    "cmd-watch-project": "3.1",
    "relative_root": "3.3",
    "term-dirname": "3.1",
    "term-idirname": "3.1",
    "wildmatch": "3.7",
}

// Compares a vs b, returns < 0 if a < b, > 0 if b > b, 0 if a == b
function vers_compare(a, b) {
  a = a.split('.');
  b = b.split('.');
  for (var i = 0; i < 3; i++) {
    var d = parseInt(a[i] || '0') - parseInt(b[i] || '0');
    if (d != 0) {
      return d;
    }
  }
  return 0; // Equal
}

function have_cap(vers, name) {
  if (name in cap_versions) {
    return vers_compare(vers, cap_versions[name]) >= 0;
  }
  return false;
}

// This is a helper that we expose for testing purposes
Client.prototype._synthesizeCapabilityCheck = function(
    resp, optional, required) {
  resp.capabilities = {}
  var version = resp.version;
  optional.forEach(function (name) {
    resp.capabilities[name] = have_cap(version, name);
  });
  required.forEach(function (name) {
    var have = have_cap(version, name);
    resp.capabilities[name] = have;
    if (!have) {
      resp.error = 'client required capability `' + name +
                   '` is not supported by this server';
    }
  });
  return resp;
}

Client.prototype.capabilityCheck = function(caps, done) {
  var optional = caps.optional || [];
  var required = caps.required || [];
  var self = this;
  this.command(['version', {
      optional: optional,
      required: required
  }], function (error, resp) {
    if (error) {
      done(error);
      return;
    }
    if (!('capabilities' in resp)) {
      // Server doesn't support capabilities, so we need to
      // synthesize the results based on the version
      resp = self._synthesizeCapabilityCheck(resp, optional, required);
      if (resp.error) {
        error = new Error(resp.error);
        error.watchmanResponse = resp;
        done(error);
        return;
      }
    }
    done(null, resp);
  });
}

// Close the connection to the service
Client.prototype.end = function() {
  this.cancelCommands('The client was ended');
  if (this.socket) {
    this.socket.end();
    this.socket = null;
  }
  this.bunser = null;
}
<|endoftext|>


<commit_before>'use strict';

const gpio = require('rpi-gpio');

// The pins we want to manipulate
let greenPin = 3
let yellowPin = 5
let redPin = 7;

let pinOrder = [greenPin, yellowPin, redPin];

// The delay between each time it lights up (in millisseconds)
let blinkDelay = 1000;

function gpioSetup() {
	gpio.setup(greenPin, gpio.DIR_OUT, () => {
		gpio.setup(yellowPin, gpio.DIR_OUT, () => {
			gpio.setup(redPin, gpio.DIR_OUT, start);
		});
	});
}

// This is the function that turns the voltage on pin 7 on and off
// It uses the value specified on `blinkDelay` as delay
function start() {

	let currentPosition = 0;

	setInterval(() => {
		lightPosition(currentPosition);

		currentPosition++;

		if (currentPosition === pinOrder.length - 1) {
			currentPosition = 0;
		}

	}, blinkDelay);
}

function lightPosition(pos) {
	for (let i = 0; i < pinOrder.length; i++) {
		gpio.write(pinOrder[i], i === pos ? true : false);
	}
}

gpioSetup();<commit_msg>Add feedback for traffic-lights code<commit_after>'use strict';

const gpio = require('rpi-gpio');

// The pins we want to manipulate
let greenPin = 3
let yellowPin = 5
let redPin = 7;

let pinOrder = [greenPin, yellowPin, redPin];

// The delay between each time it lights up (in millisseconds)
let blinkDelay = 1000;

function gpioSetup() {
	gpio.setup(greenPin, gpio.DIR_OUT, () => {
		gpio.setup(yellowPin, gpio.DIR_OUT, () => {
			gpio.setup(redPin, gpio.DIR_OUT, start);
		});
	});
}

// This is the function that turns the voltage on pin 7 on and off
// It uses the value specified on `blinkDelay` as delay
function start() {

	let currentPosition = 0;

	setInterval(() => {
		lightPosition(currentPosition);

		currentPosition++;

		if (currentPosition === pinOrder.length - 1) {
			currentPosition = 0;
		}

		console.log(`Current Pin: ${pinOrder[currentPosition]}`);

	}, blinkDelay);
}

function lightPosition(pos) {
	for (let i = 0; i < pinOrder.length; i++) {
		gpio.write(pinOrder[i], i === pos ? true : false);
	}
}

gpioSetup();<|endoftext|>


<commit_before>if( typeof( Importer ) === "undefined" ) {
	Importer = {};
}

Importer.initialize = function() {
	attachHelpTooltips();
}

/*******************************************************************
 *
 * Functions for date and timepickers
 *
 *******************************************************************/
Importer.form = {
	submit: function( formId, action ) {
		var form = $( 'form#' + formId );

		if( action != undefined ) {
			$( 'input[name=_action]', form ).val( action );
		}

		form.submit();
	}
}

Importer.datatable = {
	/**
	 * Loads data from the given URL using the specified parameters into a datatable
	 * @return jQuery promise object to retrieve the data.
	 */
	load: function(element, url, parameters, callback) {
		var dataTable;
		var spinner = element.parent().find( ".spinner" );

		return $.get( url, parameters )
			.done(function(data) {
				if( dataTable ) {
					dataTable.fnDestroy();
				}

				// Hide the spinner and show the preview pane
				element.html('

');
				element.show();
				spinner.hide();

				if( typeof(callback) != "undefined" )
					data = callback(data);

				if ( data.aoColumns.length < 100 ) {
					dataTable = element.find( "#datamatrix" ).dataTable({
						"oLanguage": {
							"sInfo": "Showing rows _START_ to _END_ out of a total of _TOTAL_ example rows"
						},

						"sScrollX": "100%",
						"sScrollY": "200px",
						"bScrollCollapse": true,
						"bAutoWidth": false,
						"bJQueryUI": true,
						"bRetrieve": false,
						"bDestroy": true,
						"iDisplayLength": 5,
						"bSort" : false,
						"aaData": data.aaData,
						"aoColumns": data.aoColumns,
						"bFilter": false,
						"bLengthChange": false
					});

					//If the data file has <200 column, 'next' action should be 'match'.
					element.parents().find('#next-exact').hide();
					element.parents().find('#next-match').show();
				}
				else {
					// Hide the spinner and show the preview pane
					element.empty().text( "Matrix too big to show preview ("+data.aoColumns.length+" columns). 'Match data' will be skipped, make sure your matrix corresponds to the study perfectly" );
					element.show();
					spinner.hide();

					//If the data file has >200 column, 'next' action should be 'exact'.
					element.parents().find('#next-match').hide();
					element.parents().find('#next-exact').show();
				}
			})
			.fail(function() {
				// Hide the spinner and show the preview pane
				element.empty().text( "Data preview could not be loaded. This means that the file you provided could not be properly read. Please specify another file or choose another sheet number." );
				element.show();
				spinner.hide();
			});
	}
};

Importer.upload = {
	initialize: function() {
        // Hide buttons of both 'next' options on upload page
        $( '#next-match' ).hide();
        $( '#next-exact' ).hide();

		// Update data preview when something changes in the parameters
		$( "#uploadParameters" ).on("change", "select", function() {
			Importer.upload.updateDataPreview();
		});

		// Also initialize the data preview now, in case a filename has been given already
		Importer.upload.updateDataPreview();

		// Make sure to add an add/modify button to the template dropdown (if present)
		Importer.upload.addMoreForTemplates();
	},

	updateDataPreview: function() {
		// Don't update the preview, if no file is specified
		var filename = $("#file").val();
		if( !filename || filename == "existing*" ) {
			$( "#exampleData" ).hide();
			return;
		}

		// Show the example data with spinner
		$( "#exampleData" ).show();
		$( "#datapreview" ).hide();
		$( "#exampleData .spinner" ).show();

		// Retrieve parameters
		var form = $('#uploadFile');
		var previewTable = $( "#datapreview" );

		// Perform the ajax call to retrieve the data
		Importer.datatable.load(previewTable, previewTable.data("url"), form.serialize());
	},

	/**
	 * Enables the addmore entry on a template selectbox
	 */
	addMoreForTemplates: function() {
	    new SelectAddMore().init({
	        rel	 : 'template',
	        url	 : baseUrl + '/templateEditor',
	        vars	: 'entity,ontologies',
	        label   : 'add / modify..',
	        style   : 'modify',
	        onClose : function() {
	            Importer.upload.refreshTemplates();
	        }
	    });
	},

	/**
	 * Refreshes the list of templates on screen
	 */
	refreshTemplates: function() {
		$( "[rel=template]").each(function(idx,el) {
			var select = $(el);
			var entity = select.data("entity");

			$.get( baseUrl + "/template/getAllForEntity", { entity: entity }, function(data) {
				// Empty select
				select.empty();
				select.off("change");

				// Add new templates
				$.each(data, function(templateId, templateName) {
					select.append( $("<option>").attr( "value", templateId ).text( templateName ) );
				});

				Importer.upload.addMoreForTemplates();
			});
		});
	}

};

Importer.match = {
	initialize: function(sessionKey, initialMapping) {
		Importer.match.showDatatable(sessionKey, initialMapping);
	},

	showDatatable: function(sessionKey, initialMapping) {
		var previewElement = $( "#data-with-headers" );

		// Perform the ajax call to retrieve the data
		Importer.datatable.load(
			previewElement,
			previewElement.data("url"),
			{ key: sessionKey },
			function(data) {
				console.log( "Enhance data", data);
				return Importer.match.addSelectBoxesToHeader(data, initialMapping);
			}
		).done(function(data) {
			if( previewElement.data( "match-url" ) ) {
				Importer.match.addMatchButtonsToDatatable(previewElement, sessionKey);
			}
		});
	},

	/**
	 * Adds a select box for each column
	 */
	addSelectBoxesToHeader: function(data, initialMapping) {
		// Update the datatable with select boxes to match the headers
		$.each(data.aoColumns, function(idx) {
			// Create a clone of the example header select
			var select = $("#example-header-select").clone();

			// Change the clone to work in the header
			select
				.attr("id", "column-match-" + idx)
				.attr("name", "column.match." + idx);

			// Set the initial mapping
			if( initialMapping && initialMapping[idx] ) {
				select.val(initialMapping[idx]);
			}

			// Add the select to the table (and show it)
			data.aoColumns[idx].sTitle += " " + select[0].outerHTML;
		});

		return data;
	},

	/**
	 * Updates the datatable header with buttons to match and clear mapping
	 */
	addMatchButtonsToDatatable: function(element, sessionKey) {
		var optionsHeader = element.find( ".fg-toolbar" ).first();
		var matchOptions = $( "
" )
			.addClass( 'match_options' )
			.append( "<button class='match'>Match</button>" )
			.append( "<button class='clear'>Clear mapping</button>" );

		optionsHeader.append(matchOptions);

		// Add click handlers to match buttons
		element.on( "click", "button.match", function() {
			Importer.match.matchHeaders( element, sessionKey );
			return false;
		});

		element.on( "click", "button.clear", function() {
			// Clear all header select boxes
			element.find( ".header-select" ).val("");
			return false;
		});
	},

	/**
	 * Perform a match for each header against the possibilities
	 */
	matchHeaders: function( element, sessionKey ) {
		var url = element.data( "match-url" );
		var parameters = { key: sessionKey };

		return $.get( url, parameters )
			.done(function(data) {
				// The data returns contains the proposed selections. Select the right
				// values in the selectboxes
				for( columnIndex in data ) {
					$( "#column-match-" + columnIndex ).val( data[columnIndex] );
				}
			});
	}
};

Importer.exact = {
	initialize: function(sessionKey) {
        $( '.options' ).hide();
		Importer.exact.matchHeaders( sessionKey );
	},

	/**
	 * Perform a match for each header against the possibilities
	 */
	matchHeaders: function( sessionKey ) {
        var url = $( '#match-headers' ).data( "match-url" );
		var parameters = { key: sessionKey };

		return $.get( url, parameters )
			.done(function(data) {
				$( '#match-text' ).text("Successful matched "+data.count+" Features, you can now import your data!");
				$( '.options' ).show();
			});
	}
};
<commit_msg>Clearified exact import measurement importer message<commit_after>if( typeof( Importer ) === "undefined" ) {
	Importer = {};
}

Importer.initialize = function() {
	attachHelpTooltips();
}

/*******************************************************************
 *
 * Functions for date and timepickers
 *
 *******************************************************************/
Importer.form = {
	submit: function( formId, action ) {
		var form = $( 'form#' + formId );

		if( action != undefined ) {
			$( 'input[name=_action]', form ).val( action );
		}

		form.submit();
	}
}

Importer.datatable = {
	/**
	 * Loads data from the given URL using the specified parameters into a datatable
	 * @return jQuery promise object to retrieve the data.
	 */
	load: function(element, url, parameters, callback) {
		var dataTable;
		var spinner = element.parent().find( ".spinner" );

		return $.get( url, parameters )
			.done(function(data) {
				if( dataTable ) {
					dataTable.fnDestroy();
				}

				// Hide the spinner and show the preview pane
				element.html('

');
				element.show();
				spinner.hide();

				if( typeof(callback) != "undefined" )
					data = callback(data);

				if ( data.aoColumns.length < 100 ) {
					dataTable = element.find( "#datamatrix" ).dataTable({
						"oLanguage": {
							"sInfo": "Showing rows _START_ to _END_ out of a total of _TOTAL_ example rows"
						},

						"sScrollX": "100%",
						"sScrollY": "200px",
						"bScrollCollapse": true,
						"bAutoWidth": false,
						"bJQueryUI": true,
						"bRetrieve": false,
						"bDestroy": true,
						"iDisplayLength": 5,
						"bSort" : false,
						"aaData": data.aaData,
						"aoColumns": data.aoColumns,
						"bFilter": false,
						"bLengthChange": false
					});

					//If the data file has <100 column, 'next' action should be 'match'.
					element.parents().find('#next-exact').hide();
					element.parents().find('#next-match').show();
				}
				else {

                    var previewMessage = "You are importing a large dataset ("+data.aoColumns.length+" columns). Make sure your matrix corresponds to the study perfectly since the wizard will skip the 'matching' step.";

					if(parameters.indexOf('sample+layout') !== -1) {
                        previewMessage += " Please make sure the first column is 'Sample name'."
                    }
                    else if(parameters.indexOf('subject+layout') !== -1) {
                        previewMessage += " Please make sure the first column is 'Subject name'."
                    }

					// Hide the spinner and show the preview pane
					element.empty().text( previewMessage );
					element.show();
					spinner.hide();

					//If the data file has >100 column, 'next' action should be 'exact'.
					element.parents().find('#next-match').hide();
					element.parents().find('#next-exact').show();
				}
			})
			.fail(function() {
				// Hide the spinner and show the preview pane
				element.empty().text( "Data preview could not be loaded. This means that the file you provided could not be properly read. Please specify another file or choose another sheet number." );
				element.show();
				spinner.hide();
			});
	}
};

Importer.upload = {
	initialize: function() {
        // Hide buttons of both 'next' options on upload page
        $( '#next-match' ).hide();
        $( '#next-exact' ).hide();

		// Update data preview when something changes in the parameters
		$( "#uploadParameters" ).on("change", "select", function() {
			Importer.upload.updateDataPreview();
		});

		// Also initialize the data preview now, in case a filename has been given already
		Importer.upload.updateDataPreview();

		// Make sure to add an add/modify button to the template dropdown (if present)
		Importer.upload.addMoreForTemplates();
	},

	updateDataPreview: function() {
		// Don't update the preview, if no file is specified
		var filename = $("#file").val();
		if( !filename || filename == "existing*" ) {
			$( "#exampleData" ).hide();
			return;
		}

		// Show the example data with spinner
		$( "#exampleData" ).show();
		$( "#datapreview" ).hide();
		$( "#exampleData .spinner" ).show();

		// Retrieve parameters
		var form = $('#uploadFile');
		var previewTable = $( "#datapreview" );

		// Perform the ajax call to retrieve the data
		Importer.datatable.load(previewTable, previewTable.data("url"), form.serialize());
	},

	/**
	 * Enables the addmore entry on a template selectbox
	 */
	addMoreForTemplates: function() {
	    new SelectAddMore().init({
	        rel	 : 'template',
	        url	 : baseUrl + '/templateEditor',
	        vars	: 'entity,ontologies',
	        label   : 'add / modify..',
	        style   : 'modify',
	        onClose : function() {
	            Importer.upload.refreshTemplates();
	        }
	    });
	},

	/**
	 * Refreshes the list of templates on screen
	 */
	refreshTemplates: function() {
		$( "[rel=template]").each(function(idx,el) {
			var select = $(el);
			var entity = select.data("entity");

			$.get( baseUrl + "/template/getAllForEntity", { entity: entity }, function(data) {
				// Empty select
				select.empty();
				select.off("change");

				// Add new templates
				$.each(data, function(templateId, templateName) {
					select.append( $("<option>").attr( "value", templateId ).text( templateName ) );
				});

				Importer.upload.addMoreForTemplates();
			});
		});
	}

};

Importer.match = {
	initialize: function(sessionKey, initialMapping) {
		Importer.match.showDatatable(sessionKey, initialMapping);
	},

	showDatatable: function(sessionKey, initialMapping) {
		var previewElement = $( "#data-with-headers" );

		// Perform the ajax call to retrieve the data
		Importer.datatable.load(
			previewElement,
			previewElement.data("url"),
			{ key: sessionKey },
			function(data) {
				console.log( "Enhance data", data);
				return Importer.match.addSelectBoxesToHeader(data, initialMapping);
			}
		).done(function(data) {
			if( previewElement.data( "match-url" ) ) {
				Importer.match.addMatchButtonsToDatatable(previewElement, sessionKey);
			}
		});
	},

	/**
	 * Adds a select box for each column
	 */
	addSelectBoxesToHeader: function(data, initialMapping) {
		// Update the datatable with select boxes to match the headers
		$.each(data.aoColumns, function(idx) {
			// Create a clone of the example header select
			var select = $("#example-header-select").clone();

			// Change the clone to work in the header
			select
				.attr("id", "column-match-" + idx)
				.attr("name", "column.match." + idx);

			// Set the initial mapping
			if( initialMapping && initialMapping[idx] ) {
				select.val(initialMapping[idx]);
			}

			// Add the select to the table (and show it)
			data.aoColumns[idx].sTitle += " " + select[0].outerHTML;
		});

		return data;
	},

	/**
	 * Updates the datatable header with buttons to match and clear mapping
	 */
	addMatchButtonsToDatatable: function(element, sessionKey) {
		var optionsHeader = element.find( ".fg-toolbar" ).first();
		var matchOptions = $( "
" )
			.addClass( 'match_options' )
			.append( "<button class='match'>Match</button>" )
			.append( "<button class='clear'>Clear mapping</button>" );

		optionsHeader.append(matchOptions);

		// Add click handlers to match buttons
		element.on( "click", "button.match", function() {
			Importer.match.matchHeaders( element, sessionKey );
			return false;
		});

		element.on( "click", "button.clear", function() {
			// Clear all header select boxes
			element.find( ".header-select" ).val("");
			return false;
		});
	},

	/**
	 * Perform a match for each header against the possibilities
	 */
	matchHeaders: function( element, sessionKey ) {
		var url = element.data( "match-url" );
		var parameters = { key: sessionKey };

		return $.get( url, parameters )
			.done(function(data) {
				// The data returns contains the proposed selections. Select the right
				// values in the selectboxes
				for( columnIndex in data ) {
					$( "#column-match-" + columnIndex ).val( data[columnIndex] );
				}
			});
	}
};

Importer.exact = {
	initialize: function(sessionKey) {
        $( '.options' ).hide();
		Importer.exact.matchHeaders( sessionKey );
	},

	/**
	 * Perform a match for each header against the possibilities
	 */
	matchHeaders: function( sessionKey ) {
        var url = $( '#match-headers' ).data( "match-url" );
		var parameters = { key: sessionKey };

		return $.get( url, parameters )
			.done(function(data) {
				$( '#match-text' ).text("Successful matched "+data.count+" Features, you can now import your data!");
				$( '.options' ).show();
			});
	}
};
<|endoftext|>


<commit_before>// Service for playing audio files
angular.module('cosmic.services').factory('cosmicPlayer',  function($interval,$q,$cordovaMedia,cosmicDB, $localstorage,deviceFS,cosmicConfig) {
	function shuffle(array) {
		var currentIndex = array.length, temporaryValue, randomIndex ;

		// While there remain elements to shuffle...
		while (0 !== currentIndex) {

			// Pick a remaining element...
			randomIndex = Math.floor(Math.random() * currentIndex);
			currentIndex -= 1;

			// And swap it with the current element.
			temporaryValue = array[currentIndex];
			array[currentIndex] = array[randomIndex];
			array[randomIndex] = temporaryValue;
		}

		return array;
	}

	var player = {
		playing        : false,
		shuffle        : false,
		loop           : true,
		onUpdate       : function(position){}, // callback on position update while playing
		onTitleChange  : function(){}, // callback on title change
		isWatchingTime : null,
		duration       : 0,
		media          : null,
		playlist       : [{artist : '',name : 'No Media', artwork : 'default_artwork.jpg'}],
		playlistIndex  : 0,
		controls : false,

		loadSettings : function(){
			this.shuffle        = ($localstorage.get('shuffle','false') === 'true');
			this.loop           = ($localstorage.get('loop','true') === 'true');
		},
		setIndex : function(title){
			this.playlistIndex=this.playlist.indexOf(title);
		},
		toogleShuffle : function(){
			this.shuffle = ! this.shuffle;
			$localstorage.set('shuffle',this.shuffle);
		},
		toogleLoop : function(){
			this.loop = ! this.loop;
			$localstorage.set('loop',this.loop);
		},
		toggleCurrentLike : function(){
			//console.log('toggle like: '+this.playlist[this.playlistIndex].like);
			if(this.media){
				this.playlist[this.playlistIndex].like = 1-this.playlist[this.playlistIndex].like;
				cosmicDB.toggleLikeTitle(this.playlist[this.playlistIndex].id);
			}
		},

			// Load a playlist in the player
		loadPlaylist: function(playlist) {
			var playlistCopy = playlist.slice();
			player.playlist = playlistCopy;
			if (this.shuffle){
				this.shufflePlaylist();
			}
		},

		shufflePlaylist : function (){
			this.playlist = shuffle(this.playlist);
		},

			// add an item of current view as next
		setNext: function(title){
			this.playlist.splice(this.playlistIndex+1,0,title);
		},

			// Play playlist item at 'playlistindex' position
		initMedia: function() {
			var self=this;
			self.clearMedia();
			self.duration = -1;
			var title = this.playlist[self.playlistIndex];
			var mypath=title.path;
			self.media=new Media(mypath);
			self.play();
			self.onTitleChange();
		},

		showMusicControls : function(){

			//console.log('Show music controls');
			var self=this;
			var title = this.playlist[self.playlistIndex];
			var notificationData = {
				artist : title.artist,
				track : title.name,
				cover : cosmicConfig.appRootStorage + 'miniatures/' + title.artwork,
				isPlaying : self.playing
			};
			MusicControls.create(notificationData, function(success){
				console.log('SUCCESS SHOW: '+success);
			},function(error){
				console.log('ERROR SHOW: '+error);
			});
			if (!self.controls){
				self.controls  = true;
				var events = function (action) {
					//console.log(action);
					switch(action){
						case 'music-controller-next':
							self.next();
							break;
						case 'music-controller-previous':
							self.prev();
							break;
						case 'music-controller-headset-plugged':
							if (!self.playing){
								self.play();
							}
							break;
						case 'music-controller-headset-unplugged':
							if (self.playing){
								self.pause();
							}
							break;
						case 'music-controller-pause':
							self.pause();
							break;
						case 'music-controller-play':
							self.play();
							break;
						case 'music-controller-media-button':
							if (self.playing){
								self.pause();
							} else {
								self.play();
							}
							break;
						default:
							break;
					}
				};
				MusicControls.subscribe(events);
				MusicControls.listen();
			}
		},

			// Release media
		clearMedia: function(){
			var self=this;
			self.stopWatchTime();
			if (self.media){
				self.media.release();
				self.media=null;
			}
		},
		setOnUpdate : function(onUpdate){
			this.onUpdate=onUpdate;
		},
		setOnTitleChange : function(onTitleChange){
			this.onTitleChange=onTitleChange;
		},

			// player launcher for the controller
		launchPlayer: function(title) {
			var self=this;
			self.setIndex(title);
			self.initMedia();
		},
		launchPlayerByIndex : function(index){
			this.playlistIndex = index;
			this.initMedia();
		},
		play: function() {
			if (this.media){
				player.playing = true;
				this.startWatchTime();
				this.duration=this.getDuration();
				this.media.play();
				this.showMusicControls();
			}
		},
		pause: function() {
			if (this.media){
				player.playing = false;
				this.media.pause();
				this.stopWatchTime();
				this.showMusicControls();
			}
		},
		stop: function() {
			this.media.stop();
			this.stopWatchTime();
			player.playing = false;
		},

			// seek to percent
		seek: function(percent) {
			var self=this;
			console.log(percent);
			console.log('Duration: '+self.duration);
			if (self.duration >0){
				var newPosition=percent*self.duration;
				self.media.seekTo(newPosition);
				console.log('seek to '+newPosition);
				self.onUpdate(newPosition);
			}
		},
		prev: function() {
			var self=this;
			self.media.getCurrentPosition(function(pos){
				if (pos<=5){
					self.playlistIndex = (self.playlistIndex + self.playlist.length - 1) % self.playlist.length;
					self.initMedia(self.playlistIndex);
				} else {
					self.seek(0);
					self.play();
				}
			});
		},
		next: function() {
			if (this.media){
				var self=this;
				self.playlistIndex = (self.playlistIndex + 1) % self.playlist.length;
				self.initMedia(self.playlistIndex);
				if (self.playlistIndex === 0 && ! self.loop){
					self.pause();
				}
			}
		},

			// Watch position every 500ms
		startWatchTime: function() {
			var self=this;
			if (self.media){
				var dur;
				var counter=0;
				self.isWatchingTime=$interval(function(){
					self.media.getCurrentPosition(function(pos){
						self.onUpdate(1000*pos);
						if (self.duration>0 && (1000*pos>=self.duration-600 || pos < 0)){
							// update Play statistics
							cosmicDB.updateTitlePlayStatistics(self.playlist[self.playlistIndex].id);
							console.log('End of current song --- play next song');
							self.next();
						}
					});
				},500);
			} else {
				console.log('on update 0');
				self.onUpdate(0);
			}
			return;
		},
		stopWatchTime : function(){
			var self=this;
			if (self.isWatchingTime){
				$interval.cancel(self.isWatchingTime);
				self.isWatchingTime=null;
			}
			return;
		},

			// get duration of current media
		getDuration: function() {
			var defered=$q.defer();
			var self=this;
			if (self.media){
				var dur;
				var counter=0;
				var inter=$interval(function(){
					dur=self.media.getDuration();
					console.log('tour : ',counter);
					if (dur>=0 || counter>10){
						$interval.cancel(inter);
						self.duration=1000*dur;
						defered.resolve(1000*dur);
					}
					counter++;
				},500);
			} else {
				defered.resolve(-1000);
			}
			return defered.promise;
		}
	};
	player.loadSettings();
	return player;
});

<commit_msg>update<commit_after>// Service for playing audio files
angular.module('cosmic.services').factory('cosmicPlayer',  function($interval,$q,$cordovaMedia,cosmicDB, $localstorage,deviceFS,cosmicConfig) {
	function shuffle(array) {
		var currentIndex = array.length, temporaryValue, randomIndex ;

		// While there remain elements to shuffle...
		while (0 !== currentIndex) {

			// Pick a remaining element...
			randomIndex = Math.floor(Math.random() * currentIndex);
			currentIndex -= 1;

			// And swap it with the current element.
			temporaryValue = array[currentIndex];
			array[currentIndex] = array[randomIndex];
			array[randomIndex] = temporaryValue;
		}

		return array;
	}

	var player = {
		playing        : false,
		shuffle        : false,
		loop           : true,
		onUpdate       : function(position){}, // callback on position update while playing
		onTitleChange  : function(){}, // callback on title change
		isWatchingTime : null,
		duration       : 0,
		media          : null,
		playlist       : [{artist : '',name : 'No Media', artwork : 'default_artwork.jpg'}],
		playlistIndex  : 0,
		controls : false,

		loadSettings : function(){
			this.shuffle        = ($localstorage.get('shuffle','false') === 'true');
			this.loop           = ($localstorage.get('loop','true') === 'true');
		},
		setIndex : function(title){
			this.playlistIndex=this.playlist.indexOf(title);
		},
		toogleShuffle : function(){
			this.shuffle = ! this.shuffle;
			$localstorage.set('shuffle',this.shuffle);
		},
		toogleLoop : function(){
			this.loop = ! this.loop;
			$localstorage.set('loop',this.loop);
		},
		toggleCurrentLike : function(){
			//console.log('toggle like: '+this.playlist[this.playlistIndex].like);
			if(this.media){
				this.playlist[this.playlistIndex].like = 1-this.playlist[this.playlistIndex].like;
				cosmicDB.toggleLikeTitle(this.playlist[this.playlistIndex].id);
			}
		},

			// Load a playlist in the player
		loadPlaylist: function(playlist) {
			var playlistCopy = playlist.slice();
			player.playlist = playlistCopy;
			if (this.shuffle){
				this.shufflePlaylist();
			}
		},

		shufflePlaylist : function (){
			this.playlist = shuffle(this.playlist);
		},

			// add an item of current view as next
		setNext: function(title){
			this.playlist.splice(this.playlistIndex+1,0,title);
		},

			// Play playlist item at 'playlistindex' position
		initMedia: function() {
			var self=this;
			self.clearMedia();
			self.duration = -1;
			var title = this.playlist[self.playlistIndex];
			var mypath=title.path;
			self.media=new Media(mypath);
			self.play();
			self.onTitleChange();
		},

		showMusicControls : function(){

			//console.log('Show music controls');
			var self=this;
			var title = this.playlist[self.playlistIndex];
			var notificationData = {
				artist : title.artist,
				track : title.name,
				cover : cosmicConfig.appRootStorage + 'miniatures/' + title.artwork,
				isPlaying : self.playing
			};
			MusicControls.create(notificationData, function(success){
				console.log('SUCCESS SHOW: '+success);
			},function(error){
				console.log('ERROR SHOW: '+error);
			});
			if (!self.controls){
				self.controls  = true;
				var events = function (action) {
					//console.log(action);
					switch(action){
						case 'music-controls-next':
							self.next();
							break;
						case 'music-controls-previous':
							self.prev();
							break;
						case 'music-controls-headset-plugged':
							if (!self.playing){
								self.play();
							}
							break;
						case 'music-controls-headset-unplugged':
							if (self.playing){
								self.pause();
							}
							break;
						case 'music-controls-pause':
							self.pause();
							break;
						case 'music-controls-play':
							self.play();
							break;
						case 'music-controls-media-button':
							if (self.playing){
								self.pause();
							} else {
								self.play();
							}
							break;
						default:
							break;
					}
				};
				MusicControls.subscribe(events);
				MusicControls.listen();
			}
		},

			// Release media
		clearMedia: function(){
			var self=this;
			self.stopWatchTime();
			if (self.media){
				self.media.release();
				self.media=null;
			}
		},
		setOnUpdate : function(onUpdate){
			this.onUpdate=onUpdate;
		},
		setOnTitleChange : function(onTitleChange){
			this.onTitleChange=onTitleChange;
		},

			// player launcher for the controller
		launchPlayer: function(title) {
			var self=this;
			self.setIndex(title);
			self.initMedia();
		},
		launchPlayerByIndex : function(index){
			this.playlistIndex = index;
			this.initMedia();
		},
		play: function() {
			if (this.media){
				player.playing = true;
				this.startWatchTime();
				this.duration=this.getDuration();
				this.media.play();
				this.showMusicControls();
			}
		},
		pause: function() {
			if (this.media){
				player.playing = false;
				this.media.pause();
				this.stopWatchTime();
				this.showMusicControls();
			}
		},
		stop: function() {
			this.media.stop();
			this.stopWatchTime();
			player.playing = false;
		},

			// seek to percent
		seek: function(percent) {
			var self=this;
			console.log(percent);
			console.log('Duration: '+self.duration);
			if (self.duration >0){
				var newPosition=percent*self.duration;
				self.media.seekTo(newPosition);
				console.log('seek to '+newPosition);
				self.onUpdate(newPosition);
			}
		},
		prev: function() {
			var self=this;
			self.media.getCurrentPosition(function(pos){
				if (pos<=5){
					self.playlistIndex = (self.playlistIndex + self.playlist.length - 1) % self.playlist.length;
					self.initMedia(self.playlistIndex);
				} else {
					self.seek(0);
					self.play();
				}
			});
		},
		next: function() {
			if (this.media){
				var self=this;
				self.playlistIndex = (self.playlistIndex + 1) % self.playlist.length;
				self.initMedia(self.playlistIndex);
				if (self.playlistIndex === 0 && ! self.loop){
					self.pause();
				}
			}
		},

			// Watch position every 500ms
		startWatchTime: function() {
			var self=this;
			if (self.media){
				var dur;
				var counter=0;
				self.isWatchingTime=$interval(function(){
					self.media.getCurrentPosition(function(pos){
						self.onUpdate(1000*pos);
						if (self.duration>0 && (1000*pos>=self.duration-600 || pos < 0)){
							// update Play statistics
							cosmicDB.updateTitlePlayStatistics(self.playlist[self.playlistIndex].id);
							console.log('End of current song --- play next song');
							self.next();
						}
					});
				},500);
			} else {
				console.log('on update 0');
				self.onUpdate(0);
			}
			return;
		},
		stopWatchTime : function(){
			var self=this;
			if (self.isWatchingTime){
				$interval.cancel(self.isWatchingTime);
				self.isWatchingTime=null;
			}
			return;
		},

			// get duration of current media
		getDuration: function() {
			var defered=$q.defer();
			var self=this;
			if (self.media){
				var dur;
				var counter=0;
				var inter=$interval(function(){
					dur=self.media.getDuration();
					console.log('tour : ',counter);
					if (dur>=0 || counter>10){
						$interval.cancel(inter);
						self.duration=1000*dur;
						defered.resolve(1000*dur);
					}
					counter++;
				},500);
			} else {
				defered.resolve(-1000);
			}
			return defered.promise;
		}
	};
	player.loadSettings();
	return player;
});

<|endoftext|>


<commit_before>/*
 * Copyright 2015 Paul T. Grogan, Massachusetts Institute of Technology
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

define(["mas", "isrm", "jquery", "spectrum", "jquery.flot.min", "jquery.flot.selection.min"],
        function(mas, isrm, $) {
    var baseline = new isrm.Model();
    baseline.entities.forEach(function(entity) {
        if(entity instanceof mas.sd.Parameter
                || (entity instanceof mas.sd.Stock
                    && ! (entity instanceof mas.sd.Smooth)
                    && ! (entity instanceof mas.sd.Delay1))) {
            $("#xAxisVariable").append(
                $('<option></option>').val(entity.id).html(entity.name));
            $("#yAxisVariable").append(
                $('<option></option>').val(entity.id).html(entity.name));
        }
    });
    $("#xAxisVariable").val('nreCost');
    $("#xAxisVariable").change(updateTradespace);
    $("#yAxisVariable").val('projDuration');
    $("#yAxisVariable").change(updateTradespace);
    $("#initTime").val(0);
    $("#timeStep").val(0.25);
    $("#maxTime").val(120);
    $("#modelVersion").val(baseline.name + " v" + baseline.version);

    $("#runColor").spectrum({
        disabled: true,
        color: '#ff3333',
        preferredFormat: "hex",
        showInput: true,
        change: updateColor,
    });

    var plotData = [[]];
    var colors = [];
    var ids = [];

    var plot = $.plot("#tradespace", plotData, {
        series: {
            points: { show: true },
            lines: { show: false },
            shadowSize: 0
        },
        legend: {
            show: false
        },
        grid: {
            hoverable: true,
            clickable: true
        },
        selection: {
            mode: "xy"
        },
        xaxis: {
            tickFormatter: (function formatter(val, axis) { return val>1e6?val.toExponential():parseFloat(val.toFixed(6)); }),
        },
        yaxis: {
            tickFormatter: (function formatter(val, axis) { return val>1e6?val.toExponential():parseFloat(val.toFixed(6)); }),
        },
        colors: colors
    });

    var overview = $.plot("#overview", plotData, {
        legend: {
            show: false
        },
        series: {
            points: { show: true, radius: 1 },
            shadowSize: 0
        },
        xaxis: {
            show: false,
            min: 0
        },
        yaxis: {
            show: false,
            min: 0
        },
        grid: {
            color: "#999"
        },
        selection: {
            mode: "xy"
        },
        colors: colors
    });

    $("#tradespace").bind("plotselected", function (event, ranges) {
        if (ranges.xaxis.to - ranges.xaxis.from < 0.00001) {
            ranges.xaxis.to = ranges.xaxis.from + 0.00001;
        }

        if (ranges.yaxis.to - ranges.yaxis.from < 0.00001) {
            ranges.yaxis.to = ranges.yaxis.from + 0.00001;
        }

        plot = $.plot("#tradespace", plotData,
            $.extend(true, {}, {
                series: {
                    points: { show: true },
                    lines: { show: false },
                    shadowSize: 0
                },
                legend: {
                    show: false
                },
                grid: {
                    hoverable: true,
                    clickable: true
                },
                selection: {
                    mode: "xy"
                },
                colors: colors
            }, {
                xaxis: { min: ranges.xaxis.from, max: ranges.xaxis.to, tickFormatter: (function formatter(val, axis) { return val>1e6?val.toExponential():parseFloat(val.toFixed(6)); }) },
                yaxis: { min: ranges.yaxis.from, max: ranges.yaxis.to, tickFormatter: (function formatter(val, axis) { return val>1e6?val.toExponential():parseFloat(val.toFixed(6)); }) }
            })
        );
        overview.setSelection(ranges, true);
    });

    refreshRuns();

    $("#overview").bind("plotselected", function (event, ranges) {
        plot.setSelection(ranges);
    });

    $("#tradespace").bind("plotclick", function(event, pos, item) {
        if(item) {
            plot.unhighlight();
            plot.highlight(item.series, item.datapoint);

            $("#runs").val(ids[item.seriesIndex]);
            $("#runs").trigger("change");
        }
    });

    function updateTradespace() {
        plotData = [];
        for(var i = 0; i < ids.length; i++) {
            plotData[i] = {data:[], label:ids[i]};
        }
        var xVar = $("#xAxisVariable").val();
        var yVar = $("#yAxisVariable").val();
        getValues(xVar, function(res) {
            var x = [];
            for(var i = 0; i < res.length; i++) {
                if(baseline.entity(xVar) instanceof mas.sd.Stock) {
                    x[i] = res[i].finalOutputs[xVar];
                } else if(baseline.entity(xVar) instanceof mas.sd.Parameter) {
                    x[i] = res[i].params[xVar];
                }
            }
            getValues(yVar, function(res) {
                var y = [];
                for(var i = 0; i < res.length; i++) {
                    if(baseline.entity(yVar) instanceof mas.sd.Stock) {
                        y[i] = res[i].finalOutputs[yVar];
                    } else if(baseline.entity(yVar) instanceof mas.sd.Parameter) {
                        y[i] = res[i].params[yVar];
                    }
                    plotData[i] = {data: [[x[i], y[i]]], label: res[i]._id};
                }
                plot.getOptions().colors = colors;
                plot.getOptions().xaxis.min = {};
                plot.getOptions().xaxis.max = {};
                plot.getOptions().yaxis.min = {};
                plot.getOptions().yaxis.max = {};
                plot.setData(plotData);
                plot.setupGrid();
                plot.draw();
                overview.getOptions().colors = colors;
                overview.setData(plotData);
                overview.setupGrid();
                overview.draw();
            });
        });

        function getValues(varId, callback) {
            var query = {
                model: baseline.name,
                version: baseline.version,
                settings: {
                    init: Number($("#initTime").val()),
                    step: Number($("#timeStep").val()),
                    max: Number($("#maxTime").val())
                }
            }
            if(baseline.entity(varId) instanceof mas.sd.Stock) {
                $.get("/data/finalOutputs/"+varId+getFilter(), $.param(query), callback);
            } else if(baseline.entity(varId) instanceof mas.sd.Parameter) {
                $.get("/data/params/"+varId+getFilter(), $.param(query), callback);
            }
        }
    }

    function refreshRuns() {
        var query = {
            model: baseline.name,
            version: baseline.version,
            settings: {
                init: Number($("#initTime").val()),
                step: Number($("#timeStep").val()),
                max: Number($("#maxTime").val())
            }
        }
        $("#runs").find('option').remove();
        $("#runs").attr('disabled','disabled');
        $("#runTag").attr('disabled','disabled');
        $("#updateTag").attr('disabled','disabled');
        $("#removeTag").attr('disabled','disabled');
        ids = [];
        colors = [];
        $.get("/data/tag"+getFilter(), $.param(query), function(res) {
            if(res !== null) {
                res.forEach(function(item) {
                    ids.push(item._id);
                    $("#runs").append($('<option></option>').val(item._id).html((item.tag&&item.tag.name)?item.tag.name:item._id));
                    colors.push((item.tag&&item.tag.color)?item.tag.color:'#ff3333');
                });
                updateTradespace();
            }
            $("#runs").removeAttr("disabled");
        });
    }

    $('#filterRuns').change(refreshRuns);
    function getFilter() {
        if($('#filterRuns').val()==='') {
            return '';
        }
        var filters = $('#filterRuns').val()
                .replace(new RegExp('\\s', 'g'), '')
                .replace(new RegExp('!=', 'g'), '=$ne')
                .replace(new RegExp('>=', 'g'), '=$gte')
                .replace(new RegExp('<=', 'g'), '=$lte')
                .replace(new RegExp('>', 'g'), '=$gt')
                .replace(new RegExp('<', 'g'), '=$lt')
                .split(new RegExp('[,;]', 'g'));
        return '?params.'+filters.join("&params.");
    }

    $("#runs").on("change", function() {
        if($("#runs").val().length===1) {
            var id = $("#runs").val()[0];
            $("#runs").attr('disabled','disabled');
            $("#runID").val(id);
            if($("#runs option:selected").text()===id) {
                $("#runTag").val([]);
                $("#removeTag").attr('disabled','disabled');
            } else {
                $("#runTag").val($("#runs option:selected").text());
                $("#removeTag").removeAttr('disabled');
            }
            if(id !== null) {
                $("#runColor").spectrum("enable");
                $("#resetColor").removeAttr('disabled');
                $("#runColor").spectrum("set", colors[ids.indexOf(id)]);

                $.get("/results/"+id+"/params", function(res) {
                    $("#runParameters").val(JSON.stringify(res));
                    $("#runs").removeAttr("disabled");
                    $("#runs").focus();
                    $("#runTag").removeAttr('disabled');
                });

                plot.unhighlight();
                plot.highlight(ids.indexOf(id), 0);
            }
        } else {
            $("#runID").val([]);
            $("#runTag").val([]);
            $("#runTag").attr('disabled','disabled');
            $("#removeTag").attr('disabled','disabled');
            //$("#runColor").spectrum("set", '#999999');
            //$("#runColor").spectrum("disable");
            //$("#resetColor").attr('disabled','disabled');
            plot.unhighlight();
        }
    });
    $("#runTag").on("input propertychange paste", function() {
        $("#updateTag").removeAttr("disabled");
    });
    $("#updateTag").on("click", function() {
        $("#updateTag").attr('disabled','disabled');
        $("#removeTag").attr('disabled','disabled');
        $.post("/results/"+$("#runs").val()[0]+"/tag/name/"+$("#runTag").val(), function() {
            $("#runs option:selected").html($("#runTag").val());
            $("#removeTag").removeAttr("disabled");
        });
    });
    function updateColor() {
        $("#resetColor").attr('disabled','disabled');
        $("#runColor").spectrum("disable");
        $("#runs").val().forEach(function(id) {
            var color = $("#runColor").val();
            $.post("/results/"+id+"/tag/color/"
                    + color.replace('#','%23'), function() {
                colors[ids.indexOf(id)] = color;
                if(id===$("#runs").val()[$("#runs").val().length-1]) {
                    $("#resetColor").removeAttr("disabled");
                    $("#runColor").spectrum("enable");
                    plot.getOptions().colors = colors;
                    plot.setData(plotData);
                    plot.draw();
                    overview.getOptions().colors = colors
                    overview.setData(plotData);
                    overview.draw();
                }
            });
        });
    };
    $("#removeTag").on("click", function() {
        $("#updateTag").attr('disabled','disabled');
        $("#removeTag").attr('disabled','disabled');
        $.ajax({
            type: "DELETE",
            url: "/results/"+$("#runs").val()[0]+"/tag/name"
        }).done(function() {
            $("#runTag").val([]);
            $("#runs option:selected").html($("#runs option:selected").val());
        });
    });
    $("#resetColor").on("click", function() {
        $("#resetColor").attr('disabled','disabled');
        $("#runs").val().forEach(function(id) {
            $.ajax({
                type: "DELETE",
                url: "/results/"+id+"/tag/color"
            }).done(function() {
                colors[ids.indexOf(id)] = '#ff3333';
                if(id===$("#runs").val()[$("#runs").val().length-1]) {
                    $("#runColor").spectrum("set", '#ff3333');
                    plot.getOptions().colors = colors;
                    plot.setData(plotData);
                    plot.draw();
                    overview.getOptions().colors = colors;
                    overview.setData(plotData);
                    overview.draw();
                }
            });
        });
    });
});<commit_msg>clean up documentation<commit_after>/*
 * Copyright 2015 Paul T. Grogan, Massachusetts Institute of Technology
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

define(["mas", "isrm", "jquery", "spectrum", "jquery.flot.min", "jquery.flot.selection.min"],
        function(mas, isrm, $) {
    var baseline = new isrm.Model();
    baseline.entities.forEach(function(entity) {
        if(entity instanceof mas.sd.Parameter
                || (entity instanceof mas.sd.Stock
                    && ! (entity instanceof mas.sd.Smooth)
                    && ! (entity instanceof mas.sd.Delay1))) {
            $("#xAxisVariable").append(
                $('<option></option>').val(entity.id).html(entity.name));
            $("#yAxisVariable").append(
                $('<option></option>').val(entity.id).html(entity.name));
        }
    });
    $("#xAxisVariable").val('nreCost');
    $("#xAxisVariable").change(updateTradespace);
    $("#yAxisVariable").val('projDuration');
    $("#yAxisVariable").change(updateTradespace);
    $("#initTime").val(0);
    $("#timeStep").val(0.25);
    $("#maxTime").val(120);
    $("#modelVersion").val(baseline.name + " v" + baseline.version);

    $("#runColor").spectrum({
        disabled: true,
        color: '#ff3333',
        preferredFormat: "hex",
        showInput: true,
        change: updateColor,
    });

    var plotData = [[]];
    var colors = [];
    var ids = [];

    var plot = $.plot("#tradespace", plotData, {
        series: {
            points: { show: true },
            lines: { show: false },
            shadowSize: 0
        },
        legend: {
            show: false
        },
        grid: {
            hoverable: true,
            clickable: true
        },
        selection: {
            mode: "xy"
        },
        xaxis: {
            tickFormatter: (function formatter(val, axis) { return val>1e6?val.toExponential():parseFloat(val.toFixed(6)); }),
        },
        yaxis: {
            tickFormatter: (function formatter(val, axis) { return val>1e6?val.toExponential():parseFloat(val.toFixed(6)); }),
        },
        colors: colors
    });

    var overview = $.plot("#overview", plotData, {
        legend: {
            show: false
        },
        series: {
            points: { show: true, radius: 1 },
            shadowSize: 0
        },
        xaxis: {
            show: false,
            min: 0
        },
        yaxis: {
            show: false,
            min: 0
        },
        grid: {
            color: "#999"
        },
        selection: {
            mode: "xy"
        },
        colors: colors
    });

    $("#tradespace").bind("plotselected", function (event, ranges) {
        if (ranges.xaxis.to - ranges.xaxis.from < 0.00001) {
            ranges.xaxis.to = ranges.xaxis.from + 0.00001;
        }

        if (ranges.yaxis.to - ranges.yaxis.from < 0.00001) {
            ranges.yaxis.to = ranges.yaxis.from + 0.00001;
        }

        plot = $.plot("#tradespace", plotData,
            $.extend(true, {}, {
                series: {
                    points: { show: true },
                    lines: { show: false },
                    shadowSize: 0
                },
                legend: {
                    show: false
                },
                grid: {
                    hoverable: true,
                    clickable: true
                },
                selection: {
                    mode: "xy"
                },
                colors: colors
            }, {
                xaxis: { min: ranges.xaxis.from, max: ranges.xaxis.to, tickFormatter: (function formatter(val, axis) { return val>1e6?val.toExponential():parseFloat(val.toFixed(6)); }) },
                yaxis: { min: ranges.yaxis.from, max: ranges.yaxis.to, tickFormatter: (function formatter(val, axis) { return val>1e6?val.toExponential():parseFloat(val.toFixed(6)); }) }
            })
        );
        overview.setSelection(ranges, true);
    });

    refreshRuns();

    $("#overview").bind("plotselected", function (event, ranges) {
        plot.setSelection(ranges);
    });

    $("#tradespace").bind("plotclick", function(event, pos, item) {
        if(item) {
            plot.unhighlight();
            plot.highlight(item.series, item.datapoint);

            $("#runs").val(ids[item.seriesIndex]);
            $("#runs").trigger("change");
        }
    });

    function updateTradespace() {
        plotData = [];
        for(var i = 0; i < ids.length; i++) {
            plotData[i] = {data:[], label:ids[i]};
        }
        var xVar = $("#xAxisVariable").val();
        var yVar = $("#yAxisVariable").val();
        getValues(xVar, function(res) {
            var x = [];
            for(var i = 0; i < res.length; i++) {
                if(baseline.entity(xVar) instanceof mas.sd.Stock) {
                    x[i] = res[i].finalOutputs[xVar];
                } else if(baseline.entity(xVar) instanceof mas.sd.Parameter) {
                    x[i] = res[i].params[xVar];
                }
            }
            getValues(yVar, function(res) {
                var y = [];
                for(var i = 0; i < res.length; i++) {
                    if(baseline.entity(yVar) instanceof mas.sd.Stock) {
                        y[i] = res[i].finalOutputs[yVar];
                    } else if(baseline.entity(yVar) instanceof mas.sd.Parameter) {
                        y[i] = res[i].params[yVar];
                    }
                    plotData[i] = {data: [[x[i], y[i]]], label: res[i]._id};
                }
                plot.getOptions().colors = colors;
                plot.getOptions().xaxis.min = {};
                plot.getOptions().xaxis.max = {};
                plot.getOptions().yaxis.min = {};
                plot.getOptions().yaxis.max = {};
                plot.setData(plotData);
                plot.setupGrid();
                plot.draw();
                overview.getOptions().colors = colors;
                overview.setData(plotData);
                overview.setupGrid();
                overview.draw();
            });
        });

        function getValues(varId, callback) {
            var query = {
                model: baseline.name,
                version: baseline.version,
                settings: {
                    init: Number($("#initTime").val()),
                    step: Number($("#timeStep").val()),
                    max: Number($("#maxTime").val())
                }
            }
            if(baseline.entity(varId) instanceof mas.sd.Stock) {
                $.get("/data/finalOutputs/"+varId+getFilter(), $.param(query), callback);
            } else if(baseline.entity(varId) instanceof mas.sd.Parameter) {
                $.get("/data/params/"+varId+getFilter(), $.param(query), callback);
            }
        }
    }

    function refreshRuns() {
        var query = {
            model: baseline.name,
            version: baseline.version,
            settings: {
                init: Number($("#initTime").val()),
                step: Number($("#timeStep").val()),
                max: Number($("#maxTime").val())
            }
        }
        $("#runs").find('option').remove();
        $("#runs").attr('disabled','disabled');
        $("#runTag").attr('disabled','disabled');
        $("#updateTag").attr('disabled','disabled');
        $("#removeTag").attr('disabled','disabled');
        ids = [];
        colors = [];
        $.get("/data/tag"+getFilter(), $.param(query), function(res) {
            if(res !== null) {
                res.forEach(function(item) {
                    ids.push(item._id);
                    $("#runs").append($('<option></option>').val(item._id).html((item.tag&&item.tag.name)?item.tag.name:item._id));
                    colors.push((item.tag&&item.tag.color)?item.tag.color:'#ff3333');
                });
                updateTradespace();
            }
            $("#runs").removeAttr("disabled");
        });
    }

    $('#filterRuns').change(refreshRuns);
    function getFilter() {
        if($('#filterRuns').val()==='') {
            return '';
        }
        var filters = $('#filterRuns').val()
                .replace(new RegExp('\\s', 'g'), '')
                .replace(new RegExp('!=', 'g'), '=$ne')
                .replace(new RegExp('>=', 'g'), '=$gte')
                .replace(new RegExp('<=', 'g'), '=$lte')
                .replace(new RegExp('>', 'g'), '=$gt')
                .replace(new RegExp('<', 'g'), '=$lt')
                .split(new RegExp('[,;]', 'g'));
        return '?params.'+filters.join("&params.");
    }

    $("#runs").on("change", function() {
        if($("#runs").val().length===1) {
            var id = $("#runs").val()[0];
            $("#runs").attr('disabled','disabled');
            $("#runID").val(id);
            if($("#runs option:selected").text()===id) {
                $("#runTag").val([]);
                $("#removeTag").attr('disabled','disabled');
            } else {
                $("#runTag").val($("#runs option:selected").text());
                $("#removeTag").removeAttr('disabled');
            }
            if(id !== null) {
                $("#runColor").spectrum("enable");
                $("#resetColor").removeAttr('disabled');
                $("#runColor").spectrum("set", colors[ids.indexOf(id)]);

                $.get("/results/"+id+"/params", function(res) {
                    $("#runParameters").val(JSON.stringify(res));
                    $("#runs").removeAttr("disabled");
                    $("#runs").focus();
                    $("#runTag").removeAttr('disabled');
                });

                plot.unhighlight();
                plot.highlight(ids.indexOf(id), 0);
            }
        } else {
            $("#runID").val([]);
            $("#runTag").val([]);
            $("#runTag").attr('disabled','disabled');
            $("#removeTag").attr('disabled','disabled');
            plot.unhighlight();
        }
    });
    $("#runTag").on("input propertychange paste", function() {
        $("#updateTag").removeAttr("disabled");
    });
    $("#updateTag").on("click", function() {
        $("#updateTag").attr('disabled','disabled');
        $("#removeTag").attr('disabled','disabled');
        $.post("/results/"+$("#runs").val()[0]+"/tag/name/"+$("#runTag").val(), function() {
            $("#runs option:selected").html($("#runTag").val());
            $("#removeTag").removeAttr("disabled");
        });
    });
    function updateColor() {
        $("#resetColor").attr('disabled','disabled');
        $("#runColor").spectrum("disable");
        $("#runs").val().forEach(function(id) {
            var color = $("#runColor").val();
            $.post("/results/"+id+"/tag/color/"
                    + color.replace('#','%23'), function() {
                colors[ids.indexOf(id)] = color;
                if(id===$("#runs").val()[$("#runs").val().length-1]) {
                    $("#resetColor").removeAttr("disabled");
                    $("#runColor").spectrum("enable");
                    plot.getOptions().colors = colors;
                    plot.setData(plotData);
                    plot.draw();
                    overview.getOptions().colors = colors
                    overview.setData(plotData);
                    overview.draw();
                }
            });
        });
    };
    $("#removeTag").on("click", function() {
        $("#updateTag").attr('disabled','disabled');
        $("#removeTag").attr('disabled','disabled');
        $.ajax({
            type: "DELETE",
            url: "/results/"+$("#runs").val()[0]+"/tag/name"
        }).done(function() {
            $("#runTag").val([]);
            $("#runs option:selected").html($("#runs option:selected").val());
        });
    });
    $("#resetColor").on("click", function() {
        $("#resetColor").attr('disabled','disabled');
        $("#runs").val().forEach(function(id) {
            $.ajax({
                type: "DELETE",
                url: "/results/"+id+"/tag/color"
            }).done(function() {
                colors[ids.indexOf(id)] = '#ff3333';
                if(id===$("#runs").val()[$("#runs").val().length-1]) {
                    $("#runColor").spectrum("set", '#ff3333');
                    plot.getOptions().colors = colors;
                    plot.setData(plotData);
                    plot.draw();
                    overview.getOptions().colors = colors;
                    overview.setData(plotData);
                    overview.draw();
                }
            });
        });
    });
});<|endoftext|>


<commit_before>"use strict";

angular.module('bzk.utils', []);

angular.module('bzk.utils').filter('bzkStatus', function() {
    var st2class = {
        'RUNNING': 'running',
        'SUCCESS': 'success',
        'FAILED': 'failed',
        'ERRORED': 'errored'
    };

    return function(job) {
        return st2class[job.status];
    };

});

angular.module('bzk.utils').factory('DateUtils', function() {
    return {
        isSet: function(date) {
            var m = moment(date);
            return m.year() != 1;
        }
    };
});

angular.module('bzk.utils').filter('bzkFinished', function() {
    return function(job) {
        if (job) {
            var m = moment(job.completed);
            return m.year() == 1 ? '-' : m.format('HH:mm:ss - DD MMM YYYY');
        }
    };
});

angular.module('bzk.utils').filter('bzkDate', function() {
    return function(d) {
        if (d) {
            var m = moment(d);
            return m.year() == 1 ? '-' : m.format('HH:mm:ss - DD MMM YYYY');
        }
    };
});

angular.module('bzk.utils').filter('bzkDuration', function() {
    return function(job) {
        if (job) {
            var m = moment(job.completed);
            if (m.year() === 1) {
                return moment().from(moment(job.started), true);
            } else {
                return m.from(job.started, true);
            }
        }
    };
});

angular.module('bzk.utils').filter('bzkExcerpt', function() {
    return function(s, width) {
        width = width || 7;
        if (s) {
            return s.substr(0, width);
        }
    };
});

angular.module('bzk.utils').filter('bzkId', function($filter) {
    return function(obj) {
        if (obj) {
            return $filter('bzkExcerpt')(obj.id, 7);
        }
    };
});

angular.module('bzk.utils').filter('titleCase', function() {
    return function(str) {
        return (str === undefined || str === null) ? '' : str.replace(/_|-/, ' ').replace(/\w\S*/g, function(txt) {
            return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
        });
    };
});

angular.module('bzk.utils').factory('Scroll', function($window) {
    return {
        toTheRight: function() {
            $('html, body').animate({
                scrollLeft: 1000
            }, 500);
        }
    };
});

angular.module('bzk.utils').directive('bzkLog', function() {
    return {
        restrict: 'A',
        scope: {
            sink: '=bzkLog'
        },
        template: '',
        link: function($scope, elem, attrs) {
            var row = 1;
            $(elem).append('

');
            var into = $(elem).find('pre');
            $scope.sink = {
                prepare: function() {
                    this.clear();
                    $scope.loading = true;
                },
                finish: function(lines) {
                    this.append(lines);
                    $scope.loading = false;
                },
                append: function(lines) {
                    var data = '';
                    _.each(lines, function(line) {
                        data += '
' + row + '' + line.msg + '
';
                        row++;
                    });
                    into.append(data);
                },
                clear: function() {
                    row = 1;
                    into.empty();
                    into.scrollTop(0);
                }
            };
        }
    };
});<commit_msg>Escape html tags in job and variant logs<commit_after>"use strict";

angular.module('bzk.utils', []);

angular.module('bzk.utils').filter('bzkStatus', function() {
    var st2class = {
        'RUNNING': 'running',
        'SUCCESS': 'success',
        'FAILED': 'failed',
        'ERRORED': 'errored'
    };

    return function(job) {
        return st2class[job.status];
    };

});

angular.module('bzk.utils').factory('DateUtils', function() {
    return {
        isSet: function(date) {
            var m = moment(date);
            return m.year() != 1;
        }
    };
});

angular.module('bzk.utils').filter('bzkFinished', function() {
    return function(job) {
        if (job) {
            var m = moment(job.completed);
            return m.year() == 1 ? '-' : m.format('HH:mm:ss - DD MMM YYYY');
        }
    };
});

angular.module('bzk.utils').filter('bzkDate', function() {
    return function(d) {
        if (d) {
            var m = moment(d);
            return m.year() == 1 ? '-' : m.format('HH:mm:ss - DD MMM YYYY');
        }
    };
});

angular.module('bzk.utils').filter('bzkDuration', function() {
    return function(job) {
        if (job) {
            var m = moment(job.completed);
            if (m.year() === 1) {
                return moment().from(moment(job.started), true);
            } else {
                return m.from(job.started, true);
            }
        }
    };
});

angular.module('bzk.utils').filter('bzkExcerpt', function() {
    return function(s, width) {
        width = width || 7;
        if (s) {
            return s.substr(0, width);
        }
    };
});

angular.module('bzk.utils').filter('bzkId', function($filter) {
    return function(obj) {
        if (obj) {
            return $filter('bzkExcerpt')(obj.id, 7);
        }
    };
});

angular.module('bzk.utils').filter('titleCase', function() {
    return function(str) {
        return (str === undefined || str === null) ? '' : str.replace(/_|-/, ' ').replace(/\w\S*/g, function(txt) {
            return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
        });
    };
});

angular.module('bzk.utils').factory('Scroll', function($window) {
    return {
        toTheRight: function() {
            $('html, body').animate({
                scrollLeft: 1000
            }, 500);
        }
    };
});

angular.module('bzk.utils').directive('bzkLog', function() {
    return {
        restrict: 'A',
        scope: {
            sink: '=bzkLog'
        },
        template: '',
        link: function($scope, elem, attrs) {
            var row = 1;
            $(elem).append('

');
            var into = $(elem).find('pre');
            $scope.sink = {
                prepare: function() {
                    this.clear();
                    $scope.loading = true;
                },
                finish: function(lines) {
                    this.append(lines);
                    $scope.loading = false;
                },
                append: function(lines) {
                    var data = '';
                    _.each(lines, function(line) {
                        data += '
' + row + '' + _.escape(line.msg) + '
';
                        row++;
                    });
                    into.append(data);
                },
                clear: function() {
                    row = 1;
                    into.empty();
                    into.scrollTop(0);
                }
            };
        }
    };
});<|endoftext|>


<commit_before>/* This is the javascript for the opt-in page. It sets/deletes
   a cookie which controls whether the flashproxy javascript
   code should run or disable itself. */

var COOKIE_NAME = "flashproxy";
/* max-age is not supported in IE. */
var COOKIE_LIFETIME = "Thu, 01 Jan 2020 00:00:00 GMT";

window.addEventListener("load", function () {

    /* Checks for a cookie with name cookie */
    function cookie_present() {
        var cookies = document.cookie.split(";");

        for (i in cookies) {
            var name = cookies[i].split("=")[0];

            while (name[0] === " ")
                name = name.substr(1);
            if (COOKIE_NAME === name)
                return true;
        }
        return false;
    }

    /* Updates the text telling the user what his current setting is.*/
    function update_setting_text() {
        var setting = document.getElementById("setting");
        var prefix = "
Your current setting is: ";

        if (cookie_present()) {
            setting.innerHTML = prefix + "use my browser as a proxy. " +
                                         "Click no below to change your setting.
";
        } else {
            setting.innerHTML = prefix + "do not use my browser as a proxy. " +
                                         "Click yes below to change your setting.
";
        }
    }

    function set_cookie() {
        document.cookie = COOKIE_NAME + "= ;path=/ ;expires=" + COOKIE_LIFETIME;
    }

    function del_cookie() {
        document.cookie = COOKIE_NAME + "= ;path=/ ;expires=Thu, 01 Jan 1970 00:00:00 GMT";
    }

    if (navigator.cookieEnabled) {
        var buttons = document.getElementById("buttons");
        buttons.addEventListener("click", update_setting_text);
        document.getElementById("yes").addEventListener("click", set_cookie);
        document.getElementById("no").addEventListener("click", del_cookie);
        buttons.style.display = "block";
        update_setting_text();
    } else {
        document.getElementById("cookies_disabled").style.display = "block";
        /* Manually set the text here as otherwise it will refer to
           the buttons, which don't show if cookies are disabled. */
        document.getElementById("setting").innerHTML = "
Your current setting is: " +
                                                       "do not use my browser as a proxy.
";
    }
});
<commit_msg>Remove comment which is no longer relevant.<commit_after>/* This is the javascript for the opt-in page. It sets/deletes
   a cookie which controls whether the flashproxy javascript
   code should run or disable itself. */

var COOKIE_NAME = "flashproxy";
/* max-age is not supported in IE. */
var COOKIE_LIFETIME = "Thu, 01 Jan 2020 00:00:00 GMT";

window.addEventListener("load", function () {

    function cookie_present() {
        var cookies = document.cookie.split(";");

        for (i in cookies) {
            var name = cookies[i].split("=")[0];

            while (name[0] === " ")
                name = name.substr(1);
            if (COOKIE_NAME === name)
                return true;
        }
        return false;
    }

    /* Updates the text telling the user what his current setting is.*/
    function update_setting_text() {
        var setting = document.getElementById("setting");
        var prefix = "
Your current setting is: ";

        if (cookie_present()) {
            setting.innerHTML = prefix + "use my browser as a proxy. " +
                                         "Click no below to change your setting.
";
        } else {
            setting.innerHTML = prefix + "do not use my browser as a proxy. " +
                                         "Click yes below to change your setting.
";
        }
    }

    function set_cookie() {
        document.cookie = COOKIE_NAME + "= ;path=/ ;expires=" + COOKIE_LIFETIME;
    }

    function del_cookie() {
        document.cookie = COOKIE_NAME + "= ;path=/ ;expires=Thu, 01 Jan 1970 00:00:00 GMT";
    }

    if (navigator.cookieEnabled) {
        var buttons = document.getElementById("buttons");
        buttons.addEventListener("click", update_setting_text);
        document.getElementById("yes").addEventListener("click", set_cookie);
        document.getElementById("no").addEventListener("click", del_cookie);
        buttons.style.display = "block";
        update_setting_text();
    } else {
        document.getElementById("cookies_disabled").style.display = "block";
        /* Manually set the text here as otherwise it will refer to
           the buttons, which don't show if cookies are disabled. */
        document.getElementById("setting").innerHTML = "
Your current setting is: " +
                                                       "do not use my browser as a proxy.
";
    }
});
<|endoftext|>