<commit_before>const fs = require('fs');
const m = require('../lib/marco');
const readline = require('readline');
const test = require('tape').test;
const split = require('split');
const through = require('through2');

test('lineToJSON', (t) => {
  // GeoJSON lines
  t.deepEqual(m.lineToJSON(''), {});
  t.deepEqual(m.lineToJSON('{'), {});
  t.deepEqual(m.lineToJSON('"type": "FeatureCollection",'), {});
  t.deepEqual(m.lineToJSON(''), {});
  t.deepEqual(m.lineToJSON('"features": ['), {});
  t.deepEqual(m.lineToJSON(']'), {});
  t.deepEqual(m.lineToJSON('}'), {});

  // Random cases
  t.deepEqual(m.lineToJSON(null), {});
  t.deepEqual(m.lineToJSON('foo'), {});

  // Expected object creation
  t.deepEqual(m.lineToJSON('{"foo": "bar"}'), { foo: "bar" });
  t.deepEqual(m.lineToJSON('{"foo": "bar"},'), { foo: "bar" });
  t.deepEqual(m.lineToJSON('{"foo": "bar"}, '), { foo: "bar" });

  t.end();
});

test('matchInReadStream', (t) => {
  t.plan(7);

  var rl = readline.createInterface({
    input: fs.createReadStream(__dirname + '/fixtures/states.json')
  });

  var match = (obj) => (obj.geometry && obj.geometry.type == 'Polygon');
  m.matchInReadStream(match, rl, function (err, data) {
    t.false(err);
    t.equal(data.geometry.type, 'Polygon');
    t.equal(data.type, 'Feature');
    t.equal(data.properties.NOM_ENT, 'Baja California');
  });

  rl = readline.createInterface({
    input: fs.createReadStream(__dirname + '/fixtures/states.json')
  });
  match = (obj) => (obj.properties && obj.properties.NOM_ENT == 'Nuevo León');
  m.matchInReadStream(match, rl, function (err, data) {
    t.false(err);
    t.equal(data.geometry.type, 'Polygon');
    t.equal(data.properties.NOM_ENT, 'Nuevo León');
  });
});

test('findState', { skip: process.env.TRAVIS }, (t) => {
  t.plan(5);

  m.findState('Aguascalientes', function (err, data) {
    t.false(err);
    t.equal(data.properties.NOM_ENT, 'Aguascalientes');
    t.equal(data.geometry.type, 'Polygon');
  });

  m.findState('Null Island', function (err, data) {
    t.false(err);
    t.false(data);
  });
});

test('findMunicipality', { skip: process.env.TRAVIS }, (t) => {
  t.plan(5);

  m.findMunicipality('Mexicali', function (err, data) {
    t.false(err);
    t.equal(data.properties.NOM_MUN, 'Mexicali');
    t.equal(data.geometry.type, 'MultiPolygon');
  });

  m.findMunicipality('Null Island', function (err, data) {
    t.false(err);
    t.false(data);
  });
});

function readableStreamFixture() {
  // Simulating pipe from command line
  var Readable = require('stream').Readable;
  var rs = Readable();
  var fixture = fs.readFileSync(__dirname + '/fixtures/dataset.csv');
  rs._read = () => {
    rs.push(fixture);
    rs.push(null);
  };
  return rs;
}

test('toStatePolygon', (t) => {
  t.plan(1);

  var rs = readableStreamFixture();
  var tr = through((buff, _, next) => {
    var feature = JSON.parse(buff.toString());
    var keys = ['type', 'properties', 'geometry'];
    t.deepEqual(Object.keys(feature), keys, 'should output a GeoJSON feature');
  });

  rs.pipe(split())
    .pipe(m.toStatePolygon())
    .pipe(tr);
});

test('toFeatureCollection', (t) => {
  t.plan(3);

  var buffer = '{ "foo": 1 }\n{ "bar" : 2 }';
  var fc = m.toFeatureCollection(buffer);

  t.true(fc.match("FeatureCollection"), 'builds a FeatureCollection');
  var obj = JSON.parse(fc);
  t.equal(obj.features.length, 2, 'wraps two features');
  t.equal(obj.features[0].foo, 1, 'haz foo');
});
<commit_msg>Simulate process.stdin without fixture file<commit_after>const fs = require('fs');
const m = require('../lib/marco');
const readline = require('readline');
const test = require('tape').test;
const split = require('split');
const through = require('through2');

test('lineToJSON', (t) => {
  // GeoJSON lines
  t.deepEqual(m.lineToJSON(''), {});
  t.deepEqual(m.lineToJSON('{'), {});
  t.deepEqual(m.lineToJSON('"type": "FeatureCollection",'), {});
  t.deepEqual(m.lineToJSON(''), {});
  t.deepEqual(m.lineToJSON('"features": ['), {});
  t.deepEqual(m.lineToJSON(']'), {});
  t.deepEqual(m.lineToJSON('}'), {});

  // Random cases
  t.deepEqual(m.lineToJSON(null), {});
  t.deepEqual(m.lineToJSON('foo'), {});

  // Expected object creation
  t.deepEqual(m.lineToJSON('{"foo": "bar"}'), { foo: "bar" });
  t.deepEqual(m.lineToJSON('{"foo": "bar"},'), { foo: "bar" });
  t.deepEqual(m.lineToJSON('{"foo": "bar"}, '), { foo: "bar" });

  t.end();
});

test('matchInReadStream', (t) => {
  t.plan(7);

  var rl = readline.createInterface({
    input: fs.createReadStream(__dirname + '/fixtures/states.json')
  });

  var match = (obj) => (obj.geometry && obj.geometry.type == 'Polygon');
  m.matchInReadStream(match, rl, function (err, data) {
    t.false(err);
    t.equal(data.geometry.type, 'Polygon');
    t.equal(data.type, 'Feature');
    t.equal(data.properties.NOM_ENT, 'Baja California');
  });

  rl = readline.createInterface({
    input: fs.createReadStream(__dirname + '/fixtures/states.json')
  });
  match = (obj) => (obj.properties && obj.properties.NOM_ENT == 'Nuevo León');
  m.matchInReadStream(match, rl, function (err, data) {
    t.false(err);
    t.equal(data.geometry.type, 'Polygon');
    t.equal(data.properties.NOM_ENT, 'Nuevo León');
  });
});

test('findState', { skip: process.env.TRAVIS }, (t) => {
  t.plan(5);

  m.findState('Aguascalientes', function (err, data) {
    t.false(err);
    t.equal(data.properties.NOM_ENT, 'Aguascalientes');
    t.equal(data.geometry.type, 'Polygon');
  });

  m.findState('Null Island', function (err, data) {
    t.false(err);
    t.false(data);
  });
});

test('findMunicipality', { skip: process.env.TRAVIS }, (t) => {
  t.plan(5);

  m.findMunicipality('Mexicali', function (err, data) {
    t.false(err);
    t.equal(data.properties.NOM_MUN, 'Mexicali');
    t.equal(data.geometry.type, 'MultiPolygon');
  });

  m.findMunicipality('Null Island', function (err, data) {
    t.false(err);
    t.false(data);
  });
});

function readableStreamFixture() {
  // Simulating pipe from command line
  var Readable = require('stream').Readable;
  var rs = Readable();
  rs._read = () => {
    rs.push('state, population\n');
    rs.push('Baja California, 3315766\n');
    rs.push(null);
  };
  return rs;
}

test('toStatePolygon', (t) => {
  t.plan(1);

  var rs = readableStreamFixture();
  var tr = through((buff, _, next) => {
    var feature = JSON.parse(buff.toString());
    var keys = ['type', 'properties', 'geometry'];
    t.deepEqual(Object.keys(feature), keys, 'should output a GeoJSON feature');
  });

  rs.pipe(split())
    .pipe(m.toStatePolygon())
    .pipe(tr);
});

test('toFeatureCollection', (t) => {
  t.plan(3);

  var buffer = '{ "foo": 1 }\n{ "bar" : 2 }';
  var fc = m.toFeatureCollection(buffer);

  t.true(fc.match("FeatureCollection"), 'builds a FeatureCollection');
  var obj = JSON.parse(fc);
  t.equal(obj.features.length, 2, 'wraps two features');
  t.equal(obj.features[0].foo, 1, 'haz foo');
});
<|endoftext|>


<commit_before>(function () {
  'use strict';

  var initialState;
  var ACTIVE_CLASS = 'dqpl-active';
  var $topBar = jQuery('.dqpl-top-bar');
  var $trigger = $topBar.find('.dqpl-menu-trigger');
  var $menu = jQuery('.dqpl-side-bar');
  var $scrim = jQuery('#dqpl-side-bar-scrim');
  // top level menuitems
  var $topBarMenuItems = findTopLevels($topBar.find('[role="menubar"]').first(), true);

  if (!$topBar.length) {
    return listenForReady();
  } else {
    ready();
  }

  function listenForReady() {
    jQuery(document).one('dqpl:ready', function () {
      $topBar = jQuery('.dqpl-top-bar');
      $trigger = $topBar.find('.dqpl-menu-trigger');
      $menu = jQuery('.dqpl-side-bar');
      $scrim = jQuery('#dqpl-side-bar-scrim');
      // top level menuitems
      $topBarMenuItems = findTopLevels($topBar.find('[role="menubar"]').first(), true);
      ready();
    });
  }

  function ready() {
    /**
     * Listen for resize so we can configure stuff based on the locking of the menu
     */
    jQuery.throttle({
      element: window,
      event: 'resize',
      delay: 100
    }, onResize);

    onResize();

    /**
     * Listen for refresh events
     * (prevents menus from getting in funky states)
     */
    $topBar.on('dqpl:refresh', onRefresh);

    /**
     * Listen for clicks outside the menu (when
     * its opened AND not locked) to close it
     */
    jQuery(document).on('click', function (e) {
      var $target = jQuery(e.target);
      var isWithin = $target.closest('.dqpl-side-bar').length;
      var isHamburger = $target.is('.dqpl-menu-trigger') || !!$target.closest('.dqpl-menu-trigger').length;
      if (isWithin || isHamburger || $menu.attr('data-locked') === 'locked') {
        return;
      }

      if ($menu.attr('aria-expanded') === 'true') {
        onTriggerClick();
      }
    });

    /**
     * Toggle menu on hamburger clicks
     */
    $trigger.on('click', onTriggerClick);

    function onTriggerClick(e, noFocus) {
      toggleSubmenu($trigger, function (_, done) {
        $trigger.toggleClass(ACTIVE_CLASS);
        var wasActive = $menu.hasClass(ACTIVE_CLASS);
        var first = wasActive ? ACTIVE_CLASS : 'dqpl-show';
        var second = first === ACTIVE_CLASS ? 'dqpl-show' : ACTIVE_CLASS;

        $menu.toggleClass(first);
        $scrim.toggleClass('dqpl-scrim-show');
        setTimeout(function () {
          $menu.toggleClass(second);
          $scrim.toggleClass('dqpl-scrim-fade-in');
          setTimeout(function () {
            done(noFocus);
          });
        }, 100);
      });
    }

    /**
     * Toggle submenu on other menu items with submenus
     */
    $topBar.on('click', '[role="menuitem"][aria-controls]', function () {
      var $this = jQuery(this);
      // trigger clicks are handled separately...
      if ($this.is($trigger)) { return; }

      toggleSubmenu($this, function ($dropdown, done) {
        $dropdown.toggleClass('dqpl-dropdown-active');
        done(false, ($dropdown.hasClass('dqpl-dropdown-active') ? $dropdown : $this));
      });
    });

    /**
     * Setup for menu items
     */
    $topBarMenuItems.prop('tabIndex', -1).first().prop('tabIndex', 0);
    $menu.find('[role="menu"]').each(function (_, menu) {
      var $menuItems = jQuery(menu).find('[role="menuitem"]');
      $menuItems.prop('tabIndex', -1).first().prop('tabIndex', 0);
    });

    /**
     * Keyboard logic for top bar
     */
    $topBar
      .on('keydown', '[role="menuitem"]', function (e) {
        var which = e.which;
        var $target = jQuery(e.target);

        switch (which) {
          case 37:
          case 39:
            e.preventDefault(); // don't scroll
            arrowHandler(
              findTopLevels($topBar.find('[role="menubar"]').first(), true),
              $target, which === 39 ? 'next' : 'prev'
            );
            break;
          case 38:
          case 40:
            e.preventDefault();
            if ($target.attr('aria-controls')) {
              $target.click();
            }
            break;
          case 13:
          case 32:
            e.preventDefault();
            $target.click();
            break;
        }
      })
      .on('click', '[role="menuitem"]', function () {
        var $target = jQuery(this);
        var $link = $target.find('a');
        if ($link.length) {
          $link[0].click();
        }
      })
      .on('keydown', '.dqpl-dropdown', function (e) {
        var which = e.which;
        var $target = jQuery(e.target);
        var $dropdown = jQuery(this);

        switch (which) {
          case 27:
          case 38:
            var id = $dropdown.prop('id');
            var $trigger = jQuery('[aria-controls="' + id + '"]');
            $trigger.click();
            break;
        }
      });

    /**
     * Keyboard logic for menu (side bar)
     * - up/down traverse through menu items
     * - right (with submenu) opens submenu / focuses first item
     * - left/escape closes submenu (if within one) OR closes menu (if at top level)
     */
    $menu
      .on('keydown', '[role="menuitem"]', function (e) {
        var which = e.which;
        var $target = jQuery(e.target);

        switch (which) {
          case 27:
          case 37:
            var isOfMenu = $target.parent().is($menu);
            if ($menu.attr('data-locked') === 'true' && isOfMenu) {
              return;
            }
            e.preventDefault();
            e.stopPropagation(); // prevent bubbling for sake of submenus

            var $thisMenu = $target.closest('[role="menu"]');
            var $thisTrigger = jQuery('[aria-controls="' + $thisMenu.prop('id') + '"]');

            $thisTrigger.click();

            if (!isOfMenu) { activateMenuitem($target, $thisTrigger); }
            break;
          case 40:
            e.preventDefault();
            arrowSetup($target, 'next');
            break;
          case 38:
            e.preventDefault();
            arrowSetup($target, 'prev');
            break;
          case 32:
          case 13:
            e.preventDefault();
            $target.trigger('click');
            if (!$target.attr('aria-controls')) {
              var $link = $target.find('a');
              if ($link.length) {
                $link[0].click();
              }
            }
            break;
          case 39:
            if ($target.attr('aria-controls')) {
              $target.click();
            }
            break;
        }
      })
      /**
       * Mouse logic for expandable submenu triggers
       */
      .on('click', '[role="menuitem"]', function (e) {
        e.stopPropagation();
        var $trigger = jQuery(this);
        if ($trigger.attr('aria-controls')) {
          toggleSubmenu($trigger, function ($submenu, done) {
            $submenu.slideToggle(400, function () {
              $trigger.toggleClass('dqpl-weight-bold');
              var $toFocus = $submenu.find('[role="menuitem"][tabindex="0"]');
              $toFocus = $toFocus.length ? $toFocus : $submenu.find('[role="menuitem"]').first();
              done(false, $toFocus);
            });
          });
        } else {
          var $link = $trigger.find('a');
          if ($link.length) {
            $link[0].click();
          }
        }
      })
      .on('keydown', function (e) {
        var which = e.which;
        if (which !== 9) { return; }
        setTimeout(function () {
          var outsideOfMenu = !$menu.has(document.activeElement).length;
          var isExpanded = $menu.attr('aria-expanded') === 'true';
          if (outsideOfMenu && isExpanded) {
            onTriggerClick(null, true);
          }
        });
      });

    /**
     * The menu is locked into visibility above 1024px viewport...
     * - ensure aria-expanded is removed/readded properly
     * - ensure the topbar menu isn't thrown off (in case the hamburger was the "active" item)
     */
    function onResize() {
      var width = jQuery(window).width();

      if (width >= 1024) {
        $menu.attr('data-prev-expanded', $menu.attr('aria-expanded'));
        $menu.removeAttr('aria-expanded');
        $scrim.removeClass('dqpl-scrim-show').removeClass('dqpl-scrim-fade-in');

        if ($trigger.prop('tabIndex') === 0) {
          // since `$trigger` gets hidden (via css) "activate" something else in the menubar
          $topBarMenuItems = findTopLevels($topBar.find('[role="menubar"]').first(), true);
          $topBarMenuItems.prop('tabIndex', -1).first().prop('tabIndex', 0);
        }
        $menu.attr('data-locked', 'true');
      } else {
        $menu.attr('aria-expanded', $menu.attr('data-prev-expanded') || 'false');
        $topBarMenuItems = findTopLevels($topBar.find('ul').first(), true);
        $menu.attr('data-locked', 'false');
        if ($menu.attr('data-prev-expanded') === 'true') {
          $scrim.addClass('dqpl-scrim-show').addClass('dqpl-scrim-fade-in');
        }
      }
    }

    /**
     * Ensure that there is 1 item with tabindex="0"
     */
    function onRefresh() {
      $topBarMenuItems = findTopLevels($topBar.find('[role="menubar"]').first(), true);
      var $activeOne = $topBarMenuItems.filter('[tabindex="0"]');
      if (!$activeOne.length) {
        $topBarMenuItems.first().prop('tabIndex', 0);
      }
    }

    /**
     * Activates a menuitem and deactivates the previously active
     * by giving the previously active menuitem tabindex="-1" and
     * giving the newly active menuitem tabindex="0"
     */
    function activateMenuitem($prevActive, $newlyActive) {
      $prevActive.prop('tabIndex', -1);
      $newlyActive.prop('tabIndex', 0).focus();
    }

    /**
     * Handles left/right arrow navigation
     */
    function arrowHandler($items, $target, dir) {
      var isNext = dir === 'next';
      var currentIdx = $items.index($target[0]);
      var $adjacent = $items.eq(isNext ? currentIdx + 1 : currentIdx - 1);

      // circularity (first or last)
      if (!$adjacent.length) {
        $adjacent = $items.eq(isNext ? 0 : $items.length - 1);
      }

      activateMenuitem($target, $adjacent);
    }

    /**
     * Setup for arrow handler...finds the top levels and calls `arrowHandler`
     */
    function arrowSetup($target, dir) {
      var $items = findTopLevels($target.closest('[role="menu"]'));
      arrowHandler($items, $target, dir);
    }

    /**
     * toggles a menu or submenu
     * @param  {jQuery} $trig      jQuery wrapped element ref of the trigger of the given menu
     * @param  {function} toggleFn a function that handles the toggling of the given menu
     */
    function toggleSubmenu($trig, toggleFn) {
      var $droplet = jQuery('#' + $trig.attr('aria-controls'));

      if (!$droplet.length) {
        return;
      }

      toggleFn($droplet, function (noFocus, $focus) {
        var prevExpanded = $droplet.attr('aria-expanded');
        var wasCollapsed = !prevExpanded || prevExpanded === 'false';
        $droplet.attr('aria-expanded', wasCollapsed);
        if ($focus) {
          $focus.focus();
        } else if (!noFocus) {
          var $active = $droplet.find('.dqpl-menuitem-selected').filter(':visible');
          $active = $active.length ?
            $active :
            $droplet.find('[role="menuitem"][tabindex="0"]').filter(':visible').first();
          var $focusMe = wasCollapsed ?
            $active :
            $droplet.closest('[aria-controls][role="menuitem"]');

          $focusMe = $focusMe.length ? $focusMe : $trigger;
          $focusMe.focus();
        }
      });
    }
  }

  /**
   * Finds the top level menu items of a menu
   */
  function findTopLevels($ul, visible) {
    var $chiles = $ul.children().filter('[role="menuitem"]');
    return (visible) ? $chiles.filter(':visible') : $chiles;
  }
}());
<commit_msg>fixes menu bug<commit_after>(function () {
  'use strict';

  var initialState;
  var ACTIVE_CLASS = 'dqpl-active';
  var $topBar = jQuery('.dqpl-top-bar');
  var $trigger = $topBar.find('.dqpl-menu-trigger');
  var $menu = jQuery('.dqpl-side-bar');
  var $scrim = jQuery('#dqpl-side-bar-scrim');
  // top level menuitems
  var $topBarMenuItems = findTopLevels($topBar.find('[role="menubar"]').first(), true);

  if (!$topBar.length) {
    return listenForReady();
  } else {
    ready();
  }

  function listenForReady() {
    jQuery(document).one('dqpl:ready', function () {
      $topBar = jQuery('.dqpl-top-bar');
      $trigger = $topBar.find('.dqpl-menu-trigger');
      $menu = jQuery('.dqpl-side-bar');
      $scrim = jQuery('#dqpl-side-bar-scrim');
      // top level menuitems
      $topBarMenuItems = findTopLevels($topBar.find('[role="menubar"]').first(), true);
      ready();
    });
  }

  function ready() {
    /**
     * Listen for resize so we can configure stuff based on the locking of the menu
     */
    jQuery.throttle({
      element: window,
      event: 'resize',
      delay: 100
    }, onResize);

    onResize();

    /**
     * Listen for refresh events
     * (prevents menus from getting in funky states)
     */
    $topBar.on('dqpl:refresh', onRefresh);

    /**
     * Listen for clicks outside the menu (when
     * its opened AND not locked) to close it
     */
    jQuery(document).on('click', function (e) {
      var $target = jQuery(e.target);
      var isWithin = $target.closest('.dqpl-side-bar').length;
      var isHamburger = $target.is('.dqpl-menu-trigger') || !!$target.closest('.dqpl-menu-trigger').length;
      if (isWithin || isHamburger || $menu.attr('data-locked') === 'locked') {
        return;
      }

      if ($menu.attr('aria-expanded') === 'true') {
        onTriggerClick();
      }
    });

    /**
     * Toggle menu on hamburger clicks
     */
    $trigger.on('click', onTriggerClick);

    function onTriggerClick(e, noFocus) {
      toggleSubmenu($trigger, function (_, done) {
        $trigger.toggleClass(ACTIVE_CLASS);
        var wasActive = $menu.hasClass(ACTIVE_CLASS);
        var first = wasActive ? ACTIVE_CLASS : 'dqpl-show';
        var second = first === ACTIVE_CLASS ? 'dqpl-show' : ACTIVE_CLASS;

        $menu.toggleClass(first);
        $scrim.toggleClass('dqpl-scrim-show');
        setTimeout(function () {
          $menu.toggleClass(second);
          $scrim.toggleClass('dqpl-scrim-fade-in');
          setTimeout(function () {
            done(noFocus);
          });
        }, 100);
      });
    }

    /**
     * Toggle submenu on other menu items with submenus
     */
    $topBar.on('click', '[role="menuitem"][aria-controls]', function () {
      var $this = jQuery(this);
      // trigger clicks are handled separately...
      if ($this.is($trigger)) { return; }

      toggleSubmenu($this, function ($dropdown, done) {
        $dropdown.toggleClass('dqpl-dropdown-active');
        done(false, ($dropdown.hasClass('dqpl-dropdown-active') ? $dropdown : $this));
      });
    });

    /**
     * Setup for menu items
     */
    $topBarMenuItems.prop('tabIndex', -1).first().prop('tabIndex', 0);
    $menu.find('[role="menu"]').each(function (_, menu) {
      var $menuItems = jQuery(menu).find('[role="menuitem"]');
      $menuItems.prop('tabIndex', -1).first().prop('tabIndex', 0);
    });

    /**
     * Keyboard logic for top bar
     */
    $topBar
      .on('keydown', '[role="menuitem"]', function (e) {
        var which = e.which;
        var $target = jQuery(e.target);

        switch (which) {
          case 37:
          case 39:
            e.preventDefault(); // don't scroll
            arrowHandler(
              findTopLevels($topBar.find('[role="menubar"]').first(), true),
              $target, which === 39 ? 'next' : 'prev'
            );
            break;
          case 38:
          case 40:
            e.preventDefault();
            if ($target.attr('aria-controls')) {
              $target.click();
            }
            break;
          case 13:
          case 32:
            e.preventDefault();
            $target.click();
            break;
        }
      })
      .on('click', '[role="menuitem"]', function () {
        var $target = jQuery(this);
        var $link = $target.find('a');
        if ($link.length) {
          $link[0].click();
        }
      })
      .on('keydown', '.dqpl-dropdown', function (e) {
        var which = e.which;
        var $target = jQuery(e.target);
        var $dropdown = jQuery(this);

        switch (which) {
          case 27:
          case 38:
            var id = $dropdown.prop('id');
            var $trigger = jQuery('[aria-controls="' + id + '"]');
            $trigger.click();
            break;
        }
      });

    /**
     * Keyboard logic for menu (side bar)
     * - up/down traverse through menu items
     * - right (with submenu) opens submenu / focuses first item
     * - left/escape closes submenu (if within one) OR closes menu (if at top level)
     */
    $menu
      .on('keydown', '[role="menuitem"]', function (e) {
        var which = e.which;
        var $target = jQuery(e.target);

        switch (which) {
          case 27:
          case 37:
            var isOfMenu = $target.parent().is($menu);
            if ($menu.attr('data-locked') === 'true' && isOfMenu) {
              return;
            }
            e.preventDefault();
            e.stopPropagation(); // prevent bubbling for sake of submenus

            var $thisMenu = $target.closest('[role="menu"]');
            var $thisTrigger = jQuery('[aria-controls="' + $thisMenu.prop('id') + '"]');

            $thisTrigger.click();

            if (!isOfMenu) { activateMenuitem($target, $thisTrigger); }
            break;
          case 40:
            e.preventDefault();
            arrowSetup($target, 'next');
            break;
          case 38:
            e.preventDefault();
            arrowSetup($target, 'prev');
            break;
          case 32:
          case 13:
            e.preventDefault();
            $target.trigger('click');
            if (!$target.attr('aria-controls')) {
              var $link = $target.find('a');
              if ($link.length) {
                $link[0].click();
              }
            }
            break;
          case 39:
            if ($target.attr('aria-controls')) {
              $target.click();
            }
            break;
        }
      })
      /**
       * Mouse logic for expandable submenu triggers
       */
      .on('click', '[role="menuitem"]', function (e) {
        e.stopPropagation();
        var $trigger = jQuery(this);
        if ($trigger.attr('aria-controls')) {
          toggleSubmenu($trigger, function ($submenu, done) {
            $submenu.slideToggle(400, function () {
              $trigger.toggleClass('dqpl-weight-bold');
              var $toFocus = $submenu.find('[role="menuitem"][tabindex="0"]');
              $toFocus = $toFocus.length ? $toFocus : $submenu.find('[role="menuitem"]').first();
              done(false, $toFocus);
            });
          });
        } else {
          var $link = $trigger.find('a');
          if ($link.length) {
            $link[0].click();
          }
        }
      })
      .on('keydown', function (e) {
        var which = e.which;
        if (which !== 9) { return; }
        setTimeout(function () {
          var outsideOfMenu = !$menu.has(document.activeElement).length;
          var isExpanded = $menu.attr('aria-expanded') === 'true';
          if (outsideOfMenu && isExpanded) {
            onTriggerClick(null, true);
          }
        });
      });

    /**
     * The menu is locked into visibility above 1024px viewport...
     * - ensure aria-expanded is removed/readded properly
     * - ensure the topbar menu isn't thrown off (in case the hamburger was the "active" item)
     */
    var lastSize;
    function onResize() {
      var width = jQuery(window).width();

      if (width >= 1024) {
        if (!lastSize || lastSize === 'narrow') {
          lastSize = 'wide';
          var expanded = $menu.attr('aria-expanded');
          if (expanded) {
            $menu.attr('data-prev-expanded', expanded);
          }

          $menu.removeAttr('aria-expanded');
          $scrim.removeClass('dqpl-scrim-show').removeClass('dqpl-scrim-fade-in');

          if ($trigger.prop('tabIndex') === 0) {
            // since `$trigger` gets hidden (via css) "activate" something else in the menubar
            $topBarMenuItems = findTopLevels($topBar.find('[role="menubar"]').first(), true);
            $topBarMenuItems.prop('tabIndex', -1).first().prop('tabIndex', 0);
          }
          $menu.attr('data-locked', 'true');
        }
      } else {
        if (!lastSize || lastSize === 'wide') {
          lastSize = 'narrow';
          var expandedVal = $menu.attr('data-prev-expanded') === 'true' ? 'true' : 'false';
          $menu.attr('aria-expanded', expandedVal);
          $topBarMenuItems = findTopLevels($topBar.find('ul').first(), true);
          $menu.attr('data-locked', 'false');
          if (expandedVal === 'true') {
            $scrim.addClass('dqpl-scrim-show').addClass('dqpl-scrim-fade-in');
          }
        }
      }
    }

    /**
     * Ensure that there is 1 item with tabindex="0"
     */
    function onRefresh() {
      $topBarMenuItems = findTopLevels($topBar.find('[role="menubar"]').first(), true);
      var $activeOne = $topBarMenuItems.filter('[tabindex="0"]');
      if (!$activeOne.length) {
        $topBarMenuItems.first().prop('tabIndex', 0);
      }
    }

    /**
     * Activates a menuitem and deactivates the previously active
     * by giving the previously active menuitem tabindex="-1" and
     * giving the newly active menuitem tabindex="0"
     */
    function activateMenuitem($prevActive, $newlyActive) {
      $prevActive.prop('tabIndex', -1);
      $newlyActive.prop('tabIndex', 0).focus();
    }

    /**
     * Handles left/right arrow navigation
     */
    function arrowHandler($items, $target, dir) {
      var isNext = dir === 'next';
      var currentIdx = $items.index($target[0]);
      var $adjacent = $items.eq(isNext ? currentIdx + 1 : currentIdx - 1);

      // circularity (first or last)
      if (!$adjacent.length) {
        $adjacent = $items.eq(isNext ? 0 : $items.length - 1);
      }

      activateMenuitem($target, $adjacent);
    }

    /**
     * Setup for arrow handler...finds the top levels and calls `arrowHandler`
     */
    function arrowSetup($target, dir) {
      var $items = findTopLevels($target.closest('[role="menu"]'));
      arrowHandler($items, $target, dir);
    }

    /**
     * toggles a menu or submenu
     * @param  {jQuery} $trig      jQuery wrapped element ref of the trigger of the given menu
     * @param  {function} toggleFn a function that handles the toggling of the given menu
     */
    function toggleSubmenu($trig, toggleFn) {
      var $droplet = jQuery('#' + $trig.attr('aria-controls'));

      if (!$droplet.length) {
        return;
      }

      toggleFn($droplet, function (noFocus, $focus) {
        var prevExpanded = $droplet.attr('aria-expanded');
        var wasCollapsed = !prevExpanded || prevExpanded === 'false';
        $droplet.attr('aria-expanded', wasCollapsed);
        if ($focus) {
          $focus.focus();
        } else if (!noFocus) {
          var $active = $droplet.find('.dqpl-menuitem-selected').filter(':visible');
          $active = $active.length ?
            $active :
            $droplet.find('[role="menuitem"][tabindex="0"]').filter(':visible').first();
          var $focusMe = wasCollapsed ?
            $active :
            $droplet.closest('[aria-controls][role="menuitem"]');

          $focusMe = $focusMe.length ? $focusMe : $trigger;
          $focusMe.focus();
        }
      });
    }
  }

  /**
   * Finds the top level menu items of a menu
   */
  function findTopLevels($ul, visible) {
    var $chiles = $ul.children().filter('[role="menuitem"]');
    return (visible) ? $chiles.filter(':visible') : $chiles;
  }
}());
<|endoftext|>


<commit_before>// PlantChicago - Firebelly 2015

// Good Design for Good Reason for Good Namespace
var PlantChicago = (function($) {

  var screen_width = 0,
      breakpoint_small = false,
      breakpoint_medium = false,
      breakpoint_large = false,
      breakpoint_array = [480,1000,1200],
      $document,
      $sidebar,
      loadingTimer,
      page_at;

  function _init() {
    // touch-friendly fast clicks
    FastClick.attach(document.body);

    // Cache some common DOM queries
    $document = $(document);
    $('body').addClass('loaded');

    // Set screen size vars
    _resize();

    // Fit them vids!
    $('main').fitVids();

    _initNav();
    _initBigClicky();
    _initSearch();
    _injectSvgSprite();
    _initPeopleModals();

    // People/post nav arrow handlers
    // Next
    $(document).keydown(function(e) {
      if (e.keyCode === 39) {
        if ($('.person.-active').length) {
          _nextPerson();
        } else if ($('body').is('.single') && $('.post-nav .next a').length) {
          var $postLink = $('.post-nav .next a').attr('href');
          window.location = $postLink;
        }
      }
    });
    // Previous
    $(document).keydown(function(e) {
      if (e.keyCode === 37) {
        if ($('.person.-active').length) {
          _prevPerson();
        } else if ($('body').is('.single') && $('.post-nav .previous a').length) {
          var $postLink = $('.post-nav .previous a').attr('href');
          window.location = $postLink;
        }
      }
    });

    // Esc handlers
    $(document).keyup(function(e) {
      if (e.keyCode === 27) {
        _hideSearch();
        _closePerson();
      }
    });

    // Smoothscroll links
    $('a.smoothscroll').click(function(e) {
      e.preventDefault();
      var href = $(this).attr('href');
      _scrollBody($(href));
    });

    // Scroll down to hash afer page load
    $(window).load(function() {
      if (window.location.hash) {
        _scrollBody($(window.location.hash));
      }
    });

  } // end init()

  function _injectSvgSprite() {
    boomsvgloader.load('/app/themes/plantchicago/assets/svgs/build/svgs-defs.svg');
  }

  function _scrollBody(element, duration, delay) {
    if ($('#wpadminbar').length) {
      wpOffset = $('#wpadminbar').height();
    } else {
      wpOffset = 0;
    }
    element.velocity("scroll", {
      duration: duration,
      delay: delay,
      offset: -wpOffset
    }, "easeOutSine");
  }

  function _initBigClicky() {
    $(document).on('click', '.bigclicky', function(e) {
      if (!$(e.target).is('a')) {
        e.preventDefault();
        var link = $(this).find('a:first');
        var href = link.attr('href');
        if (href) {
          if (e.metaKey || link.attr('target')) {
            window.open(href);
          } else {
            location.href = href;
          }
        }
      }
    });
  }

  function _initSearch() {
    $('.search-toggle').on('click', function() {
      $('.site-header .search-form').addClass('-active');
      $('.site-header .search-field:first').focus();
    });

    // Hide header search form when clicking away
    $('html, body').on('click', function(e) {
      if ($('.site-header .search-form').is('.-active') && !$(e.target).closest('.search-toggle').length) {
        console.log(e.target);
        _hideSearch();
      }
    });

    $('.search-form .close-button').on('click', function() {
      _hideSearch();
    });
  }

  function _hideSearch() {
    $('.search-form').removeClass('-active');
    $('.search-field').blur();
  }

  // Handles main nav
  function _initNav() {
    // SEO-useless nav toggler
    $('.nav-toggle').on('click', function(e) {
      $('body, .site-header, .nav-toggle').toggleClass('nav-open');
      $('.site-nav').toggleClass('-active');
    });
  }

  function _initPeopleModals() {
    $('.person-activate').on('click', function(e) {
      var $activeContainer = $('.active-person-container'),
          $activeDataContainer = $activeContainer.find('.person-data-container'),
          $thisPerson = $(this).closest('.person'),
          $personData = $thisPerson.find('.person-data'),
          thisPersonOffset = -(($('.people-section').offset().top) - ($thisPerson.offset().top));

      _showOverlay();

      $('.person.-active, .people-grid.-active').removeClass('-active');
      $activeDataContainer.empty();
      $thisPerson.addClass('-active');
      $thisPerson.closest('.people-grid').addClass('-active');
      $personData.clone().appendTo($activeDataContainer);
      $activeContainer.css('top', thisPersonOffset);
      $activeContainer.addClass('-active');
      _scrollBody($activeContainer, 500, 0);
    });

    // Shut it down!
    $('html, body').on('click', '.person-deactivate', function(e) {
      _closePerson();
      _hideOverlay();
    });
    // Close if user clicks outside modal
    $('html, body').on('click', '.global-overlay', function() {
      if($('.active-person-container').is('.-active')) {
        _closePerson();
      }
    });

    // People Grid navigation
    $('.next-person').on('click', function(e) {
      _nextPerson();
    });
    $('.previous-person').on('click', function(e) {
      _prevPerson();
    });

  }

  function _nextPerson() {
    var $active = $('.people-grid.-active').find('.person.-active');
    // find next or first person
    var $next = ($active.next('.person').length > 0) ? $active.next('.person') : $('.people-grid.-active .person:first');
    $next.find('.person-activate').trigger('click');
  }

  function _prevPerson() {
    var $active = $('.people-grid.-active').find('.person.-active');
    // find prev or last person
    var $prev = ($active.prev('.person').length > 0) ? $active.prev('.person') : $('.people-grid.-active .person:last');
    $prev.find('.person-activate').trigger('click');
  }

  function _showOverlay() {
    $('.global-overlay').addClass('-active');
  }

  function _hideOverlay() {
    $('.global-overlay').removeClass('-active');
  }

  function _closePerson() {
    var $activeContainer = $('.active-person-container'),
        $activeDataContainer = $('.person-data-container');

    _hideOverlay();
    $activeContainer.removeClass('-active');
    $('.person.-active').removeClass('-active');
    $('.person-grid.-active').removeClass('-active');
    $activeDataContainer.empty();
  }

  // Track ajax pages in Analytics
  function _trackPage() {
    if (typeof ga !== 'undefined') { ga('send', 'pageview', document.location.href); }
  }

  // Track events in Analytics
  function _trackEvent(category, action) {
    if (typeof ga !== 'undefined') { ga('send', 'event', category, action); }
  }

  // Called in quick succession as window is resized
  function _resize() {
    screenWidth = document.documentElement.clientWidth;
    breakpoint_small = (screenWidth > breakpoint_array[0]);
    breakpoint_medium = (screenWidth > breakpoint_array[1]);
    breakpoint_large = (screenWidth > breakpoint_array[2]);
  }

  // Called on scroll
  // function _scroll(dir) {
  //   var wintop = $(window).scrollTop();
  // }

  // Public functions
  return {
    init: _init,
    resize: _resize,
    scrollBody: function(section, duration, delay) {
      _scrollBody(section, duration, delay);
    }
  };

})(jQuery);

// Fire up the mothership
jQuery(document).ready(PlantChicago.init);

// Zig-zag the mothership
jQuery(window).resize(PlantChicago.resize);
<commit_msg>Fixing search focus blur issue<commit_after>// PlantChicago - Firebelly 2015

// Good Design for Good Reason for Good Namespace
var PlantChicago = (function($) {

  var screen_width = 0,
      breakpoint_small = false,
      breakpoint_medium = false,
      breakpoint_large = false,
      breakpoint_array = [480,1000,1200],
      $document,
      $sidebar,
      loadingTimer,
      page_at;

  function _init() {
    // touch-friendly fast clicks
    FastClick.attach(document.body);

    // Cache some common DOM queries
    $document = $(document);
    $('body').addClass('loaded');

    // Set screen size vars
    _resize();

    // Fit them vids!
    $('main').fitVids();

    _initNav();
    _initBigClicky();
    _initSearch();
    _injectSvgSprite();
    _initPeopleModals();

    // People/post nav arrow handlers
    // Next
    $(document).keydown(function(e) {
      if (e.keyCode === 39) {
        if ($('.person.-active').length) {
          _nextPerson();
        } else if ($('body').is('.single') && $('.post-nav .next a').length) {
          var $postLink = $('.post-nav .next a').attr('href');
          window.location = $postLink;
        }
      }
    });
    // Previous
    $(document).keydown(function(e) {
      if (e.keyCode === 37) {
        if ($('.person.-active').length) {
          _prevPerson();
        } else if ($('body').is('.single') && $('.post-nav .previous a').length) {
          var $postLink = $('.post-nav .previous a').attr('href');
          window.location = $postLink;
        }
      }
    });

    // Esc handlers
    $(document).keyup(function(e) {
      if (e.keyCode === 27) {
        _hideSearch();
        _closePerson();
      }
    });

    // Smoothscroll links
    $('a.smoothscroll').click(function(e) {
      e.preventDefault();
      var href = $(this).attr('href');
      _scrollBody($(href));
    });

    // Scroll down to hash afer page load
    $(window).load(function() {
      if (window.location.hash) {
        _scrollBody($(window.location.hash));
      }
    });

  } // end init()

  function _injectSvgSprite() {
    boomsvgloader.load('/app/themes/plantchicago/assets/svgs/build/svgs-defs.svg');
  }

  function _scrollBody(element, duration, delay) {
    if ($('#wpadminbar').length) {
      wpOffset = $('#wpadminbar').height();
    } else {
      wpOffset = 0;
    }
    element.velocity("scroll", {
      duration: duration,
      delay: delay,
      offset: -wpOffset
    }, "easeOutSine");
  }

  function _initBigClicky() {
    $(document).on('click', '.bigclicky', function(e) {
      if (!$(e.target).is('a')) {
        e.preventDefault();
        var link = $(this).find('a:first');
        var href = link.attr('href');
        if (href) {
          if (e.metaKey || link.attr('target')) {
            window.open(href);
          } else {
            location.href = href;
          }
        }
      }
    });
  }

  function _initSearch() {
    $('.search-toggle').on('click, focus', function() {
      $('.site-header .search-form').addClass('-active');
      $('.site-header .search-field:first').focus();
    });

    // Hide header search form when clicking away
    $('html, body').on('click', function(e) {
      if ($('.site-header .search-form').is('.-active') && !$(e.target).closest('.search-toggle').length) {
        console.log(e.target);
        _hideSearch();
      }
    });

    // Hide on blur
    $('.site-header .search-field').on('blur', function(e) {
      _hideSearch();
    });

    $('.search-form .close-button').on('click', function() {
      _hideSearch();
    });
  }

  function _hideSearch() {
    $('.search-form').removeClass('-active');
    $('.search-field').blur();
  }

  // Handles main nav
  function _initNav() {
    // SEO-useless nav toggler
    $('.nav-toggle').on('click', function(e) {
      $('body, .site-header, .nav-toggle').toggleClass('nav-open');
      $('.site-nav').toggleClass('-active');
    });
  }

  function _initPeopleModals() {
    $('.person-activate').on('click', function(e) {
      var $activeContainer = $('.active-person-container'),
          $activeDataContainer = $activeContainer.find('.person-data-container'),
          $thisPerson = $(this).closest('.person'),
          $personData = $thisPerson.find('.person-data'),
          thisPersonOffset = -(($('.people-section').offset().top) - ($thisPerson.offset().top));

      _showOverlay();

      $('.person.-active, .people-grid.-active').removeClass('-active');
      $activeDataContainer.empty();
      $thisPerson.addClass('-active');
      $thisPerson.closest('.people-grid').addClass('-active');
      $personData.clone().appendTo($activeDataContainer);
      $activeContainer.css('top', thisPersonOffset);
      $activeContainer.addClass('-active');
      _scrollBody($activeContainer, 500, 0);
    });

    // Shut it down!
    $('html, body').on('click', '.person-deactivate', function(e) {
      _closePerson();
      _hideOverlay();
    });
    // Close if user clicks outside modal
    $('html, body').on('click', '.global-overlay', function() {
      if($('.active-person-container').is('.-active')) {
        _closePerson();
      }
    });

    // People Grid navigation
    $('.next-person').on('click', function(e) {
      _nextPerson();
    });
    $('.previous-person').on('click', function(e) {
      _prevPerson();
    });

  }

  function _nextPerson() {
    var $active = $('.people-grid.-active').find('.person.-active');
    // find next or first person
    var $next = ($active.next('.person').length > 0) ? $active.next('.person') : $('.people-grid.-active .person:first');
    $next.find('.person-activate').trigger('click');
  }

  function _prevPerson() {
    var $active = $('.people-grid.-active').find('.person.-active');
    // find prev or last person
    var $prev = ($active.prev('.person').length > 0) ? $active.prev('.person') : $('.people-grid.-active .person:last');
    $prev.find('.person-activate').trigger('click');
  }

  function _showOverlay() {
    $('.global-overlay').addClass('-active');
  }

  function _hideOverlay() {
    $('.global-overlay').removeClass('-active');
  }

  function _closePerson() {
    var $activeContainer = $('.active-person-container'),
        $activeDataContainer = $('.person-data-container');

    _hideOverlay();
    $activeContainer.removeClass('-active');
    $('.person.-active').removeClass('-active');
    $('.person-grid.-active').removeClass('-active');
    $activeDataContainer.empty();
  }

  // Track ajax pages in Analytics
  function _trackPage() {
    if (typeof ga !== 'undefined') { ga('send', 'pageview', document.location.href); }
  }

  // Track events in Analytics
  function _trackEvent(category, action) {
    if (typeof ga !== 'undefined') { ga('send', 'event', category, action); }
  }

  // Called in quick succession as window is resized
  function _resize() {
    screenWidth = document.documentElement.clientWidth;
    breakpoint_small = (screenWidth > breakpoint_array[0]);
    breakpoint_medium = (screenWidth > breakpoint_array[1]);
    breakpoint_large = (screenWidth > breakpoint_array[2]);
  }

  // Called on scroll
  // function _scroll(dir) {
  //   var wintop = $(window).scrollTop();
  // }

  // Public functions
  return {
    init: _init,
    resize: _resize,
    scrollBody: function(section, duration, delay) {
      _scrollBody(section, duration, delay);
    }
  };

})(jQuery);

// Fire up the mothership
jQuery(document).ready(PlantChicago.init);

// Zig-zag the mothership
jQuery(window).resize(PlantChicago.resize);
<|endoftext|>


<commit_before>/**
 * APP
 *
 * The app controller manages the global scope.
 */

var util = require('util'),
    events = require('events'),
    rewriter = require('../util/jsonrewriter'),
    Amount = ripple.Amount;

var module = angular.module('app', []);

module.controller('AppCtrl', ['$rootScope', '$compile', 'rpId', 'rpNetwork',
                              function ($scope, $compile, $id, $net)
{
  reset();

  var account;

  // Global reference for debugging only (!)
  if ("object" === typeof rippleclient) {
    rippleclient.id = $id;
    rippleclient.net = $net;
  }

  function reset()
  {
    $scope.account = {};
    $scope.lines = {};
    $scope.offers = {};
    $scope.events = [];
    $scope.history = [];
    $scope.balances = {};
  }

  var myHandleAccountEvent;
  var myHandleAccountEntry;
  function handleAccountLoad(e, data)
  {
    var remote = $net.remote;

    account = data.account;

    reset();

    remote.set_secret(data.account, data.secret);

    var accountObj = remote.account(data.account);

    // We need a reference to these functions after they're bound, so we can
    // unregister them if the account is unloaded.
    myHandleAccountEvent = handleAccountEvent;
    myHandleAccountEntry = handleAccountEntry;

    accountObj.on('transaction', myHandleAccountEvent);
    accountObj.on('entry', myHandleAccountEntry);

    accountObj.entry(function (err, entry) {
      if (err) {
        // XXX: Our account does not exist, we should do something with that
        //      knowledge.
      }
    });

    // Ripple credit lines
    remote.request_account_lines(data.account)
      .on('success', handleRippleLines)
      .on('error', handleRippleLinesError).request();

    // Transactions
    remote.request_account_tx({
      'account': data.account,
      'ledger_index_min': -1,
      'descending': true,
      'limit': Options.transactions_per_page,
      'count': true
    })
      .on('success', handleAccountTx)
      .on('error', handleAccountTxError).request();

    // Outstanding offers
    remote.request_account_offers(data.account)
      .on('success', handleOffers)
      .on('error', handleOffersError).request();
  }

  function handleAccountUnload(e, data)
  {
    var remote = $net.remote;
    var accountObj = remote.account(data.account);
    accountObj.removeListener('transaction', myHandleAccountEvent);
    accountObj.removeListener('entry', myHandleAccountEntry);
  }

  function handleRippleLines(data)
  {
    $scope.$apply(function () {
      $scope.lines = {};

      for (var n=0, l=data.lines.length; n<l; n++) {
        var line = data.lines[n];

        // XXX: This reinterpretation of the server response should be in the
        //      library upstream.
        line = $.extend({}, line, {
          limit: ripple.Amount.from_json({value: line.limit, currency: line.currency, issuer: line.account}),
          limit_peer: ripple.Amount.from_json({value: line.limit_peer, currency: line.currency, issuer: account}),
          balance: ripple.Amount.from_json({value: line.balance, currency: line.currency, issuer: account})
        });

        $scope.lines[line.account+line.currency] = line;
        updateRippleBalance(line.currency, line.account, line.balance);
      }
      console.log('lines updated:', $scope.lines);
    });
  }

  function handleRippleLinesError(data)
  {
  }

  function handleOffers(data)
  {
    $scope.$apply(function () {
      data.offers.forEach(function (offerData) {
        var offer = {
          seq: +offerData.seq,
          gets: ripple.Amount.from_json(offerData.taker_gets),
          pays: ripple.Amount.from_json(offerData.taker_pays)
        };

        updateOffer(offer);
      });
      console.log('offers updated:', $scope.offers);
    });
  }

  function handleOffersError(data)
  {
  }

  function handleAccountEntry(data)
  {
    var remote = $net.remote;
    $scope.$apply(function () {
      $scope.account = data;

      // As per json wire format convention, real ledger entries are CamelCase,
      // e.g. OwnerCount, additional convenience fields are lower case, e.g.
      // reserve, max_spend.
      var reserve_base = Amount.from_json(""+remote._reserve_base),
          reserve_inc  = Amount.from_json(""+remote._reserve_inc),
          owner_count  = $scope.account.OwnerCount || 0;
      $scope.account.reserve_base = reserve_base;
      $scope.account.reserve = reserve_base.add(reserve_inc.product_human(owner_count));
      $scope.account.reserve_to_add_trust = reserve_base.add(reserve_inc.product_human(owner_count+1));
      $scope.account.reserve_low_balance = $scope.account.reserve.product_human(2);

      // Maximum amount user can spend
      var bal = Amount.from_json(data.Balance);
      $scope.account.max_spend = bal.subtract($scope.account.reserve);
    });
  }

  function handleAccountTx(data)
  {
    $scope.$apply(function () {
      $scope.history_count = data.count;

      if (data.transactions) {
        data.transactions.reverse().forEach(function (e) {
          processTxn(e.tx, e.meta, true);
        });
      }
    });
  }
  function handleAccountTxError(data)
  {

  }

  function handleAccountEvent(e)
  {
    $scope.$apply(function () {
      processTxn(e.transaction, e.meta);
    });
  }

  /**
   * Process a transaction and add it to the history table.
   */
  function processTxn(tx, meta, is_historic)
  {
    var processedTxn = rewriter.processTxn(tx, meta, account);

    if (processedTxn) {
      var transaction = processedTxn.transaction;

      // Show status notification
      if (processedTxn.tx_result === "tesSUCCESS" &&
          transaction &&
          !is_historic) {
        $scope.$broadcast('$appTxNotification', transaction);
      }

      // Add to recent notifications
      if (processedTxn.tx_result === "tesSUCCESS") {
        $scope.events.unshift(processedTxn);
      }

      // Add to payments history
      if (processedTxn.tx_type === "Payment" &&
          processedTxn.tx_result === "tesSUCCESS" &&
          processedTxn.transaction) {
        $scope.history.unshift(processedTxn);
      }

      // Update Ripple lines
      if (processedTxn.effects && !is_historic) {
        updateLines(processedTxn.effects);
      }

      // Update my offers
      if (processedTxn.effects && !is_historic) {
        // Iterate on each effect to find offers
        processedTxn.effects.forEach(function (effect) {
          // Only these types are offers
          if (_.contains([
            'offer_created',
            'offer_funded',
            'offer_partially_funded',
            'offer_cancelled'], effect.type))
          {
            var offer = {
              seq: +effect.seq,
              gets: effect.gets,
              pays: effect.pays,
              deleted: effect.deleted
            };

            updateOffer(offer);
          }
        });
      }
    }
  }

  function updateOffer(offer)
  {
    var reverseOrder = null;
    var pairs = $scope.pairs;
    for (var i = 0, l = pairs.length; i < l; i++) {
      var pair = pairs[i].name;
      if (pair.slice(0,3) == offer.gets.currency().to_json() &&
          pair.slice(4,7) == offer.pays.currency().to_json()) {
        reverseOrder = false;
        break;
      } else if (pair.slice(0,3) == offer.pays.currency().to_json() &&
                 pair.slice(4,7) == offer.gets.currency().to_json())  {
        reverseOrder = true;
        break;
      }
    }

    // TODO: Sensible default for undefined pairs
    if (reverseOrder === null) {
      reverseOrder = false;
    }

    if (reverseOrder) {
      offer.type = 'buy';
      offer.first = offer.pays;
      offer.second = offer.gets;
    } else {
      offer.type = 'sell';
      offer.first = offer.gets;
      offer.second = offer.pays;
    }

    if (!offer.deleted) {
      $scope.offers[""+offer.seq] = offer;
    } else {
      delete $scope.offers[""+offer.seq];
    }
  }
  function updateLines(effects)
  {
    if (!$.isArray(effects)) return;

    $.each(effects, function () {
      if (_.contains([
        'trust_create_local',
        'trust_create_remote',
        'trust_change_local',
        'trust_change_remote',
        'trust_change_balance'], this.type))
      {
        var effect = this,
            line = {},
            index = effect.counterparty + effect.currency;

        line.currency = effect.currency;
        line.account = effect.counterparty;

        if (effect.balance) {
          line.balance = effect.balance;
          updateRippleBalance(effect.currency,
                                    effect.counterparty,
                                    effect.balance);
        }

        if (effect.deleted) {
          delete $scope.lines[index];
          return;
        }

        if (effect.limit) {
          line.limit = effect.limit;
        }

        if (effect.limit_peer) {
          line.limit_peer = effect.limit_peer;
        }

        $scope.lines[index] = $.extend($scope.lines[index], line);
      }
    });
  }

  function updateRippleBalance(currency, new_account, new_balance)
  {
    // Ensure the balances entry exists first
    if (!$scope.balances[currency]) {
      $scope.balances[currency] = {components: {}, total: null};
    }

    var balance = $scope.balances[currency];

    if (new_account) {
      balance.components[new_account] = new_balance;
    }

    $(balance.components).sort(function(a,b){
      debugger
      return a.compareTo(b);
    });

    balance.total = null;
    for (var counterparty in balance.components) {
      var amount = balance.components[counterparty];
      balance.total = balance.total ? balance.total.add(amount) : amount;
    }
  }

  // Personalized default currency set
  if (!store.get('ripple_currencies_all')) {
    store.set('ripple_currencies_all',require('../data/currencies'));
  }

  $scope.currencies_all = store.get('ripple_currencies_all')
    ? store.get('ripple_currencies_all')
    : require('../data/currencies');

  // Personalized default pair set
  if (!store.get('ripple_pairs_all')) {
    store.set('ripple_pairs_all',require('../data/pairs'));
  }

  $scope.pairs_all = store.get('ripple_pairs_all')
    ? store.get('ripple_pairs_all')
    : require('../data/pairs');

  function compare(a, b) {
    if (a.order < b.order) return 1;
    if (a.order > b.order) return -1;
    return 0;
  }

  // sort currencies and pairs by order
  $scope.currencies_all.sort(compare);
  $scope.pairs_all.sort(compare);

  $scope.$watch('currencies_all', function(){
    store.set('ripple_currencies_all',$scope.currencies_all);
  }, true);

  $scope.$watch('pairs_all', function(){
    store.set('ripple_pairs_all',$scope.pairs_all);
  }, true);

  $scope.currencies = $scope.currencies_all.slice(1);
  $scope.pairs = $scope.pairs_all.slice(1);

  // Enable screen
  $('body').addClass('loaded');

  // Nav links same page click fix
  $('nav a').click(function(){
    if (location.hash == this.hash) {
      location.href="#/";
      location.href=this.href;
    }
  });

  // Add status box to DOM
  var template = require('../../jade/client/status.jade')();
  $compile(template)($scope, function (el, $scope) {
    el.appendTo('header');
  });

  $scope.$on('$idAccountLoad', function (e, data) {
    // Server is connected
    if ($scope.connected) {
      handleAccountLoad(e, data);
    }

    // Server is not connected yet. Handle account load after server response.
    $scope.$on('$netConnected', function(){
      if ($.isEmptyObject($scope.account)) {
        handleAccountLoad(e, data);
      }
    });
  });

  $scope.$on('$idAccountUnload', handleAccountUnload);

  // XXX: The app also needs to handle updating its data when the connection is
  //      lost and later re-established. (... or will the Ripple lib do that for us?)
  var removeFirstConnectionListener =
        $scope.$on('$netConnected', handleFirstConnection);
  function handleFirstConnection() {
    removeFirstConnectionListener();
  }

  $net.listenId($id);
  $net.init();
  $id.init();
}]);
<commit_msg>Differentiate sell/buy offers by tfSell flag<commit_after>/**
 * APP
 *
 * The app controller manages the global scope.
 */

var util = require('util'),
    events = require('events'),
    rewriter = require('../util/jsonrewriter'),
    Amount = ripple.Amount;

var module = angular.module('app', []);

module.controller('AppCtrl', ['$rootScope', '$compile', 'rpId', 'rpNetwork',
                              function ($scope, $compile, $id, $net)
{
  reset();

  var account;

  // Global reference for debugging only (!)
  if ("object" === typeof rippleclient) {
    rippleclient.id = $id;
    rippleclient.net = $net;
  }

  function reset()
  {
    $scope.account = {};
    $scope.lines = {};
    $scope.offers = {};
    $scope.events = [];
    $scope.balances = {};
  }

  var myHandleAccountEvent;
  var myHandleAccountEntry;
  function handleAccountLoad(e, data)
  {
    var remote = $net.remote;

    account = data.account;

    reset();

    remote.set_secret(data.account, data.secret);

    var accountObj = remote.account(data.account);

    // We need a reference to these functions after they're bound, so we can
    // unregister them if the account is unloaded.
    myHandleAccountEvent = handleAccountEvent;
    myHandleAccountEntry = handleAccountEntry;

    accountObj.on('transaction', myHandleAccountEvent);
    accountObj.on('entry', myHandleAccountEntry);

    accountObj.entry(function (err, entry) {
      if (err) {
        // XXX: Our account does not exist, we should do something with that
        //      knowledge.
      }
    });

    // Ripple credit lines
    remote.request_account_lines(data.account)
      .on('success', handleRippleLines)
      .on('error', handleRippleLinesError).request();

    // Transactions
    remote.request_account_tx({
      'account': data.account,
      'ledger_index_min': -1,
      'descending': true,
      'limit': Options.transactions_per_page,
      'count': true
    })
      .on('success', handleAccountTx)
      .on('error', handleAccountTxError).request();

    // Outstanding offers
    remote.request_account_offers(data.account)
      .on('success', handleOffers)
      .on('error', handleOffersError).request();
  }

  function handleAccountUnload(e, data)
  {
    var remote = $net.remote;
    var accountObj = remote.account(data.account);
    accountObj.removeListener('transaction', myHandleAccountEvent);
    accountObj.removeListener('entry', myHandleAccountEntry);
  }

  function handleRippleLines(data)
  {
    $scope.$apply(function () {
      $scope.lines = {};

      for (var n=0, l=data.lines.length; n<l; n++) {
        var line = data.lines[n];

        // XXX: This reinterpretation of the server response should be in the
        //      library upstream.
        line = $.extend({}, line, {
          limit: ripple.Amount.from_json({value: line.limit, currency: line.currency, issuer: line.account}),
          limit_peer: ripple.Amount.from_json({value: line.limit_peer, currency: line.currency, issuer: account}),
          balance: ripple.Amount.from_json({value: line.balance, currency: line.currency, issuer: account})
        });

        $scope.lines[line.account+line.currency] = line;
        updateRippleBalance(line.currency, line.account, line.balance);
      }
      console.log('lines updated:', $scope.lines);
    });
  }

  function handleRippleLinesError(data)
  {
  }

  function handleOffers(data)
  {
    $scope.$apply(function () {
      data.offers.forEach(function (offerData) {
        var offer = {
          seq: +offerData.seq,
          gets: ripple.Amount.from_json(offerData.taker_gets),
          pays: ripple.Amount.from_json(offerData.taker_pays)
        };

        updateOffer(offer);
      });
      console.log('offers updated:', $scope.offers);
    });
  }

  function handleOffersError(data)
  {
  }

  function handleAccountEntry(data)
  {
    var remote = $net.remote;
    $scope.$apply(function () {
      $scope.account = data;

      // As per json wire format convention, real ledger entries are CamelCase,
      // e.g. OwnerCount, additional convenience fields are lower case, e.g.
      // reserve, max_spend.
      var reserve_base = Amount.from_json(""+remote._reserve_base),
          reserve_inc  = Amount.from_json(""+remote._reserve_inc),
          owner_count  = $scope.account.OwnerCount || 0;
      $scope.account.reserve_base = reserve_base;
      $scope.account.reserve = reserve_base.add(reserve_inc.product_human(owner_count));
      $scope.account.reserve_to_add_trust = reserve_base.add(reserve_inc.product_human(owner_count+1));
      $scope.account.reserve_low_balance = $scope.account.reserve.product_human(2);

      // Maximum amount user can spend
      var bal = Amount.from_json(data.Balance);
      $scope.account.max_spend = bal.subtract($scope.account.reserve);
    });
  }

  function handleAccountTx(data)
  {
    $scope.$apply(function () {
      $scope.history_count = data.count;

      if (data.transactions) {
        data.transactions.reverse().forEach(function (e) {
          processTxn(e.tx, e.meta, true);
        });
      }
    });
  }
  function handleAccountTxError(data)
  {

  }

  function handleAccountEvent(e)
  {
    $scope.$apply(function () {
      processTxn(e.transaction, e.meta);
    });
  }

  /**
   * Process a transaction and add it to the history table.
   */
  function processTxn(tx, meta, is_historic)
  {
    var processedTxn = rewriter.processTxn(tx, meta, account);

    if (processedTxn) {
      var transaction = processedTxn.transaction;

      // Show status notification
      if (processedTxn.tx_result === "tesSUCCESS" &&
          transaction &&
          !is_historic) {
        $scope.$broadcast('$appTxNotification', transaction);
      }

      // Add to recent notifications
      if (processedTxn.tx_result === "tesSUCCESS") {
        $scope.events.unshift(processedTxn);
      }

      // Update Ripple lines
      if (processedTxn.effects && !is_historic) {
        updateLines(processedTxn.effects);
      }

      // Update my offers
      if (processedTxn.effects && !is_historic) {
        // Iterate on each effect to find offers
        processedTxn.effects.forEach(function (effect) {
          // Only these types are offers
          if (_.contains([
            'offer_created',
            'offer_funded',
            'offer_partially_funded',
            'offer_cancelled'], effect.type))
          {
            var offer = {
              seq: +effect.seq,
              gets: effect.gets,
              pays: effect.pays,
              deleted: effect.deleted,
              flags: processedTxn.transaction.flags
            };

            updateOffer(offer);
          }
        });
      }
    }
  }

  function updateOffer(offer)
  {
    if (offer.flags && offer.flags === ripple.Transaction.flags.OfferCreate.Sell) {
      offer.type = 'sell';
      offer.first = offer.gets;
      offer.second = offer.pays;
    } else {
      offer.type = 'buy';
      offer.first = offer.pays;
      offer.second = offer.gets;
    }

    if (!offer.deleted) {
      $scope.offers[""+offer.seq] = offer;
    } else {
      delete $scope.offers[""+offer.seq];
    }
  }

  function updateLines(effects)
  {
    if (!$.isArray(effects)) return;

    $.each(effects, function () {
      if (_.contains([
        'trust_create_local',
        'trust_create_remote',
        'trust_change_local',
        'trust_change_remote',
        'trust_change_balance'], this.type))
      {
        var effect = this,
            line = {},
            index = effect.counterparty + effect.currency;

        line.currency = effect.currency;
        line.account = effect.counterparty;

        if (effect.balance) {
          line.balance = effect.balance;
          updateRippleBalance(effect.currency,
                                    effect.counterparty,
                                    effect.balance);
        }

        if (effect.deleted) {
          delete $scope.lines[index];
          return;
        }

        if (effect.limit) {
          line.limit = effect.limit;
        }

        if (effect.limit_peer) {
          line.limit_peer = effect.limit_peer;
        }

        $scope.lines[index] = $.extend($scope.lines[index], line);
      }
    });
  }

  function updateRippleBalance(currency, new_account, new_balance)
  {
    // Ensure the balances entry exists first
    if (!$scope.balances[currency]) {
      $scope.balances[currency] = {components: {}, total: null};
    }

    var balance = $scope.balances[currency];

    if (new_account) {
      balance.components[new_account] = new_balance;
    }

    $(balance.components).sort(function(a,b){
      debugger
      return a.compareTo(b);
    });

    balance.total = null;
    for (var counterparty in balance.components) {
      var amount = balance.components[counterparty];
      balance.total = balance.total ? balance.total.add(amount) : amount;
    }
  }

  // Personalized default currency set
  if (!store.get('ripple_currencies_all')) {
    store.set('ripple_currencies_all',require('../data/currencies'));
  }

  $scope.currencies_all = store.get('ripple_currencies_all')
    ? store.get('ripple_currencies_all')
    : require('../data/currencies');

  // Personalized default pair set
  if (!store.get('ripple_pairs_all')) {
    store.set('ripple_pairs_all',require('../data/pairs'));
  }

  $scope.pairs_all = store.get('ripple_pairs_all')
    ? store.get('ripple_pairs_all')
    : require('../data/pairs');

  function compare(a, b) {
    if (a.order < b.order) return 1;
    if (a.order > b.order) return -1;
    return 0;
  }

  // sort currencies and pairs by order
  $scope.currencies_all.sort(compare);
  $scope.pairs_all.sort(compare);

  $scope.$watch('currencies_all', function(){
    store.set('ripple_currencies_all',$scope.currencies_all);
  }, true);

  $scope.$watch('pairs_all', function(){
    store.set('ripple_pairs_all',$scope.pairs_all);
  }, true);

  $scope.currencies = $scope.currencies_all.slice(1);
  $scope.pairs = $scope.pairs_all.slice(1);

  // Enable screen
  $('body').addClass('loaded');

  // Nav links same page click fix
  $('nav a').click(function(){
    if (location.hash == this.hash) {
      location.href="#/";
      location.href=this.href;
    }
  });

  // Add status box to DOM
  var template = require('../../jade/client/status.jade')();
  $compile(template)($scope, function (el, $scope) {
    el.appendTo('header');
  });

  $scope.$on('$idAccountLoad', function (e, data) {
    // Server is connected
    if ($scope.connected) {
      handleAccountLoad(e, data);
    }

    // Server is not connected yet. Handle account load after server response.
    $scope.$on('$netConnected', function(){
      if ($.isEmptyObject($scope.account)) {
        handleAccountLoad(e, data);
      }
    });
  });

  $scope.$on('$idAccountUnload', handleAccountUnload);

  // XXX: The app also needs to handle updating its data when the connection is
  //      lost and later re-established. (... or will the Ripple lib do that for us?)
  var removeFirstConnectionListener =
        $scope.$on('$netConnected', handleFirstConnection);
  function handleFirstConnection() {
    removeFirstConnectionListener();
  }

  $net.listenId($id);
  $net.init();
  $id.init();
}]);
<|endoftext|>


<commit_before>'use strict';

const mongo = require('../lib/db');

const User = require('../models/User');
const Checkin = require('../models/Checkin');

const users = require('./fixtures/users');
const checkins = require('./fixtures/checkins');

// mongodb connect
before(function before(done) {
  this.timeout(10000);

  if (mongo.connection._hasOpened) {
    process.nextTick(done);
  } else {
    mongo.connection.once('open', done);
  }
});

// mongodb clean
beforeEach(() => mongo.connection.db.dropDatabase());

// mongodb insert
beforeEach(() => Promise.all([
  User.collection.collection.insert(users),
  Checkin.collection.collection.insert(checkins),
]));
<commit_msg>chore(test): clear mongoose model after testing<commit_after>'use strict';

const mongo = require('../lib/db');

const User = require('../models/User');
const Checkin = require('../models/Checkin');

const users = require('./fixtures/users');
const checkins = require('./fixtures/checkins');

// mongodb connect
before(function before(done) {
  this.timeout(10000);

  if (mongo.connection._hasOpened) {
    process.nextTick(done);
  } else {
    mongo.connection.once('open', done);
  }
});

after(() => {
  mongo.models = {};
  mongo.modelSchemas = {};
});

// mongodb clean
beforeEach(() => mongo.connection.db.dropDatabase());

// mongodb insert
beforeEach(() => Promise.all([
  User.collection.collection.insert(users),
  Checkin.collection.collection.insert(checkins),
]));
<|endoftext|>


<commit_before>'use strict';

Darwinator.Player = function(game, x, y, cursors) {
    Darwinator.Entity.call(this, game, x, y, 'player');
    this.cursors = cursors;
    this.anchor.setTo(0.5, 0.5);
    this.initKeys(game);
    this.initAnimations();

    this.attributes.strength  = Darwinator.PLAYER_BASE_STRENGTH;
    this.attributes.agility   = Darwinator.PLAYER_BASE_AGILITY;
    this.attributes.intellect = Darwinator.PLAYER_BASE_INTELLECT;
    this.updateAttributes();

    this.weapon      = null;
    this.dashTimer   = null;
    this.direction   = 90;
    this.dashCounter = 0;

    // for development only
    this.immortal = false;
}

Darwinator.Player.prototype = Object.create(Darwinator.Entity.prototype);

Darwinator.Player.prototype.update = function () {

    var pointer = this.game.input.activePointer;
    if (pointer.isDown){
    this.weapon.fire(pointer.worldX, pointer.worldY);
}

    /*
    *  If dashing, override manual controls and
    *  just keep the values assigned in dash. Once
    *  dash is completed, return to normal controls.
    */
    if (this.isDashing()) {
        this.dashCounter--;
        this.game.physics.arcade.velocityFromAngle(this.direction, this.currentSpeed, this.body.velocity);

        // Make a fake-dash, and check if colliding. Always reset after, but end dash if collision
        // would occour.
        var preX = this.body.x,
          preY = this.body.y,
          realVelX = this.body.x + this.body.velocity.x * this.game.time.physicsElapsed,
          realVelY = this.body.y + this.body.velocity.y * this.game.time.physicsElapsed;
        this.body.x = realVelX;
        this.body.y = realVelY;
        var dashCollide = this.game.physics.arcade.overlap(this, this.game.level.collisionLayer)
        this.body.x = preX;
        this.body.y = preY;
        if(dashCollide) {
        this.body.velocity.setTo(0,0);
        this.dashCounter = 0;
        }
    } else {
        this.currentSpeed = this.speed;
        this.body.velocity.setTo(0,0);
        var dir = [0,0];
        var moving = false;

        if (this.cursors.left.isDown || this.leftKey.isDown) {
          dir[0] = -1;
          moving = true;
        } else if (this.cursors.right.isDown || this.rightKey.isDown) {
          dir[0] = 1;
          moving = true;
        }
        if (this.cursors.up.isDown || this.upKey.isDown) {
          if (this.getBounds().y <= 0 || this.getBounds().y <= 0) { // top right
            this.body.velocity.y = 0;
          }
          dir[1] = 1;
          moving = true;
        } else if (this.cursors.down.isDown || this.downKey.isDown) {
          dir[1] = -1;
          moving = true;
        }

        if (!moving) {
          this.animations.stop();
          this.body.frame = 4;
        } else {
          //Going upwards
          if (dir[1] === 1) {
            this.direction = 270;
            this.animations.play('walk-up');
            //Also going right or left
            if(dir[0] === 1) {
              this.direction = 315;
            } else if (dir[0] === -1) {
              this.direction = 225;
            }
          //Going downwards
          } else if (dir[1] === -1) {
            this.direction = 90;
            this.animations.play('walk-down');
            //Also going right or left
            if (dir[0] === 1) {
              this.direction = 45;
            } else if (dir[0] === -1) {
              this.direction = 135;
            }
            //Going right
          } else if (dir[0] === 1) {
            this.direction = 0;
            this.animations.play('walk-right');
            //Going left
          } else if (dir[0] === -1) {
            this.direction = 180;
            this.animations.play('walk-left');
          }
          // Set speed and angle
          this.game.physics.arcade.velocityFromAngle(this.direction, this.currentSpeed, this.body.velocity);
        }
    }
    if (this.sprintKey.isDown && this.currBreath > 1 && moving) {
        this.body.velocity.multiply(2,2);
        this.currBreath--;
    } else if (this.currBreath < this.stamina) {
        this.currBreath += 0.2;
}

};

Darwinator.Player.prototype.initKeys = function (game) {

    this.upKey     = game.input.keyboard.addKey(Phaser.Keyboard.W);
    this.leftKey   = game.input.keyboard.addKey(Phaser.Keyboard.A);
    this.downKey   = game.input.keyboard.addKey(Phaser.Keyboard.S);
    this.rightKey  = game.input.keyboard.addKey(Phaser.Keyboard.D);
    this.sprintKey = game.input.keyboard.addKey(Phaser.Keyboard.SHIFT);
    this.telKey    = game.input.keyboard.addKey(Phaser.Keyboard.Q);
    this.dodgeKey  = game.input.keyboard.addKey(Phaser.Keyboard.R);

    this.telKey.onDown.add(function() {
        var onCooldown = (Date.now() - this.lastAbilityUse) < this.abilityCooldownMs;
        if (!onCooldown) {
            var pointer = this.game.input.activePointer;
            this.reset(pointer.worldX, pointer.worldY, this.health);
            this.lastAbilityUse = Date.now();
        }
    }, this);

    this.dodgeKey.onDown.add(this.dodge, this);

    var checkTimer = function (key) {

        if (!this.isDashing() && !!key.lastReleased && this.game.time.now - key.lastReleased < 200 && this.currBreath > 30) {

            this.dashCounter = 10;
            this.currentSpeed = 1000;
            this.currBreath -= 30;

            if (key === this.cursors.left || key === this.leftKey) {
                this.direction = 180;
            } else if (key === this.cursors.right || key === this.rightKey) {
                this.direction = 0;
            } else if (key === this.cursors.up || key === this.upKey) {
                this.direction = 270;
            } else if (key === this.cursors.down || key === this.downKey) {
                this.direction = 90;
            }
        }
    };

    var addTimer = function(key) {
        key.lastReleased = this.game.time.now;
    };

    this.upKey.onUp.add(addTimer, this);
    this.leftKey.onUp.add(addTimer, this);
    this.downKey.onUp.add(addTimer, this);
    this.rightKey.onUp.add(addTimer, this);
    this.cursors.up.onUp.add(addTimer, this);
    this.cursors.down.onUp.add(addTimer, this);
    this.cursors.right.onUp.add(addTimer, this);
    this.cursors.left.onUp.add(addTimer, this);

    this.upKey.onDown.add(checkTimer, this);
    this.leftKey.onDown.add(checkTimer, this);
    this.downKey.onDown.add(checkTimer, this);
    this.rightKey.onDown.add(checkTimer, this);
    this.cursors.up.onDown.add(checkTimer, this);
    this.cursors.down.onDown.add(checkTimer, this);
    this.cursors.right.onDown.add(checkTimer, this);
    this.cursors.left.onDown.add(checkTimer, this);

};

Darwinator.Entity.prototype.updateAttributes = function () {

    this.health         = Darwinator.PLAYER_BASE_HEALTH  + this.attributes.strength;
    this.damage         = Darwinator.PLAYER_BASE_DAMAGE  + this.attributes.strength;
    this.speed          = Darwinator.PLAYER_BASE_SPEED   + this.attributes.agility * 3 - this.attributes.strength;
    this.stamina        = Darwinator.PLAYER_BASE_STAMINA + this.attributes.agility * 2 - this.attributes.strength / 5;
    this.aim            = this.attributes.intellect; // Intended to define how well the enemy aims. 0 = "shitty" aim, 100 = "perfect" aim
    this.criticalStrike = this.attributes.intellect / 100; // Critical strike percentage
    this.currBreath     = this.stamina;
    this.currentSpeed   = this.speed;

    var red   = 'color: red; font-weight: bold;';
    var green = 'color: #02c;';

    console.log('%c Updated player attributes! ', 'background: #222; color: #dc3');

    console.log('%c\tStrength:  ' + this.attributes.strength,  green);
    console.log('%c\tAgility:   ' + this.attributes.agility,   green);
    console.log('%c\tIntellect: ' + this.attributes.intellect, green);

    console.log('\tHealth:  ' + '%c' + this.health,  red);
    console.log('\tDamage:  ' + '%c' + this.damage,  red);
    console.log('\tSpeed:   ' + '%c' + this.speed,   red);
    console.log('\tStamina: ' + '%c' + this.stamina + '\n', red);
};

Darwinator.Player.prototype.initAnimations = function () {
    var anims = [['walk-left', [8,9,10,11], 10, true], ['walk-right', [12,13,14,15], 10, true],
               ['walk-up', [0,1,2,3], 10, true], ['walk-down', [4,5,6,7], 10, true]];

    this.setAnimations(anims);
};

Darwinator.Player.prototype.isDashing = function () {
  return this.dashCounter > 0;
};

Darwinator.Player.prototype.resetAttributes = function () {
    this.attributes.strength  = Darwinator.PLAYER_BASE_STRENGTH;
    this.attributes.agility   = Darwinator.PLAYER_BASE_AGILITY;
    this.attributes.intellect = Darwinator.PLAYER_BASE_INTELLECT;
    this.updateAttributes();
};
<commit_msg>replaced incorrect prototype reference<commit_after>'use strict';

Darwinator.Player = function(game, x, y, cursors) {
    Darwinator.Entity.call(this, game, x, y, 'player');
    this.cursors = cursors;
    this.anchor.setTo(0.5, 0.5);
    this.initKeys(game);
    this.initAnimations();

    this.attributes.strength  = Darwinator.PLAYER_BASE_STRENGTH;
    this.attributes.agility   = Darwinator.PLAYER_BASE_AGILITY;
    this.attributes.intellect = Darwinator.PLAYER_BASE_INTELLECT;
    this.updateAttributes();

    this.weapon      = null;
    this.dashTimer   = null;
    this.direction   = 90;
    this.dashCounter = 0;

    // for development only
    this.immortal = false;
}

Darwinator.Player.prototype = Object.create(Darwinator.Entity.prototype);

Darwinator.Player.prototype.update = function () {

    var pointer = this.game.input.activePointer;
    if (pointer.isDown){
    this.weapon.fire(pointer.worldX, pointer.worldY);
}

    /*
    *  If dashing, override manual controls and
    *  just keep the values assigned in dash. Once
    *  dash is completed, return to normal controls.
    */
    if (this.isDashing()) {
        this.dashCounter--;
        this.game.physics.arcade.velocityFromAngle(this.direction, this.currentSpeed, this.body.velocity);

        // Make a fake-dash, and check if colliding. Always reset after, but end dash if collision
        // would occour.
        var preX = this.body.x,
          preY = this.body.y,
          realVelX = this.body.x + this.body.velocity.x * this.game.time.physicsElapsed,
          realVelY = this.body.y + this.body.velocity.y * this.game.time.physicsElapsed;
        this.body.x = realVelX;
        this.body.y = realVelY;
        var dashCollide = this.game.physics.arcade.overlap(this, this.game.level.collisionLayer)
        this.body.x = preX;
        this.body.y = preY;
        if(dashCollide) {
        this.body.velocity.setTo(0,0);
        this.dashCounter = 0;
        }
    } else {
        this.currentSpeed = this.speed;
        this.body.velocity.setTo(0,0);
        var dir = [0,0];
        var moving = false;

        if (this.cursors.left.isDown || this.leftKey.isDown) {
          dir[0] = -1;
          moving = true;
        } else if (this.cursors.right.isDown || this.rightKey.isDown) {
          dir[0] = 1;
          moving = true;
        }
        if (this.cursors.up.isDown || this.upKey.isDown) {
          if (this.getBounds().y <= 0 || this.getBounds().y <= 0) { // top right
            this.body.velocity.y = 0;
          }
          dir[1] = 1;
          moving = true;
        } else if (this.cursors.down.isDown || this.downKey.isDown) {
          dir[1] = -1;
          moving = true;
        }

        if (!moving) {
          this.animations.stop();
          this.body.frame = 4;
        } else {
          //Going upwards
          if (dir[1] === 1) {
            this.direction = 270;
            this.animations.play('walk-up');
            //Also going right or left
            if(dir[0] === 1) {
              this.direction = 315;
            } else if (dir[0] === -1) {
              this.direction = 225;
            }
          //Going downwards
          } else if (dir[1] === -1) {
            this.direction = 90;
            this.animations.play('walk-down');
            //Also going right or left
            if (dir[0] === 1) {
              this.direction = 45;
            } else if (dir[0] === -1) {
              this.direction = 135;
            }
            //Going right
          } else if (dir[0] === 1) {
            this.direction = 0;
            this.animations.play('walk-right');
            //Going left
          } else if (dir[0] === -1) {
            this.direction = 180;
            this.animations.play('walk-left');
          }
          // Set speed and angle
          this.game.physics.arcade.velocityFromAngle(this.direction, this.currentSpeed, this.body.velocity);
        }
    }
    if (this.sprintKey.isDown && this.currBreath > 1 && moving) {
        this.body.velocity.multiply(2,2);
        this.currBreath--;
    } else if (this.currBreath < this.stamina) {
        this.currBreath += 0.2;
}

};

Darwinator.Player.prototype.initKeys = function (game) {

    this.upKey     = game.input.keyboard.addKey(Phaser.Keyboard.W);
    this.leftKey   = game.input.keyboard.addKey(Phaser.Keyboard.A);
    this.downKey   = game.input.keyboard.addKey(Phaser.Keyboard.S);
    this.rightKey  = game.input.keyboard.addKey(Phaser.Keyboard.D);
    this.sprintKey = game.input.keyboard.addKey(Phaser.Keyboard.SHIFT);
    this.telKey    = game.input.keyboard.addKey(Phaser.Keyboard.Q);
    this.dodgeKey  = game.input.keyboard.addKey(Phaser.Keyboard.R);

    this.telKey.onDown.add(function() {
        var onCooldown = (Date.now() - this.lastAbilityUse) < this.abilityCooldownMs;
        if (!onCooldown) {
            var pointer = this.game.input.activePointer;
            this.reset(pointer.worldX, pointer.worldY, this.health);
            this.lastAbilityUse = Date.now();
        }
    }, this);

    this.dodgeKey.onDown.add(this.dodge, this);

    var checkTimer = function (key) {

        if (!this.isDashing() && !!key.lastReleased && this.game.time.now - key.lastReleased < 200 && this.currBreath > 30) {

            this.dashCounter = 10;
            this.currentSpeed = 1000;
            this.currBreath -= 30;

            if (key === this.cursors.left || key === this.leftKey) {
                this.direction = 180;
            } else if (key === this.cursors.right || key === this.rightKey) {
                this.direction = 0;
            } else if (key === this.cursors.up || key === this.upKey) {
                this.direction = 270;
            } else if (key === this.cursors.down || key === this.downKey) {
                this.direction = 90;
            }
        }
    };

    var addTimer = function(key) {
        key.lastReleased = this.game.time.now;
    };

    this.upKey.onUp.add(addTimer, this);
    this.leftKey.onUp.add(addTimer, this);
    this.downKey.onUp.add(addTimer, this);
    this.rightKey.onUp.add(addTimer, this);
    this.cursors.up.onUp.add(addTimer, this);
    this.cursors.down.onUp.add(addTimer, this);
    this.cursors.right.onUp.add(addTimer, this);
    this.cursors.left.onUp.add(addTimer, this);

    this.upKey.onDown.add(checkTimer, this);
    this.leftKey.onDown.add(checkTimer, this);
    this.downKey.onDown.add(checkTimer, this);
    this.rightKey.onDown.add(checkTimer, this);
    this.cursors.up.onDown.add(checkTimer, this);
    this.cursors.down.onDown.add(checkTimer, this);
    this.cursors.right.onDown.add(checkTimer, this);
    this.cursors.left.onDown.add(checkTimer, this);

};

Darwinator.Player.prototype.updateAttributes = function () {

    this.health         = Darwinator.PLAYER_BASE_HEALTH  + this.attributes.strength;
    this.damage         = Darwinator.PLAYER_BASE_DAMAGE  + this.attributes.strength;
    this.speed          = Darwinator.PLAYER_BASE_SPEED   + this.attributes.agility * 3 - this.attributes.strength;
    this.stamina        = Darwinator.PLAYER_BASE_STAMINA + this.attributes.agility * 2 - this.attributes.strength / 5;
    this.aim            = this.attributes.intellect; // Intended to define how well the enemy aims. 0 = "shitty" aim, 100 = "perfect" aim
    this.criticalStrike = this.attributes.intellect / 100; // Critical strike percentage
    this.currBreath     = this.stamina;
    this.currentSpeed   = this.speed;

    var red   = 'color: red; font-weight: bold;';
    var green = 'color: #02c;';

    console.log('%c Updated player attributes! ', 'background: #222; color: #dc3');

    console.log('%c\tStrength:  ' + this.attributes.strength,  green);
    console.log('%c\tAgility:   ' + this.attributes.agility,   green);
    console.log('%c\tIntellect: ' + this.attributes.intellect, green);

    console.log('\tHealth:  ' + '%c' + this.health,  red);
    console.log('\tDamage:  ' + '%c' + this.damage,  red);
    console.log('\tSpeed:   ' + '%c' + this.speed,   red);
    console.log('\tStamina: ' + '%c' + this.stamina + '\n', red);
};

Darwinator.Player.prototype.initAnimations = function () {
    var anims = [['walk-left', [8,9,10,11], 10, true], ['walk-right', [12,13,14,15], 10, true],
               ['walk-up', [0,1,2,3], 10, true], ['walk-down', [4,5,6,7], 10, true]];

    this.setAnimations(anims);
};

Darwinator.Player.prototype.isDashing = function () {
  return this.dashCounter > 0;
};

Darwinator.Player.prototype.resetAttributes = function () {
    this.attributes.strength  = Darwinator.PLAYER_BASE_STRENGTH;
    this.attributes.agility   = Darwinator.PLAYER_BASE_AGILITY;
    this.attributes.intellect = Darwinator.PLAYER_BASE_INTELLECT;
    this.updateAttributes();
};
<|endoftext|>