<commit_before>// Load in dependencies
var fs = require('fs');
var vm = require('vm');
var astw = require('astw');
var expect = require('chai').expect;
var ecmaScopes = require('../');

// TODO: Rename this file to lexical tests

// Define test utilities
var testUtils = {
  loadScript: function (filepath) {
    before(function loadScriptFn () {
      // Load our script and parse its AST
      this.script = fs.readFileSync(filepath, 'utf8');
      this.walker = astw(this.script);
    });
    before(function openVmFn () {
      // Load our file into the VM
      this.vm = {};
      vm.runInNewContext(this.script, this.vm);
    });
    after(function cleanup () {
      // Clean up the script and vm
      delete this.script;
      delete this.walker;
      delete this.vm;
    });
  }
};

// Define our tests
describe('ecma-scopes\' lexical scopes:', function () {
  // TODO: Load from JSON, convert to dash-case, and load file
  // TODO: Then iterate in a `forEach` loop
  ecmaScopes.lexical.forEach(function testLexicalCase (type, typeIndex) {
    describe('a "' + type + '"', function () {
      // Resolve and load our scope file
      // e.g. `test-files/lexical-FunctionDeclaration.js`
      var filepath = __dirname + '/test-files/lexical-' + type + '.js';
      testUtils.loadScript(filepath);

      // Collect the parents for analysis within the lexical scope
      before(function collectParents () {
        // TODO: Is there a cleaner way to do this?
        var parents = this.parents = [];
        this.walker(function evaluateNode (node) {
          // If we have already hit our lexical container, stop
          if (parents.length !== 0) {
            return;
          }

          // If the node is an Identifier and `lexical`
          if (node.type === 'Identifier' && node.name === 'lexical') {
            // Walk its parents until we resolve a function
            node = node.parent;
            while (node) {
              // Save the parent node
              parents.push(node);

              // If the node is a `Function`, stop
              // TODO: Handle `FunctionExpression
              // TODO: We can stop at the first lexical scope...
              if (node.type === 'FunctionDeclaration') {
                return;
              }

              // Resolve the next parent node
              node = node.parent;
            }
          }
        });
      });

      it('is a lexical scope', function () {
        expect(this.vm).to.not.have.ownProperty('lexical');
      });

      it('contains `lexical` inside of a "' + type + '"', function () {
        var container = this.parents[this.parents.length - 1];
        expect(container.type).to.equal(type);
      });

      // TODO: For `block` scoping, we need a clarifier for lexical and other block scopes
      it('does not contain `lexical` inside of other lexical scopes', function () {
        // TODO: We need our JSON to be done for this to work
        // Collect the other lexical scopes
        var otherLexicalScopes = ecmaScopes.lexical.slice();
        otherLexicalScopes.splice(typeIndex, 1);

        // Verify each of the nodes is not in there
        this.parents.forEach(function assertNotOtherLexical (parent) {
          expect(parent.type).to.not.equal(undefined);
          expect(otherLexicalScopes).to.not.contain(parent.type);
        });
      });
    });
  });
});
<commit_msg>Repaired test<commit_after>// Load in dependencies
var fs = require('fs');
var vm = require('vm');
var astw = require('astw');
var expect = require('chai').expect;
var ecmaScopes = require('../');

// TODO: Rename this file to lexical tests

// Define test utilities
var testUtils = {
  loadScript: function (filepath) {
    before(function loadScriptFn () {
      // Load our script and parse its AST
      this.script = fs.readFileSync(filepath, 'utf8');
      this.walker = astw(this.script);
    });
    before(function openVmFn () {
      // Load our file into the VM
      this.vm = {};
      vm.runInNewContext(this.script, this.vm);
    });
    after(function cleanup () {
      // Clean up the script and vm
      delete this.script;
      delete this.walker;
      delete this.vm;
    });
  }
};

// Define our tests
describe('ecma-scopes\' lexical scopes:', function () {
  // TODO: Load from JSON, convert to dash-case, and load file
  // TODO: Then iterate in a `forEach` loop
  ecmaScopes.lexical.forEach(function testLexicalCase (type, typeIndex) {
    describe('a "' + type + '"', function () {
      // Resolve and load our scope file
      // e.g. `test-files/lexical-FunctionDeclaration.js`
      var filepath = __dirname + '/test-files/lexical-' + type + '.js';
      testUtils.loadScript(filepath);

      // Collect the parents for analysis within the lexical scope
      before(function collectParents () {
        // TODO: Is there a cleaner way to do this?
        var parents = this.parents = [];
        this.walker(function evaluateNode (node) {
          // If we have already hit our lexical container, stop
          if (parents.length !== 0) {
            return;
          }

          // If the node is an Identifier and `lexical`
          if (node.type === 'Identifier' && node.name === 'lexical') {
            // Walk its parents until we resolve a function
            node = node.parent;
            while (node) {
              // Save the parent node
              parents.push(node);

              // If the node is our type, stop
              if (node.type === type) {
                return;
              }

              // Resolve the next parent node
              node = node.parent;
            }
          }
        });
      });

      it('is a lexical scope', function () {
        expect(this.vm).to.not.have.ownProperty('lexical');
      });

      it('contains `lexical` inside of a "' + type + '"', function () {
        var container = this.parents[this.parents.length - 1];
        expect(container.type).to.equal(type);
      });

      // TODO: For `block` scoping, we need a clarifier for lexical and other block scopes
      it('does not contain `lexical` inside of other lexical scopes', function () {
        // TODO: We need our JSON to be done for this to work
        // Collect the other lexical scopes
        var otherLexicalScopes = ecmaScopes.lexical.slice();
        otherLexicalScopes.splice(typeIndex, 1);

        // Verify each of the nodes is not in there
        this.parents.forEach(function assertNotOtherLexical (parent) {
          expect(parent.type).to.not.equal(undefined);
          expect(otherLexicalScopes).to.not.contain(parent.type);
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>define(["Tone/core/Tone", "Tone/source/Source", "Tone/source/Oscillator", "Tone/signal/Signal", "Tone/signal/Threshold"],
function(Tone){

	"use strict";

	/**
	 *
	 *  @static
	 *  @private
	 *  @type {Float32Array}
	 */
	var pulseCurve = new Float32Array(256);

	for(var i=0; i < 128; i++) {
		pulseCurve[i] = -1;
		pulseCurve[i+128] = 1;
	}

	/**
	 *  @class Pulse Oscillator with control over width
	 *
	 *  @constructor
	 *  @extends {Tone.Source}
	 *  @param {number=} frequency the frequency of the oscillator
	 *  @param {number=} [width = 0.5] the width of the pulse
	 */
	Tone.PulseOscillator = function(frequency, width){

		Tone.Source.call(this);

		/**
		 *  the width of the pulse
		 *  @type {Tone.Signal}
		 */
		this.width = new Tone.Signal(this.defaultArg(width, 0.5));

		/**
		 *  the sawtooth oscillator
		 *  @type {Tone.Oscillator}
		 *  @private
		 */
		this._sawtooth = new Tone.Oscillator(frequency, "sawtooth");

		/**
		 *  the oscillators frequency
		 *  @type {Tone.Signal}
		 */
		this.frequency = this._sawtooth.frequency;

		/**
		 *  the oscillators detune
		 *  @type {Tone.Signal}
		 */
		this.detune = this._sawtooth.detune;

		/**
		 *  threshold the signal to turn it into a square
		 *
		 *  @type {WaveShaperNode}
		 *  @private
		 */
		this._thresh = this.context.createWaveShaper();
		this._thresh.curve = pulseCurve;

		this.chain(this._sawtooth, this._thresh, this.output);
		this.width.connect(this._thresh);
	};

	Tone.extend(Tone.PulseOscillator, Tone.Source);

	/**
	 *  set the width of the oscillators
	 *  @param {number} width
	 */
	Tone.PulseOscillator.prototype.setWidth = function(width){
		this.width.setValue(width);
	};

	/**
	 *  start the oscillator
	 *
	 *  @param  {Tone.Time} time
	 */
	Tone.PulseOscillator.prototype.start = function(time){
		if (this.state === Tone.Source.State.STOPPED){
			time = this.toSeconds(time);
			this._sawtooth.start(time);
			this.width.output.gain.setValueAtTime(1, time);
			this.state = Tone.Source.State.STARTED;
		}
	};

	/**
	 *  stop the oscillator
	 *
	 *  @param  {Tone.Time} time
	 */
	Tone.PulseOscillator.prototype.stop = function(time){
		if (this.state === Tone.Source.State.STARTED){
			time = this.toSeconds(time);
			this._sawtooth.stop(time);
			//the width is still connected to the output.
			//that needs to be stopped also
			this.width.output.gain.setValueAtTime(0, time);
			this.state = Tone.Source.State.STOPPED;
		}
	};

	/**
	 *  clean up method
	 */
	Tone.PulseOscillator.prototype.dispose = function(){
		Tone.Source.prototype.dispose.call(this);
		this._sawtooth.dispose();
		this.width.dispose();
		this._thresh.disconnect();
		this._sawtooth = null;
		this.frequency = null;
		this.detune = null;
		this.width = null;
		this._thresh = null;
	};

	return Tone.PulseOscillator;
});<commit_msg>PulseOscillator setters<commit_after>define(["Tone/core/Tone", "Tone/source/Source", "Tone/source/Oscillator", "Tone/signal/Signal", "Tone/signal/Threshold"],
function(Tone){

	"use strict";

	/**
	 *
	 *  @static
	 *  @private
	 *  @type {Float32Array}
	 */
	var pulseCurve = new Float32Array(256);
	for(var i=0; i < 128; i++) {
		pulseCurve[i] = -1;
		pulseCurve[i+128] = 1;
	}

	/**
	 *  @class Pulse Oscillator with control over width
	 *
	 *  @constructor
	 *  @extends {Tone.Source}
	 *  @param {number=} frequency the frequency of the oscillator
	 *  @param {number} [width = 0.5] the width of the pulse
	 */
	Tone.PulseOscillator = function(){

		Tone.Source.call(this);
		var options = this.optionsObject(arguments, ["frequency", "width"], Tone.Oscillator.defaults);

		/**
		 *  the width of the pulse
		 *  @type {Tone.Signal}
		 */
		this.width = new Tone.Signal(options.width);

		/**
		 *  the sawtooth oscillator
		 *  @type {Tone.Oscillator}
		 *  @private
		 */
		this._sawtooth = new Tone.Oscillator({
			frequency : options.frequency,
			detune : options.detune,
			type : "sawtooth",
			phase : options.phase
		});

		/**
		 *  the oscillators frequency
		 *  @type {Tone.Signal}
		 */
		this.frequency = this._sawtooth.frequency;

		/**
		 *  the oscillators detune
		 *  @type {Tone.Signal}
		 */
		this.detune = this._sawtooth.detune;

		/**
		 *  callback which is invoked when the oscillator is stoped
		 *  @type {function()}
		 */
		this.onended = options.onended;

		/**
		 *  threshold the signal to turn it into a square
		 *
		 *  @type {WaveShaperNode}
		 *  @private
		 */
		this._thresh = this.context.createWaveShaper();
		this._thresh.curve = pulseCurve;

		//connections
		this.chain(this._sawtooth, this._thresh, this.output);
		this.width.connect(this._thresh);
		this._sawtooth.onended = this._onended.bind(this);
	};

	Tone.extend(Tone.PulseOscillator, Tone.Source);

	/**
	 *  the default parameters
	 *
	 *  @static
	 *  @const
	 *  @type {Object}
	 */
	Tone.PulseOscillator.defaults = {
		"frequency" : 440,
		"detune" : 0,
		"phase" : 0,
		"width" : 0.5,
		"onended" : function(){},
	};

	/**
	 *  set the width of the oscillators
	 *  @param {number} width
	 */
	Tone.PulseOscillator.prototype.setWidth = function(width){
		this.width.setValue(width);
	};

	/**
	 *  set the phase of the oscillator
	 *  @param {number} phase
	 */
	Tone.PulseOscillator.prototype.setPhase = function(phase){
		this._sawtooth.setPhase(phase);
	};

	/**
	 *  exponentially ramp the frequency of the oscillator over the rampTime
	 *  inherited from Tone.Oscillator
	 *
	 *  @param {Tone.Time}	val
	 *  @param {Tone.Time=} rampTime when the oscillator will arrive at the frequency
	 */
	Tone.PulseOscillator.prototype.setFrequency = Tone.Oscillator.prototype.setFrequency;

	/**
	 *  bulk setter
	 *  @param {Object} params
	 */
	Tone.PulseOscillator.prototype.set = function(params){
		if (!this.isUndef(params.width)) this.setWidth(params.width);
		this._sawtooth.set({
			"phase" : params.phase,
			"frequency" : params.frequency,
			"detune" : params.detune
		});
	};

	/**
	 *  start the oscillator
	 *
	 *  @param  {Tone.Time} time
	 */
	Tone.PulseOscillator.prototype.start = function(time){
		if (this.state === Tone.Source.State.STOPPED){
			time = this.toSeconds(time);
			this._sawtooth.start(time);
			this.width.output.gain.setValueAtTime(1, time);
			this.state = Tone.Source.State.STARTED;
		}
	};

	/**
	 *  stop the oscillator
	 *
	 *  @param  {Tone.Time} time
	 */
	Tone.PulseOscillator.prototype.stop = function(time){
		if (this.state === Tone.Source.State.STARTED){
			time = this.toSeconds(time);
			this._sawtooth.stop(time);
			//the width is still connected to the output.
			//that needs to be stopped also
			this.width.output.gain.setValueAtTime(0, time);
			this.state = Tone.Source.State.STOPPED;
		}
	};

	/**
	 *  internal on end call
	 *  @private
	 */
	Tone.PulseOscillator.prototype._onended = function(){
		this.state = Tone.Source.State.STOPPED;
		this.onended();
	};

	/**
	 *  clean up method
	 */
	Tone.PulseOscillator.prototype.dispose = function(){
		Tone.Source.prototype.dispose.call(this);
		this._sawtooth.dispose();
		this.width.dispose();
		this._thresh.disconnect();
		this._sawtooth = null;
		this.frequency = null;
		this.detune = null;
		this.width = null;
		this._thresh = null;
	};

	return Tone.PulseOscillator;
});<|endoftext|>


<commit_before>
var utils = require('./utils.js');
var context = require('./context.js');
var path = require('path');

module.exports = {
	create: create
};

function create(rootDir) {
	return {
		buildModule: buildModule
	};

	function buildModule(moduleId, opts) {
		opts = opts || {};
		var localImports = opts.imports || {};
		var extImports = opts.extImports || {};
		var globals = opts.globals || {};

		var ctx = context.create({
			externalResolverFn: function(id) {
				// Specify an external resolver that
				// TODO: Add suggestions if they're missing an import
				if (!extImports.hasOwnProperty(id)) {
					throw 'External dependency [' + id + '] was not satisfied for module: [' + fname + ']';
				}
				return extImports[id];
			},
			globalResolverFn: function(globalId) {
				// For single modules, we expect them to provide a mapping of globals
				// TODO: Suggestions if they forgot/misspelled a global
				if (!globals.hasOwnProperty(globalId)) {
					var msg = 'Could '
					var keys = utils.objectKeys(globals);
					var similar = utils.findSimilar(globalId, keys);

				}
				return globals[globalId];
			}
		});

		utils.each(localImports, function(val, id) {
			ctx.addMapping({
				_id: id,
				init: function() { return val; }
			});
		});

		var fname = path.join(rootDir, utils.directoryFromModuleId(moduleId) + '.js');
		var m = require(fname);
		m._id = moduleId;
		var mapping = ctx.addMapping(m, undefined, fname);
		return ctx.loadModule(mapping.id);
	}
};<commit_msg>updated testing api<commit_after>
var utils = require('./utils.js');
var context = require('./context.js');
var path = require('path');

module.exports = {
	create: create
};

function create(rootDir) {
	return {
		buildModule: buildModule
	};

	function buildModule(moduleId, opts) {
		opts = opts || {};
		var locals = opts.locals || {};
		var externals = opts.externals || {};
		var globals = opts.globals || {};

		var ctx = context.create({
			externalResolverFn: function(id) {
				// Specify an external resolver that
				// TODO: Add suggestions if they're missing an import
				if (!externals.hasOwnProperty(id)) {
					throw 'External dependency [' + id + '] was not satisfied for module: [' + fname + ']';
				}
				return externals[id];
			},
			globalResolverFn: function(globalId) {
				// For single modules, we expect them to provide a mapping of globals
				// TODO: Suggestions if they forgot/misspelled a global
				if (!globals.hasOwnProperty(globalId)) {
					var msg = 'Could '
					var keys = utils.objectKeys(globals);
					var similar = utils.findSimilar(globalId, keys);

				}
				return globals[globalId];
			}
		});

		utils.each(locals, function(val, id) {
			ctx.addMapping({
				_id: id,
				init: function() { return val; }
			});
		});

		var fname = path.join(rootDir, utils.directoryFromModuleId(moduleId) + '.js');
		var m = require(fname);
		m._id = moduleId;
		var mapping = ctx.addMapping(m, undefined, fname);
		return ctx.loadModule(mapping.id);
	}
};<|endoftext|>


<commit_before>
var App = {}

App.deal = function () {
    App.socket.emit('deal');
}

App.stand = function () {
    App.socket.emit('stand');
}

App.hit = function () {
    App.socket.emit('hit');
}

App.getSuitHtml = function (suit) {
    var image = 'club.png';
    if (suit === 'H') {
        image = 'heart.png';
    } else if (suit === 'S') {
        image = 'spade.png';
    } else if (suit === 'D') {
        image = 'diamond.png';
    }
    return "";
}
App.getRankHtml = function (rank) {
    if (rank === 1) {
        return 'A';
    } else if (rank === 11) {
        return 'J';
    } else if (rank === 12) {
        return 'Q';
    } else if (rank === 13) {
        return 'K';
    }
    return rank;
}
App.getCardsHtml = function (cards) {
    var html = '';
    for (var i = 0; i < cards.length; i++) {

        var card = cards[i];

        html += App.getRankHtml(card.face);
        html += App.getSuitHtml(card.suit);
    }
    return html;
}
App.updatePlayer = function (player) {

    var html = App.getCardsHtml(player.cards);

    $('#playerCards').html(html);
    $('#playerScore').text(player.score);
}
App.updateDealer = function (dealer) {

    var html = App.getCardsHtml(dealer.cards);

    $('#dealerCards').html(html);
    $('#dealerScore').text(dealer.score);
}

App.updateResult = function (result) {
    var displayResult = result;

    if (result === 'None') {
        displayResult = '';
    }
    $('#result').text(displayResult);
}

App.disableButton = function (id) {

    $(id).attr('disabled', 'disabled');
}

App.enableButton = function (id) {
    $(id).removeAttr('disabled');
}
App.disableDeal = function () {
    App.disableButton('#deal');
    App.enableButton('#hit');
    App.enableButton('#stand');
}
App.enableDeal = function () {

    App.enableButton('#deal');
    App.disableButton('#hit');
    App.disableButton('#stand');
}
App.enableDealIfGameFinished = function (result) {
    if (result !== 'None') {
        App.enableDeal();
    }
}
App.dealResult = function (game) {
    App.disableDeal();
    App.updateDealer(game.dealer);
    App.updatePlayer(game.player);
    App.updateResult(game.result);
}
App.hitResult = function (game) {
    App.disableDeal();

    App.updateDealer(game.dealer);
    App.updatePlayer(game.player);
    App.updateResult(game.result);
}
App.standResult = function (game) {

    App.updateDealer(game.dealer);
    App.updatePlayer(game.player);
    App.updateResult(game.result);

    App.enableDealIfGameFinished(game.result);
}
App.socket = {}
App.registerClientActions = function () {

    $('#deal').click(function () {
        App.deal();
    });
    $('#stand').click(function () {
        App.stand();
    });
        $('#hit').click(function () {
        App.hit();
    });
}
App.registerServerActions = function () {
    App.socket.on('stand', function (game) {
        App.standResult(game);
    });
    App.socket.on('deal', function (game) {
        App.dealResult(game);
    });
    App.socket.on('hit', function (game) {
        App.hitResult(game);
    });
}

App.getUserName = function()
{
    App.socket.on('connect', function (){
      App.socket.emit('adduser', prompt("What's your name?"));
             });
        var userList = [];
    App.socket.on('update', function (users){
        userList = users;
        $('#user').empty();
        for(var i=0; i<userList.length; i++) {
            $('#user').append("
" + userList[i] + "
");
        }
    });
}
App.init = function () {

    var socket = io.connect('http://localhost:3000');
    App.socket = socket;
    App.registerClientActions();
    App.registerServerActions();
    App.enableDeal();
    App.getUserName();
}

$(document).ready(function () {
    App.init();
});<commit_msg>Fixed Bust forcing stand issue<commit_after>
var App = {}

App.deal = function () {
    App.socket.emit('deal');
}

App.stand = function () {
    App.socket.emit('stand');
}

App.hit = function () {
    App.socket.emit('hit');
}

App.getSuitHtml = function (suit) {
    var image = 'club.png';
    if (suit === 'H') {
        image = 'heart.png';
    } else if (suit === 'S') {
        image = 'spade.png';
    } else if (suit === 'D') {
        image = 'diamond.png';
    }
    return "";
}
App.getRankHtml = function (rank) {
    if (rank === 1) {
        return 'A';
    } else if (rank === 11) {
        return 'J';
    } else if (rank === 12) {
        return 'Q';
    } else if (rank === 13) {
        return 'K';
    }
    return rank;
}
App.getCardsHtml = function (cards) {
    var html = '';
    for (var i = 0; i < cards.length; i++) {

        var card = cards[i];

        html += App.getRankHtml(card.face);
        html += App.getSuitHtml(card.suit);
    }
    return html;
}
App.updatePlayer = function (player) {

    var html = App.getCardsHtml(player.cards);

    $('#playerCards').html(html);
    $('#playerScore').text(player.score);
}
App.updateDealer = function (dealer) {

    var html = App.getCardsHtml(dealer.cards);

    $('#dealerCards').html(html);
    $('#dealerScore').text(dealer.score);
}

App.updateResult = function (result) {
    var displayResult = result;

    if (result === 'None') {
        displayResult = '';
    }
    $('#result').text(displayResult);
}

App.disableButton = function (id) {

    $(id).attr('disabled', 'disabled');
}

App.enableButton = function (id) {
    $(id).removeAttr('disabled');
}
App.disableDeal = function () {
    App.disableButton('#deal');
    App.enableButton('#hit');
    App.enableButton('#stand');
}
App.enableDeal = function () {

    App.enableButton('#deal');
    App.disableButton('#hit');
    App.disableButton('#stand');
}
App.enableDealIfGameFinished = function (result) {
    if (result !== 'None') {
        App.enableDeal();
    }
}
App.dealResult = function (game) {
    App.disableDeal();
    App.updateDealer(game.dealer);
    App.updatePlayer(game.player);
    App.updateResult(game.result);
}
App.hitResult = function (game) {
    //App.disableDeal();

    App.updateDealer(game.dealer);
    App.updatePlayer(game.player);
    App.updateResult(game.result);
    App.enableDealIfGameFinished(game.result);
}
App.standResult = function (game) {

    App.updateDealer(game.dealer);
    App.updatePlayer(game.player);
    App.updateResult(game.result);
    App.enableDealIfGameFinished(game.result);
}
App.socket = {}
App.registerClientActions = function () {

    $('#deal').click(function () {
        App.deal();
    });
    $('#stand').click(function () {
        App.stand();
    });
        $('#hit').click(function () {
        App.hit();
    });
}
App.registerServerActions = function () {
    App.socket.on('stand', function (game) {
        App.standResult(game);
    });
    App.socket.on('deal', function (game) {
        App.dealResult(game);
    });
    App.socket.on('hit', function (game) {
        App.hitResult(game);
    });
}

App.getUserName = function()
{
    App.socket.on('connect', function (){
      App.socket.emit('adduser', prompt("What's your name?"));
             });
        var userList = [];
    App.socket.on('update', function (users){
        userList = users;
        $('#user').empty();
        for(var i=0; i<userList.length; i++) {
            $('#user').append("
" + userList[i] + "
");
        }
    });
}
App.init = function () {

    var socket = io.connect('http://localhost:3000');
    App.socket = socket;
    App.registerClientActions();
    App.registerServerActions();
    App.enableDeal();
    App.getUserName();
}

$(document).ready(function () {
    App.init();
});<|endoftext|>


<commit_before>/*global module, describe, beforeEach, inject, it, expect*/
describe('Controller: AboutCtrl', function () {
    'use strict';

      // load the controller's module
    beforeEach(module('vicarApp'));

    var AboutCtrl,
        scope;

      // Initialize the controller and a mock scope
    beforeEach(inject(function ($controller, $rootScope) {
        scope = $rootScope.$new();
        AboutCtrl = $controller('AboutCtrl', {
            $scope: scope
        });
    }));

    it('should attach a list of awesomeThings to the scope', function () {
        expect(scope.awesomeThings.length).toBe(3);
    });
});
<commit_msg>No unit tests errors. (Hardly any unit tests either :)<commit_after>/*global module, describe, beforeEach, inject, it, expect*/
describe('Controller: AboutCtrl', function () {
    'use strict';

      // load the controller's module
    beforeEach(module('vicarApp'));

    var AboutCtrl,
        scope;

      // Initialize the controller and a mock scope
    beforeEach(inject(function ($controller, $rootScope) {
        scope = $rootScope.$new();
        AboutCtrl = $controller('AboutCtrl', {
            $scope: scope
        });
    }));

});
<|endoftext|>


<commit_before>var _ = require("lodash");
var async = require("async");
var config = require("config");
var cheerio = require("cheerio");
var querystring = require("querystring");
var dailyRequest = require("request").defaults({
    baseUrl : config.zhihu_daily_api
});

var story = require("../story");
var utils = require("../utils");
const PREFIX = "/api/4/imgs/";

/**
 * 从知乎日报服务器获取最新的知乎日报 ID 列表。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.fetchLatestStoryIDs = function (p_callback)
{
    if (!_.isFunction(p_callback)) return;

    dailyRequest.get({ url: "/news/latest", json: true }, function (err, res, body)
    {
        if (!err && res.statusCode == 200)
        {
            // 因知乎日报的 API 返回的图片太小，这里直接丢弃，后面再通过其他途径获取图片。
            p_callback(null, {
                date: body.date,
                ids: body.stories.map(function (value)
                {
                    return value.id;
                })
            });
        }
        else
        {
            p_callback(new Error("request zhihu-daily api ('/news/latest') error:" + err.message), null);
        }
    });
};

/**
 * 从知乎日报服务器获取指定日期的知乎日报 ID 列表。
 * @param  {String} p_date       指定的日期。如果小于 20130519，返回值 res 为 {}。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.fetchStoryIDs = function (p_date, p_callback)
{
    if (!_.isFunction(p_callback)) return;

    // 因知乎日报 API 返回的是指定日期的前一天的日报，
    // 所以要加一天才能获取指定日期的日报。
    var date = utils.nextZhihuDay(p_date);
    if (date)
    {
        if (utils.convertZhihuDateToMoment(date).isBefore(utils.MIN_DATE))
        {
            // 20130519 之前是没有知乎日报的。
            p_callback(null, {});
        }
        else
        {
            dailyRequest.get({ url: "/news/before/" + date, json: true }, function (err, res, body)
            {
                if (!err && res.statusCode == 200)
                {
                    p_callback(null, {
                        date: body.date,
                        ids: body.stories.map(function (value)
                        {
                            return value.id;
                        })
                    });
                }
                else
                {
                    p_callback(new Error("request zhihu-daily api ('/news/before/:date') error:" + err.message), null);
                }
            });
        }
    }
    else
    {
        p_callback(new Error("p_date has a wrong format."), null);
    }
};

/**
 * 从知乎日报服务器获取指定 ID 的知乎日报。
 * @param  {String} p_id         指定的 ID。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.fetchStory = function (p_id, p_callback)
{
    if (!_.isFunction(p_callback)) return;

    // 首先检查 ID 是否为纯数字。
    if (/^\d+$/.test(p_id))
    {
        dailyRequest.get({ url: "/news/" + p_id, json: true }, function (err, res, body)
        {
            if (!err && res.statusCode == 200)
            {
                var result = {};
                result.id = body.id;
                result.title = body.title;

                // TODO: 图片暂时不入库，后面再说。
                result.image = PREFIX + querystring.escape(body.image);

                result.imageSource = body.image_source;
                result.shareURL = body.share_url;

                if (body.body)
                {
                    var $ = cheerio.load(body.body, { decodeEntities: false });
                    result.backgrounds = $(".headline>.headline-background .headline-background-link").map(function (i, e)
                    {
                        return {
                            href: $(e).attr("href"),
                            title : $(e).children(".heading").text(),
                            text : $(e).children(".heading-content").text()
                        };
                    }).get();

                    result.contents = $(".content-inner>.question").map(function (i, e)
                    {
                        var question = {};
                        question.title = $(e).children(".question-title").text();
                        question.answers = $(e).children(".answer").map(function (i, e)
                        {
                            // TODO: 图片暂时不入库，后面再说。
                            $(e).find(".content img").each(function (i, e)
                            {
                                var src = $(e).attr("src");
                                if (src != null && src != "")
                                {
                                    $(e).attr("src", PREFIX + querystring.escape(src));
                                }
                            });

                            // TODO: 图片暂时不入库，后面再说。
                            var avatar = $(e).find(".meta>.avatar").attr("src");
                            if (avatar != null && avatar != "")
                            {
                                avatar = PREFIX + querystring.escape(avatar);
                            }
                            else
                            {
                                avatar = "";
                            }

                            return {
                                avatar : avatar,
                                name: $(e).find(".meta>.author").text(),
                                bio : $(e).find(".meta>.bio").text(),
                                content : $(e).children(".content").html()
                            };
                        }).get();

                        var a = $(e).find(".view-more>a");
                        if (a.length > 0)
                        {
                            question.link = {
                                href : a.attr("href"),
                                text : a.text(),
                            };
                        }

                        return question;
                    }).get();
                }
                p_callback(null, result);
            }
            else
            {
                p_callback(new Error("request zhihu-daily api ('/news/:id') error:" + err.message), null);
            }
        });
    }
    else
    {
        p_callback(new Error("p_id has a wrong format."), null);
    }
};

/**
 * 离线指定的日报。
 * @param  {String} p_id         知乎日报 ID。
 * @param  {String} p_date       日报对应的日期。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.cacheStory = function (p_id, p_date, p_callback)
{
    async.retry({
        times: config.crawler.daily_retry,
        interval: config.crawler.daily_interval * 1000
    }, this.fetchStory.bind(this, p_id), function (err, res)
    {
        // 记录未成功抓取的日报。
        if (err)
        {
            story.logUncachedStory(p_id, p_date, p_callback);
        }
        else
        {
            res.date = p_date;
            story.saveStory(res, p_callback);
        }
    });
};

/**
 * 离线最新的知乎日报。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.cacheLatestStories = function (p_callback)
{
    async.waterfall(
        [
            _fetchLatestStoryIDsTask.bind(this),
            _preprocessTask,
            _cacheStoriesTask.bind(this)
        ],
        p_callback
    );
};

/**
 * 离线指定日期的知乎日报。
 * @param  {String} p_date       指定的日期。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.cacheStoriesOfDate = function (p_date, p_callback)
{
    async.waterfall(
        [
            _fetchStoryIDsTask.bind(this, p_date),
            _preprocessTask,
            _cacheStoriesTask.bind(this)
        ],
        p_callback
    );
};

/**
 * 离线知乎日报。
 * @param  {Array} p_ids         指定的知乎日报 ID 列表。
 * @param  {String} p_date       指定的日期。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.cacheStories = function (p_ids, p_date, p_callback)
{
    async.waterfall(
        [
            _preprocessTask.bind(this, p_ids, p_date),
            _cacheStoriesTask.bind(this)
        ],
        p_callback
    );
};

/**
 * 预处理：排除已离线的日报。
 */
function _preprocessTask(p_ids, p_date, p_callback)
{
    story.query({
        date: p_date,
        cached: true
    }, {
        id: 1,
        _id: 0
    }, function (err , res)
    {
        if (!err && res)
        {
            var cachedIDs = _.map(res, function (value)
            {
                return value.id;
            });
            _.remove(p_ids, function (id)
            {
                return _.indexOf(cachedIDs, id) != -1;
            });
        }
        p_callback(null, p_ids, p_date);
    });
}

/**
 * 获取最新的知乎日报 ID 列表。
 */
function _fetchLatestStoryIDsTask(p_callback)
{
    this.fetchLatestStoryIDs(function (err, res)
    {
        if (err)
        {
            p_callback(err);
        }
        else
        {
            p_callback(null, res.ids, res.date);
        }
    });
}

/**
 * 获取指定日期的知乎日报 ID 列表。
 */
function _fetchStoryIDsTask(p_date, p_callback)
{
    this.fetchStoryIDs(p_date, function (err, res)
    {
        if (err)
        {
            p_callback(err);
        }
        else
        {
            p_callback(null, res.ids, res.date);
        }
    });
}

/**
 * 离线知乎日报。
 */
function _cacheStoriesTask(p_ids, p_date, p_callback)
{
    var result = { date: p_date, cached: [] };
    async.eachSeries(p_ids, function (id, done)
    {
        this.cacheStory(id, p_date, function (err, res)
        {
            if (!err)
            {
                result.cached.push(id);
            }
            done();
        });
    }.bind(this), function ()
    {
        p_callback(null, result);
    });
}

/**
 * 从知乎日报服务器获取获取指定的图片。
 * @param  {String} p_url        指定的图片地址。
 * @param  {Function} p_callback 回调函数：function(err, res)。
 */
exports.fetchImage = function (p_url, p_res)
{
    if (!_.isFunction(p_callback)) return;
    // TODO:
};
<commit_msg>update comments<commit_after>var _ = require("lodash");
var async = require("async");
var config = require("config");
var cheerio = require("cheerio");
var querystring = require("querystring");
var dailyRequest = require("request").defaults({
    baseUrl : config.zhihu_daily_api
});

var story = require("../story");
var utils = require("../utils");
const PREFIX = "/api/4/imgs/";

/**
 * 从知乎日报服务器获取最新的知乎日报 ID 列表。
 * @param {Function(err, res)} [p_callback]
 */
exports.fetchLatestStoryIDs = function (p_callback)
{
    if (!_.isFunction(p_callback)) return;

    dailyRequest.get({ url: "/news/latest", json: true }, function (err, res, body)
    {
        if (!err && res.statusCode == 200)
        {
            // 因知乎日报的 API 返回的图片太小，这里直接丢弃，后面再通过其他途径获取图片。
            p_callback(null, {
                date: body.date,
                ids: body.stories.map(function (value)
                {
                    return value.id;
                })
            });
        }
        else
        {
            p_callback(new Error("request zhihu-daily api ('/news/latest') error:" + err.message), null);
        }
    });
};

/**
 * 从知乎日报服务器获取指定日期的知乎日报 ID 列表。
 * @param {String} p_date 日期。如果小于"20130519"，返回值 res 为 {}。
 * @param {Function(err, res)} [p_callback]
 */
exports.fetchStoryIDs = function (p_date, p_callback)
{
    if (!_.isFunction(p_callback)) return;

    // 因知乎日报 API 返回的是指定日期的前一天的日报，
    // 所以要加一天才能获取指定日期的日报。
    var date = utils.nextZhihuDay(p_date);
    if (date)
    {
        if (utils.convertZhihuDateToMoment(date).isBefore(utils.MIN_DATE))
        {
            // "20130519"之前是没有知乎日报的。
            p_callback(null, {});
        }
        else
        {
            dailyRequest.get({ url: "/news/before/" + date, json: true }, function (err, res, body)
            {
                if (!err && res.statusCode == 200)
                {
                    p_callback(null, {
                        date: body.date,
                        ids: body.stories.map(function (value)
                        {
                            return value.id;
                        })
                    });
                }
                else
                {
                    p_callback(new Error("request zhihu-daily api ('/news/before/:date') error:" + err.message), null);
                }
            });
        }
    }
    else
    {
        p_callback(new Error("p_date has a wrong format."), null);
    }
};

/**
 * 从知乎日报服务器获取指定 ID 的知乎日报。
 * @param {String} p_id ID。
 * @param {Function(err, res)} [p_callback]
 */
exports.fetchStory = function (p_id, p_callback)
{
    if (!_.isFunction(p_callback)) return;

    // 检查 ID 是否为纯数字。
    if (/^\d+$/.test(p_id))
    {
        dailyRequest.get({ url: "/news/" + p_id, json: true }, function (err, res, body)
        {
            if (!err && res.statusCode == 200)
            {
                var result = {};
                result.id = body.id;
                result.title = body.title;

                // TODO: 图片暂时不入库，后面再说。
                result.image = PREFIX + querystring.escape(body.image);

                result.imageSource = body.image_source;
                result.shareURL = body.share_url;

                if (body.body)
                {
                    var $ = cheerio.load(body.body, { decodeEntities: false });
                    result.backgrounds = $(".headline>.headline-background .headline-background-link").map(function (i, e)
                    {
                        return {
                            href: $(e).attr("href"),
                            title : $(e).children(".heading").text(),
                            text : $(e).children(".heading-content").text()
                        };
                    }).get();

                    result.contents = $(".content-inner>.question").map(function (i, e)
                    {
                        var question = {};
                        question.title = $(e).children(".question-title").text();
                        question.answers = $(e).children(".answer").map(function (i, e)
                        {
                            // TODO: 图片暂时不入库，后面再说。
                            $(e).find(".content img").each(function (i, e)
                            {
                                var src = $(e).attr("src");
                                if (src != null && src != "")
                                {
                                    $(e).attr("src", PREFIX + querystring.escape(src));
                                }
                            });

                            // TODO: 图片暂时不入库，后面再说。
                            var avatar = $(e).find(".meta>.avatar").attr("src");
                            if (avatar != null && avatar != "")
                            {
                                avatar = PREFIX + querystring.escape(avatar);
                            }
                            else
                            {
                                avatar = "";
                            }

                            return {
                                avatar : avatar,
                                name: $(e).find(".meta>.author").text(),
                                bio : $(e).find(".meta>.bio").text(),
                                content : $(e).children(".content").html()
                            };
                        }).get();

                        var a = $(e).find(".view-more>a");
                        if (a.length > 0)
                        {
                            question.link = {
                                href : a.attr("href"),
                                text : a.text(),
                            };
                        }

                        return question;
                    }).get();
                }
                p_callback(null, result);
            }
            else
            {
                p_callback(new Error("request zhihu-daily api ('/news/:id') error:" + err.message), null);
            }
        });
    }
    else
    {
        p_callback(new Error("p_id has a wrong format."), null);
    }
};

/**
 * 离线指定的日报。
 * @param {String} p_id ID。
 * @param {String} p_date 日期。
 * @param {Function(err, res)} [p_callback]
 */
exports.cacheStory = function (p_id, p_date, p_callback)
{
    async.retry({
        times: config.crawler.daily_retry,
        interval: config.crawler.daily_interval * 1000
    }, this.fetchStory.bind(this, p_id), function (err, res)
    {
        // 不管抓取失败与否，都将 ID 记录下来（完备）。
        if (err)
        {
            story.logUncachedStory(p_id, p_date, p_callback);
        }
        else
        {
            res.date = p_date;
            story.saveStory(res, p_callback);
        }
    });
};

/**
 * 离线最新的知乎日报。
 * @param {Function(err, res)} [p_callback]
 */
exports.cacheLatestStories = function (p_callback)
{
    async.waterfall(
        [
            _fetchLatestStoryIDsTask.bind(this),
            _preprocessTask,
            _cacheStoriesTask.bind(this)
        ],
        p_callback
    );
};

/**
 * 离线指定日期的知乎日报。
 * @param {String} p_date 指定的日期。
 * @param {Function(err, res)} [p_callback]
 */
exports.cacheStoriesOfDate = function (p_date, p_callback)
{
    async.waterfall(
        [
            _fetchStoryIDsTask.bind(this, p_date),
            _preprocessTask,
            _cacheStoriesTask.bind(this)
        ],
        p_callback
    );
};

/**
 * 离线知乎日报。
 * @param {Array} p_ids ID 列表。
 * @param {String} p_date 日期。
 * @param {Function(err, res)} [p_callback]
 */
exports.cacheStories = function (p_ids, p_date, p_callback)
{
    async.waterfall(
        [
            _preprocessTask.bind(this, p_ids, p_date),
            _cacheStoriesTask.bind(this)
        ],
        p_callback
    );
};

/**
 * 预处理：排除已离线的日报。
 * @param {Array} p_ids ID 列表。
 * @param {String} p_date 日期。
 * @param {Function(err, ids, date)} [p_callback]
 */
function _preprocessTask(p_ids, p_date, p_callback)
{
    story.query({
        date: p_date,
        cached: true
    }, {
        id: 1,
        _id: 0
    }, function (err , res)
    {
        if (!err && res)
        {
            var cachedIDs = _.map(res, function (value)
            {
                return value.id;
            });
            _.remove(p_ids, function (id)
            {
                return _.indexOf(cachedIDs, id) != -1;
            });
        }
        p_callback(null, p_ids, p_date);
    });
}

/**
 * 获取最新的知乎日报 ID 列表。
 * @param {Function(err, ids, date)} [p_callback]
 */
function _fetchLatestStoryIDsTask(p_callback)
{
    this.fetchLatestStoryIDs(function (err, res)
    {
        if (err)
        {
            p_callback(err);
        }
        else
        {
            p_callback(null, res.ids, res.date);
        }
    });
}

/**
 * 获取指定日期的知乎日报 ID 列表。
 * @param {String} p_date 日期。
 * @param {Function(err, ids, date)} [p_callback]
 */
function _fetchStoryIDsTask(p_date, p_callback)
{
    this.fetchStoryIDs(p_date, function (err, res)
    {
        if (err)
        {
            p_callback(err);
        }
        else
        {
            p_callback(null, res.ids, res.date);
        }
    });
}

/**
 * 离线知乎日报。
 * @param {Aarray} p_ids ID 列表。
 * @param {String} p_date 日期。
 * @param {Function(err, res)} [p_callback]
 */
function _cacheStoriesTask(p_ids, p_date, p_callback)
{
    var result = { date: p_date, cached: [] };
    async.eachSeries(p_ids, function (id, done)
    {
        this.cacheStory(id, p_date, function (err, res)
        {
            if (!err)
            {
                result.cached.push(id);
            }
            done();
        });
    }.bind(this), function ()
    {
        p_callback(null, result);
    });
}

/**
 * 从知乎日报服务器获取获取指定的图片。
 * @param {String} p_url 图片地址。
 * @param {Function(err, res)} [p_callback]
 */
exports.fetchImage = function (p_url, p_res)
{
    if (!_.isFunction(p_callback)) return;
    // TODO:
};
<|endoftext|>


<commit_before>import _on from './on';
import _off from './off';
import { delegateHandler } from './delegate';
import iterate from './iterate';
import words from './eachWord';
import randomId from './randomId';
import data from './data';
import isFunction from './isFunction';
import isString from './isString';
import isArray from './isArray';

// The registry of bound events
// (necessary for advanced event handling)
const events = new Map();

/**
 * Helper funciton to find the elements event binding id
 * @param  {HTMLElement} elm - HTML Element to get the ID from
 * @return {String} - The elements event binding ID
 */
export function eventListId(elm) {
  if(!elm || !isFunction(elm.addEventListener)) { return null; }

  // On non HTML Elements (like window or document) we set a property instead of
  // using the data-eventlistid attribute
  let id = data(elm, 'eventlistid');
  const noData = id === false;

  if(noData) { id = elm._eventlistid; }
  if(id) { return id; }

  id = randomId(10);

  if(noData) { elm._eventlistid = id }
  else { data(elm, 'eventlistid', id) }

  return id;
}

/**
 * Helper function to find all bound events on a HTML element
 * (found from custom cache that only works if the handlers have been bound via
 * the 'on' method)
 * @param  {HTMLElement} elm - HTML Element events are bound to
 * @return {Object} - Object containing all events bound to the element
 */
export function getEvents(elm) {
  const elmid = eventListId(elm);
  if(!elmid) { return null; }
  if(!events.has(elmid)) { events.set(elmid, new Map()); }
  return events.get(elmid);
}

// Internal method to trigger all bound handlers to an event
function triggerHandlers(e, handlers = [], target = e.target) {
  iterate(handlers, (handler) => {
    if(handler.call(target, e) === false) {
      e.preventDefault();
      e.stopPropagation();
      return false;
    }
  });
}

// Internal function to determine the function to use when event is fired
function callback(e) {
  const elmEvents = getEvents(e.currentTarget);
  const evts = elmEvents ? elmEvents.get(e.type) : null;

  if(!evts) { return; }

  const { handlers, delegates } = evts;
  // Normal handlers use the 'currentTarget' as the element
  triggerHandlers(e, handlers, e.currentTarget);
  // Delegates look at the target of the event to determine whether the element
  // should trigger the event handler or not
  if(delegates.size > 0) { triggerHandlers(e, [...delegates.values()].map((obj) => obj.cb)); }
}

// Internal helper function to iterate each part of a namespaced event name
function eachEventNamespace(evtName, cb) {
  evtName.split('.').reduce((evt, part) => {
    evt = evt ? `${evt}.${part}` : part;
    cb(evt);
    return evt;
  }, '');
}

/**
 * Bind event handler for one or more event names (space separated).
 * (NOTE: in order to enable unbinding of delegates and all handlers for an event,
 * all events ar cached and an event caching id is set on the element via the
 * data-eventlistid or the _eventlistid property)
 * @param  {HTMLElement} elm - HTML Element to bind the event to
 * @param  {String} eventNames - Space separated string of event names to bind the handler to
 * @param  {String} [delegation] - Optional delegation selector
 * @param  {Function} handler - Handler to bind
 * @return {HTMLElement} - the 'elm'
 */
export default function on(elm, eventNames, delegation, handler) {
  const evts = getEvents(elm);
  const strEvts = isString(eventNames);

  if(!evts || !(strEvts || isArray(eventNames))) { return elm; }

  // If only handler has been given as argument in the place of the delegation
  // selector, correct the variables
  if(isFunction(delegation)) { [handler, delegation] = [delegation, undefined]; }
  if(!isFunction(handler)) { return elm; }

  // Delegation handlers has to be stores separately to enable better unbinding control
  // so we check if we are dealing with a delegate
  const isDelegate = isString(delegation);
  const itrCb = (evtName) => {
    // Go through event and namespaces
    eachEventNamespace(evtName, (evtNS) => {
      // Get the current handlers and push the handler to it
      // NOTE: We use arrays for handler collections over Set(), as functions
      // are treated individually anyway, thus loosing the benefits of using Set()
      const evt = evts.get(evtNS) || { handlers: [], delegates: new Map() };

      if(!isDelegate) {
        // No delegate handlers we just add to the 'handlers' collection
        evt.handlers.push(handler);
      } else {
        // Delegates will have to be stored, with the selector and a callback function
        // that triggers all the handlers if the delegation element is the correct one
        const delegate = evt.delegates.get(delegation) || {
          // CB is a delegation handler that triggers all the stored handlers
          // if the delegation selector is met
          cb: delegateHandler(delegation, (e) => { triggerHandlers(e, delegate.handlers); }),
          handlers: []
        };

        // Add handler to the delegate
        delegate.handlers.push(handler);
        evt.delegates.set(delegation, delegate);
      }

      // Bind the event if it is the first handler for this event
      if(!evts.has(evtNS)) { _on(elm, evtNS, callback); }

      // Make sure the events are stored
      evts.set(evtNS, evt);
    });
  };

  if(strEvts) { words(eventNames, itrCb); }
  else { iterate(eventNames, itrCb); }

  return elm;
}

/**
 * Unbinds events (space separated string) for the given element. If no handler
 * function is defined it removes all handlers for the given events. If no event
 * names has been defined it removes all events bound to the element.
 * (in order to remove all handlers on the element, all handlers must have been
 * bound via the 'on' method)
 * @param  {HTMLElement} elm - HTML Element to unbind the event from
 * @param  {String} [eventNames] - Space separated string of event names to unbind the handler from
 * @param  {String} [delegation] - Delegation selector to unbind
 * @param  {Function} [handler] - Handler to remove
 * @return {HTMLElement} - the 'elm'
 */
export function off(elm, eventNames, delegation, handler) {
  const evts = getEvents(elm);
  if(!evts) { return elm; }

  const strEvts = isString(eventNames);

  // If no events have been given, remove all event listeners
  if(!strEvts && !isArray(eventNames)) {
    evts.forEach((evtObj, evtName) => _off(elm, evtName, callback));
    evts.clear();
    return elm;
  }

  // If only handler has been given as argument in the place of the delegation
  // selector, correct the variables
  if(isFunction(delegation)) { [handler, delegation] = [delegation, undefined]; }

  const removeAll = !isFunction(handler);
  const removeDelegate = isString(delegation);
  const itrCb = (evtName) => {
    // go through event and namespaces
    eachEventNamespace(evtName, (evtNS) => {
      const evt = evts.get(evtNS);
      if(!evt) { return; }

      if(!removeDelegate) {
        evt.handlers = removeAll ? [] : evt.handlers.filter((h) => h !== handler);
        // If we are removing all event handlers, we remove delegations as well
        if(removeAll) { evt.delegates.clear(); }
      } else {
        const delegate = evt.delegates.get(delegation);
        if(!delegate) { return; }

        // Remove all handers or a single specific handler from the delegation
        delegate.handlers = removeAll? [] : delegate.handlers.filter((h) => h !== handler);
        // If there are no handlers left, remove the delegation cache.
        if(delegate.handlers.length === 0) { evt.delegates.delete(delegation); }
      }

      // If there are no more handlers, remove all
      if(evt.handlers.length === 0 && evt.delegates.size === 0) {
        evts.delete(evtNS);
        _off(elm, evtNS, callback);
      }
    });
  };

  if(strEvts) { words(eventNames, itrCb); }
  else { iterate(eventNames, itrCb); }

  return elm;
}
<commit_msg>eventPlus: Normalize spacing between functions<commit_after>import _on from './on';
import _off from './off';
import { delegateHandler } from './delegate';
import iterate from './iterate';
import words from './eachWord';
import randomId from './randomId';
import data from './data';
import isFunction from './isFunction';
import isString from './isString';
import isArray from './isArray';

// The registry of bound events
// (necessary for advanced event handling)
const events = new Map();

/**
 * Helper funciton to find the elements event binding id
 * @param  {HTMLElement} elm - HTML Element to get the ID from
 * @return {String} - The elements event binding ID
 */
export function eventListId(elm) {
  if(!elm || !isFunction(elm.addEventListener)) { return null; }

  // On non HTML Elements (like window or document) we set a property instead of
  // using the data-eventlistid attribute
  let id = data(elm, 'eventlistid');
  const noData = id === false;

  if(noData) { id = elm._eventlistid; }
  if(id) { return id; }

  id = randomId(10);

  if(noData) { elm._eventlistid = id }
  else { data(elm, 'eventlistid', id) }

  return id;
}

/**
 * Helper function to find all bound events on a HTML element
 * (found from custom cache that only works if the handlers have been bound via
 * the 'on' method)
 * @param  {HTMLElement} elm - HTML Element events are bound to
 * @return {Object} - Object containing all events bound to the element
 */
export function getEvents(elm) {
  const elmid = eventListId(elm);
  if(!elmid) { return null; }
  if(!events.has(elmid)) { events.set(elmid, new Map()); }
  return events.get(elmid);
}

// Internal method to trigger all bound handlers to an event
function triggerHandlers(e, handlers = [], target = e.target) {
  iterate(handlers, (handler) => {
    if(handler.call(target, e) === false) {
      e.preventDefault();
      e.stopPropagation();
      return false;
    }
  });
}

// Internal function to determine the function to use when event is fired
function callback(e) {
  const elmEvents = getEvents(e.currentTarget);
  const evts = elmEvents ? elmEvents.get(e.type) : null;

  if(!evts) { return; }

  const { handlers, delegates } = evts;
  // Normal handlers use the 'currentTarget' as the element
  triggerHandlers(e, handlers, e.currentTarget);
  // Delegates look at the target of the event to determine whether the element
  // should trigger the event handler or not
  if(delegates.size > 0) { triggerHandlers(e, [...delegates.values()].map((obj) => obj.cb)); }
}

// Internal helper function to iterate each part of a namespaced event name
function eachEventNamespace(evtName, cb) {
  evtName.split('.').reduce((evt, part) => {
    evt = evt ? `${evt}.${part}` : part;
    cb(evt);
    return evt;
  }, '');
}

/**
 * Bind event handler for one or more event names (space separated).
 * (NOTE: in order to enable unbinding of delegates and all handlers for an event,
 * all events ar cached and an event caching id is set on the element via the
 * data-eventlistid or the _eventlistid property)
 * @param  {HTMLElement} elm - HTML Element to bind the event to
 * @param  {String} eventNames - Space separated string of event names to bind the handler to
 * @param  {String} [delegation] - Optional delegation selector
 * @param  {Function} handler - Handler to bind
 * @return {HTMLElement} - the 'elm'
 */
export default function on(elm, eventNames, delegation, handler) {
  const evts = getEvents(elm);
  const strEvts = isString(eventNames);

  if(!evts || !(strEvts || isArray(eventNames))) { return elm; }

  // If only handler has been given as argument in the place of the delegation
  // selector, correct the variables
  if(isFunction(delegation)) { [handler, delegation] = [delegation, undefined]; }
  if(!isFunction(handler)) { return elm; }

  // Delegation handlers has to be stores separately to enable better unbinding control
  // so we check if we are dealing with a delegate
  const isDelegate = isString(delegation);
  const itrCb = (evtName) => {
    // Go through event and namespaces
    eachEventNamespace(evtName, (evtNS) => {
      // Get the current handlers and push the handler to it
      // NOTE: We use arrays for handler collections over Set(), as functions
      // are treated individually anyway, thus loosing the benefits of using Set()
      const evt = evts.get(evtNS) || { handlers: [], delegates: new Map() };

      if(!isDelegate) {
        // No delegate handlers we just add to the 'handlers' collection
        evt.handlers.push(handler);
      } else {
        // Delegates will have to be stored, with the selector and a callback function
        // that triggers all the handlers if the delegation element is the correct one
        const delegate = evt.delegates.get(delegation) || {
          // CB is a delegation handler that triggers all the stored handlers
          // if the delegation selector is met
          cb: delegateHandler(delegation, (e) => { triggerHandlers(e, delegate.handlers); }),
          handlers: []
        };

        // Add handler to the delegate
        delegate.handlers.push(handler);
        evt.delegates.set(delegation, delegate);
      }

      // Bind the event if it is the first handler for this event
      if(!evts.has(evtNS)) { _on(elm, evtNS, callback); }

      // Make sure the events are stored
      evts.set(evtNS, evt);
    });
  };

  if(strEvts) { words(eventNames, itrCb); }
  else { iterate(eventNames, itrCb); }

  return elm;
}

/**
 * Unbinds events (space separated string) for the given element. If no handler
 * function is defined it removes all handlers for the given events. If no event
 * names has been defined it removes all events bound to the element.
 * (in order to remove all handlers on the element, all handlers must have been
 * bound via the 'on' method)
 * @param  {HTMLElement} elm - HTML Element to unbind the event from
 * @param  {String} [eventNames] - Space separated string of event names to unbind the handler from
 * @param  {String} [delegation] - Delegation selector to unbind
 * @param  {Function} [handler] - Handler to remove
 * @return {HTMLElement} - the 'elm'
 */
export function off(elm, eventNames, delegation, handler) {
  const evts = getEvents(elm);
  if(!evts) { return elm; }

  const strEvts = isString(eventNames);

  // If no events have been given, remove all event listeners
  if(!strEvts && !isArray(eventNames)) {
    evts.forEach((evtObj, evtName) => _off(elm, evtName, callback));
    evts.clear();
    return elm;
  }

  // If only handler has been given as argument in the place of the delegation
  // selector, correct the variables
  if(isFunction(delegation)) { [handler, delegation] = [delegation, undefined]; }

  const removeAll = !isFunction(handler);
  const removeDelegate = isString(delegation);
  const itrCb = (evtName) => {
    // go through event and namespaces
    eachEventNamespace(evtName, (evtNS) => {
      const evt = evts.get(evtNS);
      if(!evt) { return; }

      if(!removeDelegate) {
        evt.handlers = removeAll ? [] : evt.handlers.filter((h) => h !== handler);
        // If we are removing all event handlers, we remove delegations as well
        if(removeAll) { evt.delegates.clear(); }
      } else {
        const delegate = evt.delegates.get(delegation);
        if(!delegate) { return; }

        // Remove all handers or a single specific handler from the delegation
        delegate.handlers = removeAll? [] : delegate.handlers.filter((h) => h !== handler);
        // If there are no handlers left, remove the delegation cache.
        if(delegate.handlers.length === 0) { evt.delegates.delete(delegation); }
      }

      // If there are no more handlers, remove all
      if(evt.handlers.length === 0 && evt.delegates.size === 0) {
        evts.delete(evtNS);
        _off(elm, evtNS, callback);
      }
    });
  };

  if(strEvts) { words(eventNames, itrCb); }
  else { iterate(eventNames, itrCb); }

  return elm;
}
<|endoftext|>


<commit_before>var assert = require('chai').assert;
var rewire = require('rewire');
var RestBuilder = rewire('../lib/rest-builder');
var mock = require('mock-object');
var mockDB = mock(require('../lib/db'));
var shared = require('./util/shared');
var user = require('./util/models/user');
var noarg = require('./util/noarg');

mockDB.get.addSideEffect(function() {
  var args = Array.prototype.slice.call(arguments);
  var cb = args.pop();
  cb(null, {});
});

RestBuilder.__set__('db', mockDB);

function setUpRestBuilder() {
  beforeEach(function(done) {
    this.server = shared.createServer();
    this.rb = new RestBuilder(this.server);
    this.server.listen(8080, noarg(done));
    this.client = shared.createClient();
  });
  afterEach(function() {
    this.server.close();
    this.server = null;
    this.client = null;
  });
}

function getMockPre() {
  var called = false;
  function mockPre(req, res, next) {
    called = true;
    return next();
  }
  mockPre.assertCalled = function assertCalled(message) {
    assert.ok(called, message);
  }
  return mockPre;
}

describe('RestBuilder', function() {
  describe('defineGetSingle', function() {
    setUpRestBuilder();
    describe('no processors', function() {
      it('should call db.get', function(done) {
        this.rb.defineGetSingle('users', user, [], []);
        this.client.get('/users/1', function(err, req, res) {
          assert.ifError(err);
          mockDB.get.assertCalledOnceWithArgsIncluding(['1', user]);
          done();
        });
      });
    });
    describe('with preprocessors', function () {
      it('should call a single preprocessor', function(done) {
        var called = false;
        var mockPre = getMockPre();
        this.rb.defineGetSingle('users', user, [mockPre], []);
        this.client.get('/users/1', function(err, req, res) {
          mockPre.assertCalled('should call preprocessors');
          assert.ifError(err);
          mockDB.get.assertCalledOnceWithArgsIncluding(['1', user]);
          done();
        });
      });
      it('should call all the preprocessors', function (done) {
        var mockPre = getMockPre();
        var _mockPre = getMockPre();
        this.rb.defineGetSingle('users', user, [mockPre, _mockPre], []);
        this.client.get('/users/1', function(err, req, res) {
          mockPre.assertCalled('should call first preprocessor');
          _mockPre.assertCalled('should call second preprocessor');
          assert.ifError(err);
          mockDB.get.assertCalledOnceWithArgsIncluding(['1', user]);
          done();
        });
      });
    });
  });
});
<commit_msg>Add test for getMany<commit_after>var assert = require('chai').assert;
var rewire = require('rewire');
var RestBuilder = rewire('../lib/rest-builder');
var mock = require('mock-object');
var mockDB = mock(require('../lib/db'));
var shared = require('./util/shared');
var user = require('./util/models/user');
var noarg = require('./util/noarg');

mockDB.get.addSideEffect(function() {
  var args = Array.prototype.slice.call(arguments);
  var cb = args.pop();
  cb(null, {});
});

RestBuilder.__set__('db', mockDB);

function setUpRestBuilder() {
  beforeEach(function(done) {
    this.server = shared.createServer();
    this.rb = new RestBuilder(this.server);
    this.server.listen(8080, noarg(done));
    this.client = shared.createClient();
  });
  afterEach(function() {
    this.server.close();
    this.server = null;
    this.client = null;
  });
}

function getMockPre() {
  var called = false;
  function mockPre(req, res, next) {
    called = true;
    return next();
  }
  mockPre.assertCalled = function assertCalled(message) {
    assert.ok(called, message);
  }
  return mockPre;
}

describe('RestBuilder', function() {
  describe('defineGetSingle', function() {
    setUpRestBuilder();
    describe('no processors', function() {
      it('should call db.get', function(done) {
        this.rb.defineGetSingle('users', user, [], []);
        this.client.get('/users/1', function(err, req, res) {
          assert.ifError(err);
          mockDB.get.assertCalledOnceWithArgsIncluding(['1', user]);
          done();
        });
      });
    });
    describe('with preprocessors', function () {
      it('should call a single preprocessor', function(done) {
        var called = false;
        var mockPre = getMockPre();
        this.rb.defineGetSingle('users', user, [mockPre], []);
        this.client.get('/users/1', function(err, req, res) {
          mockPre.assertCalled('should call preprocessors');
          assert.ifError(err);
          mockDB.get.assertCalledOnceWithArgsIncluding(['1', user]);
          done();
        });
      });
      it('should call all the preprocessors', function (done) {
        var mockPre = getMockPre();
        var _mockPre = getMockPre();
        this.rb.defineGetSingle('users', user, [mockPre, _mockPre], []);
        this.client.get('/users/1', function(err, req, res) {
          mockPre.assertCalled('should call first preprocessor');
          _mockPre.assertCalled('should call second preprocessor');
          assert.ifError(err);
          mockDB.get.assertCalledOnceWithArgsIncluding(['1', user]);
          done();
        });
      });
    });
  });
  describe('defineGetMany', function () {
    setUpRestBuilder();
    describe('no processors', function () {
      it('should call db.get with no params', function (done) {
        this.rb.defineGetMany('users', user, [], []);
        this.client.get('/users', function(err, req, res) {
          assert.ifError(err);
          mockDB.get.assertCalledOnceWithArgsIncluding([user]);
          done();
        });
      });
    });
    describe('with preprocessors', function () {

    });
  });
});
<|endoftext|>


<commit_before>import update from 'react-addons-update';
import fxns from '../../utils/fxns';

import { SET_RSVP, UPDATE_PERSON_RSVP, UPDATE_PLUS } from '../actions/actionTypes';

const initialState = {};

export default function rsvpReducers(state = initialState, action) {
  switch (action.type) {
    case SET_RSVP: {
      return update(action.rsvp, {
        processed: { $set: fxns.rsvpProcessData(action.rsvp) }
      });
    }
    case UPDATE_PERSON_RSVP: {
      const guests = state.guests;
      const updatedPerson = update(guests[action.index], { rsvp: { $set: action.rsvp } });
      const updatedGuests = update(guests, {
        $splice: [[action.index, 1, updatedPerson]]
      });
      const updatedRsvp = update(state, { guests: { $set: updatedGuests } });

      return updatedRsvp;
    }
    case UPDATE_PLUS: {
      const plus = parseInt(action.plus, 10);

      return update(state, { plus: { bringing: { $set: plus } } });
    }
    default:
      return state;
  }
}
<commit_msg>RSVP - update processed property with state change<commit_after>import update from 'react-addons-update';
import fxns from '../../utils/fxns';

import { SET_RSVP, UPDATE_PERSON_RSVP, UPDATE_PLUS } from '../actions/actionTypes';

const initialState = {};

export default function rsvpReducers(state = initialState, action) {
  switch (action.type) {
    case SET_RSVP: {
      return update(action.rsvp, {
        processed: { $set: fxns.rsvpProcessData(action.rsvp) }
      });
    }
    case UPDATE_PERSON_RSVP: {
      const guests = state.guests;
      const updatedPerson = update(guests[action.index], { rsvp: { $set: action.rsvp } });
      const updatedGuests = update(guests, {
        $splice: [[action.index, 1, updatedPerson]]
      });
      const updatedRsvp = update(state, { guests: { $set: updatedGuests } });

      const processed = fxns.rsvpProcessData(updatedRsvp);
      const updatedRsvpProcessed = update(updatedRsvp, { processed: { $set: processed } });

      return updatedRsvpProcessed;
    }
    case UPDATE_PLUS: {
      const plus = parseInt(action.plus, 10);
      const updatedPlus = update(state, { plus: { bringing: { $set: plus } } });

      const processed = fxns.rsvpProcessData(updatedPlus);
      const updatedPlusProcessed = update(updatedPlus, { processed: { $set: processed } });

      return updatedPlusProcessed;
    }
    default:
      return state;
  }
}
<|endoftext|>


<commit_before>$(document).ready(function() {
  showLoader();
  var uri = "/api/audit-failure-detection/" + currentPage();
  if (clusterAlias()) {
    uri = "/api/audit-failure-detection/alias/" + clusterAlias();
  }
  if (detectionId() > 0) {
    uri = "/api/audit-failure-detection/id/" + detectionId();
  }
  $.get(appUrl(uri), function(auditEntries) {
    auditEntries = auditEntries || [];
    $.get(appUrl("/api/replication-analysis-changelog"), function(analysisChangelog) {
      analysisChangelog = analysisChangelog || [];
      displayAudit(auditEntries, analysisChangelog);
    }, "json");
  }, "json");

  function displayAudit(auditEntries, analysisChangelog) {
    var changelogMap = {}
    analysisChangelog.forEach(function(changelogEntry) {
      changelogMap[getInstanceId(changelogEntry.AnalyzedInstanceKey.Hostname, changelogEntry.AnalyzedInstanceKey.Port)] = changelogEntry.Changelog;
    });

    hideLoader();
    auditEntries.forEach(function(audit) {
      var analyzedInstanceDisplay = audit.AnalysisEntry.AnalyzedInstanceKey.Hostname + ":" + audit.AnalysisEntry.AnalyzedInstanceKey.Port;
      var row = jQuery('
');
      var moreInfoElement = $('');
      moreInfoElement.attr("data-detection-id", audit.Id);

      $('', {
        text: audit.AnalysisEntry.Analysis
      }).prepend(moreInfoElement).appendTo(row);
      $('', {
        text: analyzedInstanceDisplay,
        href: appUrl("/web/search/" + analyzedInstanceDisplay)
      }).wrap($("")).parent().appendTo(row);
      $('', {
        text: audit.AnalysisEntry.CountReplicas
      }).appendTo(row);
      $('', {
        text: audit.AnalysisEntry.ClusterDetails.ClusterName,
        href: appUrl("/web/cluster/" + audit.AnalysisEntry.ClusterDetails.ClusterName)
      }).wrap($("")).parent().appendTo(row);
      $('', {
        text: audit.AnalysisEntry.ClusterDetails.ClusterAlias,
        href: appUrl("/web/cluster/alias/" + audit.AnalysisEntry.ClusterDetails.ClusterAlias)
      }).wrap($("")).parent().appendTo(row);
      $('', {
        text: audit.RecoveryStartTimestamp
      }).appendTo(row);

      var moreInfo = "";
      moreInfo += '
Detected: ' + audit.RecoveryStartTimestamp + '
';
      if (audit.AnalysisEntry.SlaveHosts.length > 0) {
        moreInfo += '
' + audit.AnalysisEntry.CountReplicas + ' replicating hosts :
';
        audit.AnalysisEntry.SlaveHosts.forEach(function(instanceKey) {
          moreInfo += "
" + getInstanceTitle(instanceKey.Hostname, instanceKey.Port) + "
";
        });
        moreInfo += "

";
      }
      var changelog = changelogMap[getInstanceId(audit.AnalysisEntry.AnalyzedInstanceKey.Hostname, audit.AnalysisEntry.AnalyzedInstanceKey.Port)];
      if (changelog) {
        moreInfo += '
Changelog :
';
        changelog.reverse().forEach(function(changelogEntry) {
          var changelogEntryTokens = changelogEntry.split(';');
          var changelogEntryTimestamp = changelogEntryTokens[0];
          var changelogEntryAnalysis = changelogEntryTokens[1];

          if (changelogEntryTimestamp > audit.RecoveryStartTimestamp) {
            // This entry is newer than the detection time; irrelevant
            return;
          }
          moreInfo += "
" + changelogEntryTimestamp + " " + changelogEntryAnalysis + "
";
        });
        moreInfo += "

";
      }
      moreInfo += '
Related recovery
';

      moreInfo += "
Proccessed by " + audit.ProcessingNodeHostname + "
";
      row.appendTo('#audit tbody');

      var row = $('
');
      row.attr("data-detection-id-more-info", audit.Id);
      row.addClass("more-info");
      $('').append(moreInfo).appendTo(row);
      row.hide().appendTo('#audit tbody');
    });
    if (auditEntries.length == 1) {
      $("[data-detection-id-more-info]").show();
    }
    if (currentPage() <= 0) {
      $("#audit .pager .previous").addClass("disabled");
    }
    if (auditEntries.length == 0) {
      $("#audit .pager .next").addClass("disabled");
    }
    $("#audit .pager .previous").not(".disabled").find("a").click(function() {
      window.location.href = appUrl("/web/audit-failure-detection/" + (currentPage() - 1));
    });
    $("#audit .pager .next").not(".disabled").find("a").click(function() {
      window.location.href = appUrl("/web/audit-failure-detection/" + (currentPage() + 1));
    });
    $("#audit .pager .disabled a").click(function() {
      return false;
    });
    $("body").on("click", ".more-detection-info", function(event) {
      var detectionId = $(event.target).attr("data-detection-id");
      $('[data-detection-id-more-info=' + detectionId + ']').slideToggle();
    });
  }
});
<commit_msg>fixed cluster alias<commit_after>$(document).ready(function() {
  showLoader();
  var uri = "/api/audit-failure-detection/" + currentPage();
  if (clusterAlias() != "") {
    uri = "/api/audit-failure-detection/alias/" + clusterAlias();
  }
  if (detectionId() > 0) {
    uri = "/api/audit-failure-detection/id/" + detectionId();
  }
  $.get(appUrl(uri), function(auditEntries) {
    auditEntries = auditEntries || [];
    $.get(appUrl("/api/replication-analysis-changelog"), function(analysisChangelog) {
      analysisChangelog = analysisChangelog || [];
      displayAudit(auditEntries, analysisChangelog);
    }, "json");
  }, "json");

  function displayAudit(auditEntries, analysisChangelog) {
    var changelogMap = {}
    analysisChangelog.forEach(function(changelogEntry) {
      changelogMap[getInstanceId(changelogEntry.AnalyzedInstanceKey.Hostname, changelogEntry.AnalyzedInstanceKey.Port)] = changelogEntry.Changelog;
    });

    hideLoader();
    auditEntries.forEach(function(audit) {
      var analyzedInstanceDisplay = audit.AnalysisEntry.AnalyzedInstanceKey.Hostname + ":" + audit.AnalysisEntry.AnalyzedInstanceKey.Port;
      var row = jQuery('
');
      var moreInfoElement = $('');
      moreInfoElement.attr("data-detection-id", audit.Id);

      $('', {
        text: audit.AnalysisEntry.Analysis
      }).prepend(moreInfoElement).appendTo(row);
      $('', {
        text: analyzedInstanceDisplay,
        href: appUrl("/web/search/" + analyzedInstanceDisplay)
      }).wrap($("")).parent().appendTo(row);
      $('', {
        text: audit.AnalysisEntry.CountReplicas
      }).appendTo(row);
      $('', {
        text: audit.AnalysisEntry.ClusterDetails.ClusterName,
        href: appUrl("/web/cluster/" + audit.AnalysisEntry.ClusterDetails.ClusterName)
      }).wrap($("")).parent().appendTo(row);
      $('', {
        text: audit.AnalysisEntry.ClusterDetails.ClusterAlias,
        href: appUrl("/web/cluster/alias/" + audit.AnalysisEntry.ClusterDetails.ClusterAlias)
      }).wrap($("")).parent().appendTo(row);
      $('', {
        text: audit.RecoveryStartTimestamp
      }).appendTo(row);

      var moreInfo = "";
      moreInfo += '
Detected: ' + audit.RecoveryStartTimestamp + '
';
      if (audit.AnalysisEntry.SlaveHosts.length > 0) {
        moreInfo += '
' + audit.AnalysisEntry.CountReplicas + ' replicating hosts :
';
        audit.AnalysisEntry.SlaveHosts.forEach(function(instanceKey) {
          moreInfo += "
" + getInstanceTitle(instanceKey.Hostname, instanceKey.Port) + "
";
        });
        moreInfo += "

";
      }
      var changelog = changelogMap[getInstanceId(audit.AnalysisEntry.AnalyzedInstanceKey.Hostname, audit.AnalysisEntry.AnalyzedInstanceKey.Port)];
      if (changelog) {
        moreInfo += '
Changelog :
';
        changelog.reverse().forEach(function(changelogEntry) {
          var changelogEntryTokens = changelogEntry.split(';');
          var changelogEntryTimestamp = changelogEntryTokens[0];
          var changelogEntryAnalysis = changelogEntryTokens[1];

          if (changelogEntryTimestamp > audit.RecoveryStartTimestamp) {
            // This entry is newer than the detection time; irrelevant
            return;
          }
          moreInfo += "
" + changelogEntryTimestamp + " " + changelogEntryAnalysis + "
";
        });
        moreInfo += "

";
      }
      moreInfo += '
Related recovery
';

      moreInfo += "
Proccessed by " + audit.ProcessingNodeHostname + "
";
      row.appendTo('#audit tbody');

      var row = $('
');
      row.attr("data-detection-id-more-info", audit.Id);
      row.addClass("more-info");
      $('').append(moreInfo).appendTo(row);
      row.hide().appendTo('#audit tbody');
    });
    if (auditEntries.length == 1) {
      $("[data-detection-id-more-info]").show();
    }
    if (currentPage() <= 0) {
      $("#audit .pager .previous").addClass("disabled");
    }
    if (auditEntries.length == 0) {
      $("#audit .pager .next").addClass("disabled");
    }
    $("#audit .pager .previous").not(".disabled").find("a").click(function() {
      window.location.href = appUrl("/web/audit-failure-detection/" + (currentPage() - 1));
    });
    $("#audit .pager .next").not(".disabled").find("a").click(function() {
      window.location.href = appUrl("/web/audit-failure-detection/" + (currentPage() + 1));
    });
    $("#audit .pager .disabled a").click(function() {
      return false;
    });
    $("body").on("click", ".more-detection-info", function(event) {
      var detectionId = $(event.target).attr("data-detection-id");
      $('[data-detection-id-more-info=' + detectionId + ']').slideToggle();
    });
  }
});
<|endoftext|>


<commit_before>var hold = true;
var result;
function SimplePromise() {
    return new Promise(function (resolve, reject) {
        for (var i = 0; i < 100000; i++) {

        }
        timer.setTimeout(function () {
            test.echo(10);
            resolve(1);
        },1);
    });
}

function CallAsync() {

    test.asyncFunction().then(function (x) {
        result = x;
        //test.echo(x);
        hold = false;
    });
}

function PromiseWrapper(executor) {
    return new Promise(function (resolve, reject) {
        executor((value) => { resolve(value) }, (reason) => { reject(reason) })
    });
}

<commit_msg>minor fix test script<commit_after>var hold = true;
var result;
function SimplePromise() {
    return new Promise(function (resolve, reject) {
        for (var i = 0; i < 100000; i++) {

        }
        timer.setTimeout(function () {
            test.echo(10);
            resolve(1);
        },1000);
    });
}

function CallAsync() {

    test.asyncFunction().then(function (x) {
        result = x;
        //test.echo(x);
        hold = false;
    });
}

function PromiseWrapper(executor) {
    return new Promise(function (resolve, reject) {
        executor((value) => { resolve(value) }, (reason) => { reject(reason) })
    });
}

<|endoftext|>


<commit_before>define([
    "../registry",
    '../3rdparty/modernizr-2.0.6',
    '../3rdparty/jquery.placeholder'
], function(patterns) {
    var pattern_spec = {
        name: "placeholder",
        trigger: ":input[placeholder]",

        init: function($el) {
            return $el.placeholder();
        }
    };

    patterns.register(pattern_spec);
});
// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<commit_msg>Only activate placeholder pattern when needed<commit_after>define([
    "../registry",
    '../3rdparty/modernizr-2.0.6',
    '../3rdparty/jquery.placeholder'
], function(patterns) {
    var pattern_spec = {
        name: "placeholder",
        trigger: ":input[placeholder]",

        init: function($el) {
            return $el.placeholder();
        }
    };

    if (!Modernizr.input.placeholder)
        patterns.register(pattern_spec);
});
// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<|endoftext|>


<commit_before>(function (enyo) {
	//*@protected
	/**
		This is a delegate (strategy) used by _enyo.DataGridList_ for vertically oriented
		lists. This is used by all lists for this strategy and does not get copied but
		called directly from the list. It is only available to _enyo.DataGridLists_.
	*/
	var p = enyo.clone(enyo.DataGridList.delegates.vertical);
	enyo.kind.extendMethods(p, {
		/**
			Once the list is initially rendered it will generate its scroller (so
			we know that is available). Now we need to cache our initial size values
			and apply them to our pages individually.
		*/
		rendered: function (list) {
			// get our initial sizing cached now since we should actually have
			// bounds at this point
			this.updateMetrics(list);
			// now if we already have a length then that implies we have a controller
			// and that we have data to render at this point, otherwise we don't
			// want to do any more initialization
			if (list.collection && list.collection.length) { this.reset(list); }
		},
		/**
			Reset the page with the added class update to the list.
		*/
		reset: enyo.inherit(function (sup) {
			return function (list) {
				sup.apply(this, arguments);
				if (list.hasReset && !list.hasClass("reset")) {
					list.canAddResetClass = true;
				}
			};
		}),
		/**
			Unlike in DataList we can calculate the page heights since we know the structure
			and layout of the page precisely.
		*/
		pageHeight: function (list, page) {
			var n  = page.node || page.hasNode(),
				a  = n.children.length,
				mx = list.metrics.pages[page.index], s;
			s = (Math.floor(a/list.columns)+(a%list.columns? 1: 0))*(list.tileHeight+list.spacing);
			n.style.height = s + "px";
			mx.height = s;
			return s;
		},
		/**
			This method generates the markup for the page content.
		*/
		generatePage: enyo.inherit(function (sup) {
			return function (list, page) {
				sup.apply(this, arguments);
				this.layout(list, page);
			};
		}),
		/**
			Returns the calculated width for the given page.
		*/
		pageWidth: function (list, page) {
			var s  = list.boundsCache.width,
				n  = page.node || page.hasNode(),
				mx = list.metrics.pages[page.index];
			n.style.width = s + "px";
			mx.width = s;
			return s;
		},
		/**
			Retrieves the default page size.
		*/
		defaultPageSize: function (list) {
			return (Math.ceil(this.controlsPerPage(list)/list.columns) * (list.tileHeight+list.spacing));
		},
		/**
			Calculates metric values required for the absolute positioning and scaling of
			the children in the list.
		*/
		updateMetrics: function (list) {
			this.updateBounds(list);
			var bs = list.boundsCache,
				w  = bs.width,
				s  = list.spacing,
				m  = list.minWidth,
				h  = list.minHeight;
			// the number of columns is the ratio of the available width minus the spacing
			// by the minimum tile width plus the spacing
			list.columns    = Math.max(Math.floor((w-s) / (m+s)), 1);
			// the actual tile width is a ratio of the remaining width after all columns
			// and spacing are accounted for and the number of columns that we know we should have
			list.tileWidth  = ((w-(s*(list.columns+1)))/list.columns);
			// the actual tile height is related to the tile width
			list.tileHeight = (h*(list.tileWidth/m));
			// unfortunately this forces us to recalculate the number of controls that can
			// be used for each page
			this.controlsPerPage(list);
			// Compute first and last row index bounds
			if (list.collection) {
				this.updateIndexBound(list);
			}
		},
		/**
			Calculates index bound that is required for adjusting page position
			You can call this method after DataGridList is rendered.
		*/
		updateIndexBound: function(list) {
			// If user calls this method before DataGridList is rendered
			if (list.boundsCache === undefined) {
				this.updateMetrics(list);
			}

			list.indexBoundFirstRow = list.columns;
			list.indexBoundLastRow = (Math.ceil(list.collection.length / list.columns) - 1) * list.columns - 1;
		},
		/**
			The number of controls necessary to fill a page will change depending on some
			factors such as scaling and list-size adjustments. It is a function of the calculated
			size required (pageSizeMultiplier * the current boundary height) and the adjusted tile height and
			spacing.
		*/
		controlsPerPage: enyo.inherit(function (sup) {
			return function (list) {
				var orig    = list._updatedControlsPerPage,
					perPage = sup.apply(this, arguments);
				if (orig != list._updatedControlsPerPage) {
					// we need to adjust this value as it did not take into account
					// the spacing or the columns
					perPage = list.controlsPerPage = (perPage * list.columns);
				}
				return perPage;
			};
		}),
		childSize: function (list) {
			// currently DataGridList is only vertical
			/*jshint -W093 */
			return (list.childSize = (list.tileHeight + list.spacing));
		},
		/**
			Takes a given page and arbitrarily positions its children according to the pre-computed
			metrics of the list.

			TODO: This could be optimized to use requestAnimationFrame as well as render not by
			child index but by row thus cutting down some of the over-calculation when iterating
			over every child.
		*/
		layout: function (list, page) {
			if (list.canAddResetClass) {
				list.addClass("reset");
				delete list.canAddResetClass;
			}
			var cc = list.columns,
				s  = list.spacing,
				w  = list.tileWidth,
				h  = list.tileHeight,
				r  = 0,
				n  = page,
				cn = n.children, co;
			if (cn.length) {
				for (var i=0, c; (c=cn[i]); ++i) {
					// the column
					co = i % cc;
					c.addStyles(
						"top: "    + Math.round(s  + (r  * (h+s))) + "px; " +
						(list.rtl ? "right: " : "left: ") + Math.round(s  + (co * (w+s))) + "px; " +
						"width: "  + Math.round(w) +                 "px; " +
						"height: " + Math.round(h) +                 "px"
					);
					// check if we need to increment the row
					if ((i+1) % cc === 0) { ++r; }
				}
			}
		},
		/**
			Recalculates the buffer size based on the current metrics for the given
			list. This may or may not be completely accurate until the final page is
			scrolled into view.
		*/
		adjustBuffer: function (list) {
			var pc = this.pageCount(list),
				ds = this.defaultPageSize(list),
				bs = 0, sp = list.psizeProp, ss = list.ssizeProp,
				n = list.$.buffer.node || list.$.buffer.hasNode(), p;
			if (n) {
				for (var i=0; i<pc; ++i) {
					p = list.metrics.pages[i];
					bs += (p && p[sp]) || ds;
				}
				bs += list.spacing;
				list.bufferSize = bs;
				n.style[sp] = bs + "px";
				n.style[ss] = this[ss](list) + "px";
			}
		},
		/**
			Delegate's resize event handler.
		*/
		didResize: function (list) {
			// store the previous stats for comparative purposes
			var prev = list.boundsCache;

			// flag the list to have its bounds updated
			list._updateBounds = true;
			this.updateMetrics(list);

			// if no change it the viewport then we didn't update anything size-wise
			// and do not need to refresh at all
			if (
				prev.left   === list.boundsCache.left  &&
				prev.top    === list.boundsCache.top   &&
				prev.width  === list.boundsCache.width &&
				prev.height === list.boundsCache.height
			) {
				return;
			}

			// it is necessary to update the content of the list according to our
			// new sizing
			this.refresh(list);
		}
	}, true);
	enyo.DataGridList.delegates.verticalGrid = p;
})(enyo);

<commit_msg>BHV-10114 Make protected logic against direct calling of `updateIndexBound`<commit_after>(function (enyo) {
	//*@protected
	/**
		This is a delegate (strategy) used by _enyo.DataGridList_ for vertically oriented
		lists. This is used by all lists for this strategy and does not get copied but
		called directly from the list. It is only available to _enyo.DataGridLists_.
	*/
	var p = enyo.clone(enyo.DataGridList.delegates.vertical);
	enyo.kind.extendMethods(p, {
		/**
			Once the list is initially rendered it will generate its scroller (so
			we know that is available). Now we need to cache our initial size values
			and apply them to our pages individually.
		*/
		rendered: function (list) {
			// get our initial sizing cached now since we should actually have
			// bounds at this point
			this.updateMetrics(list);
			// now if we already have a length then that implies we have a controller
			// and that we have data to render at this point, otherwise we don't
			// want to do any more initialization
			if (list.collection && list.collection.length) { this.reset(list); }
		},
		/**
			Reset the page with the added class update to the list.
		*/
		reset: enyo.inherit(function (sup) {
			return function (list) {
				sup.apply(this, arguments);
				if (list.hasReset && !list.hasClass("reset")) {
					list.canAddResetClass = true;
				}
			};
		}),
		/**
			Unlike in DataList we can calculate the page heights since we know the structure
			and layout of the page precisely.
		*/
		pageHeight: function (list, page) {
			var n  = page.node || page.hasNode(),
				a  = n.children.length,
				mx = list.metrics.pages[page.index], s;
			s = (Math.floor(a/list.columns)+(a%list.columns? 1: 0))*(list.tileHeight+list.spacing);
			n.style.height = s + "px";
			mx.height = s;
			return s;
		},
		/**
			This method generates the markup for the page content.
		*/
		generatePage: enyo.inherit(function (sup) {
			return function (list, page) {
				sup.apply(this, arguments);
				this.layout(list, page);
			};
		}),
		/**
			Returns the calculated width for the given page.
		*/
		pageWidth: function (list, page) {
			var s  = list.boundsCache.width,
				n  = page.node || page.hasNode(),
				mx = list.metrics.pages[page.index];
			n.style.width = s + "px";
			mx.width = s;
			return s;
		},
		/**
			Retrieves the default page size.
		*/
		defaultPageSize: function (list) {
			return (Math.ceil(this.controlsPerPage(list)/list.columns) * (list.tileHeight+list.spacing));
		},
		/**
			Calculates metric values required for the absolute positioning and scaling of
			the children in the list.
		*/
		updateMetrics: function (list) {
			this.updateBounds(list);
			var bs = list.boundsCache,
				w  = bs.width,
				s  = list.spacing,
				m  = list.minWidth,
				h  = list.minHeight;
			// the number of columns is the ratio of the available width minus the spacing
			// by the minimum tile width plus the spacing
			list.columns    = Math.max(Math.floor((w-s) / (m+s)), 1);
			// the actual tile width is a ratio of the remaining width after all columns
			// and spacing are accounted for and the number of columns that we know we should have
			list.tileWidth  = ((w-(s*(list.columns+1)))/list.columns);
			// the actual tile height is related to the tile width
			list.tileHeight = (h*(list.tileWidth/m));
			// unfortunately this forces us to recalculate the number of controls that can
			// be used for each page
			this.controlsPerPage(list);
			// Compute first and last row index bounds
			this.updateIndexBound(list);
		},
		/**
			Calculates index bound that is required for adjusting page position
			You can call this method after DataGridList is rendered.
		*/
		updateIndexBound: function(list) {
			if (list.collection) {
				return;
			}
			// If user calls this method before DataGridList is rendered
			if (list.boundsCache === undefined) {
				this.updateMetrics(list);
			}

			list.indexBoundFirstRow = list.columns;
			list.indexBoundLastRow = (Math.ceil(list.collection.length / list.columns) - 1) * list.columns - 1;
		},
		/**
			The number of controls necessary to fill a page will change depending on some
			factors such as scaling and list-size adjustments. It is a function of the calculated
			size required (pageSizeMultiplier * the current boundary height) and the adjusted tile height and
			spacing.
		*/
		controlsPerPage: enyo.inherit(function (sup) {
			return function (list) {
				var orig    = list._updatedControlsPerPage,
					perPage = sup.apply(this, arguments);
				if (orig != list._updatedControlsPerPage) {
					// we need to adjust this value as it did not take into account
					// the spacing or the columns
					perPage = list.controlsPerPage = (perPage * list.columns);
				}
				return perPage;
			};
		}),
		childSize: function (list) {
			// currently DataGridList is only vertical
			/*jshint -W093 */
			return (list.childSize = (list.tileHeight + list.spacing));
		},
		/**
			Takes a given page and arbitrarily positions its children according to the pre-computed
			metrics of the list.

			TODO: This could be optimized to use requestAnimationFrame as well as render not by
			child index but by row thus cutting down some of the over-calculation when iterating
			over every child.
		*/
		layout: function (list, page) {
			if (list.canAddResetClass) {
				list.addClass("reset");
				delete list.canAddResetClass;
			}
			var cc = list.columns,
				s  = list.spacing,
				w  = list.tileWidth,
				h  = list.tileHeight,
				r  = 0,
				n  = page,
				cn = n.children, co;
			if (cn.length) {
				for (var i=0, c; (c=cn[i]); ++i) {
					// the column
					co = i % cc;
					c.addStyles(
						"top: "    + Math.round(s  + (r  * (h+s))) + "px; " +
						(list.rtl ? "right: " : "left: ") + Math.round(s  + (co * (w+s))) + "px; " +
						"width: "  + Math.round(w) +                 "px; " +
						"height: " + Math.round(h) +                 "px"
					);
					// check if we need to increment the row
					if ((i+1) % cc === 0) { ++r; }
				}
			}
		},
		/**
			Recalculates the buffer size based on the current metrics for the given
			list. This may or may not be completely accurate until the final page is
			scrolled into view.
		*/
		adjustBuffer: function (list) {
			var pc = this.pageCount(list),
				ds = this.defaultPageSize(list),
				bs = 0, sp = list.psizeProp, ss = list.ssizeProp,
				n = list.$.buffer.node || list.$.buffer.hasNode(), p;
			if (n) {
				for (var i=0; i<pc; ++i) {
					p = list.metrics.pages[i];
					bs += (p && p[sp]) || ds;
				}
				bs += list.spacing;
				list.bufferSize = bs;
				n.style[sp] = bs + "px";
				n.style[ss] = this[ss](list) + "px";
			}
		},
		/**
			Delegate's resize event handler.
		*/
		didResize: function (list) {
			// store the previous stats for comparative purposes
			var prev = list.boundsCache;

			// flag the list to have its bounds updated
			list._updateBounds = true;
			this.updateMetrics(list);

			// if no change it the viewport then we didn't update anything size-wise
			// and do not need to refresh at all
			if (
				prev.left   === list.boundsCache.left  &&
				prev.top    === list.boundsCache.top   &&
				prev.width  === list.boundsCache.width &&
				prev.height === list.boundsCache.height
			) {
				return;
			}

			// it is necessary to update the content of the list according to our
			// new sizing
			this.refresh(list);
		}
	}, true);
	enyo.DataGridList.delegates.verticalGrid = p;
})(enyo);

<|endoftext|>


<commit_before>import Model, { hasMany, belongsTo, attr } from '@ember-data/model';
import { computed } from '@ember/object';

export default Model.extend({
  title: attr('string'),
  description: attr('string'),
  uploadDate: attr('date'),
  originalAuthor: attr('string'),
  citation: attr('string'),
  copyrightPermission: attr('boolean'),
  copyrightRationale: attr('string'),
  filename: attr('string'),
  mimetype: attr('string'),
  filesize: attr('number'),
  link: attr('string'),
  absoluteFileUri: attr('string'),
  userRole: belongsTo('learning-material-user-role', { async: true }),
  status: belongsTo('learning-material-status', { async: true }),
  owningUser: belongsTo('user', { async: true }),
  sessionLearningMaterials: hasMany('session-learning-material', {
    async: true,
  }),
  courseLearningMaterials: hasMany('course-learning-material', { async: true }),
  type: computed('filename', 'citation', 'link', function () {
    if (this.filename) {
      return 'file';
    }
    if (this.citation) {
      return 'citation';
    }
    if (this.link) {
      return 'link';
    }

    return null;
  }),
  url: computed('absoluteFileUri', 'citation', 'link', 'type', function () {
    if (this.type === 'file') {
      return this.absoluteFileUri;
    }
    if (this.type === 'link') {
      return this.link;
    }

    return null;
  }),
  isFile: computed.equal('type', 'file'),
  isLink: computed.equal('type', 'link'),
  isCitation: computed.equal('type', 'citation'),
  fileHash: null,
});
<commit_msg>converts Learning Material model to class syntax.<commit_after>import Model, { hasMany, belongsTo, attr } from '@ember-data/model';

export default class LearningMaterial extends Model {
  @attr('string')
  title;
  @attr('string')
  description;
  @attr('date')
  uploadDate;
  @attr('string')
  originalAuthor;
  @attr('string')
  citation;
  @attr('boolean')
  copyrightPermission;
  @attr('string')
  copyrightRationale;
  @attr('string')
  filename;
  @attr('string')
  mimetype;
  @attr('number')
  filesize;
  @attr('string')
  link;
  @attr('string')
  absoluteFileUri;
  @belongsTo('learning-material-user-role', { async: true })
  userRole;
  @belongsTo('learning-material-status', { async: true })
  status;
  @belongsTo('user', { async: true })
  owningUser;
  @hasMany('session-learning-material', { async: true })
  sessionLearningMaterials;
  @hasMany('course-learning-material', { async: true })
  courseLearningMaterials;

  get type() {
    if (this.filename) {
      return 'file';
    }
    if (this.citation) {
      return 'citation';
    }
    if (this.link) {
      return 'link';
    }

    return null;
  }

  get url() {
    if (this.type === 'file') {
      return this.absoluteFileUri;
    }
    if (this.type === 'link') {
      return this.link;
    }

    return null;
  }

  get isFile() {
    return 'file' === this.type;
  }

  get isLink() {
    return 'link' === this.type;
  }

  get isCitation() {
    return 'citation' === this.type;
  }

  fileHash = null;
}
<|endoftext|>