<commit_before>(function() {
  function SongPlayer() {
    var SongPlayer = {};

    var currentSong = null;

    /**
    * @desc(A short description) Buzz object audio file
    * @type(The type, such as {Object}, {Array}, {Number}, etc.) {Object}
    */
    var currentBuzzObject = null;

    /**
    * @function(Name of the function) setSong
    * @desc Stops currently playing song and loads new audio file as currentBuzzObject
    * @param(A list of parameters and their type) {Object} song
    */
    var setSong = function(song) {
      if (currentBuzzObject) {
        currentBuzzObject.stop();
        currentSong.playing = null;
      }

      currentBuzzObject = new buzz.sound(song.audioUrl, {
        formats: ['mp3'],
        preload: true
      });

      currentSong = song;
    };

    SongPlayer.play = function(song) {
      if (currentSong !== song) {
        setSong(song);
        currentBuzzObject.play();
        song.playing = true;
      }
    };

    SongPlayer.pause = function(song) {
      currentBuzzObject.pause();
      song.playing = false;
    };

    return SongPlayer;
  }

  angular
    .module('blocJams')
    .factory('SongPlayer', SongPlayer);
})();
<commit_msg>Assignment 7 Services Pt2 completed<commit_after>(function() {
  function SongPlayer() {
    var SongPlayer = {};

    /**
    * @desc(A short description) selected song object and private attribute
    * @type(The type, such as {Object}, {Array}, {Number}, etc.) {Object}
    */
    var currentSong = null;

    /**
    * @desc Buzz object audio file and private attribute
    * @type {Object}
    */
    var currentBuzzObject = null;

    /**
    * @function(Name of the function) setSong
    * @desc A private function stopping the currently playing song and loading the new audio file as currentBuzzObject
    * @param(A list of parameters and their type) {Object} song
    */
    var setSong = function(song) {
      if (currentBuzzObject) {
        currentBuzzObject.stop();
        currentSong.playing = null;
      }

      currentBuzzObject = new buzz.sound(song.audioUrl, {
        formats: ['mp3'],
        preload: true
      });

      currentSong = song;
    };

    /**
    * @function playSong
    * @desc A private function playing the current song and setting the playing property of the song object to true
    * @param {Object} song
    */
    var playSong = function(song){
      currentBuzzObject.play();
      song.playing = true;
    };

    /**
    * @function SongPlayer.play
    * @desc This public method plays the selected song
    * @param {Object} song
    */
    SongPlayer.play = function(song) {
      if (currentSong !== song) {
        setSong(song);
        playSong(song);
      }
    };

    /**
    * @function SongPlayer.pause
    * @desc This public method pauses the selected song
    * @param {Object} song
    */
    SongPlayer.pause = function(song) {
      currentBuzzObject.pause();
      song.playing = false;
    };

    return SongPlayer;
  }

  angular
    .module('blocJams')
    .factory('SongPlayer', SongPlayer);
})();
<|endoftext|>


<commit_before>/*****************************************************************************/
/*                          Main JS for whileaway                            */
/*****************************************************************************/

$(document).ready(function(){
    // Form UI fixes

    $('#keyword').change(function() {
    	option_val = $('#keyword > option:selected').val();
    	$('#keyword-span').html(option_val);
    	$('#keyword').width($('#keyword-span').width());
    });

    $('#keyword').change();

    $('#date').change(function() {
    	option_val = $('#date > option:selected').val();
    	$('#date-span').html(option_val);
    	$('#date').width($('#date-span').width());
    });

    $('#date').change();

    function inputWidth() {
    	$('#number-span').html($('#number').val());
    	$('#number').css('width', $('#number-span').width());
    }

    inputWidth();

    $('#number').bind('keyup input paste', inputWidth);

    window.onresize = function() {
    	$('#keyword').change();
    	$('#date').change();
    	inputWidth();
    }

    // Fetching and displaying stories
    getNews();

    // onchange of input fields, call getNews()
    $('#number').bind('keyup input paste', function(){getNews();});
    $('#date').change(function(){getNews();});
    $('#keyword').change(function(){getNews();});
});

function getNews(){
	amount = $('#number').val();
	scope = $('#date option:selected').val();
	keyword = $('#keyword option:selected').val();
	if (keyword == 'news') {
		keyword = '';
	};

	try {
		validate(amount, scope, keyword);
	} catch (e) {
		alert(e);
		return;
	}

	// make asynchronous request
	getNewsFromAPI(amount, scope, keyword);
}

function handleNews(news){
	$('#form button').html('Go');

	str = '
';
	$.each(news, function(index, story) {
		headline = story[0];
		link = story[1];
		date = story[2];
		// summary = story[3];

		// str += '
' + headline + ' (more…, ' + date.f('d MMM yyyy HH:mm') + ')
';
        str += '
';
		str += '' + headline + '';
        str += '

Insert summary here
Read more…
'
        str += '
  '
	});
	str += '
';
	$('#headlines').html(str);

    // display summary on headline click
    $('.headline a').click(function(e){
        e.preventDefault();
        $(this).next('div').toggle(300);
    });
}

function validate(amount, scope, keyword) {
	scopes = ['days', 'weeks', 'months'];
	if (scopes.indexOf(scope) < 0) {
		throw 'Invalid scope';
	}

	if (isNaN(amount)) {
		throw 'Invalid amount';
	}

	$.trim(keyword);
}
<commit_msg>Fix + improvement<commit_after>/*****************************************************************************/
/*                          Main JS for whileaway                            */
/*****************************************************************************/

$(document).ready(function(){
    // Form UI fixes

    $('#keyword').change(function() {
    	option_val = $('#keyword > option:selected').val();
    	$('#keyword-span').html(option_val);
    	$('#keyword').width($('#keyword-span').width());
    });

    $('#keyword').change();

    $('#date').change(function() {
    	option_val = $('#date > option:selected').val();
    	$('#date-span').html(option_val);
    	$('#date').width($('#date-span').width());
    });

    $('#date').change();

    function inputWidth() {
    	$('#number-span').html($('#number').val());
    	$('#number').css('width', $('#number-span').width());
    }

    inputWidth();

    $('#number').bind('keyup input paste', inputWidth);

    window.onresize = function() {
    	$('#keyword').change();
    	$('#date').change();
    	inputWidth();
    }

    // Fetching and displaying stories
    getNews();

    // onchange of input fields, call getNews()
    $('#number').bind('keyup input paste', function(){getNews();});
    $('#date').change(function(){getNews();});
    $('#keyword').change(function(){getNews();});
});

function getNews(){
	amount = $('#number').val();
	scope = $('#date option:selected').val();
	keyword = $('#keyword option:selected').val();
	if (keyword == 'news') {
		keyword = '';
	};

	try {
		validate(amount, scope, keyword);
	} catch (e) {
		alert(e);
		return;
	}

	// make asynchronous request
	getNewsFromAPI(amount, scope, keyword);
}

function handleNews(news){
	$('#form button').html('Go');

	str = '
';
	$.each(news, function(index, story) {
		headline = story[0];
		link = story[1];
		date = story[2];
		// summary = story[3];

		// str += '
' + headline + ' (more…, ' + date.f('d MMM yyyy HH:mm') + ')
';
        str += '
';
		str += '' + headline + '';
        str += '

Insert summary here
Read more…
'
        str += '
  '
	});
	str += '
';
	$('#headlines').html(str);

    // display summary on headline click
    $('.headline > a').click(function(e){
        e.preventDefault();
        $(this).next('div').toggle(300);
    });
}

function validate(amount, scope, keyword) {
	scopes = ['days', 'weeks', 'months'];
	if (scopes.indexOf(scope) < 0) {
		throw 'Invalid scope';
	}

	if (isNaN(amount)) {
		throw 'Invalid amount';
	}

	$.trim(keyword);
}
<|endoftext|>


<commit_before>"use strict";
/* jshint undef: true, unused: true */
/* global Mustache, promise  */

var Applet = function () {
  var i = this; // === this instance

  i.funcs = [];

  i.data_cache = {};

  var args    = _(arguments).toArray().flattenDeep().value();

  _.each(args, function (val) {
    if (_.isString(val)) {
      i.run(val);
    } else {
      if (_.isFunction(val)) {
        i.new_func(val);
      } else {
        throw new Error(
          "Not a function." +
            "Only strings and functions allowed in constructor: " +
              typeof(val) + " -> " + val
        );
      }
    }
  });
}; // === Applet constructor ===========================

(function () { // === scope ==============================

  // =====================================================
  // === HELPERS
  // =====================================================

  var log;

  log = Applet.log = function () {
    if (window.console)
      return console.log.apply(console, arguments);
    return this;
  };

  // Examples:
  //
  //   .new_id()           ->  Integer
  //   .new_id('prefix_')  ->  String
  //
  Applet.new_id = function (prefix) {
    if (!Applet.hasOwnProperty('_id'))
      Applet._id = -1;
    Applet._id = Applet._id + 1;
    return (prefix) ? prefix + Applet._id : Applet._id;
  }; // === func

  // Returns id.
  // Sets id of element if no id is set.
  //
  // .dom_id(raw_or_jquery)
  // .dom_id('prefix', raw_or_jquer)
  //
  Applet.dom_id = function () {
    var args = _.toArray(arguments);
    var o      = _.find(args, _.negate(_.isString));
    var prefix = _.find(args, _.isString);
    var old    = o.attr('id');

    if (old && !_.isEmpty(old))
      return old;

    var new_id = Applet.new_id(prefix || 'id_for_applet_') ;
    o.attr('id', new_id);
    return new_id;
  }; // === id

  Applet.insert_after = function (script) {
    $($(script).contents()).insertAfter($(script));
  }; // === insert_after

  Applet.insert_before = function (script) {
    $($(script).contents()).insertBefore($(script));
  }; // === insert_before

  Applet.is_true = function (data, raw_key) {
    if (!Applet.FRONT_BANGS)
      Applet.FRONT_BANGS = /^\!+/;

    var key        = _.trim(raw_key);
    var bang_match = key.match(Applet.FRONT_BANGS);
    var dots       = ( bang_match ? key.replace(bang_match[0], '') : key ).split('.');
    var keys       = _.map( dots, _.trim );

    var current = data;
    var ans  = false;

    _.detect(keys, function (key) {
      if (_.has(current, key)) {
        current = data[key];
        ans = !!current;
      } else {
        ans = undefined;
      }

      return !ans;
    });

    if (ans === undefined)
      return ans;

    if (bang_match) {
      _.times(bang_match[0].length, function () {
        ans = !ans;
      });
    }

    return ans;
  }; // === func

  Applet.attrs = function (dom) {
    return _.reduce(
      dom.attributes,
      function (kv, o) {
        kv[o.name] = o.value;
        return kv;
      },
      {}
    );
  }; // === attrs

  Applet.standard_name = function (str) {
    return _.trim(str).replace(/\ +/g, ' ').toLowerCase();
  };

  Applet.remove_attr = function (node, name) {
    var val = $(node).attr(name);
    $(node).removeAttr(name);
    return val;
  };

  Applet.node_array = function (unknown) {
    var arr = [];
    _.each($(unknown), function (dom) {
      if (dom.nodeType !== 1)
        return arr.push(dom);

      arr.push({
        tag    : dom.nodeName,
        attrs  : Applet.attrs(dom),
        custom : {},
        childs : Applet.node_array($(dom).contents())
      });
    });

    return arr;
  };

  Applet.top_descendents = function (dom, selector) {
    var arr = [];
    _.each($(dom), function (node) {
      var o = $(node);
      if (o.is(selector))
        return arr.push(o);
      arr = arr.concat(Applet.top_descendents(o.children(), selector));
    }); // === func

    return arr;
  }; // === func

  // =====================================================
  // === PROTOTYPE
  // =====================================================

  Applet.prototype.config_for_func = function (f) {
    var i = this;

    if (!i.func_ids) {
      i.func_id_to_config = {}; // === used by callbacks to store info.
      i.func_ids          = {}; // give each callback an id to be used in .configs
    }

    var id = _.findKey(i.func_ids, function (v) { return v === f; } );

    if (!id) {
      id                      = Applet.new_id('config_id_');
      i.func_id_to_config[id] = {};
      i.func_ids[id]          = f;
    }

    return i.func_id_to_config[id];
  }; // === config_id

  // === Examples:
  //
  // .run(name, 'str')
  // .run(name, 'str', {...})
  // .run({name: 'str', ... more meta data}, ...data args)
  //
  Applet.prototype.run = function () {

    var raw_args = _.toArray(arguments);

    var first = raw_args[0];
    var args  = _.slice(raw_args, 1);

    var instance = this;

    var meta, name;

    if (_.isPlainObject(first)) {
      meta = _.extend(first, {
        name   : Applet.standard_name(first.name),
        applet : instance
      });
      name = first.name;
    } else {
      meta = {
        name   : Applet.standard_name(first),
        applet : instance
      };
    }

    if (!_.isString(meta.name))
      throw new Error(":name must be a String: " + meta.name.toString());

    if (meta.name === 'data' && _.isPlainObject(args[0]))
      instance.data_cache = _.extend(instance.data_cache, args[0]);

    var i = 0, f;

    while (instance.funcs[i]) {
      f                = instance.funcs[i];
      meta.this_config = instance.config_for_func(f);
      meta.this_func   = f;
      meta.data_cache  = instance.data_cache;

      f.apply(null, [meta].concat(args));
      ++i;
    }

    return instance;
  }; // === func

  Applet.prototype.new_func = function () {

    var arr = _.flatten(_.toArray(arguments));
    var i   = this;

    _.each(arr, function (f) {

      if (!_.isFunction(f))
        throw new Error('Error: Not a function');

      if (f({name : 'this position', applet: i}) === 'top')
        i.funcs.unshift(f);
      else
        i.funcs.push(f);
    });

    return this;
  };

  // =====================================================
  // === FUNCTIONS
  // =====================================================

  Applet.funcs = {};

  // === template ====================
  Applet.funcs.template = function (o) {
    if (o.name === 'this position')
      return 'top';

    if (o.name !== 'dom')
      return;

    var selector    = 'script[type^="text/mustache"]:not(script.compiled)';
    var scripts     = (o.target || $('body')).find(selector).addBack(selector);
    if (scripts.length < 1)
      return;

    _.each(scripts, function (raw) {
      var t              = $(raw);
      var types          = t.attr('type').split('/');
      var html           = t.html();
      var placeholder_id = Applet.dom_id(t);
      var data_key       = types[2];
      var id             = Applet.dom_id(t, 'mustache_templates_' + (data_key || ''));
      var pos            = 'replace';

      t.addClass('compiled');

      switch (_.trim(types[1])) {
        case 'mustache-top':
          pos = 'top';
        break;

        case 'mustache-bottom':
          pos = 'bottom';
        break;
      } // === switch type[1]

      var meta = {
        id             : id,
        key            : data_key,
        html           : html,
        mustache       : html,
        placeholder_id : placeholder_id,
        elements       : null,
        pos            : pos
      };

      o.applet.new_func(
        function (o, data) {
          if (o.name !== 'data' || !_.isPlainObject(data[meta.key]))
            return;

          // === Remove old nodes:
          if (meta.elements && meta.pos === 'replace') {
            meta.elements.remove();
          }

          var html = $(Mustache.render(meta.mustache, data));
          if (meta.pos === 'replace' || meta.pos === 'bottom')
            html.insertBefore($('#' + meta.placeholder_id));
          else
            html.insertAfter($('#' + meta.placeholder_id));

          meta.elements = html;
          o.applet.run({
            name   : 'dom',
            target : html
          });
        }
      ); // === new_func

    });

  }; // ==== funcs: template ==========

  // === show_if ====================
  Applet.funcs.show_if = function (o) {

    if (o.name !== 'dom') return;

    var selector   = '*[data-show_if]';
    var targets    = $(o.target || $('body')).find(selector).addBack(selector);

    _.each(targets, function (raw_node) {
      var node    = $(raw_node);
      var the_key = Applet.remove_attr(raw_node, 'data-show_if');

      if (!Applet.is_true(o.data_cache, the_key))
        node.hide();

      var the_id  = Applet.dom_id(node);

      o.applet.new_func(
        function (o, data) {
          if (o.name !== 'data') return;

          switch (Applet.is_true(data, the_key)) {
            case true:
              $('#' + the_id).show();
            return;

            case false:
              $('#' + the_id).hide();
            return;
          } // === switch value

        } // === func
      );

    }); // === each

  }; // === funcs: show_if ========

  // === hide_if ====================
  Applet.funcs.hide_if = function (o) {
    if (o.name !== 'dom') return;

    var selector   = '*[data-hide_if]';
    var targets    = $(o.target || $('body')).find(selector).addBack(selector);

    _.each(targets, function (raw_node) {
      var node = $(raw_node);
      var key  = Applet.remove_attr(node, 'data-hide_if');

      if (Applet.is_true(o.data_cache, key) === true)
        node.hide();

      var id  = Applet.dom_id(node);

      o.applet.new_func(
        function (o, data) {
          if (o.name !== 'data') return;

          switch (Applet.is_true(data, key)) {
            case true:
              $('#' + id).hide();
            return;
            case false:
              $('#' + id).show();
            return;
          } // === switch value
        }
      ); // === new_func

    }); // === each target

  }; // === funcs: hide_if ========

  // === ajax =====================
  Applet.funcs.ajax = function (o, data) {

    switch (o.name) {

      case 'ajax':
        if (o['send?']) {
          o.promise = promise.post(o.url, data, o.headers);
          o.promise.then(function (err, text, xhr) {
            o.applet.run({
              name: 'ajax response',
              raw_response: {err: err, text: text, xhr: xhr},
              request : {
                form_id : o.form_id,
                url     : o.url,
                data    : data,
                headers : o.headers
              },
              promise: o.promise
            });
          });
        }
      break;

      case 'ajax response':
        if (!o.response && o.raw_response) {
          var status     = o.raw_response.xhr && o.raw_response.xhr.status;
          var err        = o.raw_response.err;
          var err_tags   = [];
          if (err) {
            err_tags.push('server');
            err_tags.push(status);
          }

          o.response = {};

          var json;
          try {
            json = JSON.parse(o.raw_response.text);
          } catch(e) {
            err = true;
            if (_.isEmpty(err_tags))
              err_tags.push('invalid json');
          }

          if (err)
            o.response = {error: {tags: err_tags, msg: o.raw_response.text}};
          else
            o.response = json;
        }
      break;

    } // === switch o.name

  }; // === funcs: ajax

  // === form =====================
  Applet.funcs.form = function (o) {

    if (o.name === 'ajax response' && o.request) {
      $('#' + o.request.form_id ).prop('disabled', false);
      return;
    }

    if (o.name !== 'dom')
      return;

    var selector = $('form:not(form.compiled) button.submit');
    var target   = $(o.target || $('body')).find(selector).addBack(selector);

    if (!o.this_func.submit) {
      o.this_func.submit = function (a) {
        return function (e) {
          var form = $(this).closest('form');
          form.prop('disabled', true);
          e.preventDefault();
          e.stopPropagation();

          promise.get('/_csrf').then(function (err, text) {
            var data = form.serializeJSON();
            if (!err) {
              try {
                data._csrf = JSON.parse(text)._csrf || "";
              } catch (e) {
              }
            }

            a.run({
              name    : 'ajax',
              'send?' : true,
              form_id : form.attr('id'),
              url     : form.attr('action'),
              headers : {"Accept": "application/json"},
            }, data);
          });

        }; // === return function
      };
    } // === if this_func

    var i = 0;
    while (target[i]) {
      $(target[i]).on('click', o.this_func.submit(o.applet));
      ++i;
    } // === while
  }; // === funcs: form

})(); // === end scope =================================

<commit_msg>Touchups: added 'ajax raw response'<commit_after>"use strict";
/* jshint undef: true, unused: true */
/* global Mustache, promise  */

var Applet = function () {
  var i = this; // === this instance

  i.funcs = [];

  i.data_cache = {};

  var args    = _(arguments).toArray().flattenDeep().value();

  _.each(args, function (val) {
    if (_.isString(val)) {
      i.run(val);
    } else {
      if (_.isFunction(val)) {
        i.new_func(val);
      } else {
        throw new Error(
          "Not a function." +
            "Only strings and functions allowed in constructor: " +
              typeof(val) + " -> " + val
        );
      }
    }
  });
}; // === Applet constructor ===========================

(function () { // === scope ==============================

  // =====================================================
  // === HELPERS
  // =====================================================

  var log;

  log = Applet.log = function () {
    if (window.console)
      return console.log.apply(console, arguments);
    return this;
  };

  // Examples:
  //
  //   .new_id()           ->  Integer
  //   .new_id('prefix_')  ->  String
  //
  Applet.new_id = function (prefix) {
    if (!Applet.hasOwnProperty('_id'))
      Applet._id = -1;
    Applet._id = Applet._id + 1;
    return (prefix) ? prefix + Applet._id : Applet._id;
  }; // === func

  // Returns id.
  // Sets id of element if no id is set.
  //
  // .dom_id(raw_or_jquery)
  // .dom_id('prefix', raw_or_jquer)
  //
  Applet.dom_id = function () {
    var args = _.toArray(arguments);
    var o      = _.find(args, _.negate(_.isString));
    var prefix = _.find(args, _.isString);
    var old    = o.attr('id');

    if (old && !_.isEmpty(old))
      return old;

    var new_id = Applet.new_id(prefix || 'id_for_applet_') ;
    o.attr('id', new_id);
    return new_id;
  }; // === id

  Applet.insert_after = function (script) {
    $($(script).contents()).insertAfter($(script));
  }; // === insert_after

  Applet.insert_before = function (script) {
    $($(script).contents()).insertBefore($(script));
  }; // === insert_before

  Applet.is_true = function (data, raw_key) {
    if (!Applet.FRONT_BANGS)
      Applet.FRONT_BANGS = /^\!+/;

    var key        = _.trim(raw_key);
    var bang_match = key.match(Applet.FRONT_BANGS);
    var dots       = ( bang_match ? key.replace(bang_match[0], '') : key ).split('.');
    var keys       = _.map( dots, _.trim );

    var current = data;
    var ans  = false;

    _.detect(keys, function (key) {
      if (_.has(current, key)) {
        current = data[key];
        ans = !!current;
      } else {
        ans = undefined;
      }

      return !ans;
    });

    if (ans === undefined)
      return ans;

    if (bang_match) {
      _.times(bang_match[0].length, function () {
        ans = !ans;
      });
    }

    return ans;
  }; // === func

  Applet.attrs = function (dom) {
    return _.reduce(
      dom.attributes,
      function (kv, o) {
        kv[o.name] = o.value;
        return kv;
      },
      {}
    );
  }; // === attrs

  Applet.standard_name = function (str) {
    return _.trim(str).replace(/\ +/g, ' ').toLowerCase();
  };

  Applet.remove_attr = function (node, name) {
    var val = $(node).attr(name);
    $(node).removeAttr(name);
    return val;
  };

  Applet.node_array = function (unknown) {
    var arr = [];
    _.each($(unknown), function (dom) {
      if (dom.nodeType !== 1)
        return arr.push(dom);

      arr.push({
        tag    : dom.nodeName,
        attrs  : Applet.attrs(dom),
        custom : {},
        childs : Applet.node_array($(dom).contents())
      });
    });

    return arr;
  };

  Applet.top_descendents = function (dom, selector) {
    var arr = [];
    _.each($(dom), function (node) {
      var o = $(node);
      if (o.is(selector))
        return arr.push(o);
      arr = arr.concat(Applet.top_descendents(o.children(), selector));
    }); // === func

    return arr;
  }; // === func

  // =====================================================
  // === PROTOTYPE
  // =====================================================

  Applet.prototype.config_for_func = function (f) {
    var i = this;

    if (!i.func_ids) {
      i.func_id_to_config = {}; // === used by callbacks to store info.
      i.func_ids          = {}; // give each callback an id to be used in .configs
    }

    var id = _.findKey(i.func_ids, function (v) { return v === f; } );

    if (!id) {
      id                      = Applet.new_id('config_id_');
      i.func_id_to_config[id] = {};
      i.func_ids[id]          = f;
    }

    return i.func_id_to_config[id];
  }; // === config_id

  // === Examples:
  //
  // .run(name, 'str')
  // .run(name, 'str', {...})
  // .run({name: 'str', ... more meta data}, ...data args)
  //
  Applet.prototype.run = function () {

    var raw_args = _.toArray(arguments);

    var first = raw_args[0];
    var args  = _.slice(raw_args, 1);

    var instance = this;

    var meta, name;

    if (_.isPlainObject(first)) {
      meta = _.extend(first, {
        name   : Applet.standard_name(first.name),
        applet : instance
      });
      name = first.name;
    } else {
      meta = {
        name   : Applet.standard_name(first),
        applet : instance
      };
    }

    if (!_.isString(meta.name))
      throw new Error(":name must be a String: " + meta.name.toString());

    if (meta.name === 'data' && _.isPlainObject(args[0]))
      instance.data_cache = _.extend(instance.data_cache, args[0]);

    var i = 0, f;

    while (instance.funcs[i]) {
      f                = instance.funcs[i];
      meta.this_config = instance.config_for_func(f);
      meta.this_func   = f;
      meta.data_cache  = instance.data_cache;

      f.apply(null, [meta].concat(args));
      ++i;
    }

    return instance;
  }; // === func

  Applet.prototype.new_func = function () {

    var arr = _.flatten(_.toArray(arguments));
    var i   = this;

    _.each(arr, function (f) {

      if (!_.isFunction(f))
        throw new Error('Error: Not a function');

      if (f({name : 'this position', applet: i}) === 'top')
        i.funcs.unshift(f);
      else
        i.funcs.push(f);
    });

    return this;
  };

  // =====================================================
  // === FUNCTIONS
  // =====================================================

  Applet.funcs = {};

  // === template ====================
  Applet.funcs.template = function (o) {
    if (o.name === 'this position')
      return 'top';

    if (o.name !== 'dom')
      return;

    var selector    = 'script[type^="text/mustache"]:not(script.compiled)';
    var scripts     = (o.target || $('body')).find(selector).addBack(selector);
    if (scripts.length < 1)
      return;

    _.each(scripts, function (raw) {
      var t              = $(raw);
      var types          = t.attr('type').split('/');
      var html           = t.html();
      var placeholder_id = Applet.dom_id(t);
      var data_key       = types[2];
      var id             = Applet.dom_id(t, 'mustache_templates_' + (data_key || ''));
      var pos            = 'replace';

      t.addClass('compiled');

      switch (_.trim(types[1])) {
        case 'mustache-top':
          pos = 'top';
        break;

        case 'mustache-bottom':
          pos = 'bottom';
        break;
      } // === switch type[1]

      var meta = {
        id             : id,
        key            : data_key,
        html           : html,
        mustache       : html,
        placeholder_id : placeholder_id,
        elements       : null,
        pos            : pos
      };

      o.applet.new_func(
        function (o, data) {
          if (o.name !== 'data' || !_.isPlainObject(data[meta.key]))
            return;

          // === Remove old nodes:
          if (meta.elements && meta.pos === 'replace') {
            meta.elements.remove();
          }

          var html = $(Mustache.render(meta.mustache, data));
          if (meta.pos === 'replace' || meta.pos === 'bottom')
            html.insertBefore($('#' + meta.placeholder_id));
          else
            html.insertAfter($('#' + meta.placeholder_id));

          meta.elements = html;
          o.applet.run({
            name   : 'dom',
            target : html
          });
        }
      ); // === new_func

    });

  }; // ==== funcs: template ==========

  // === show_if ====================
  Applet.funcs.show_if = function (o) {

    if (o.name !== 'dom') return;

    var selector   = '*[data-show_if]';
    var targets    = $(o.target || $('body')).find(selector).addBack(selector);

    _.each(targets, function (raw_node) {
      var node    = $(raw_node);
      var the_key = Applet.remove_attr(raw_node, 'data-show_if');

      if (!Applet.is_true(o.data_cache, the_key))
        node.hide();

      var the_id  = Applet.dom_id(node);

      o.applet.new_func(
        function (o, data) {
          if (o.name !== 'data') return;

          switch (Applet.is_true(data, the_key)) {
            case true:
              $('#' + the_id).show();
            return;

            case false:
              $('#' + the_id).hide();
            return;
          } // === switch value

        } // === func
      );

    }); // === each

  }; // === funcs: show_if ========

  // === hide_if ====================
  Applet.funcs.hide_if = function (o) {
    if (o.name !== 'dom') return;

    var selector   = '*[data-hide_if]';
    var targets    = $(o.target || $('body')).find(selector).addBack(selector);

    _.each(targets, function (raw_node) {
      var node = $(raw_node);
      var key  = Applet.remove_attr(node, 'data-hide_if');

      if (Applet.is_true(o.data_cache, key) === true)
        node.hide();

      var id  = Applet.dom_id(node);

      o.applet.new_func(
        function (o, data) {
          if (o.name !== 'data') return;

          switch (Applet.is_true(data, key)) {
            case true:
              $('#' + id).hide();
            return;
            case false:
              $('#' + id).show();
            return;
          } // === switch value
        }
      ); // === new_func

    }); // === each target

  }; // === funcs: hide_if ========

  // === ajax =====================
  Applet.funcs.ajax = function (o, data) {

    switch (o.name) {

      case 'ajax':
        if (o['send?']) {
          o.promise = promise.post(o.url, data, o.headers);
          o.promise.then(function (err, text, xhr) {
            o.applet.run({
              name: 'ajax raw response',
              raw_response: {err: err, text: text, xhr: xhr},
              request : {
                form_id : o.form_id,
                url     : o.url,
                data    : data,
                headers : o.headers
              },
              promise: o.promise
            });
          });
        }
      break;

      case 'ajax raw response':
        if (!o.response && o.raw_response) {
          var raw        = o.raw_response;
          var status     = o.raw_response.xhr && o.raw_response.xhr.status;
          var err        = o.raw_response.err;
          var err_tags   = [];
          if (err) {
            err_tags.push('server');
            err_tags.push(status);
          }

          var new_o = _.extend(o, {
            name     : "ajax response",
            response : {}
          });

          var json;
          try {
            json = JSON.parse(raw.text);
          } catch(e) {
            err = true;
            if (_.isEmpty(err_tags))
              err_tags.push('invalid json');
          }

          if (err)
            new_o.response = {error: {tags: err_tags, msg: raw.text}};
          else
            new_o.response = json;

          o.applet.run(new_o, new_o.response);
        } // if !o.response && !o.raw_response
      break;

    } // === switch o.name

  }; // === funcs: ajax

  // === form =====================
  Applet.funcs.form = function (o) {

    if (o.name === 'ajax response' && o.request) {
      $('#' + o.request.form_id ).prop('disabled', false);
      return;
    }

    if (o.name !== 'dom')
      return;

    var selector = $('form:not(form.compiled) button.submit');
    var target   = $(o.target || $('body')).find(selector).addBack(selector);

    if (!o.this_func.submit) {
      o.this_func.submit = function (a) {
        return function (e) {
          var form = $(this).closest('form');
          form.prop('disabled', true);
          e.preventDefault();
          e.stopPropagation();

          promise.get('/_csrf').then(function (err, text) {
            var data = form.serializeJSON();
            if (!err) {
              try {
                data._csrf = JSON.parse(text)._csrf || "";
              } catch (e) {
              }
            }

            a.run({
              name    : 'ajax',
              'send?' : true,
              form_id : form.attr('id'),
              url     : form.attr('action'),
              headers : {"Accept": "application/json"},
            }, data);
          });

        }; // === return function
      };
    } // === if this_func

    var i = 0;
    while (target[i]) {
      $(target[i]).on('click', o.this_func.submit(o.applet));
      ++i;
    } // === while
  }; // === funcs: form

})(); // === end scope =================================

<|endoftext|>


<commit_before>/**
 * Main JavaScript
 * Site Name
 *
 * Copyright (c) 2015. by Way2CU, http://way2cu.com
 * Authors:
 */

var Site = Site || {};

/**
 * Check if site is being displayed on mobile.
 * @return boolean
 */
Site.is_mobile = function() {
	// make sure variable cache exists
	Site.variable_cache = Site.variable_cache || {};

	// check for cached value
	if ('mobile_version' in Site.variable_cache) {
		var result = Site.variable_cache['mobile_version'];

	} else {
		// detect if site is mobile
		var result = false;
		var elements = document.getElementsByName('viewport');

		// check all tags and find `meta`
		for (var i=0, count=elements.length; i<count; i++) {
			var tag = elements[i];

			if (tag.tagName == 'META') {
				result = true;
				break;
			}
		}

		// cache value so next time we are faster
		Site.variable_cache['mobile_version'] = result;
	}

	return result;
};

/**
 * Function called when document and images have been completely loaded.
 */
Site.on_load = function() {
};

// connect document `load` event with handler function
$(Site.on_load);
<commit_msg>Main script: Moved variable cache outside of function.<commit_after>/**
 * Main JavaScript
 * Site Name
 *
 * Copyright (c) 2015. by Way2CU, http://way2cu.com
 * Authors:
 */

// create or use existing site scope
var Site = Site || {};

// make sure variable cache exists
Site.variable_cache = Site.variable_cache || {};

/**
 * Check if site is being displayed on mobile.
 * @return boolean
 */
Site.is_mobile = function() {
	var result = false;

	// check for cached value
	if ('mobile_version' in Site.variable_cache) {
		result = Site.variable_cache['mobile_version'];

	} else {
		// detect if site is mobile
		var elements = document.getElementsByName('viewport');

		// check all tags and find `meta`
		for (var i=0, count=elements.length; i<count; i++) {
			var tag = elements[i];

			if (tag.tagName == 'META') {
				result = true;
				break;
			}
		}

		// cache value so next time we are faster
		Site.variable_cache['mobile_version'] = result;
	}

	return result;
};

/**
 * Function called when document and images have been completely loaded.
 */
Site.on_load = function() {
};

// connect document `load` event with handler function
$(Site.on_load);
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { connect } from 'react-redux';
import { update_books } from '../actions';
import { Button } from 'react-bootstrap';
require('../../styles/index.scss');

class SignInScreen extends Component {
   componentDidMount() {
       const { user } = this.props
        const { dispatch } = this.props
        // get the books on site load
       // dispatch(update_books());
    }

render() {
    var isProduction = process.env.NODE_ENV === 'production';
    if (isProduction) var url = 'https://my-nightlife-coordinator.herokuapp.com/';
    else var url = 'http://127.0.0.1:3000/';
    return (

The Book Thing

            <Button bsStyle="primary" bsSize="lg">Sign in with Twitter

            </Button>

Trade books with people from all over

        )
    }
}

SignInScreen = connect()(SignInScreen)
export default SignInScreen

<commit_msg>modified the authentication link in the client for the production app<commit_after>import React, { Component } from 'react';
import { connect } from 'react-redux';
import { update_books } from '../actions';
import { Button } from 'react-bootstrap';
require('../../styles/index.scss');

class SignInScreen extends Component {
   componentDidMount() {
       const { user } = this.props
        const { dispatch } = this.props
        // get the books on site load
       // dispatch(update_books());
    }

render() {
    var isProduction = process.env.NODE_ENV === 'production';
    if (isProduction) var url = 'https://the-book-thing.herokuapp.com/';
    else var url = 'http://127.0.0.1:3000/';
    return (

The Book Thing

            <Button bsStyle="primary" bsSize="lg">Sign in with Twitter

            </Button>

Trade books with people from all over

        )
    }
}

SignInScreen = connect()(SignInScreen)
export default SignInScreen

<|endoftext|>


<commit_before>describe("About Expects", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should expect true", function() {
    expect(false).toBeTruthy(); //This should be true
  });

  //To understand reality, we must compare our expectations against reality.
  it("should expect equality", function () {
    var expectedValue = FILL_ME_IN;
    var actualValue = 1 + 1;

    expect(actualValue === expectedValue).toBeTruthy();
  });

  //Some ways of asserting equality are better than others.
  it("should assert equality a better way", function () {
    var expectedValue = FILL_ME_IN;
    var actualValue = 1 + 1;

  // toEqual() compares using common sense equality.
    expect(actualValue).toEqual(expectedValue);
  });

  //Sometimes you need to be really exact about what you "type".
  it("should assert equality with ===", function () {
    var expectedValue = FILL_ME_IN;
    var actualValue = (1 + 1).toString();

  // toBe() will always use === to compare.
    expect(actualValue).toBe(expectedValue);
  });

  //Sometimes we will ask you to fill in the values.
  it("should have filled in values", function () {
    expect(1 + 1).toEqual(FILL_ME_IN);
  });
});
<commit_msg>fixes indentation for comments and a punctuation mistake.<commit_after>describe("About Expects", function() {

  //  We shall contemplate truth by testing reality, via spec expectations.
  it("should expect true", function() {
    expect(false).toBeTruthy(); //This should be true
  });

  //  To understand reality, we must compare our expectations against reality.
  it("should expect equality", function () {
    var expectedValue = FILL_ME_IN;
    var actualValue = 1 + 1;

    expect(actualValue === expectedValue).toBeTruthy();
  });

  //  Some ways of asserting equality are better than others.
  it("should assert equality a better way", function () {
    var expectedValue = FILL_ME_IN;
    var actualValue = 1 + 1;

  // toEqual() compares using common sense equality.
    expect(actualValue).toEqual(expectedValue);
  });

  //  Sometimes you need to be really exact about what you "type.""
  it("should assert equality with ===", function () {
    var expectedValue = FILL_ME_IN;
    var actualValue = (1 + 1).toString();

  // toBe() will always use === to compare.
    expect(actualValue).toBe(expectedValue);
  });

  // Sometimes we will ask you to fill in the values.
  it("should have filled in values", function () {
    expect(1 + 1).toEqual(FILL_ME_IN);
  });
});
<|endoftext|>


<commit_before>'use strict';
var boom = require('boom');
var config = require('../config');
var moment = require('moment');
var _ = require('lodash');
var centroids = require('../data/dsw-admin2-centroids.json');
var knex = require('../services/db');
var dataLoader = require('../utils/yaml-md-loader');

// Generate an array with timesteps relevant for the dashboards
function generateTimesteps (startDate) {
  let timeSteps = [];
  var now = moment();
  for (let d = startDate.clone(); d <= now; d.month(d.month() + 1)) {
    timeSteps.push(d.clone());
  }
  return timeSteps;
}

// Generate a date for each object
function addTimestep (rows) {
  rows.forEach(function (row) {
    row.timestep = moment.utc(`${row.year}-${row.month}-01`);
  });
  return rows;
}

// Sum data for a particular field, prior to startDate of the dashboards
function sumOldData (allData, field, startDate) {
  let oldData = _.filter(allData, function (o) { return o.timestep < startDate; });
  return _.sumBy(oldData, field);
}

module.exports = {
  access: {
    handler: (request, reply) => {
      let contentP = dataLoader(`${config.baseDir}/content/section-access-home.md`);

      let dataP = knex.select('iso', 'year', 'month').from('dispensers')
        .sum('ppl_served as new_people_served')
        .count('wid as dispensers_installed')
        .groupByRaw('iso, month, year')
        .then(function (rows) {
          // Generate an array with relevant time-steps
          let startDate = moment.utc(config.startDate).startOf('month');
          let timeSteps = generateTimesteps(startDate);

          // Add the timestep to each data point
          rows = addTimestep(rows);

          // Group by ISO code and loop over each region
          let dispenserData = [];
          _(rows).groupBy('iso').forEach(function (r, iso) {
            if (iso === 'undefined') {
              return;
            }
            let region = {
              iso: iso,
              values: []
            };

            // Calculate the total dispensers installed and people served
            // prior to start date of the dashboards, before ignoring
            // those objects
            let dispenserCount = sumOldData(r, 'dispensers_installed', startDate);
            let peopleCount = sumOldData(r, 'new_people_served', startDate);

            _.forEach(timeSteps, function (step) {
              // Check if there is data for a given time-step
              let match = _.find(r, o => o.timestep.format('YYYY-MM-DD') === step.format('YYYY-MM-DD'));
              if (match) {
                // If so, update the counts and add it to the regional values
                match.dispenser_total = dispenserCount += match.dispensers_installed;
                match.people_total = peopleCount += match.new_people_served;
                delete match['iso'];
                delete match['year'];
                delete match['month'];
                region.values.push(match);
              } else {
                // Otherwise create a new object for the time-step
                region.values.push({
                  new_people_served: 0,
                  dispensers_installed: 0,
                  timestep: step,
                  dispenser_total: dispenserCount,
                  people_total: peopleCount
                });
              }
            });
            dispenserData.push(region);
          });

          // Add an array with centroids for the regions
          let isos = _.map(dispenserData, 'iso');
          let geoData = [];
          _.forEach(isos, function (iso) {
            geoData.push(_.find(centroids, {'iso': iso}));
          });

          return {
            data: dispenserData,
            geo: geoData
          };
        });

      Promise.all([dataP, contentP])
        .then(res => {
          res[0].content = res[1];
          reply(res[0]);
        })
        .catch(err => {
          console.log('err', err);
          reply(boom.wrap(err));
        });
    }
  },

  usage: {
    handler: (request, reply) => {
      reply({
        statusCode: 200,
        message: 'Usage'
      });
    }
  },

  reliability: {
    handler: (request, reply) => {
      let contentP = dataLoader(`${config.baseDir}/content/section-reliability-home.md`);

      let dataP = Promise.all([
        knex.select('year', 'month').from('dispensers')
        .count('wid as dispensers_installed')
        .groupByRaw('month, year'),
        knex.select('category', 'year', 'month').from('issues')
        .count('rowid as outages_reported')
        .groupByRaw('month, year, category'),
        knex.select('id', 'category').from('issues_category')
      ]).then(function (results) {
        let dispenserData = results[0];
        let outageData = results[1];
        let outageMeta = results[2];

        // Generate an array with relevant time-steps
        // Issues are only logged since 2015-07-01
        let startDate = moment.utc('2015-07-01').startOf('month');
        let timeSteps = generateTimesteps(startDate);

        // Add the timestep to each data point
        dispenserData = addTimestep(dispenserData);
        outageData = addTimestep(outageData);

        // Calculate dispenser total prior to startDate dashboards
        let dispenserCount = sumOldData(dispenserData, 'dispensers_installed', startDate);

        // Generate dispenser objects per timestep
        let dispenserValues = [];
        _.forEach(timeSteps, function (step) {
          // Check if there is dispenser data for a given time-step
          let match = _.find(dispenserData, o => o.timestep.format('YYYY-MM-DD') === step.format('YYYY-MM-DD'));
          if (match) {
            // If so, update the counts and add it to the regional values
            match.dispenser_total = dispenserCount += match.dispensers_installed;
            // delete match['dispensers_installed'];
            delete match['year'];
            delete match['month'];
            dispenserValues.push(match);
          } else {
            // Otherwise create a new object for the time-step
            dispenserValues.push({
              timestep: step,
              dispenser_total: dispenserCount
            });
          }
        });

        // Generate outage objects per timestep
        let outageValues = [];
        _.forEach(timeSteps, function (step) {
          let outagesTimestep = {
            timestep: step,
            outages: {}
          };
          _.forEach(outageData, function (o) {
            if (o.timestep.format('YYYY-MM-DD') === step.format('YYYY-MM-DD')) {
              outagesTimestep.outages[o.category] = o.outages_reported;
            }
          });
          outagesTimestep.outages['total'] = _(outagesTimestep.outages).map().sum();
          outageValues.push(outagesTimestep);
        });

        // Merge outages and dispensers
        var finalValues = [];
        _.forEach(dispenserValues, function (d) {
          let m = _.assign(d, _.find(outageValues, o => o.timestep.format('YYYY-MM-DD') === d.timestep.format('YYYY-MM-DD')));
          finalValues.push(m);
        });

        return {
          meta: outageMeta,
          data: finalValues
        };
      });

      Promise.all([dataP, contentP])
        .then(res => {
          res[0].content = res[1];
          reply(res[0]);
        })
        .catch(err => {
          console.log('err', err);
          reply(boom.wrap(err));
        });
    }
  },

  carbon: {
    handler: (request, reply) => {
      reply({
        statusCode: 200,
        message: 'carbon'
      });
    }
  }
};
<commit_msg>Specifiy string format on moment Not specifying will be deprecated in future versions of moment https://github.com/moment/moment/issues/1407<commit_after>'use strict';
var boom = require('boom');
var config = require('../config');
var moment = require('moment');
var _ = require('lodash');
var centroids = require('../data/dsw-admin2-centroids.json');
var knex = require('../services/db');
var dataLoader = require('../utils/yaml-md-loader');

// Generate an array with timesteps relevant for the dashboards
function generateTimesteps (startDate) {
  let timeSteps = [];
  var now = moment();
  for (let d = startDate.clone(); d <= now; d.month(d.month() + 1)) {
    timeSteps.push(d.clone());
  }
  return timeSteps;
}

// Generate a date for each object
function addTimestep (rows) {
  rows.forEach(function (row) {
    row.timestep = moment.utc(`${row.year}-${row.month}-01`, 'YYYY-MM-DD');
  });
  return rows;
}

// Sum data for a particular field, prior to startDate of the dashboards
function sumOldData (allData, field, startDate) {
  let oldData = _.filter(allData, function (o) { return o.timestep < startDate; });
  return _.sumBy(oldData, field);
}

module.exports = {
  access: {
    handler: (request, reply) => {
      let contentP = dataLoader(`${config.baseDir}/content/section-access-home.md`);

      let dataP = knex.select('iso', 'year', 'month').from('dispensers')
        .sum('ppl_served as new_people_served')
        .count('wid as dispensers_installed')
        .groupByRaw('iso, month, year')
        .then(function (rows) {
          // Generate an array with relevant time-steps
          let startDate = moment.utc(config.startDate, 'YYYY-MM-DD').startOf('month');
          let timeSteps = generateTimesteps(startDate);

          // Add the timestep to each data point
          rows = addTimestep(rows);

          // Group by ISO code and loop over each region
          let dispenserData = [];
          _(rows).groupBy('iso').forEach(function (r, iso) {
            if (iso === 'undefined') {
              return;
            }
            let region = {
              iso: iso,
              values: []
            };

            // Calculate the total dispensers installed and people served
            // prior to start date of the dashboards, before ignoring
            // those objects
            let dispenserCount = sumOldData(r, 'dispensers_installed', startDate);
            let peopleCount = sumOldData(r, 'new_people_served', startDate);

            _.forEach(timeSteps, function (step) {
              // Check if there is data for a given time-step
              let match = _.find(r, o => o.timestep.format('YYYY-MM-DD') === step.format('YYYY-MM-DD'));
              if (match) {
                // If so, update the counts and add it to the regional values
                match.dispenser_total = dispenserCount += match.dispensers_installed;
                match.people_total = peopleCount += match.new_people_served;
                delete match['iso'];
                delete match['year'];
                delete match['month'];
                region.values.push(match);
              } else {
                // Otherwise create a new object for the time-step
                region.values.push({
                  new_people_served: 0,
                  dispensers_installed: 0,
                  timestep: step,
                  dispenser_total: dispenserCount,
                  people_total: peopleCount
                });
              }
            });
            dispenserData.push(region);
          });

          // Add an array with centroids for the regions
          let isos = _.map(dispenserData, 'iso');
          let geoData = [];
          _.forEach(isos, function (iso) {
            geoData.push(_.find(centroids, {'iso': iso}));
          });

          return {
            data: dispenserData,
            geo: geoData
          };
        });

      Promise.all([dataP, contentP])
        .then(res => {
          res[0].content = res[1];
          reply(res[0]);
        })
        .catch(err => {
          console.log('err', err);
          reply(boom.wrap(err));
        });
    }
  },

  usage: {
    handler: (request, reply) => {
      reply({
        statusCode: 200,
        message: 'Usage'
      });
    }
  },

  reliability: {
    handler: (request, reply) => {
      let contentP = dataLoader(`${config.baseDir}/content/section-reliability-home.md`);

      let dataP = Promise.all([
        knex.select('year', 'month').from('dispensers')
        .count('wid as dispensers_installed')
        .groupByRaw('month, year'),
        knex.select('category', 'year', 'month').from('issues')
        .count('rowid as outages_reported')
        .groupByRaw('month, year, category'),
        knex.select('id', 'category').from('issues_category')
      ]).then(function (results) {
        let dispenserData = results[0];
        let outageData = results[1];
        let outageMeta = results[2];

        // Generate an array with relevant time-steps
        // Issues are only logged since 2015-07-01
        let startDate = moment.utc('2015-07-01', 'YYYY-MM-DD').startOf('month');
        let timeSteps = generateTimesteps(startDate);

        // Add the timestep to each data point
        dispenserData = addTimestep(dispenserData);
        outageData = addTimestep(outageData);

        // Calculate dispenser total prior to startDate dashboards
        let dispenserCount = sumOldData(dispenserData, 'dispensers_installed', startDate);

        // Generate dispenser objects per timestep
        let dispenserValues = [];
        _.forEach(timeSteps, function (step) {
          // Check if there is dispenser data for a given time-step
          let match = _.find(dispenserData, o => o.timestep.format('YYYY-MM-DD') === step.format('YYYY-MM-DD'));
          if (match) {
            // If so, update the counts and add it to the regional values
            match.dispenser_total = dispenserCount += match.dispensers_installed;
            // delete match['dispensers_installed'];
            delete match['year'];
            delete match['month'];
            dispenserValues.push(match);
          } else {
            // Otherwise create a new object for the time-step
            dispenserValues.push({
              timestep: step,
              dispenser_total: dispenserCount
            });
          }
        });

        // Generate outage objects per timestep
        let outageValues = [];
        _.forEach(timeSteps, function (step) {
          let outagesTimestep = {
            timestep: step,
            outages: {}
          };
          _.forEach(outageData, function (o) {
            if (o.timestep.format('YYYY-MM-DD') === step.format('YYYY-MM-DD')) {
              outagesTimestep.outages[o.category] = o.outages_reported;
            }
          });
          outagesTimestep.outages['total'] = _(outagesTimestep.outages).map().sum();
          outageValues.push(outagesTimestep);
        });

        // Merge outages and dispensers
        var finalValues = [];
        _.forEach(dispenserValues, function (d) {
          let m = _.assign(d, _.find(outageValues, o => o.timestep.format('YYYY-MM-DD') === d.timestep.format('YYYY-MM-DD')));
          finalValues.push(m);
        });

        return {
          meta: outageMeta,
          data: finalValues
        };
      });

      Promise.all([dataP, contentP])
        .then(res => {
          res[0].content = res[1];
          reply(res[0]);
        })
        .catch(err => {
          console.log('err', err);
          reply(boom.wrap(err));
        });
    }
  },

  carbon: {
    handler: (request, reply) => {
      reply({
        statusCode: 200,
        message: 'carbon'
      });
    }
  }
};
<|endoftext|>


<commit_before>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe(FILL_ME_IN);
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe(FILL_ME_IN);
      expect(meglomaniac.henchWoman).toBe(FILL_ME_IN);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect(FILL_ME_IN).toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(meglomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>COmpleated Koans in AboutObjects.js<commit_after>//Completed 7/29/2014 by Ralph Samuel

describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe('Joker');
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe('Harley');
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect('They are Pinky and the Brain Brain Brain Brain').toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2014);
    expect(meglomaniac.calculateAge()).toBe(44);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(true);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(false);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(false);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(true);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(false);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(undefined);
    expect(colouredCircle.colour).toBe('red');

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe('This circle has a radius of: 10');
    expect(colouredCircle.describe()).toBe('This circle has a radius of: 5');
  });
});
<|endoftext|>


<commit_before>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe(FILL_ME_IN);
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe(FILL_ME_IN);
      expect(meglomaniac.henchWoman).toBe(FILL_ME_IN);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect(FILL_ME_IN).toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(meglomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>finished Objects<commit_after>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe("Harley");
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect("They are Pinky and the Brain Brain Brain Brain Brain").toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2015);
    expect(meglomaniac.calculateAge()).toBe(45);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(true);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(false);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(false);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(true);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(false);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(undefined);
    expect(colouredCircle.colour).toBe("red");

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe("This circle has a radius of: 10");
    expect(colouredCircle.describe()).toBe("This circle has a radius of: 5");
  });
});
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 */

import _ from 'lodash';

import sundial from 'sundial';

import i18next from './language';
import { capitalize, validateEmail } from './utils';
import * as errors from './validation/errors';

import config from '../config';

const t = i18next.t.bind(i18next);

// ensure config vars are defined
export const ABOUT_MAX_LENGTH = config.ABOUT_MAX_LENGTH || 256;
export const PASSWORD_MIN_LENGTH = config.PASSWORD_MIN_LENGTH || 8;
export const PASSWORD_MAX_LENGTH = config.PASSWORD_MAX_LENGTH  || 72;
export const CLINICIAN_NAME_MAX_LENGTH = config.CLINICIAN_NAME_MAX_LENGTH || 140;
export const CLINICIAN_PHONE_MAX_LENGTH = config.CLINICIAN_PHONE_MAX_LENGTH || 30;

/**
 * Validation response when a field passes the validation checks
 *
 * @return {Object}
 */
export const valid = () => ({
  valid: true,
  message: null
});

/**
 * Validation response when a field fails the validation checks
 *
 * @param  {String} message error message that will be displayed in the form
 *
 * @return {Object}
 */
export const invalid = (message) => ({
  valid: false,
  message: message
});

/**
 * The date type validator. N.B It is has been extracted from inline definition in type
 * validators due to it being used inside of another.
 *
 * @param  {String} fieldLabel
 * @param  {Object} fieldValue
 * @param  {Object} currentDateObj for testing purposes
 * @return {Object}
 */
const dateValidator = (fieldLabel, fieldValue, currentDateObj) => {
  let now = new Date();
  let dateMask = t('M-D-YYYY');
  let dateString;

  currentDateObj = currentDateObj || Date.UTC(now.getFullYear(), now.getMonth(), now.getDate());

  if (!fieldValue) {
    return invalid(errors.isRequired(fieldLabel));
  }

  if (!fieldValue.day || !fieldValue.month || !fieldValue.year) {
    return invalid(errors.incompleteDate(fieldLabel));
  }

  let month = parseInt(fieldValue.month, 10) + 1; // month is zero indexed

  dateString = `${month}-${fieldValue.day}-${fieldValue.year}`;
  if (!sundial.isValidDateForMask(dateString, dateMask)) {
    return invalid(errors.invalidDate());
  }

  if (currentDateObj < sundial.parseFromFormat(dateString, dateMask)) {
    return invalid(errors.futureDate(fieldLabel));
  }

  return valid();
};

/**
 * Map of type validators for use in validateField()
 *
 * @type {Object}
 */
export const typeValidators = {
  name: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }
    return valid();
  },
  about: (fieldLabel, fieldValue) => {
    if (fieldValue && fieldValue.length > ABOUT_MAX_LENGTH) {
      return invalid(errors.isTooLong(ABOUT_MAX_LENGTH, fieldLabel));
    }

    return valid();
  },
  email: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }

    if (!validateEmail(fieldValue)) {
      return invalid(errors.invalidEmail(fieldLabel));
    }

    return valid();
  },
  password: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }

    if (/\s/g.test(fieldValue)) { //check for white-space (spaces, tabs)
      return invalid(errors.containsWhiteSpaces(fieldLabel));
    }

    if (fieldValue.length < PASSWORD_MIN_LENGTH) {
      return invalid(errors.isTooShort(PASSWORD_MIN_LENGTH, fieldLabel));
    }

    if (fieldValue.length > PASSWORD_MAX_LENGTH) {
      return invalid(errors.isTooLong(PASSWORD_MAX_LENGTH, fieldLabel));
    }

    return valid();
  },
  confirmPassword: (fieldLabel, fieldValue, prerequisites) => {
    if (!prerequisites.password || prerequisites.password.length === 0) {
      return invalid(errors.noPassword());
    }

    if (prerequisites.password !== fieldValue) {
      return invalid(errors.passwordsDontMatch());
    }

    return valid();
  },
  date: dateValidator,
  diagnosisDate: (fieldLabel, fieldValue, prerequisites) => {
    let dateMask = t('M-D-YYYY');
    let validDateCheck = dateValidator(fieldLabel, fieldValue);
    let birthdayObj, birthdayDateString;
    let diagnosisDateObj, diagnosisDateString;
    if (!validDateCheck.valid) {
      return validDateCheck;
    }

    if (!prerequisites.birthday) {
      return invalid(errors.noBirthday());
    }

    if (!dateValidator('', prerequisites.birthday).valid) {
      return invalid(errors.invalidBirthday());
    }

    birthdayDateString = t('{{month}}-{{day}}-{{year}}', {month: prerequisites.birthday.month, day: prerequisites.birthday.day, year: prerequisites.birthday.year});
    birthdayObj = sundial.parseFromFormat(birthdayDateString, dateMask);

    diagnosisDateString = t('{{month}}-{{day}}-{{year}}', {month: fieldValue.month, day: fieldValue.day, year: fieldValue.year});
    diagnosisDateObj = sundial.parseFromFormat(diagnosisDateString, dateMask);

    if (birthdayObj > diagnosisDateObj) {
      return invalid(errors.mustBeAfterBirthday(fieldLabel));
    }

    return valid();
  },
  clinicName: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }

    if (fieldValue.length > CLINICIAN_NAME_MAX_LENGTH) {
      return invalid(errors.isTooLong(CLINICIAN_NAME_MAX_LENGTH, fieldLabel));
    }
    return valid();
  },
  clinicPhone: (fieldLabel, fieldValue) => {
    if (fieldValue && fieldValue.length > CLINICIAN_PHONE_MAX_LENGTH) {
      return invalid(errors.isTooLong(CLINICIAN_PHONE_MAX_LENGTH, fieldLabel));
    }
    return valid();
  },
  clinicalRole: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }
    return valid();
  }
};

/**
 * Validates a single form field
 *
 * @param  {String} type
 * @param  {String} fieldLabel
 * @param  {String|Number|Object} fieldValue
 * @param  {Object|null} prerequisites
 * @return {Object}               either the results of invalid(message) or valid()
 */
export const validateField = (type, fieldLabel, fieldValue, prerequisites) => {
  if(!typeValidators[type]) { // @TODO: Gordon Dent: at present we do not have generic validation, we may way to add this
    return valid();
  }
  return typeValidators[type](fieldLabel, fieldValue, prerequisites);
};

/**
 * Validates an array of fields
 *
 * @param  {Array} form
 *
 * @return {Object} an object which is either empty (valid form) or contains entries for field names with error messages
 */
export const validateForm = (form) => {
  if (!form) { // @TODO: Gordon Dent: may want to check if not object too
    return {};
  }

  return form
    .map((field) => {
      let result = validateField(field.type, field.label, field.value, field.prerequisites);
      result.name = field.name;

      return result;
    })
    .filter((result) => !result.valid)
    // add comment here about component expectation
    .reduce((reduction, result) => {
      reduction[result.name] = result.message;
      return reduction;
    }, {});
};
<commit_msg>Fixed Birthday and Diagnosed Day bug v1<commit_after>/**
 * Copyright (c) 2016, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 */

import _ from 'lodash';

import sundial from 'sundial';

import i18next from './language';
import { capitalize, validateEmail } from './utils';
import * as errors from './validation/errors';

import config from '../config';

const t = i18next.t.bind(i18next);

// ensure config vars are defined
export const ABOUT_MAX_LENGTH = config.ABOUT_MAX_LENGTH || 256;
export const PASSWORD_MIN_LENGTH = config.PASSWORD_MIN_LENGTH || 8;
export const PASSWORD_MAX_LENGTH = config.PASSWORD_MAX_LENGTH  || 72;
export const CLINICIAN_NAME_MAX_LENGTH = config.CLINICIAN_NAME_MAX_LENGTH || 140;
export const CLINICIAN_PHONE_MAX_LENGTH = config.CLINICIAN_PHONE_MAX_LENGTH || 30;

/**
 * Validation response when a field passes the validation checks
 *
 * @return {Object}
 */
export const valid = () => ({
  valid: true,
  message: null
});

/**
 * Validation response when a field fails the validation checks
 *
 * @param  {String} message error message that will be displayed in the form
 *
 * @return {Object}
 */
export const invalid = (message) => ({
  valid: false,
  message: message
});

/**
 * The date type validator. N.B It is has been extracted from inline definition in type
 * validators due to it being used inside of another.
 *
 * @param  {String} fieldLabel
 * @param  {Object} fieldValue
 * @param  {Object} currentDateObj for testing purposes
 * @return {Object}
 */
const dateValidator = (fieldLabel, fieldValue, currentDateObj) => {
  let now = new Date();
  let dateMask = t('M-D-YYYY');
  let dateString;

  currentDateObj = currentDateObj || Date.UTC(now.getFullYear(), now.getMonth(), now.getDate());

  if (!fieldValue) {
    return invalid(errors.isRequired(fieldLabel));
  }

  if (!fieldValue.day || !fieldValue.month || !fieldValue.year) {
    return invalid(errors.incompleteDate(fieldLabel));
  }

  let month = parseInt(fieldValue.month, 10) + 1; // month is zero indexed

  dateString = `${month}-${fieldValue.day}-${fieldValue.year}`;
  if (!sundial.isValidDateForMask(dateString, dateMask)) {
    return invalid(errors.invalidDate());
  }

  if (currentDateObj < sundial.parseFromFormat(dateString, dateMask)) {
    return invalid(errors.futureDate(fieldLabel));
  }

  return valid();
};

/**
 * Map of type validators for use in validateField()
 *
 * @type {Object}
 */
export const typeValidators = {
  name: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }
    return valid();
  },
  about: (fieldLabel, fieldValue) => {
    if (fieldValue && fieldValue.length > ABOUT_MAX_LENGTH) {
      return invalid(errors.isTooLong(ABOUT_MAX_LENGTH, fieldLabel));
    }

    return valid();
  },
  email: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }

    if (!validateEmail(fieldValue)) {
      return invalid(errors.invalidEmail(fieldLabel));
    }

    return valid();
  },
  password: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }

    if (/\s/g.test(fieldValue)) { //check for white-space (spaces, tabs)
      return invalid(errors.containsWhiteSpaces(fieldLabel));
    }

    if (fieldValue.length < PASSWORD_MIN_LENGTH) {
      return invalid(errors.isTooShort(PASSWORD_MIN_LENGTH, fieldLabel));
    }

    if (fieldValue.length > PASSWORD_MAX_LENGTH) {
      return invalid(errors.isTooLong(PASSWORD_MAX_LENGTH, fieldLabel));
    }

    return valid();
  },
  confirmPassword: (fieldLabel, fieldValue, prerequisites) => {
    if (!prerequisites.password || prerequisites.password.length === 0) {
      return invalid(errors.noPassword());
    }

    if (prerequisites.password !== fieldValue) {
      return invalid(errors.passwordsDontMatch());
    }

    return valid();
  },
  date: dateValidator,
  diagnosisDate: (fieldLabel, fieldValue, prerequisites) => {
    let dateMask = t('M-D-YYYY');
    let validDateCheck = dateValidator(fieldLabel, fieldValue);
    let birthdayObj, birthdayDateString;
    let diagnosisDateObj, diagnosisDateString;
    if (!validDateCheck.valid) {
      return validDateCheck;
    }

    if (!prerequisites.birthday) {
      return invalid(errors.noBirthday());
    }

    if (!dateValidator('', prerequisites.birthday).valid) {
      return invalid(errors.invalidBirthday());
    }

    // checks to see if diagnosis date is earlier than birthdate (which is not allowed)
    var invalidYear = prerequisites.birthday.year > fieldValue.year;
    var invalidMonth = prerequisites.birthday.month > fieldValue.month;
    var invalidDay = prerequisites.birthday.day > fieldValue.day;

    if (invalidYear || invalidMonth || invalidDay) {
      return invalid(errors.mustBeAfterBirthday(fieldLabel));
    }

    return valid();
  },
  clinicName: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }

    if (fieldValue.length > CLINICIAN_NAME_MAX_LENGTH) {
      return invalid(errors.isTooLong(CLINICIAN_NAME_MAX_LENGTH, fieldLabel));
    }
    return valid();
  },
  clinicPhone: (fieldLabel, fieldValue) => {
    if (fieldValue && fieldValue.length > CLINICIAN_PHONE_MAX_LENGTH) {
      return invalid(errors.isTooLong(CLINICIAN_PHONE_MAX_LENGTH, fieldLabel));
    }
    return valid();
  },
  clinicalRole: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }
    return valid();
  }
};

/**
 * Validates a single form field
 *
 * @param  {String} type
 * @param  {String} fieldLabel
 * @param  {String|Number|Object} fieldValue
 * @param  {Object|null} prerequisites
 * @return {Object}               either the results of invalid(message) or valid()
 */
export const validateField = (type, fieldLabel, fieldValue, prerequisites) => {
  if(!typeValidators[type]) { // @TODO: Gordon Dent: at present we do not have generic validation, we may way to add this
    return valid();
  }
  return typeValidators[type](fieldLabel, fieldValue, prerequisites);
};

/**
 * Validates an array of fields
 *
 * @param  {Array} form
 *
 * @return {Object} an object which is either empty (valid form) or contains entries for field names with error messages
 */
export const validateForm = (form) => {
  if (!form) { // @TODO: Gordon Dent: may want to check if not object too
    return {};
  }

  return form
    .map((field) => {
      let result = validateField(field.type, field.label, field.value, field.prerequisites);
      result.name = field.name;

      return result;
    })
    .filter((result) => !result.valid)
    // add comment here about component expectation
    .reduce((reduction, result) => {
      reduction[result.name] = result.message;
      return reduction;
    }, {});
};
<|endoftext|>


<commit_before>describe("About Objects", function () {

  describe("Properties", function () {
    var megalomaniac;

    beforeEach(function () {
       megalomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(megalomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(megalomaniac.henchwoman).toBe("Harley");
      expect(megalomaniac.henchWoman).toBe("harley");
    });
  });

  it("should know properties that are functions act like methods", function () {
    var megalomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = megalomaniac.battleCry(4);
    expect(FILL_ME_IN).toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date();
    var currentYear = (currentDate.getFullYear());
    var megalomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(megalomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function () {
    var megalomaniac;
    beforeEach(function () {
      megalomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in megalomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in megalomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var megalomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in megalomaniac).toBe(FILL_ME_IN);

    megalomaniac.secretary = "Agent Smith";
    expect("secretary" in megalomaniac).toBe(FILL_ME_IN);

    delete megalomaniac.henchman;
    expect("henchman" in megalomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
      function Circle(radius)
      {
        this.radius = radius;
      }

      var simpleCircle = new Circle(10);
      var colouredCircle = new Circle(5);
      colouredCircle.colour = "red";

      expect(simpleCircle.colour).toBe(FILL_ME_IN);
      expect(colouredCircle.colour).toBe(FILL_ME_IN);

      Circle.prototype.describe = function () {
        return "This circle has a radius of: " + this.radius;
      };

      expect(simpleCircle.describe()).toBe(FILL_ME_IN);
      expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>answered 3rd objects<commit_after>describe("About Objects", function () {

  describe("Properties", function () {
    var megalomaniac;

    beforeEach(function () {
       megalomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(megalomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(megalomaniac.henchwoman).toBe("Harley");
      expect(megalomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var megalomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = megalomaniac.battleCry(4);
    expect(FILL_ME_IN).toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date();
    var currentYear = (currentDate.getFullYear());
    var megalomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2015);
    expect(megalomaniac.calculateAge()).toBe(45);
  });

  describe("'in' keyword", function () {
    var megalomaniac;
    beforeEach(function () {
      megalomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in megalomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in megalomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var megalomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in megalomaniac).toBe(FILL_ME_IN);

    megalomaniac.secretary = "Agent Smith";
    expect("secretary" in megalomaniac).toBe(FILL_ME_IN);

    delete megalomaniac.henchman;
    expect("henchman" in megalomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
      function Circle(radius)
      {
        this.radius = radius;
      }

      var simpleCircle = new Circle(10);
      var colouredCircle = new Circle(5);
      colouredCircle.colour = "red";

      expect(simpleCircle.colour).toBe(FILL_ME_IN);
      expect(colouredCircle.colour).toBe(FILL_ME_IN);

      Circle.prototype.describe = function () {
        return "This circle has a radius of: " + this.radius;
      };

      expect(simpleCircle.describe()).toBe(FILL_ME_IN);
      expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<|endoftext|>


<commit_before>describe("About Objects", function () {

  describe("Properties", function () {
    var megalomaniac;

    beforeEach(function () {
       megalomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(megalomaniac.mastermind).toBe(FILL_ME_IN);
    });

    it("should confirm that properties are case sensitive", function () {
      expect(megalomaniac.henchwoman).toBe(FILL_ME_IN);
      expect(megalomaniac.henchWoman).toBe(FILL_ME_IN);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var megalomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = megalomaniac.battleCry(4);
    expect(FILL_ME_IN).toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date();
    var currentYear = (currentDate.getFullYear());
    var megalomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(megalomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function () {
    var megalomaniac;
    beforeEach(function () {
      megalomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in megalomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in megalomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var megalomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in megalomaniac).toBe(FILL_ME_IN);

    megalomaniac.secretary = "Agent Smith";
    expect("secretary" in megalomaniac).toBe(FILL_ME_IN);

    delete megalomaniac.henchman;
    expect("henchman" in megalomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
      function Circle(radius)
      {
        this.radius = radius;
      }

      var simpleCircle = new Circle(10);
      var colouredCircle = new Circle(5);
      colouredCircle.colour = "red";

      expect(simpleCircle.colour).toBe(FILL_ME_IN);
      expect(colouredCircle.colour).toBe(FILL_ME_IN);

      Circle.prototype.describe = function () {
        return "This circle has a radius of: " + this.radius;
      };

      expect(simpleCircle.describe()).toBe(FILL_ME_IN);
      expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>aboutObjects<commit_after>describe("About Objects", function () {

  describe("Properties", function () {
    var megalomaniac;

    beforeEach(function () {
       megalomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(megalomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(megalomaniac.henchwoman).toBe("Harley");
      expect(megalomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var megalomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

//the array(5).join above is creating a string from an array with 5 blanks (.length=5) and joing with Brain
    var battleCry = megalomaniac.battleCry(4);
    expect('They are Pinky and the Brain Brain Brain Brain').toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date();
    var currentYear = (currentDate.getFullYear());
    var megalomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2016);
    expect(megalomaniac.calculateAge()).toBe(46);
  });

  describe("'in' keyword", function () {
    var megalomaniac;
    beforeEach(function () {
      megalomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in megalomaniac;

      expect(hasBomb).toBe(true);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in megalomaniac;

      expect(hasDetonator).toBe(false);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var megalomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in megalomaniac).toBe(false);

    megalomaniac.secretary = "Agent Smith";
    expect("secretary" in megalomaniac).toBe(true);

    delete megalomaniac.henchman;
    expect("henchman" in megalomaniac).toBe(false);
  });

  it("should use prototype to add to all objects", function () {
      function Circle(radius)
      {
        this.radius = radius;
      }

      var simpleCircle = new Circle(10);
      var colouredCircle = new Circle(5);
      colouredCircle.colour = "red";

      expect(simpleCircle.colour).toBe(undefined);
      expect(colouredCircle.colour).toBe("red");

      Circle.prototype.describe = function () {
        return "This circle has a radius of: " + this.radius;
      };

      expect(simpleCircle.describe()).toBe("This circle has a radius of: 10");
      expect(colouredCircle.describe()).toBe("This circle has a radius of: 5");
  });
});
<|endoftext|>