<commit_before>'use strict';
angular.module('arethusa.core').service('state', [
  'configurator',
  'navigator',
  '$rootScope',
  'documentStore',
  'keyCapture',
  '$location',
  function (configurator, navigator, $rootScope, documentStore, keyCapture, $location) {
    var self = this;
    var tokenRetrievers;

    this.documents = function() {
      return documentStore.store;
    };

    function configure() {
      self.conf = configurator.configurationFor('main');
      tokenRetrievers = configurator.getRetrievers(self.conf.retrievers);
    }

    // We hold tokens locally during retrieval phase.
    // Once we are done, they will be exposed through
    // this.replaceState, which also triggers
    // the stateLoaded event.
    var tokens = {};

    // Loading a state
    var saveTokens = function (container, tokens) {
      angular.forEach(tokens, function (token, id) {
        var updatedToken;
        var savedToken = container[id];
        if (savedToken) {
          updatedToken = angular.extend(savedToken, token);
        } else {
          updatedToken = token;
        }
        container[id] = token;
      });
    };

    this.retrieveTokens = function () {
      var container = {};
      navigator.reset();
      self.deselectAll();
      angular.forEach(tokenRetrievers, function (retriever, name) {
        retriever.getData(function (data) {
          navigator.addSentences(data);
          moveToSentence();
          saveTokens(container, navigator.currentSentence());
          //saveTokens(container, data[0].tokens);
          declarePreselections(retriever.preselections);
          declareLoaded(retriever);
        });
      });
      tokens = container;
    };

    function moveToSentence() {
      var param = self.conf.chunkParam;
      if (param) {
        var id = $location.search()[param];
        if (id) {
          if (navigator.goTo(id)) {
            return;
          }
        }
      }
      // If goTo failed, we just update the id with the starting value 0
      navigator.updateId();
    }

    this.checkLoadStatus = function () {
      var loaded = true;
      angular.forEach(tokenRetrievers, function (el, name) {
        loaded = loaded && el.loaded;
      });
      if (loaded) {
        this.replaceState(tokens, true);
      }
    };

    function declarePreselections(ids) {
      selectMultipleTokens(ids);
    }

    var declareLoaded = function (retriever) {
      retriever.loaded = true;
      self.checkLoadStatus();
    };

    // Delegators
    this.asString = function (id) {
      return this.tokens[id].string;
    };

    this.getToken = function (id) {
      return self.tokens[id] || {};
    };

    // Selections
    this.selectedTokens = {};
    // ids will be inserted here

    this.hasSelections = function() {
      return Object.keys(self.selectedTokens).length !== 0;
    };

    this.isSelected = function (id) {
      return id in this.selectedTokens;
    };

    // multi-selects tokens, given an array of ids
    this.multiSelect = function (ids) {
      self.deselectAll();
      selectMultipleTokens(ids);
    };

    function selectMultipleTokens(ids) {
      angular.forEach(ids, function (id, i) {
        self.selectToken(id, 'ctrl-click');
      });
    }

    this.changeHead = function (tokenId, newHeadId) {
      if (self.headsFor(newHeadId).indexOf(tokenId) !== -1) {
        self.tokens[newHeadId].head.id = self.tokens[tokenId].head.id;
      }
      self.tokens[tokenId].head.id = newHeadId;
    };

    this.handleChangeHead = function (newHeadId, type) {
      var preventSelection = false;
      angular.forEach(this.selectedTokens, function (type, index) {
        if (self.headCanBeChanged(index, newHeadId, type)) {
          self.changeHead(index, newHeadId);
          preventSelection = preventSelection || true;
        }
      });
      return preventSelection;
    };

    this.headCanBeChanged = function(id, newId, type) {
      return id !== newId && (type === 'click' || type === 'ctrl-click');
    };

    this.headsFor = function (id) {
      var currentToken = self.tokens[id];
      var heads = [];
      while (currentToken && currentToken.head.id) {
        var headId = currentToken.head.id;
        heads.push(headId);
        currentToken = self.tokens[headId];
      }
      return heads;
    };

    // type should be either 'click', 'ctrl-click' or 'hover'
    this.selectToken = function (id, type, changeHead) {
      var preventSelection = false;
      if (type === 'click') {
        preventSelection = changeHead ? self.handleChangeHead(id, type) : false;
        self.deselectAll();
      }
      if (!preventSelection && self.isSelectable(self.selectionType(id), type)) {
        self.selectedTokens[id] = type;
      }
    };

    this.selectionType = function (id) {
      return this.selectedTokens[id];
    };

    this.isSelectable = function (oldVal, newVal) {
      // if an element was hovered, we only select it when another
      // selection type is present (such as 'click'), if there was
      // no selection at all (oldVal === undefined), we select too
      return oldVal === 'hover' && newVal !== 'hover' || !oldVal;
    };

    this.deselectToken = function (id, type) {
      // only deselect when the old selection type is the same as
      // the argument, i.e. a hover selection can only deselect a
      // hover selection, but not a click selection
      if (this.selectionType(id) === type) {
        delete this.selectedTokens[id];
      }
    };

    this.toggleSelection = function (id, type, changeHead) {
      // only deselect when the selectionType is the same.
      // a hovered selection can still be selected by click.
      if (this.isSelected(id) && this.selectionType(id) == type) {
        this.deselectToken(id, type);
      } else {
        this.selectToken(id, type, changeHead);
      }
    };

    this.deselectAll = function () {
      for (var el in this.selectedTokens)
        delete this.selectedTokens[el];
    };

    this.firstSelected = function() {
      return Object.keys(self.selectedTokens)[0];
    };

    this.selectSurroundingToken = function (direction) {
      // take the first current selection
      var firstId = self.firstSelected();
      var allIds = Object.keys(self.tokens);
      var index = allIds.indexOf(firstId);
      // select newId - make a roundtrip if we reached the bounds of the array
      var newId;
      switch (direction) {
      case 'next':
        newId = allIds[index + 1] || allIds[0];
        break;
      case 'prev':
        newId = allIds[index - 1] || allIds[allIds.length - 1];
        break;
      }
      // deselect all previously selected tokens
      self.deselectAll();
      // and select the new one
      self.selectToken(newId, 'click');
    };

    this.selectNextToken = function () {
      self.selectSurroundingToken('next');
    };
    this.selectPrevToken = function () {
      self.selectSurroundingToken('prev');
    };

    // Events
    // Listeners can be internal (angular-implementation) or external (everything
    // else). The future might bring a further distinction between different
    // of events listeners listen to - we'll see.
    this.listeners = [];
    this.externalListeners = [];

    this.registerListener = function (listener) {
      if (listener.external) {
        this.externalListeners.push(listener);
      } else {
        this.listeners.push(listener);
      }
    };

    this.fireEvent = function (target, property, oldVal, newVal) {
      var event = {
          target: target,
          property: property,
          oldVal: oldVal,
          newVal: newVal
        };
      event.time = new Date();
      this.notifyListeners(event);
    };

    this.notifyListeners = function (event) {
      this.notifyAngularListeners(event);
      this.notifyExternalListeners(event);
    };

    this.notifyAngularListeners = function (event) {
      angular.forEach(this.listeners, function (obj, i) {
        obj.catchEvent(event);
      });
    };

    this.notifyExternalListeners = function (event) {
      angular.forEach(this.externalListeners, function (obj, i) {
        obj.catchArethusaEvent(event);
      });
    };

    this.setState = function (id, category, val) {
      var token = this.tokens[id];
      var oldVal = token[category];
      this.fireEvent(token, category, oldVal, val);
      token[category] = val;
    };

    this.unsetState = function (id, category) {
      var token = this.tokens[id];
      var oldVal = token[category];
      this.fireEvent(token, category, oldVal, null);
      delete token[category];
    };

    this.replaceState = function (tokens, keepSelections) {
      // We have to wrap this as there might be watchers on allLoaded,
      // such as the MainCtrl which has to reinit all plugins when the
      // state tokens are replaced
      if (!keepSelections) self.deselectAll();
      self.tokens = tokens;
      self.broadcast('stateLoaded');
    };

    this.setStyle = function (id, style) {
      self.getToken(id).style = style;
    };

    this.addStyle = function(id, style) {
      var token = self.getToken(id);
      if (!token.style) {
        token.style = {};
      }
      angular.extend(token.style, style);
    };

    this.removeStyle = function(id, style) {
      var tokenStyle = self.getToken(id).style;
      if (! tokenStyle) return;

      var styles = arethusaUtil.toAry(style);
      angular.forEach(styles, function(style, i) {
        delete tokenStyle[style];
      });
    };

    this.unsetStyle = function (id) {
      delete self.getToken(id).style;
    };

    this.addStatusObjects = function () {
      angular.forEach(self.tokens, addStatus);
    };

    function addStatus(token) {
      if (! token.status) {
        token.status = {};
      }
    }

    this.countTotalTokens = function () {
      self.totalTokens = Object.keys(self.tokens).length;
    };

    this.countTokens = function (conditionFn) {
      var count = 0;
      angular.forEach(self.tokens, function (token, id) {
        if (conditionFn(token)) {
          count++;
        }
      });
      return count;
    };

    this.addToken = function(token, id) {
      self.tokens[id] = token;
      addStatus(token);
      self.broadcast('tokenAdded', token);
    };

    this.removeToken = function(id) {
      var token = self.getToken(id);
      delete self.tokens[id];
      self.broadcast('tokenRemoved', token);
    };

    // New event handling through $rootScope
    this.on = function(event, fn) {
      $rootScope.$on(event, fn);
    };

    this.broadcast = function(event, arg) {
      $rootScope.$broadcast(event, arg);
    };

    this.postInit = function () {
      self.addStatusObjects();
      self.countTotalTokens();
    };

    keyCapture.initCaptures(function(kC) {
      return {
        selections: [
          kC.create('nextToken', function() { kC.doRepeated(self.selectNextToken); }),
          kC.create('prevToken', function() { kC.doRepeated(self.selectPrevToken); }),
          kC.create('deselect', function() { self.deselectAll(); }, 'esc' )
        ]
      };
    });

    this.init = function () {
      configure();
      self.retrieveTokens();
    };
  }
]);
<commit_msg>Fix token state.removeToken()<commit_after>'use strict';
angular.module('arethusa.core').service('state', [
  'configurator',
  'navigator',
  '$rootScope',
  'documentStore',
  'keyCapture',
  '$location',
  function (configurator, navigator, $rootScope, documentStore, keyCapture, $location) {
    var self = this;
    var tokenRetrievers;

    this.documents = function() {
      return documentStore.store;
    };

    function configure() {
      self.conf = configurator.configurationFor('main');
      tokenRetrievers = configurator.getRetrievers(self.conf.retrievers);
    }

    // We hold tokens locally during retrieval phase.
    // Once we are done, they will be exposed through
    // this.replaceState, which also triggers
    // the stateLoaded event.
    var tokens = {};

    // Loading a state
    var saveTokens = function (container, tokens) {
      angular.forEach(tokens, function (token, id) {
        var updatedToken;
        var savedToken = container[id];
        if (savedToken) {
          updatedToken = angular.extend(savedToken, token);
        } else {
          updatedToken = token;
        }
        container[id] = token;
      });
    };

    this.retrieveTokens = function () {
      var container = {};
      navigator.reset();
      self.deselectAll();
      angular.forEach(tokenRetrievers, function (retriever, name) {
        retriever.getData(function (data) {
          navigator.addSentences(data);
          moveToSentence();
          saveTokens(container, navigator.currentSentence());
          //saveTokens(container, data[0].tokens);
          declarePreselections(retriever.preselections);
          declareLoaded(retriever);
        });
      });
      tokens = container;
    };

    function moveToSentence() {
      var param = self.conf.chunkParam;
      if (param) {
        var id = $location.search()[param];
        if (id) {
          if (navigator.goTo(id)) {
            return;
          }
        }
      }
      // If goTo failed, we just update the id with the starting value 0
      navigator.updateId();
    }

    this.checkLoadStatus = function () {
      var loaded = true;
      angular.forEach(tokenRetrievers, function (el, name) {
        loaded = loaded && el.loaded;
      });
      if (loaded) {
        this.replaceState(tokens, true);
      }
    };

    function declarePreselections(ids) {
      selectMultipleTokens(ids);
    }

    var declareLoaded = function (retriever) {
      retriever.loaded = true;
      self.checkLoadStatus();
    };

    // Delegators
    this.asString = function (id) {
      return this.tokens[id].string;
    };

    this.getToken = function (id) {
      return self.tokens[id] || {};
    };

    // Selections
    this.selectedTokens = {};
    // ids will be inserted here

    this.hasSelections = function() {
      return Object.keys(self.selectedTokens).length !== 0;
    };

    this.isSelected = function (id) {
      return id in this.selectedTokens;
    };

    // multi-selects tokens, given an array of ids
    this.multiSelect = function (ids) {
      self.deselectAll();
      selectMultipleTokens(ids);
    };

    function selectMultipleTokens(ids) {
      angular.forEach(ids, function (id, i) {
        self.selectToken(id, 'ctrl-click');
      });
    }

    this.changeHead = function (tokenId, newHeadId) {
      if (self.headsFor(newHeadId).indexOf(tokenId) !== -1) {
        self.tokens[newHeadId].head.id = self.tokens[tokenId].head.id;
      }
      self.tokens[tokenId].head.id = newHeadId;
    };

    this.handleChangeHead = function (newHeadId, type) {
      var preventSelection = false;
      angular.forEach(this.selectedTokens, function (type, index) {
        if (self.headCanBeChanged(index, newHeadId, type)) {
          self.changeHead(index, newHeadId);
          preventSelection = preventSelection || true;
        }
      });
      return preventSelection;
    };

    this.headCanBeChanged = function(id, newId, type) {
      return id !== newId && (type === 'click' || type === 'ctrl-click');
    };

    this.headsFor = function (id) {
      var currentToken = self.tokens[id];
      var heads = [];
      while (currentToken && currentToken.head.id) {
        var headId = currentToken.head.id;
        heads.push(headId);
        currentToken = self.tokens[headId];
      }
      return heads;
    };

    // type should be either 'click', 'ctrl-click' or 'hover'
    this.selectToken = function (id, type, changeHead) {
      var preventSelection = false;
      if (type === 'click') {
        preventSelection = changeHead ? self.handleChangeHead(id, type) : false;
        self.deselectAll();
      }
      if (!preventSelection && self.isSelectable(self.selectionType(id), type)) {
        self.selectedTokens[id] = type;
      }
    };

    this.selectionType = function (id) {
      return this.selectedTokens[id];
    };

    this.isSelectable = function (oldVal, newVal) {
      // if an element was hovered, we only select it when another
      // selection type is present (such as 'click'), if there was
      // no selection at all (oldVal === undefined), we select too
      return oldVal === 'hover' && newVal !== 'hover' || !oldVal;
    };

    this.deselectToken = function (id, type) {
      // only deselect when the old selection type is the same as
      // the argument, i.e. a hover selection can only deselect a
      // hover selection, but not a click selection
      if (this.selectionType(id) === type) {
        delete this.selectedTokens[id];
      }
    };

    this.toggleSelection = function (id, type, changeHead) {
      // only deselect when the selectionType is the same.
      // a hovered selection can still be selected by click.
      if (this.isSelected(id) && this.selectionType(id) == type) {
        this.deselectToken(id, type);
      } else {
        this.selectToken(id, type, changeHead);
      }
    };

    this.deselectAll = function () {
      for (var el in this.selectedTokens)
        delete this.selectedTokens[el];
    };

    this.firstSelected = function() {
      return Object.keys(self.selectedTokens)[0];
    };

    this.selectSurroundingToken = function (direction) {
      // take the first current selection
      var firstId = self.firstSelected();
      var allIds = Object.keys(self.tokens);
      var index = allIds.indexOf(firstId);
      // select newId - make a roundtrip if we reached the bounds of the array
      var newId;
      switch (direction) {
      case 'next':
        newId = allIds[index + 1] || allIds[0];
        break;
      case 'prev':
        newId = allIds[index - 1] || allIds[allIds.length - 1];
        break;
      }
      // deselect all previously selected tokens
      self.deselectAll();
      // and select the new one
      self.selectToken(newId, 'click');
    };

    this.selectNextToken = function () {
      self.selectSurroundingToken('next');
    };
    this.selectPrevToken = function () {
      self.selectSurroundingToken('prev');
    };

    // Events
    // Listeners can be internal (angular-implementation) or external (everything
    // else). The future might bring a further distinction between different
    // of events listeners listen to - we'll see.
    this.listeners = [];
    this.externalListeners = [];

    this.registerListener = function (listener) {
      if (listener.external) {
        this.externalListeners.push(listener);
      } else {
        this.listeners.push(listener);
      }
    };

    this.fireEvent = function (target, property, oldVal, newVal) {
      var event = {
          target: target,
          property: property,
          oldVal: oldVal,
          newVal: newVal
        };
      event.time = new Date();
      this.notifyListeners(event);
    };

    this.notifyListeners = function (event) {
      this.notifyAngularListeners(event);
      this.notifyExternalListeners(event);
    };

    this.notifyAngularListeners = function (event) {
      angular.forEach(this.listeners, function (obj, i) {
        obj.catchEvent(event);
      });
    };

    this.notifyExternalListeners = function (event) {
      angular.forEach(this.externalListeners, function (obj, i) {
        obj.catchArethusaEvent(event);
      });
    };

    this.setState = function (id, category, val) {
      var token = this.tokens[id];
      var oldVal = token[category];
      this.fireEvent(token, category, oldVal, val);
      token[category] = val;
    };

    this.unsetState = function (id, category) {
      var token = this.tokens[id];
      var oldVal = token[category];
      this.fireEvent(token, category, oldVal, null);
      delete token[category];
    };

    this.replaceState = function (tokens, keepSelections) {
      // We have to wrap this as there might be watchers on allLoaded,
      // such as the MainCtrl which has to reinit all plugins when the
      // state tokens are replaced
      if (!keepSelections) self.deselectAll();
      self.tokens = tokens;
      self.broadcast('stateLoaded');
    };

    this.setStyle = function (id, style) {
      self.getToken(id).style = style;
    };

    this.addStyle = function(id, style) {
      var token = self.getToken(id);
      if (!token.style) {
        token.style = {};
      }
      angular.extend(token.style, style);
    };

    this.removeStyle = function(id, style) {
      var tokenStyle = self.getToken(id).style;
      if (! tokenStyle) return;

      var styles = arethusaUtil.toAry(style);
      angular.forEach(styles, function(style, i) {
        delete tokenStyle[style];
      });
    };

    this.unsetStyle = function (id) {
      delete self.getToken(id).style;
    };

    this.addStatusObjects = function () {
      angular.forEach(self.tokens, addStatus);
    };

    function addStatus(token) {
      if (! token.status) {
        token.status = {};
      }
    }

    this.countTotalTokens = function () {
      self.totalTokens = Object.keys(self.tokens).length;
    };

    this.countTokens = function (conditionFn) {
      var count = 0;
      angular.forEach(self.tokens, function (token, id) {
        if (conditionFn(token)) {
          count++;
        }
      });
      return count;
    };

    this.addToken = function(token, id) {
      self.tokens[id] = token;
      addStatus(token);
      self.countTotalTokens();
      self.broadcast('tokenAdded', token);
    };

    this.removeToken = function(id) {
      var token = self.getToken(id);
      // broadcast before we actually delete, in case a plugin needs access
      // during the cleanup process
      self.broadcast('tokenRemoved', token);
      delete self.tokens[id];
      self.countTotalTokens();
    };

    // New event handling through $rootScope
    this.on = function(event, fn) {
      $rootScope.$on(event, fn);
    };

    this.broadcast = function(event, arg) {
      $rootScope.$broadcast(event, arg);
    };

    this.postInit = function () {
      self.addStatusObjects();
      self.countTotalTokens();
    };

    keyCapture.initCaptures(function(kC) {
      return {
        selections: [
          kC.create('nextToken', function() { kC.doRepeated(self.selectNextToken); }),
          kC.create('prevToken', function() { kC.doRepeated(self.selectPrevToken); }),
          kC.create('deselect', function() { self.deselectAll(); }, 'esc' )
        ]
      };
    });

    this.init = function () {
      configure();
      self.retrieveTokens();
    };
  }
]);
<|endoftext|>


<commit_before>/* @flow */
import React from 'react'
import styled, { css } from 'styled-components'
import { colors, fonts, fontSize, lineUnit, media } from 'styles/base'
import { background, color, underlineIn, underlineOut } from 'styles/links'

type Props = {}

const Wrapper = styled.div`
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0;
  right: 0;
  height: 7.2rem;
  left: 100px;
  background: ${colors.white};
  padding: 2.4rem;
  padding-left: 0;
  z-index: 300;

  ${media.mobile`
    height: 12rem;
    left: 170px;
    padding: 4.8rem;
    padding-left: 0;
  `} ${media.desktop`
    background: transparent;
    width: 200px;
    height: auto;
    left: auto;
    bottom: 0;
  `};
`

const List = styled.ul`
  text-align: right;
  font-family: ${fonts.heading};
  font-weight: 700;
  font-size: ${fontSize.small};
  line-height: ${lineUnit};
  z-index: 710;

  ${media.mobile`
    font-size: ${fontSize.normal};
  `};
`

const Link = styled.li`
  margin-left: 1rem;
  margin-bottom: 1.2rem;
  display: inline-block;

  ${media.desktop`
    display: block;
  `} a, a:link, a:visited, a:hover, a:active {
    transition: background-size 100ms ease;
    text-shadow: none;
    ${color(colors.black)} ${underlineOut};
  }

  a:hover {
    background-size: ${props => (props.blog ? '70% 1px' : '100% 1px')};
  }
`

const Source = styled.div`
  margin-top: auto;
  line-height: $lineUnit;
  color: ${colors.gray};
  text-align: right;
  font-size: ${fontSize.tiny};
  display: none;

  ${media.desktop`
    display: block;
    font-size: ${fontSize.small};
  `};
  a,
  a:link,
  a:visited,
  a:hover,
  a:active {
    transition: background-size 100ms ease;
    text-shadow: none;
    ${color(colors.gray)} ${underlineOut};
  }

  a:hover {
    text-shadow: none;
    ${underlineIn};
  }
`

const Links = () => (
  <Wrapper>
    <List>
      <Link blog={true}>
        Blog
      </Link>
      <Link>
        Work
      </Link>
      <Link>
        Scratch
      </Link>
      <Link>
        Contact
      </Link>
    </List>
    <Source>
      Source on GitHub
    </Source>
  </Wrapper>
)

export default Links
<commit_msg>Rework navigation links to reflect content organization.<commit_after>/* @flow */
import React from 'react'
import styled, { css } from 'styled-components'
import { colors, fonts, fontSize, lineUnit, media } from 'styles/base'
import { background, color, underlineIn, underlineOut } from 'styles/links'

type Props = {}

const Wrapper = styled.div`
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0;
  right: 0;
  height: 7.2rem;
  left: 100px;
  background: ${colors.white};
  padding: 2.4rem;
  padding-left: 0;
  z-index: 300;

  ${media.mobile`
    height: 12rem;
    left: 170px;
    padding: 4.8rem;
    padding-left: 0;
  `};
  ${media.desktop`
    background: transparent;
    width: 200px;
    height: auto;
    left: auto;
    bottom: 0;
  `};
`

const List = styled.ul`
  text-align: right;
  font-family: ${fonts.heading};
  font-size: ${fontSize.small};
  line-height: 1.2;
  z-index: 710;
  letter-spacing: 0.1;

  ${media.mobile`
    font-size: ${fontSize.normal};
  `};
`

const Link = styled.li`
  margin-left: 1rem;
  margin-bottom: 1.2rem;
  display: inline-block;

  ${props => {
    if (props.small) {
      return `font-weight: normal;`
    }
    return `font-weight: 700;`
  }};

  ${media.desktop`
    display: block;
  `};
  a,
  a:link,
  a:visited,
  a:hover,
  a:active {
    transition: background-size 100ms ease;
    text-shadow: none;
    ${props => {
      if (props.small) {
        return color(colors.gray)
      } else if (props.emphasis) {
        return color(colors.blue)
      }
      return color(colors.black)
    }};
    ${underlineOut};
  }

  a:hover {
    background-size: ${props => (props.blog ? '60% 1px' : '100% 1px')};
  }
`

const Source = styled.div`
  margin-top: auto;
  line-height: $lineUnit;
  color: ${colors.gray};
  text-align: right;
  font-size: ${fontSize.tiny};
  display: none;

  ${media.desktop`
    display: block;
    font-size: ${fontSize.small};
  `};
  a,
  a:link,
  a:visited,
  a:hover,
  a:active {
    transition: background-size 100ms ease;
    text-shadow: none;
    ${color(colors.gray)} ${underlineOut};
  }

  a:hover {
    text-shadow: none;
    ${underlineIn};
  }
`

const Links = () => (
  <Wrapper>
    <List>
      <Link>
        Work
      </Link>
      <Link blog={true}>
        Blog
      </Link>
      <Link>
        About
      </Link>
      <Link emphasis>
        Contact
      </Link>
      <Link small>
        Lists
      </Link>
    </List>
    <Source>
      Source on GitHub
    </Source>
  </Wrapper>
)

export default Links
<|endoftext|>


<commit_before>/*
 * Metamaps.Debug.js.erb
 *
 * Dependencies: none!
 */

Metamaps.Debug = function () {
  console.debug(Metamaps)
  console.debug(`Metamaps Version: ${Metamaps.VERSION}`)
}
Metamaps.debug = function () {
  Metamaps.Debug()
}
<commit_msg>can't use ` with uglify<commit_after>/*
 * Metamaps.Debug.js.erb
 *
 * Dependencies: none!
 */

Metamaps.Debug = function () {
  console.debug(Metamaps)
  console.debug('Metamaps Version: ' + Metamaps.VERSION)
}
Metamaps.debug = function () {
  Metamaps.Debug()
}
<|endoftext|>


<commit_before>(function(root, factory) {
  'use strict';

  if (typeof module !== 'undefined' && module.exports) {
    var d3 = require('d3');
    window.d3 = d3;
    module.exports = factory(d3);
  } else {
    root.ClimateChart = factory(root.d3);
  }
}(this, function(d3) {
  'use strict';

  ///////////////////////
  // private functions //
  ///////////////////////

  function _parseData(data, o) {
    data.forEach(function(d) {
      d[o.xAccessor] = parseFloat(d[o.xAccessor]);
      d[o.yAccessor] = parseFloat(d[o.yAccessor]);
      d[o.sizeAccessor] = parseFloat(d[o.sizeAccessor]);
    });

    data = data.filter(function(d) {
      return !isNaN(d[o.xAccessor]) && !isNaN(d[o.yAccessor]) && !isNaN(d[o.sizeAccessor]);
    });

    return data;
  }

  function _merge() {
    var obj = {};
    var key;

    for (var i = 0; i < arguments.length; i++) {
      for (key in arguments[i]) {
        if (arguments[i].hasOwnProperty(key)) {
          obj[key] = arguments[i][key];
        }
      }
    }

    return obj;
  }

  /////////////////////
  // tooltip factory //
  /////////////////////

  var Tooltip = function() {

    var tooltip, top, left, ttHead, ttBody, chartWidth;

    function create(parent, cw) {
      chartWidth = cw;
      tooltip = parent.append('div').classed('tooltip', true);
      ttHead = tooltip.append('div').classed('tool-head', true);
      ttBody = tooltip.append('div').classed('tool-body', true);
      return this;
    }

    function update(data) {
      ttHead.text(data.countryname_en);
      ttBody.text(data.co2_t_pc_2012);
    }

    function updatePosition(coords) {
      top = coords[1] - 50;
      left = coords[0] > (chartWidth / 2) ? coords[0] - 190 : coords[0] + 10;

      tooltip.style({
        top: top + 'px',
        left: left + 'px'
      });
    }

    function hide() {
      tooltip.style('display', 'none');
    }

    function show() {
      tooltip.style('display', 'block');
    }

    return {
      create: create,
      update: update,
      updatePosition: updatePosition,
      show: show,
      hide: hide
    };
  };

  ///////////////////
  // chart factory //
  ///////////////////

  return function(_selector, _options) {

    if (typeof _selector === 'undefined') {
        throw new Error('You need to specify a selector.');
    }

    if (typeof _options === 'undefined' || !_options.path) {
        throw new Error('You need to specify options: path');
    }

    var optionsDefault = {
        xAccessor: 'gdp_2014',
        yAccessor: 'co2_t_pc_2012',
        sizeAccessor: 'population_2014',
        xAxisLabel: 'gdp 2014',
        yAxisLabel: 'unemployment 2013',
        colors: {
          A: '#005fcc',
          B: '#5c0000',
          C: '#009300',
          D: '#ea8500'
        },
        isLogScale: true,
        pointRange: [10, 1000],
        xTicks: 5,
        yTicks: 5,
        height: 400,
        lang: 'de',
        interactive: true,
        showLegend: false,
        margin: {
          top: 50,
          right: 50,
          bottom: 50,
          left: 50
        },
        filter: null,
        minRadius: 4,
        maxRadius: 15,
        maxWidth: 960,
        aspectRatio: .7,
        transitionDuration: 500,
        locale: 'en'
    };

    var svg,
        x,
        y,
        r,
        xAxis,
        yAxis,
        xExtent,
        yExtent,
        rExtent,
        parent,
        data,
        options,
        selector,
        bubbles,
        margin,
        width,
        height,
        tooltip = new Tooltip();

    function onMouseEnter(d) {
      if(d.node.datum().disabled) {
        return false;
      }
      tooltip.update(d.node.datum());
      tooltip.show();
      d.node.classed('active', true);
    }

    function onMouseMove() {
      tooltip.updatePosition(d3.mouse(parent.node()));
    }

    function onMouseLeave(d) {
      d.node.classed('active', false);
      tooltip.hide();
    }

    function initScales() {
      xExtent = d3.extent(data, function(d) { return d[options.xAccessor]; });
      yExtent = d3.extent(data, function(d) { return d[options.yAccessor]; });
      rExtent = d3.extent(data, function(d) { return d[options.sizeAccessor]; });

      if(options.isLogScale) {
        x = d3.scale.log().domain(xExtent).range([0, width]);
      }
      else {
        x = d3.scale.linear().domain(xExtent).range([0, width]);
      }

      y = d3.scale.linear().domain([-.5, yExtent[1]]).range([height, 0]);
      r = d3.scale.sqrt().domain(rExtent).range([options.minRadius, options.maxRadius]);
    }

    function initAxis() {
      xAxis = d3.svg.axis()
        .orient('bottom')
        .scale(x)
        .ticks(4, function(d) {
          return new Intl.NumberFormat(options.locale).format(d);
        });

      yAxis = d3.svg.axis().orient('left').scale(y);
    }

    function updateDimensions(winWidth) {
      width = winWidth < options.maxWidth ? winWidth : options.maxWidth;
      width = width - margin.right - margin.left;
      height = width * options.aspectRatio;
    }

    function labelPositionLeft(d) {
      var posX = x(d[options.xAccessor]);
      var factor = posX > options.maxWidth / 2 ? -1 : 1;
      posX += (r(d[options.sizeAccessor]) + 5) * factor;
      posX += margin.left;
      posX += 'px';
      return posX;
    }

    function labelPositionTop(d) {
      return (y(d[options.yAccessor]) - 6 + margin.top) + 'px';
    }

    function createBubbles() {
      bubbles = svg.selectAll('circle.bubble')
        .data(data)
        .enter()
        .append('circle')
        .classed('bubble', true)
        .attr('cx', function(d) { return x(d[options.xAccessor]); })
        .attr('cy', function(d) { return y(d[options.yAccessor]); })
        .attr('r', function(d) { return r(d[options.sizeAccessor]); })
        .attr('fill', function(d) { return options.colors[d.fraction]; })
        .attr('stroke', function(d) { return options.colors[d.fraction]; });
    }

    function createLabels() {
      this.selectAll('div.label')
        .data(data.filter(function(d) {
          return d.labeled !== '';
        }))
        .enter()
        .append('div')
        .classed('label', true)
        .classed('left', function(d) { return x(d[options.xAccessor]) > (width / 2); })
        .style('left', labelPositionLeft)
        .style('top', labelPositionTop)
        .style('display', 'block')
        .html(function(d) { return d.label_html; });
    }

    function createVoronoi() {
      var voro = d3.geom.voronoi()
        .clipExtent([[0, 0], [width, height]])
        .x(function(d) { return x(d[options.xAccessor]); })
        .y(function(d) { return y(d[options.yAccessor]); });

      this.select('.voronoi-overlay').remove();

      this.append('g')
        .classed('voronoi-overlay', true)
        .selectAll('path.voro')
        .data(voro(data))
        .enter()
        .append('path')
        .classed('voro', true)
        .attr('d', function(d) { return 'M' + d.join(',') + 'Z'; })
        .on('mouseenter', onMouseEnter)
        .on('mouseleave', onMouseLeave)
        .each(function(d) {
          d3.select(this)
            .datum()
            .node = bubbles.filter(function(b) {
              return b.countryname_en === d.point.countryname_en;
            });
        })
        .on('mousemove', onMouseMove);

    }

    function createAxis() {
      if(svg.selectAll('.climate-chart .x.axis')[0].length > 0) {
        this.selectAll('.x.axis')
          .transition()
          .duration(options.transitionDuration)
          .call(xAxis);

        return;
      }

      svg.selectAll('.climate-chart .y.axis').remove();

      this.append('g')
        .classed('y axis', true)
        .call(yAxis);

      this.append('g')
        .classed('x axis', true)
        .attr('transform', 'translate(0,' + height + ')')
        .call(xAxis);
    }
    function renderChart() {
      margin = options.margin;

      updateDimensions(window.innerWidth);
      parent = d3.select(selector);
      parent.node().innerHTML = '';

      parent = parent
        .append('div')
        .classed('climate-chart-wrapper', true);

      tooltip.create(parent, width);

      svg = parent
        .append('svg')
        .classed('climate-chart', true)
        .attr('width', width + margin.right + margin.left)
        .attr('height', height + margin.top + margin.bottom)
        .append('g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

      initScales();
      initAxis();

      svg.call(createAxis);
      svg.call(createBubbles);
      svg.call(createVoronoi);

      parent.call(createLabels);
    }

    function bindEvents() {
      window.addEventListener('resize', function() {
        renderChart(_selector, options, data);
      });
    }

    function updateChart(isGroupFocus) {
      if(!isGroupFocus) {
        initScales();
      }

      svg.selectAll('circle.bubble')
        .transition()
        .duration(options.transitionDuration)
        .attr('cx', function(d) { return x(d[options.xAccessor]); })
        .attr('cy', function(d) { return y(d[options.yAccessor]); })
        .attr('r', function(d) { return r(d[options.sizeAccessor]); });

      svg.selectAll('text.label')
        .transition()
        .duration(options.transitionDuration)
        .attr('x', function(d) { return x(d[options.xAccessor]) - r(d[options.sizeAccessor]) - 2; })
        .attr('y', function(d) { return y(d[options.yAccessor]); });

      svg.call(createVoronoi);
    }

    function focusGroup(groupId) {
      //filter data
      var filteredData = data.filter(function(d) {
        return d.fraction === groupId;
      });

      // calculate new x-extent
      var nExtent = d3.extent(filteredData, function(d) {
        return d[options.xAccessor];
      });

      //set new domain for x-axis
      x.domain(nExtent);

      //animate x-axis to new extent
      svg.selectAll('.x.axis')
        .transition()
        .duration(options.transitionDuration)
        .call(xAxis);

      //highlight all circles in group
      svg.selectAll('circle.bubble')
        .style('opacity', .2)
        .each(function(d) { d.disabled = true; })
        .filter(function(d) { return d.fraction === groupId; })
        .style('opacity', 1)
        .each(function(d) { d.disabled = false; });

      parent.selectAll('div.label')
        .style('display', 'none')
        .filter(function(d) { return d.fraction === groupId; })
        .transition()
        .duration(options.transitionDuration)
        .style('left', labelPositionLeft)
        .style('display', 'block');

      updateChart(true);
      svg.call(createVoronoi);
    }

    function reset() {
      updateChart();
      xAxis.scale(x);

      svg.call(createAxis);
      svg.call(createVoronoi);

      parent.selectAll('div.label')
        .style('display', 'block')
        .transition()
        .duration(options.transitionDuration)
        .style('left', labelPositionLeft);

      svg.selectAll('circle.bubble')
        .style('opacity', 1)
        .each(function(d) { d.disabled = false; });
    }

    function update(newOpts) {
      options = _merge(options, newOpts);
      updateChart();
    }

    _options = _merge(optionsDefault, _options);

    d3.csv(_options.path, function(err, csvData) {
      if(err) {
        throw new Error('Data not found.');
      }
      data = _parseData(csvData, _options);
      options = _options;
      selector = _selector;
      renderChart();
      bindEvents();
    });

    /////////////
    // exports //
    /////////////

    return {
      update: update,
      focusGroup: focusGroup,
      reset: reset
    };
  };

}));
<commit_msg>Add axis descriptions.<commit_after>(function(root, factory) {
  'use strict';

  if (typeof module !== 'undefined' && module.exports) {
    var d3 = require('d3');
    window.d3 = d3;
    module.exports = factory(d3);
  } else {
    root.ClimateChart = factory(root.d3);
  }
}(this, function(d3) {
  'use strict';

  ///////////////////////
  // private functions //
  ///////////////////////

  function _parseData(data, o) {
    data.forEach(function(d) {
      d[o.xAccessor] = parseFloat(d[o.xAccessor]);
      d[o.yAccessor] = parseFloat(d[o.yAccessor]);
      d[o.sizeAccessor] = parseFloat(d[o.sizeAccessor]);
    });

    data = data.filter(function(d) {
      return !isNaN(d[o.xAccessor]) && !isNaN(d[o.yAccessor]) && !isNaN(d[o.sizeAccessor]);
    });

    return data;
  }

  function _merge() {
    var obj = {};
    var key;

    for (var i = 0; i < arguments.length; i++) {
      for (key in arguments[i]) {
        if (arguments[i].hasOwnProperty(key)) {
          obj[key] = arguments[i][key];
        }
      }
    }

    return obj;
  }

  /////////////////////
  // tooltip factory //
  /////////////////////

  var Tooltip = function() {

    var tooltip, top, left, ttHead, ttBody, chartWidth;

    function create(parent, cw) {
      chartWidth = cw;
      tooltip = parent.append('div').classed('tooltip', true);
      ttHead = tooltip.append('div').classed('tool-head', true);
      ttBody = tooltip.append('div').classed('tool-body', true);
      return this;
    }

    function update(data) {
      ttHead.text(data.countryname_en);
      ttBody.text(data.co2_t_pc_2012);
    }

    function updatePosition(coords) {
      top = coords[1] - 50;
      left = coords[0] > (chartWidth / 2) ? coords[0] - 190 : coords[0] + 10;

      tooltip.style({
        top: top + 'px',
        left: left + 'px'
      });
    }

    function hide() {
      tooltip.style('display', 'none');
    }

    function show() {
      tooltip.style('display', 'block');
    }

    return {
      create: create,
      update: update,
      updatePosition: updatePosition,
      show: show,
      hide: hide
    };
  };

  ///////////////////
  // chart factory //
  ///////////////////

  return function(_selector, _options) {

    if (typeof _selector === 'undefined') {
        throw new Error('You need to specify a selector.');
    }

    if (typeof _options === 'undefined' || !_options.path) {
        throw new Error('You need to specify options: path');
    }

    var optionsDefault = {
        xAccessor: 'gdp_2014',
        yAccessor: 'co2_t_pc_2012',
        sizeAccessor: 'population_2014',
        xAxisLabel: 'gdp 2014',
        yAxisLabel: 'unemployment 2013',
        colors: {
          A: '#005fcc',
          B: '#5c0000',
          C: '#009300',
          D: '#ea8500'
        },
        isLogScale: true,
        pointRange: [10, 1000],
        xTicks: 5,
        yTicks: 5,
        height: 400,
        lang: 'de',
        interactive: true,
        showLegend: false,
        margin: {
          top: 50,
          right: 50,
          bottom: 50,
          left: 50
        },
        filter: null,
        minRadius: 4,
        maxRadius: 15,
        maxWidth: 960,
        aspectRatio: .7,
        transitionDuration: 500,
        locale: 'en'
    };

    var svg,
        x,
        y,
        r,
        xAxis,
        yAxis,
        xExtent,
        yExtent,
        rExtent,
        parent,
        data,
        options,
        selector,
        bubbles,
        margin,
        width,
        height,
        tooltip = new Tooltip();

    function onMouseEnter(d) {
      if(d.node.datum().disabled) {
        return false;
      }
      tooltip.update(d.node.datum());
      tooltip.show();
      d.node.classed('active', true);
    }

    function onMouseMove() {
      tooltip.updatePosition(d3.mouse(parent.node()));
    }

    function onMouseLeave(d) {
      d.node.classed('active', false);
      tooltip.hide();
    }

    function initScales() {
      xExtent = d3.extent(data, function(d) { return d[options.xAccessor]; });
      yExtent = d3.extent(data, function(d) { return d[options.yAccessor]; });
      rExtent = d3.extent(data, function(d) { return d[options.sizeAccessor]; });

      if(options.isLogScale) {
        x = d3.scale.log().domain(xExtent).range([0, width]);
      }
      else {
        x = d3.scale.linear().domain(xExtent).range([0, width]);
      }

      y = d3.scale.linear().domain([-.5, yExtent[1]]).range([height, 0]);
      r = d3.scale.sqrt().domain(rExtent).range([options.minRadius, options.maxRadius]);
    }

    function initAxis() {
      xAxis = d3.svg.axis()
        .orient('bottom')
        .scale(x)
        .ticks(4, function(d) {
          return new Intl.NumberFormat(options.locale).format(d);
        });

      yAxis = d3.svg.axis().orient('left').scale(y);
    }

    function updateDimensions(winWidth) {
      width = winWidth < options.maxWidth ? winWidth : options.maxWidth;
      width = width - margin.right - margin.left;
      height = width * options.aspectRatio;
    }

    function labelPositionLeft(d) {
      var posX = x(d[options.xAccessor]);
      var factor = posX > options.maxWidth / 2 ? -1 : 1;
      posX += (r(d[options.sizeAccessor]) + 5) * factor;
      posX += margin.left;
      posX += 'px';
      return posX;
    }

    function labelPositionTop(d) {
      return (y(d[options.yAccessor]) - 6 + margin.top) + 'px';
    }

    function createBubbles() {
      bubbles = svg.selectAll('circle.bubble')
        .data(data)
        .enter()
        .append('circle')
        .classed('bubble', true)
        .attr('cx', function(d) { return x(d[options.xAccessor]); })
        .attr('cy', function(d) { return y(d[options.yAccessor]); })
        .attr('r', function(d) { return r(d[options.sizeAccessor]); })
        .attr('fill', function(d) { return options.colors[d.fraction]; })
        .attr('stroke', function(d) { return options.colors[d.fraction]; });
    }

    function createLabels() {
      this.selectAll('div.label')
        .data(data.filter(function(d) {
          return d.labeled !== '';
        }))
        .enter()
        .append('div')
        .classed('label', true)
        .classed('left', function(d) { return x(d[options.xAccessor]) > (width / 2); })
        .style('left', labelPositionLeft)
        .style('top', labelPositionTop)
        .style('display', 'block')
        .html(function(d) { return d.label_html; });
    }

    function createVoronoi() {
      var voro = d3.geom.voronoi()
        .clipExtent([[0, 0], [width, height]])
        .x(function(d) { return x(d[options.xAccessor]); })
        .y(function(d) { return y(d[options.yAccessor]); });

      this.select('.voronoi-overlay').remove();

      this.append('g')
        .classed('voronoi-overlay', true)
        .selectAll('path.voro')
        .data(voro(data))
        .enter()
        .append('path')
        .classed('voro', true)
        .attr('d', function(d) { return 'M' + d.join(',') + 'Z'; })
        .on('mouseenter', onMouseEnter)
        .on('mouseleave', onMouseLeave)
        .each(function(d) {
          d3.select(this)
            .datum()
            .node = bubbles.filter(function(b) {
              return b.countryname_en === d.point.countryname_en;
            });
        })
        .on('mousemove', onMouseMove);

    }

    function createAxis() {
      if(svg.selectAll('.climate-chart .x.axis')[0].length > 0) {
        this.selectAll('.x.axis')
          .transition()
          .duration(options.transitionDuration)
          .call(xAxis);

        return;
      }

      svg.selectAll('.climate-chart .y.axis').remove();

      this.append('g')
        .classed('y axis', true)
        .call(yAxis);

      this.append('g')
        .classed('x axis', true)
        .attr('transform', 'translate(0,' + height + ')')
        .call(xAxis);
    }

    function createAxisDescription() {
      svg.append('text')
        .attr('text-anchor', 'end')
        .attr('x', width)
        .attr('y', height + 40)
        .text(options.xAxisDescription || options.xAccessor);

      svg.append('text')
        .attr('text-anchor', 'end')
        .attr('y', 10)
        .attr('dy', '.75em')
        .attr('transform', 'rotate(-90)')
        .text(options.yAxisDescription || options.yAccessor);
    }

    function renderChart() {
      margin = options.margin;

      updateDimensions(window.innerWidth);
      parent = d3.select(selector);
      parent.node().innerHTML = '';

      parent = parent
        .append('div')
        .classed('climate-chart-wrapper', true);

      tooltip.create(parent, width);

      svg = parent
        .append('svg')
        .classed('climate-chart', true)
        .attr('width', width + margin.right + margin.left)
        .attr('height', height + margin.top + margin.bottom)
        .append('g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

      initScales();
      initAxis();

      svg.call(createAxis);
      svg.call(createAxisDescription);
      svg.call(createBubbles);
      svg.call(createVoronoi);

      parent.call(createLabels);
    }

    function bindEvents() {
      window.addEventListener('resize', function() {
        renderChart(_selector, options, data);
      });
    }

    function updateChart(isGroupFocus) {
      if(!isGroupFocus) {
        initScales();
      }

      svg.selectAll('circle.bubble')
        .transition()
        .duration(options.transitionDuration)
        .attr('cx', function(d) { return x(d[options.xAccessor]); })
        .attr('cy', function(d) { return y(d[options.yAccessor]); })
        .attr('r', function(d) { return r(d[options.sizeAccessor]); });

      svg.selectAll('text.label')
        .transition()
        .duration(options.transitionDuration)
        .attr('x', function(d) { return x(d[options.xAccessor]) - r(d[options.sizeAccessor]) - 2; })
        .attr('y', function(d) { return y(d[options.yAccessor]); });

      svg.call(createVoronoi);
    }

    function focusGroup(groupId) {
      //filter data
      var filteredData = data.filter(function(d) {
        return d.fraction === groupId;
      });

      // calculate new x-extent
      var nExtent = d3.extent(filteredData, function(d) {
        return d[options.xAccessor];
      });

      //set new domain for x-axis
      x.domain(nExtent);

      //animate x-axis to new extent
      svg.selectAll('.x.axis')
        .transition()
        .duration(options.transitionDuration)
        .call(xAxis);

      //highlight all circles in group
      svg.selectAll('circle.bubble')
        .style('opacity', .2)
        .each(function(d) { d.disabled = true; })
        .filter(function(d) { return d.fraction === groupId; })
        .style('opacity', 1)
        .each(function(d) { d.disabled = false; });

      parent.selectAll('div.label')
        .style('display', 'none')
        .filter(function(d) { return d.fraction === groupId; })
        .transition()
        .duration(options.transitionDuration)
        .style('left', labelPositionLeft)
        .style('display', 'block');

      updateChart(true);
      svg.call(createVoronoi);
    }

    function reset() {
      updateChart();
      xAxis.scale(x);

      svg.call(createAxis);
      svg.call(createVoronoi);

      parent.selectAll('div.label')
        .style('display', 'block')
        .transition()
        .duration(options.transitionDuration)
        .style('left', labelPositionLeft);

      svg.selectAll('circle.bubble')
        .style('opacity', 1)
        .each(function(d) { d.disabled = false; });
    }

    function update(newOpts) {
      options = _merge(options, newOpts);
      updateChart();
    }

    _options = _merge(optionsDefault, _options);

    d3.csv(_options.path, function(err, csvData) {
      if(err) {
        throw new Error('Data not found.');
      }
      data = _parseData(csvData, _options);
      options = _options;
      selector = _selector;
      renderChart();
      bindEvents();
    });

    /////////////
    // exports //
    /////////////

    return {
      update: update,
      focusGroup: focusGroup,
      reset: reset
    };
  };

}));
<|endoftext|>


<commit_before>/**
 *
 * @revision    $Id: user-agent.js 2012-03-24 16:21:10 Aleksey $
 * @created     2012-03-24 16:21:10
 * @category    Express Helpers
 * @package     express-useragent
 * @version     0.0.1
 * @copyright   Copyright (c) 2009-2012 - All rights reserved.
 * @license     MIT License
 * @author      Alexey Gordeyev IK <aleksej@gordejev.lv>
 * @link        http://www.gordejev.lv
 *
 */

var UserAgent = {
    version : '0.0.1',
    _Versions : {
        Firefox: /firefox\/([\d\w\.\-]+)/i,
        IE: /msie\s([\d\.]+[\d])/i,
        Chrome: /chrome\/([\d\w\.\-]+)/i,
        Safari: /version\/([\d\w\.\-]+)/i,
        Ps3: /([\d\w\.\-]+)\)\s*$/i,
        Psp: /([\d\w\.\-]+)\)?\s*$/i
    },
    _Browsers : {
        Konqueror: /konqueror/i,
        Chrome: /chrome/i,
        Safari: /safari/i,
        IE: /msie/i,
        Opera: /opera/i,
        PS3: /playstation 3/i,
        PSP: /playstation portable/i,
        Firefox: /firefox/i
    },
    _OS : {
        WindowsVista: /windows nt 6\.0/i,
        Windows7: /windows nt 6\.\d+/i,
        Windows2003: /windows nt 5\.2/i,
        WindowsXP: /windows nt 5\.1/i,
        Windows2000: /windows nt 5\.0/i,
        OSX: /os x (\d+)[._](\d+)/i,
        Linux: /linux/i,
        Wii: /wii/i,
        PS3: /playstation 3/i,
        PSP: /playstation portable/i,
        iPad: /\(iPad.*os (\d+)[._](\d+)/i,
        iPhone: /\(iPhone.*os (\d+)[._](\d+)/i
    },
    _Platform : {
        Windows: /windows/i,
        Mac: /macintosh/i,
        Linux: /linux/i,
        Wii: /wii/i,
        Playstation: /playstation/i,
        iPad: /ipad/i,
        iPod: /ipod/i,
        iPhone: /iphone/i,
        Android: /android/i,
        Blackberry: /blackberry/i
    },
    Agent : {
        isMobile : false,
        isiPad : false,
        isiPod : false,
        isiPhone : false,
        isAndroid : false,
        isBlackberry : false,
        isOpera : false,
        isIE : false,
        isSafari : false,
        isFirefox : false,
        isWebkit : false,
        isChrome : false,
        isKonqueror : false,
        isDesktop : false,
        isWindows : false,
        isLinux : false,
        isMac : false,
        Browser : 'unknown',
        Version : 'unknown',
        OS : 'unknown',
        Platform : 'unknown',
        source:''
    }
};

UserAgent.getBrowser = function(string) {
    switch (true) {
        case this._Browsers.Konqueror.test(string):
            this.Agent.isKonqueror = true;
            return 'Konqueror';
        case this._Browsers.Chrome.test(string):
            this.Agent.isChrome = true;
            return 'Chrome';
        case this._Browsers.Safari.test(string):
            this.Agent.isSafari = true;
            return 'Safari';
        case this._Browsers.IE.test(string):
            this.Agent.isIE = true;
            return 'IE';
        case this._Browsers.Opera.test(string):
            this.Agent.isOpera = true;
            return 'Opera';
        case this._Browsers.PS3.test(string):
            return 'ps3';
        case this._Browsers.PSP.test(string):
            return 'psp';
        case this._Browsers.Firefox.test(string):
            this.Agent.isFirefox = true;
            return 'Firefox';
        default:
            return 'unknown';
    }
};

UserAgent.getBrowserVersion = function(string) {
    var regex;

    switch (this.Agent.Browser) {
        case 'Chrome':
            if (this._Versions.Chrome.test(string)) {
                return RegExp.$1;
            }
            break;
        case 'Safari':
            if (this._Versions.Safari.test(string)) {
                return RegExp.$1;
            }
            break;
        case 'Firefox':
            if (this._Versions.Firefox.test(string)) {
                return RegExp.$1;
            }
            break;
        case 'IE':
            if (this._Versions.IE.test(string)) {
                return RegExp.$1;
            }
            break;
        case 'ps3':
            if (this._Versions.Ps3.test(string)) {
                return RegExp.$1;
            }
            break;
        case 'psp':
            if (this._Versions.Psp.test(string)) {
                return RegExp.$1;
            }
            break;
        default:
            regex = /#{name}[\/ ]([\d\w\.\-]+)/i;
            if (regex.test(string)) {
                return RegExp.$1;
            }
    }
};

UserAgent.getOS = function(string) {
    switch (true) {
        case this._OS.WindowsVista.test(string):
            this.Agent.isWindows = true;
            this.Agent.isDesktop = true;
            return 'Windows Vista';
        case this._OS.Windows7.test(string):
            this.Agent.isWindows = true;
            this.Agent.isDesktop = true;
            return 'Windows 7';
        case this._OS.Windows2003.test(string):
            this.Agent.isWindows = true;
            return 'Windows 2003';
        case this._OS.WindowsXP.test(string):
            this.Agent.isWindows = true;
            this.Agent.isDesktop = true;
            return 'Windows XP';
        case this._OS.Windows2000.test(string):
            this.Agent.isWindows = true;
            return 'Windows 2000';
        case this._OS.Linux.test(string):
            this.Agent.isLinux = true;
            this.Agent.isDesktop = true;
            return 'Linux';
        case this._OS.Wii.test(string):
            return 'Wii';
        case this._OS.PS3.test(string):
            return 'Playstation';
        case this._OS.PSP.test(string):
            return 'Playstation';
        case this._OS.OSX.test(string):
            this.Agent.isMac = true;
            return string.match(this._OS.OSX)[0].replace('_', '.');
        case this._OS.iPad.test(string):
            this.Agent.isiPad = true;
            return string.match(this._OS.iPad)[0].replace('_', '.');
        case this._OS.iPhone.test(string):
            this.Agent.isiPhone = true;
            return string.match(this._OS.iPhone)[0].replace('_', '.');
        default:
            return 'unknown';
    }
};

UserAgent.getPlatform = function(string) {
    switch (true) {
        case this._Platform.Windows.test(string):
            return "Microsoft Windows";
        case this._Platform.Mac.test(string):
            return "Apple Mac";
        case this._Platform.Android.test(string):
            return "Android";
        case this._Platform.Blackberry.test(string):
            return "Blackberry";
        case this._Platform.Linux.test(string):
            return "Linux";
        case this._Platform.Wii.test(string):
            return "Wii";
        case this._Platform.Playstation.test(string):
            return "Playstation";
        case this._Platform.iPad.test(string):
            return "iPad";
        case this._Platform.iPod.test(string):
            return "iPod";
        case this._Platform.iPhone.test(string):
            return "iPhone";
        default:
            return 'unknown';
    }
};

UserAgent.parse = function parse(source) {
    this.Agent.source = source.replace(/^\s*/, '').replace(/\s*$/, '');
    this.Agent.Browser = this.getBrowser(this.Agent.source);
    this.Agent.Version = this.getBrowserVersion(this.Agent.source);
    this.Agent.OS = this.getOS(this.Agent.source);
    this.Agent.Platform = this.getPlatform(this.Agent.source);

    return this.Agent;
};

UserAgent.express = function() {
    return function(req, res, next) {
        var source = req.headers['user-agent'],
        ua = UserAgent;
        ua.Agent.source = source.replace(/^\s*/, '').replace(/\s*$/, '');
        ua.Agent.Browser = ua.getBrowser(ua.Agent.source);
        ua.Agent.Version = ua.getBrowserVersion(ua.Agent.source);
        ua.Agent.OS = ua.getOS(ua.Agent.source);
        ua.Agent.Platform = ua.getPlatform(ua.Agent.source);
        req.useragent = ua.Agent;
        res.local("useragent", ua.Agent);
        next();
    }
};

module.exports = UserAgent;

<commit_msg>Update tests<commit_after>/**
 *
 * @revision    $Id: user-agent.js 2012-03-24 16:21:10 Aleksey $
 * @created     2011-12-10 17:19:10
 * @category    Express Helpers
 * @package     express-useragent
 * @version     0.0.1
 * @copyright   Copyright (c) 2009-2011 - All rights reserved.
 * @license     MIT License
 * @author      Alexey Gordeyev IK <aleksej@gordejev.lv>
 * @link        http://www.gordejev.lv
 *
 */

var UserAgent = {
    version : '0.0.1',
    _Versions : {
        Firefox: /firefox\/([\d\w\.\-]+)/i,
        IE: /msie\s([\d\.]+[\d])/i,
        Chrome: /chrome\/([\d\w\.\-]+)/i,
        Safari: /version\/([\d\w\.\-]+)/i,
        Ps3: /([\d\w\.\-]+)\)\s*$/i,
        Psp: /([\d\w\.\-]+)\)?\s*$/i
    },
    _Browsers : {
        Konqueror: /konqueror/i,
        Chrome: /chrome/i,
        Safari: /safari/i,
        IE: /msie/i,
        Opera: /opera/i,
        PS3: /playstation 3/i,
        PSP: /playstation portable/i,
        Firefox: /firefox/i
    },
    _OS : {
        WindowsVista: /windows nt 6\.0/i,
        Windows7: /windows nt 6\.\d+/i,
        Windows2003: /windows nt 5\.2/i,
        WindowsXP: /windows nt 5\.1/i,
        Windows2000: /windows nt 5\.0/i,
        OSX: /os x (\d+)[._](\d+)/i,
        Linux: /linux/i,
        Wii: /wii/i,
        PS3: /playstation 3/i,
        PSP: /playstation portable/i,
        iPad: /\(iPad.*os (\d+)[._](\d+)/i,
        iPhone: /\(iPhone.*os (\d+)[._](\d+)/i
    },
    _Platform : {
        Windows: /windows/i,
        Mac: /macintosh/i,
        Linux: /linux/i,
        Wii: /wii/i,
        Playstation: /playstation/i,
        iPad: /ipad/i,
        iPod: /ipod/i,
        iPhone: /iphone/i,
        Android: /android/i,
        Blackberry: /blackberry/i
    },
    Agent : {
        isMobile : false,
        isiPad : false,
        isiPod : false,
        isiPhone : false,
        isAndroid : false,
        isBlackberry : false,
        isOpera : false,
        isIE : false,
        isSafari : false,
        isFirefox : false,
        isWebkit : false,
        isChrome : false,
        isKonqueror : false,
        isDesktop : false,
        isWindows : false,
        isLinux : false,
        isMac : false,
        Browser : 'unknown',
        Version : 'unknown',
        OS : 'unknown',
        Platform : 'unknown',
        source:''
    }
};

UserAgent.getBrowser = function(string) {
    switch (true) {
        case this._Browsers.Konqueror.test(string):
            this.Agent.isKonqueror = true;
            return 'Konqueror';
        case this._Browsers.Chrome.test(string):
            this.Agent.isChrome = true;
            return 'Chrome';
        case this._Browsers.Safari.test(string):
            this.Agent.isSafari = true;
            return 'Safari';
        case this._Browsers.IE.test(string):
            this.Agent.isIE = true;
            return 'IE';
        case this._Browsers.Opera.test(string):
            this.Agent.isOpera = true;
            return 'Opera';
        case this._Browsers.PS3.test(string):
            return 'ps3';
        case this._Browsers.PSP.test(string):
            return 'psp';
        case this._Browsers.Firefox.test(string):
            this.Agent.isFirefox = true;
            return 'Firefox';
        default:
            return 'unknown';
    }
};

UserAgent.getBrowserVersion = function(string) {
    var regex;

    switch (this.Agent.Browser) {
        case 'Chrome':
            if (this._Versions.Chrome.test(string)) {
                return RegExp.$1;
            }
            break;
        case 'Safari':
            if (this._Versions.Safari.test(string)) {
                return RegExp.$1;
            }
            break;
        case 'Firefox':
            if (this._Versions.Firefox.test(string)) {
                return RegExp.$1;
            }
            break;
        case 'IE':
            if (this._Versions.IE.test(string)) {
                return RegExp.$1;
            }
            break;
        case 'ps3':
            if (this._Versions.Ps3.test(string)) {
                return RegExp.$1;
            }
            break;
        case 'psp':
            if (this._Versions.Psp.test(string)) {
                return RegExp.$1;
            }
            break;
        default:
            regex = /#{name}[\/ ]([\d\w\.\-]+)/i;
            if (regex.test(string)) {
                return RegExp.$1;
            }
    }
};

UserAgent.getOS = function(string) {
    switch (true) {
        case this._OS.WindowsVista.test(string):
            this.Agent.isWindows = true;
            this.Agent.isDesktop = true;
            return 'Windows Vista';
        case this._OS.Windows7.test(string):
            this.Agent.isWindows = true;
            this.Agent.isDesktop = true;
            return 'Windows 7';
        case this._OS.Windows2003.test(string):
            this.Agent.isWindows = true;
            return 'Windows 2003';
        case this._OS.WindowsXP.test(string):
            this.Agent.isWindows = true;
            this.Agent.isDesktop = true;
            return 'Windows XP';
        case this._OS.Windows2000.test(string):
            this.Agent.isWindows = true;
            return 'Windows 2000';
        case this._OS.Linux.test(string):
            this.Agent.isLinux = true;
            this.Agent.isDesktop = true;
            return 'Linux';
        case this._OS.Wii.test(string):
            return 'Wii';
        case this._OS.PS3.test(string):
            return 'Playstation';
        case this._OS.PSP.test(string):
            return 'Playstation';
        case this._OS.OSX.test(string):
            this.Agent.isMac = true;
            return string.match(this._OS.OSX)[0].replace('_', '.');
        case this._OS.iPad.test(string):
            this.Agent.isiPad = true;
            return string.match(this._OS.iPad)[0].replace('_', '.');
        case this._OS.iPhone.test(string):
            this.Agent.isiPhone = true;
            return string.match(this._OS.iPhone)[0].replace('_', '.');
        default:
            return 'unknown';
    }
};

UserAgent.getPlatform = function(string) {
    switch (true) {
        case this._Platform.Windows.test(string):
            return "Microsoft Windows";
        case this._Platform.Mac.test(string):
            return "Apple Mac";
        case this._Platform.Android.test(string):
            return "Android";
        case this._Platform.Blackberry.test(string):
            return "Blackberry";
        case this._Platform.Linux.test(string):
            return "Linux";
        case this._Platform.Wii.test(string):
            return "Wii";
        case this._Platform.Playstation.test(string):
            return "Playstation";
        case this._Platform.iPad.test(string):
            return "iPad";
        case this._Platform.iPod.test(string):
            return "iPod";
        case this._Platform.iPhone.test(string):
            return "iPhone";
        default:
            return 'unknown';
    }
};

// WebKit
UserAgent.parse = function parse(source) {
    var ua = this;
    ua.Agent.source = source.replace(/^\s*/, '').replace(/\s*$/, '');
    ua.Agent.Browser = ua.getBrowser(ua.Agent.source);
    ua.Agent.Version = ua.getBrowserVersion(ua.Agent.source);
    ua.Agent.OS = ua.getOS(ua.Agent.source);
    ua.Agent.Platform = ua.getPlatform(ua.Agent.source);

    return ua.Agent;
};

UserAgent.express = function() {
    return function(req, res, next) {
        var source = req.headers['user-agent'],
        ua = UserAgent;
        ua.Agent.source = source.replace(/^\s*/, '').replace(/\s*$/, '');
        ua.Agent.Browser = ua.getBrowser(ua.Agent.source);
        ua.Agent.Version = ua.getBrowserVersion(ua.Agent.source);
        ua.Agent.OS = ua.getOS(ua.Agent.source);
        ua.Agent.Platform = ua.getPlatform(ua.Agent.source);
        req.useragent = ua.Agent;
        res.local("useragent", ua.Agent);
        next();
    }
};

module.exports = UserAgent;<|endoftext|>


<commit_before>Handlebars = require("../../vendor/js/handlebars-v2.0.0.js");
moment = require("../../vendor/js/moment.2.8.3.min.js");
require("datejs");
require("../myuw_m.js");
require("../handlebars-helpers.js");

var assert = require("assert");
describe('Handlebar-helpers', function(){
    describe('phonenumber', function(){
        it('should replace 10 digits with a formatted phone number', function(){
            var template = Handlebars.compile("{{formatPhoneNumber '5035551234'}}");
            var output = template();
            assert.equal(output, "503-555-1234");
        });
        it('should return the original string', function(){
            var template = Handlebars.compile("{{formatPhoneNumber '5551234'}}");
            var output = template();
            assert.equal(output, "5551234");
            template = Handlebars.compile("{{formatPhoneNumber 'abcdefghij'}}");
            output = template();
            assert.equal(output, "abcdefghij");
        });

    });

    describe('toFromNowDate', function(){
        it('should say in an hour', function(){
            var date = new Date();
            date.setHours(date.getHours()+1);
            var str = date.toString();
            var template = Handlebars.compile("{{toFromNowDate '"+str+"'}}");
            var output = template();
            assert.equal(output, "in an hour");
        });
        it('should say tomorrow', function(){
            var date = new Date();
            date.setDate(date.getDate()+1);
            var str = date.toString();
            var template = Handlebars.compile("{{toFromNowDate '"+str+"'}}");
            var output = template();
            assert.equal(output, "in a day");
        });

    });

    describe("safeLabel", function() {
        it ("should replace spaces", function() {
            var template = Handlebars.compile("{{safeLabel 'TRAIN,101/A'}}");
            var output = template();
            assert.equal(output, "TRAIN_101_A");
            template = Handlebars.compile("{{safeLabel 'B BIO,201/A'}}");
            output = template();
            assert.equal(output, "B_BIO_201_A");
            template = Handlebars.compile("{{safeLabel 'M&ESS,501/A'}}");
            output = template();
            assert.equal(output, "M_ESS_501_A");
        });
    });

    describe("toUrlSafe", function() {
        it ("should replace spaces", function() {
            var template = Handlebars.compile("{{toUrlSafe ' '}}");
            var output = template();
            assert.equal(output, "%20");
            template = Handlebars.compile("{{toUrlSafe '_   _'}}");
            output = template();
            assert.equal(output, "_%20%20%20_");
            template = Handlebars.compile("{{toUrlSafe '_&_'}}");
            output = template();
            assert.equal(output, "_%26_");
        });
    });

    describe("toLowerCase", function() {
        it ("should replace unicode", function() {
            var template = Handlebars.compile("{{toLowerCase 'OK!'}}");
            var output = template();
            assert.equal(output, "ok!");

            template = Handlebars.compile("{{toLowerCase 'È'}}");
            output = template();
            assert.equal(output, "è");
        });
        it ("should be ok with blank values", function() {
            var template = Handlebars.compile("{{toLowerCase ''}}");
            var output = template();
            assert.equal(output, "");
        });

    });

    describe("termNoYear", function() {
        it ("should work on non-summer terms", function() {
            var template = Handlebars.compile("{{termNoYear '2013,spring' }}");
            var output = template();

            assert.equal(output, 'spring');
        });
        it ("should work on summer terms", function() {
            var template = Handlebars.compile("{{termNoYear '2013,spring,b-term' }}");
            var output = template();

            assert.equal(output, 'spring b-term');
        });

    });

    describe('acal_banner_date_format', function() {
        it("should give sunday (one date)", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-25'}}");
            var output = template();
            assert.equal(output, 'Jan 25 (Sunday)');
        });

        it("should give sunday", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-25' '2015-01-25' }}");
            var output = template();
            assert.equal(output, 'Jan 25 (Sunday)');
        });
        it("should give monday", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-26' '2015-01-26' }}");
            var output = template();
            assert.equal(output, 'Jan 26 (Monday)');
        });
        it("should give tuesday", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-27' '2015-01-27' }}");
            var output = template();
            assert.equal(output, 'Jan 27 (Tuesday)');
        });
        it("should give wednesday", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-28' '2015-01-28' }}");
            var output = template();
            assert.equal(output, 'Jan 28 (Wednesday)');
        });
        it("should give thursday", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-29' '2015-01-29' }}");
            var output = template();
            assert.equal(output, 'Jan 29 (Thursday)');
        });
        it("should give friday", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-30' '2015-01-30' }}");
            var output = template();
            assert.equal(output, 'Jan 30 (Friday)');
        });
        it("should give saturday", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-31' '2015-01-31' }}");
            var output = template();
            assert.equal(output, 'Jan 31 (Saturday)');
        });
        it("should give Jan", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-01' '2015-01-01' }}");
            var output = template();
            assert.equal(output, 'Jan 1 (Thursday)');
        });
        it("should give Feb", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-02-01' '2015-02-01' }}");
            var output = template();
            assert.equal(output, 'Feb 1 (Sunday)');
        });
        it("should give Mar", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-03-01' '2015-03-01' }}");
            var output = template();
            assert.equal(output, 'Mar 1 (Sunday)');
        });
        it("should give Apr", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-04-01' '2015-04-01' }}");
            var output = template();
            assert.equal(output, 'Apr 1 (Wednesday)');
        });
        it("should give May", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-05-01' '2015-05-01' }}");
            var output = template();
            assert.equal(output, 'May 1 (Friday)');
        });
        it("should give June", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-06-01' '2015-06-01' }}");
            var output = template();
            assert.equal(output, 'June 1 (Monday)');
        });
        it("should give July", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-07-01' '2015-07-01' }}");
            var output = template();
            assert.equal(output, 'July 1 (Wednesday)');
        });
        it("should give Aug", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-08-01' '2015-08-01' }}");
            var output = template();
            assert.equal(output, 'Aug 1 (Saturday)');
        });
        it("should give Sept", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-09-01' '2015-09-01' }}");
            var output = template();
            assert.equal(output, 'Sept 1 (Tuesday)');
        });
        it("should give Oct", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-10-01' '2015-10-01' }}");
            var output = template();
            assert.equal(output, 'Oct 1 (Thursday)');
        });
        it("should give Nov", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-11-01' '2015-11-01' }}");
            var output = template();
            assert.equal(output, 'Nov 1 (Sunday)');
        });
        it("should give Dec", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-12-01' '2015-12-01' }}");
            var output = template();
            assert.equal(output, 'Dec 1 (Tuesday)');
        });

        it("should give in-month range", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-12-01' '2015-12-02' }}");
            var output = template();
            assert.equal(output, 'Dec 1 - 2');
        });

        it("should give multi-month range", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-09-29' '2015-10-25' }}");
            var output = template();
            assert.equal(output, 'Sept 29 - Oct 25');
        });
    });

    describe('acal_page_date_format', function() {
        it("should give Jan (one value)", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-01-01' }}");
            var output = template();
            assert.equal(output, 'Jan 1');
        });

        it("should give Jan", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-01-01' '2015-01-01' }}");
            var output = template();
            assert.equal(output, 'Jan 1');
        });
        it("should give Feb", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-02-01' '2015-02-01' }}");
            var output = template();
            assert.equal(output, 'Feb 1');
        });
        it("should give Mar", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-03-01' '2015-03-01' }}");
            var output = template();
            assert.equal(output, 'Mar 1');
        });
        it("should give Apr", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-04-01' '2015-04-01' }}");
            var output = template();
            assert.equal(output, 'Apr 1');
        });
        it("should give May", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-05-01' '2015-05-01' }}");
            var output = template();
            assert.equal(output, 'May 1');
        });
        it("should give June", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-06-01' '2015-06-01' }}");
            var output = template();
            assert.equal(output, 'June 1');
        });
        it("should give July", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-07-01' '2015-07-01' }}");
            var output = template();
            assert.equal(output, 'July 1');
        });
        it("should give Aug", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-08-01' '2015-08-01' }}");
            var output = template();
            assert.equal(output, 'Aug 1');
        });
        it("should give Sept", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-09-01' '2015-09-01' }}");
            var output = template();
            assert.equal(output, 'Sept 1');
        });
        it("should give Oct", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-10-01' '2015-10-01' }}");
            var output = template();
            assert.equal(output, 'Oct 1');
        });
        it("should give Nov", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-11-01' '2015-11-01' }}");
            var output = template();
            assert.equal(output, 'Nov 1');
        });
        it("should give Dec", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-12-01' '2015-12-01' }}");
            var output = template();
            assert.equal(output, 'Dec 1');
        });

        it("should give in-month range", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-12-01' '2015-12-02' }}");
            var output = template();
            assert.equal(output, 'Dec 1 - 2');
        });

        it("should give multi-month range", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-09-29' '2015-10-25' }}");
            var output = template();
            assert.equal(output, 'Sept 29 - Oct 25');
        });
    });

    describe("muwm-2505", function() {
        it ("should have the right date", function() {
            var template = Handlebars.compile("{{toFriendlyDate '2013-03-04' }}");
            var output = template();

            assert.equal(output, 'Mon, Mar 4');

        });
    });
});
<commit_msg>remove test with external dependency<commit_after>Handlebars = require("../../vendor/js/handlebars-v2.0.0.js");
moment = require("../../vendor/js/moment.2.8.3.min.js");
require("datejs");
require("../handlebars-helpers.js");

var assert = require("assert");
describe('Handlebar-helpers', function(){
    describe('phonenumber', function(){
        it('should replace 10 digits with a formatted phone number', function(){
            var template = Handlebars.compile("{{formatPhoneNumber '5035551234'}}");
            var output = template();
            assert.equal(output, "503-555-1234");
        });
        it('should return the original string', function(){
            var template = Handlebars.compile("{{formatPhoneNumber '5551234'}}");
            var output = template();
            assert.equal(output, "5551234");
            template = Handlebars.compile("{{formatPhoneNumber 'abcdefghij'}}");
            output = template();
            assert.equal(output, "abcdefghij");
        });

    });

    describe('toFromNowDate', function(){
        it('should say in an hour', function(){
            var date = new Date();
            date.setHours(date.getHours()+1);
            var str = date.toString();
            var template = Handlebars.compile("{{toFromNowDate '"+str+"'}}");
            var output = template();
            assert.equal(output, "in an hour");
        });
        it('should say tomorrow', function(){
            var date = new Date();
            date.setDate(date.getDate()+1);
            var str = date.toString();
            var template = Handlebars.compile("{{toFromNowDate '"+str+"'}}");
            var output = template();
            assert.equal(output, "in a day");
        });

    });

    describe("toUrlSafe", function() {
        it ("should replace spaces", function() {
            var template = Handlebars.compile("{{toUrlSafe ' '}}");
            var output = template();
            assert.equal(output, "%20");
            template = Handlebars.compile("{{toUrlSafe '_   _'}}");
            output = template();
            assert.equal(output, "_%20%20%20_");
            template = Handlebars.compile("{{toUrlSafe '_&_'}}");
            output = template();
            assert.equal(output, "_%26_");
        });
    });

    describe("toLowerCase", function() {
        it ("should replace unicode", function() {
            var template = Handlebars.compile("{{toLowerCase 'OK!'}}");
            var output = template();
            assert.equal(output, "ok!");

            template = Handlebars.compile("{{toLowerCase 'È'}}");
            output = template();
            assert.equal(output, "è");
        });
        it ("should be ok with blank values", function() {
            var template = Handlebars.compile("{{toLowerCase ''}}");
            var output = template();
            assert.equal(output, "");
        });

    });

    describe("termNoYear", function() {
        it ("should work on non-summer terms", function() {
            var template = Handlebars.compile("{{termNoYear '2013,spring' }}");
            var output = template();

            assert.equal(output, 'spring');
        });
        it ("should work on summer terms", function() {
            var template = Handlebars.compile("{{termNoYear '2013,spring,b-term' }}");
            var output = template();

            assert.equal(output, 'spring b-term');
        });

    });

    describe('acal_banner_date_format', function() {
        it("should give sunday (one date)", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-25'}}");
            var output = template();
            assert.equal(output, 'Jan 25 (Sunday)');
        });

        it("should give sunday", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-25' '2015-01-25' }}");
            var output = template();
            assert.equal(output, 'Jan 25 (Sunday)');
        });
        it("should give monday", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-26' '2015-01-26' }}");
            var output = template();
            assert.equal(output, 'Jan 26 (Monday)');
        });
        it("should give tuesday", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-27' '2015-01-27' }}");
            var output = template();
            assert.equal(output, 'Jan 27 (Tuesday)');
        });
        it("should give wednesday", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-28' '2015-01-28' }}");
            var output = template();
            assert.equal(output, 'Jan 28 (Wednesday)');
        });
        it("should give thursday", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-29' '2015-01-29' }}");
            var output = template();
            assert.equal(output, 'Jan 29 (Thursday)');
        });
        it("should give friday", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-30' '2015-01-30' }}");
            var output = template();
            assert.equal(output, 'Jan 30 (Friday)');
        });
        it("should give saturday", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-31' '2015-01-31' }}");
            var output = template();
            assert.equal(output, 'Jan 31 (Saturday)');
        });
        it("should give Jan", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-01-01' '2015-01-01' }}");
            var output = template();
            assert.equal(output, 'Jan 1 (Thursday)');
        });
        it("should give Feb", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-02-01' '2015-02-01' }}");
            var output = template();
            assert.equal(output, 'Feb 1 (Sunday)');
        });
        it("should give Mar", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-03-01' '2015-03-01' }}");
            var output = template();
            assert.equal(output, 'Mar 1 (Sunday)');
        });
        it("should give Apr", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-04-01' '2015-04-01' }}");
            var output = template();
            assert.equal(output, 'Apr 1 (Wednesday)');
        });
        it("should give May", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-05-01' '2015-05-01' }}");
            var output = template();
            assert.equal(output, 'May 1 (Friday)');
        });
        it("should give June", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-06-01' '2015-06-01' }}");
            var output = template();
            assert.equal(output, 'June 1 (Monday)');
        });
        it("should give July", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-07-01' '2015-07-01' }}");
            var output = template();
            assert.equal(output, 'July 1 (Wednesday)');
        });
        it("should give Aug", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-08-01' '2015-08-01' }}");
            var output = template();
            assert.equal(output, 'Aug 1 (Saturday)');
        });
        it("should give Sept", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-09-01' '2015-09-01' }}");
            var output = template();
            assert.equal(output, 'Sept 1 (Tuesday)');
        });
        it("should give Oct", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-10-01' '2015-10-01' }}");
            var output = template();
            assert.equal(output, 'Oct 1 (Thursday)');
        });
        it("should give Nov", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-11-01' '2015-11-01' }}");
            var output = template();
            assert.equal(output, 'Nov 1 (Sunday)');
        });
        it("should give Dec", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-12-01' '2015-12-01' }}");
            var output = template();
            assert.equal(output, 'Dec 1 (Tuesday)');
        });

        it("should give in-month range", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-12-01' '2015-12-02' }}");
            var output = template();
            assert.equal(output, 'Dec 1 - 2');
        });

        it("should give multi-month range", function() {
            var template = Handlebars.compile("{{acal_banner_date_format '2015-09-29' '2015-10-25' }}");
            var output = template();
            assert.equal(output, 'Sept 29 - Oct 25');
        });
    });

    describe('acal_page_date_format', function() {
        it("should give Jan (one value)", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-01-01' }}");
            var output = template();
            assert.equal(output, 'Jan 1');
        });

        it("should give Jan", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-01-01' '2015-01-01' }}");
            var output = template();
            assert.equal(output, 'Jan 1');
        });
        it("should give Feb", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-02-01' '2015-02-01' }}");
            var output = template();
            assert.equal(output, 'Feb 1');
        });
        it("should give Mar", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-03-01' '2015-03-01' }}");
            var output = template();
            assert.equal(output, 'Mar 1');
        });
        it("should give Apr", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-04-01' '2015-04-01' }}");
            var output = template();
            assert.equal(output, 'Apr 1');
        });
        it("should give May", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-05-01' '2015-05-01' }}");
            var output = template();
            assert.equal(output, 'May 1');
        });
        it("should give June", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-06-01' '2015-06-01' }}");
            var output = template();
            assert.equal(output, 'June 1');
        });
        it("should give July", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-07-01' '2015-07-01' }}");
            var output = template();
            assert.equal(output, 'July 1');
        });
        it("should give Aug", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-08-01' '2015-08-01' }}");
            var output = template();
            assert.equal(output, 'Aug 1');
        });
        it("should give Sept", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-09-01' '2015-09-01' }}");
            var output = template();
            assert.equal(output, 'Sept 1');
        });
        it("should give Oct", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-10-01' '2015-10-01' }}");
            var output = template();
            assert.equal(output, 'Oct 1');
        });
        it("should give Nov", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-11-01' '2015-11-01' }}");
            var output = template();
            assert.equal(output, 'Nov 1');
        });
        it("should give Dec", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-12-01' '2015-12-01' }}");
            var output = template();
            assert.equal(output, 'Dec 1');
        });

        it("should give in-month range", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-12-01' '2015-12-02' }}");
            var output = template();
            assert.equal(output, 'Dec 1 - 2');
        });

        it("should give multi-month range", function() {
            var template = Handlebars.compile("{{acal_page_date_format '2015-09-29' '2015-10-25' }}");
            var output = template();
            assert.equal(output, 'Sept 29 - Oct 25');
        });
    });

    describe("muwm-2505", function() {
        it ("should have the right date", function() {
            var template = Handlebars.compile("{{toFriendlyDate '2013-03-04' }}");
            var output = template();

            assert.equal(output, 'Mon, Mar 4');

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