<commit_before>var _ = require('underscore');
var Backbone = require('backbone');
var EditorHelpers = require('builder/components/form-components/helpers/editor');

var FillColorFixedView = require('builder/components/form-components/editors/fill-color/fill-color-fixed-view');
var FillColorByValueView = require('builder/components/form-components/editors/fill-color/fill-color-by-value-view');

var DialogConstants = require('builder/components/form-components/_constants/_dialogs');
var FillConstants = require('builder/components/form-components/_constants/_fill');
var tabPaneTemplate = require('builder/components/tab-pane/tab-pane.tpl');
var createRadioLabelsTabPane = require('builder/components/tab-pane/create-radio-labels-tab-pane');

Backbone.Form.editors.FillColor = Backbone.Form.editors.Base.extend({
  className: 'Form-InputFillColor',

  initialize: function (options) {
    Backbone.Form.editors.Base.prototype.initialize.call(this, options);
    EditorHelpers.setOptions(this, options);

    if (this.options.editorAttrs) {
      this.options = _.extend(this.options, {
        columns: this.options.options,
        query: this.options.query,
        configModel: this.options.configModel,
        userModel: this.options.userModel,
        editorAttrs: this.options.editorAttrs,
        imageEnabled: this.options.editorAttrs.imageEnabled,
        modals: this.options.modals
      });

      this._colorAttributes = this.model.get('fillColor');
      this._sizeAttributes = this.model.get('fillSize');

      var editorAttrs = this.options.editorAttrs;

      if (editorAttrs.hidePanes) {
        this._hidePanes = editorAttrs.hidePanes;

        if (!_.contains(this._hidePanes, FillConstants.Panes.BY_VALUE)) {
          if (!this.options.configModel) throw new Error('configModel param is required');
          if (!this.options.userModel) throw new Error('userModel param is required');
          if (!this.options.modals) throw new Error('modals param is required');
          if (!this.options.query) throw new Error('query param is required');
        }
      }

      if (editorAttrs.categorizeColumns) {
        this._categorizeColumns = true;
      }

      this._imageInputModel = new Backbone.Model(
        _.extend({ type: 'image' }, this._colorAttributes)
      );

      this._fixedColorInputModel = new Backbone.Model(
        _.extend({ type: 'color' }, this._colorAttributes)
      );

      this._valueColorInputModel = new Backbone.Model(
        _.extend({ type: 'color' }, this._colorAttributes)
      );

      this._sizeModel = new Backbone.Model(this._sizeAttributes);
    }

    this._initViews();
  },

  _initViews: function () {
    var self = this;

    var fixedPane = {
      name: FillConstants.Panes.FIXED,
      label: _t('form-components.editors.fill.input-number.solid'),
      createContentView: function () {
        return self._generateFixedContentView();
      }
    };

    var valuePane = {
      name: FillConstants.Panes.BY_VALUE,
      label: _t('form-components.editors.fill.input-number.by-value'),
      createContentView: function () {
        return self._generateValueContentView();
      }
    };

    this._tabPaneTabs = [];

    if (this.options.editorAttrs && this.options.editorAttrs.hidePanes) {
      var hidePanes = this.options.editorAttrs.hidePanes;

      if (!_.contains(hidePanes, FillConstants.Panes.FIXED)) {
        this._tabPaneTabs.push(fixedPane);
      }

      if (!_.contains(hidePanes, FillConstants.Panes.BY_VALUE)) {
        this._tabPaneTabs.push(valuePane);
      }
    } else {
      this._tabPaneTabs = [fixedPane, valuePane];
    }

    var tabPaneOptions = {
      tabPaneOptions: {
        template: tabPaneTemplate,
        tabPaneItemOptions: {
          tagName: 'li',
          klassName: 'CDB-NavMenu-item'
        }
      },
      tabPaneItemLabelOptions: {
        tagName: 'div',
        className: 'CDB-Text CDB-Size-medium'
      }
    };

    var selectedTabPaneIndex = this._getSelectedTabPaneIndex();
    this._tabPaneTabs[selectedTabPaneIndex].selected = true;

    this._tabPaneView = createRadioLabelsTabPane(this._tabPaneTabs, tabPaneOptions);
    this.$el.append(this._tabPaneView.render().$el);
  },

  _getSelectedTabPaneIndex: function () {
    var FIXED_TAB_PANE_INDEX = 0;
    var VALUE_TAB_PANE_INDEX = 1;

    return this.model.get('fillColor').range &&
      this._tabPaneTabs.length > 1
      ? VALUE_TAB_PANE_INDEX
      : FIXED_TAB_PANE_INDEX;
  },

  _removeFillColorFixedDialog: function () {
    this._fillColorFixedView.removeDialog();
  },

  _removeFillColorByValueDialog: function () {
    this._fillColorByValueView.removeDialog();
  },

  _generateFixedContentView: function () {
    this._fillColorFixedView = new FillColorFixedView({
      model: this.model,
      columns: this.options.columns,
      query: this.options.query,
      configModel: this.options.configModel,
      userModel: this.options.userModel,
      editorAttrs: this.options.editorAttrs,
      modals: this.options.modals,
      imageEnabled: this.options.imageEnabled,
      dialogMode: DialogConstants.Mode.FLOAT,
      colorAttributes: this._colorAttributes,
      fixedColorInputModel: this._fixedColorInputModel,
      imageInputModel: this._imageInputModel,
      sizeModel: this._sizeModel,
      popupConfig: {
        cid: this.cid,
        $el: this.$el
      }
    });

    this.applyESCBind(this._removeFillColorFixedDialog);
    this.applyClickOutsideBind(this._removeFillColorFixedDialog);

    this._fillColorFixedView.on('onInputChanged', function (input) {
      this.trigger('change', input);
    }, this);

    return this._fillColorFixedView;
  },

  _generateValueContentView: function () {
    this._fillColorByValueView = new FillColorByValueView({
      columns: this.options.columns,
      query: this.options.query,
      configModel: this.options.configModel,
      userModel: this.options.userModel,
      editorAttrs: this.options.editorAttrs,
      model: this.model,
      dialogMode: DialogConstants.Mode.FLOAT,
      colorAttributes: this._colorAttributes,
      categorizeColumns: this.options.categorizeColumns,
      imageEnabled: this.options.imageEnabled,
      modals: this.options.modals,
      hideTabs: this.options.hideTabs,
      valueColorInputModel: this._valueColorInputModel,
      popupConfig: {
        cid: this.cid,
        $el: this.$el
      }
    });

    this.applyESCBind(this._removeFillColorByValueDialog);
    this.applyClickOutsideBind(this._removeFillColorByValueDialog);

    this._fillColorByValueView.on('onInputChanged', function (input) {
      this.trigger('change', input);
    }, this);

    return this._fillColorByValueView;
  },

  getValue: function (param) {
    var selectedTabPaneName = this._tabPaneView.getSelectedTabPaneName();

    return selectedTabPaneName === FillConstants.Panes.FIXED
      ? this._getFillFixedValues()
      : this._getFillByValueValues();
  },

  _getFillFixedValues: function () {
    var colorOmitAttributes = [
      'createContentView',
      'selected',
      'type',
      'image',
      'marker',
      'range'
    ];

    var imageOmitAttributes = [
      'createContentView',
      'selected',
      'type',
      'fixed',
      'range'
    ];

    var colorAttributes = _.omit(this._fixedColorInputModel.toJSON(), colorOmitAttributes);
    var imageAttributes = _.omit(this._imageInputModel.toJSON(), imageOmitAttributes);
    var values = _.extend({}, imageAttributes, colorAttributes);

    this._fixedColorInputModel.set(values);
    this._imageInputModel.set(values);

    delete values.fillColor;
    return values;
  },

  _getFillByValueValues: function () {
    var colorOmitAttributes = [
      'createContentView',
      'selected',
      'type',
      'quantification',
      'domain'
    ];

    var values = _.omit(this._valueColorInputModel.toJSON(), colorOmitAttributes);

    this._valueColorInputModel.set(values);

    return values;
  }
});
<commit_msg>Fix categorical values<commit_after>var _ = require('underscore');
var Backbone = require('backbone');
var EditorHelpers = require('builder/components/form-components/helpers/editor');

var FillColorFixedView = require('builder/components/form-components/editors/fill-color/fill-color-fixed-view');
var FillColorByValueView = require('builder/components/form-components/editors/fill-color/fill-color-by-value-view');

var DialogConstants = require('builder/components/form-components/_constants/_dialogs');
var FillConstants = require('builder/components/form-components/_constants/_fill');
var tabPaneTemplate = require('builder/components/tab-pane/tab-pane.tpl');
var createRadioLabelsTabPane = require('builder/components/tab-pane/create-radio-labels-tab-pane');

Backbone.Form.editors.FillColor = Backbone.Form.editors.Base.extend({
  className: 'Form-InputFillColor',

  initialize: function (options) {
    Backbone.Form.editors.Base.prototype.initialize.call(this, options);
    EditorHelpers.setOptions(this, options);

    if (this.options.editorAttrs) {
      this.options = _.extend(this.options, {
        columns: this.options.options,
        query: this.options.query,
        configModel: this.options.configModel,
        userModel: this.options.userModel,
        editorAttrs: this.options.editorAttrs,
        imageEnabled: this.options.editorAttrs.imageEnabled,
        modals: this.options.modals
      });

      this._colorAttributes = this.model.get('fillColor');
      this._sizeAttributes = this.model.get('fillSize');

      var editorAttrs = this.options.editorAttrs;

      if (editorAttrs.hidePanes) {
        this._hidePanes = editorAttrs.hidePanes;

        if (!_.contains(this._hidePanes, FillConstants.Panes.BY_VALUE)) {
          if (!this.options.configModel) throw new Error('configModel param is required');
          if (!this.options.userModel) throw new Error('userModel param is required');
          if (!this.options.modals) throw new Error('modals param is required');
          if (!this.options.query) throw new Error('query param is required');
        }
      }

      if (editorAttrs.categorizeColumns) {
        this._categorizeColumns = true;
      }

      this._imageInputModel = new Backbone.Model(
        _.extend({ type: 'image' }, this._colorAttributes)
      );

      this._fixedColorInputModel = new Backbone.Model(
        _.extend({ type: 'color' }, this._colorAttributes)
      );

      this._valueColorInputModel = new Backbone.Model(
        _.extend({ type: 'color' }, this._colorAttributes)
      );

      this._sizeModel = new Backbone.Model(this._sizeAttributes);
    }

    this._initViews();
  },

  _initViews: function () {
    var self = this;

    var fixedPane = {
      name: FillConstants.Panes.FIXED,
      label: _t('form-components.editors.fill.input-number.solid'),
      createContentView: function () {
        return self._generateFixedContentView();
      }
    };

    var valuePane = {
      name: FillConstants.Panes.BY_VALUE,
      label: _t('form-components.editors.fill.input-number.by-value'),
      createContentView: function () {
        return self._generateValueContentView();
      }
    };

    this._tabPaneTabs = [];

    if (this.options.editorAttrs && this.options.editorAttrs.hidePanes) {
      var hidePanes = this.options.editorAttrs.hidePanes;

      if (!_.contains(hidePanes, FillConstants.Panes.FIXED)) {
        this._tabPaneTabs.push(fixedPane);
      }

      if (!_.contains(hidePanes, FillConstants.Panes.BY_VALUE)) {
        this._tabPaneTabs.push(valuePane);
      }
    } else {
      this._tabPaneTabs = [fixedPane, valuePane];
    }

    var tabPaneOptions = {
      tabPaneOptions: {
        template: tabPaneTemplate,
        tabPaneItemOptions: {
          tagName: 'li',
          klassName: 'CDB-NavMenu-item'
        }
      },
      tabPaneItemLabelOptions: {
        tagName: 'div',
        className: 'CDB-Text CDB-Size-medium'
      }
    };

    var selectedTabPaneIndex = this._getSelectedTabPaneIndex();
    this._tabPaneTabs[selectedTabPaneIndex].selected = true;

    this._tabPaneView = createRadioLabelsTabPane(this._tabPaneTabs, tabPaneOptions);
    this.$el.append(this._tabPaneView.render().$el);
  },

  _getSelectedTabPaneIndex: function () {
    var FIXED_TAB_PANE_INDEX = 0;
    var VALUE_TAB_PANE_INDEX = 1;

    return this.model.get('fillColor').range &&
      this._tabPaneTabs.length > 1
      ? VALUE_TAB_PANE_INDEX
      : FIXED_TAB_PANE_INDEX;
  },

  _removeFillColorFixedDialog: function () {
    this._fillColorFixedView.removeDialog();
  },

  _removeFillColorByValueDialog: function () {
    this._fillColorByValueView.removeDialog();
  },

  _generateFixedContentView: function () {
    this._fillColorFixedView = new FillColorFixedView({
      model: this.model,
      columns: this.options.columns,
      query: this.options.query,
      configModel: this.options.configModel,
      userModel: this.options.userModel,
      editorAttrs: this.options.editorAttrs,
      modals: this.options.modals,
      imageEnabled: this.options.imageEnabled,
      dialogMode: DialogConstants.Mode.FLOAT,
      colorAttributes: this._colorAttributes,
      fixedColorInputModel: this._fixedColorInputModel,
      imageInputModel: this._imageInputModel,
      sizeModel: this._sizeModel,
      popupConfig: {
        cid: this.cid,
        $el: this.$el
      }
    });

    this.applyESCBind(this._removeFillColorFixedDialog);
    this.applyClickOutsideBind(this._removeFillColorFixedDialog);

    this._fillColorFixedView.on('onInputChanged', function (input) {
      this.trigger('change', input);
    }, this);

    return this._fillColorFixedView;
  },

  _generateValueContentView: function () {
    this._fillColorByValueView = new FillColorByValueView({
      columns: this.options.columns,
      query: this.options.query,
      configModel: this.options.configModel,
      userModel: this.options.userModel,
      editorAttrs: this.options.editorAttrs,
      model: this.model,
      dialogMode: DialogConstants.Mode.FLOAT,
      colorAttributes: this._colorAttributes,
      categorizeColumns: this.options.categorizeColumns,
      imageEnabled: this.options.imageEnabled,
      modals: this.options.modals,
      hideTabs: this.options.hideTabs,
      valueColorInputModel: this._valueColorInputModel,
      popupConfig: {
        cid: this.cid,
        $el: this.$el
      }
    });

    this.applyESCBind(this._removeFillColorByValueDialog);
    this.applyClickOutsideBind(this._removeFillColorByValueDialog);

    this._fillColorByValueView.on('onInputChanged', function (input) {
      this.trigger('change', input);
    }, this);

    return this._fillColorByValueView;
  },

  getValue: function (param) {
    var selectedTabPaneName = this._tabPaneView.getSelectedTabPaneName();

    return selectedTabPaneName === FillConstants.Panes.FIXED
      ? this._getFillFixedValues()
      : this._getFillByValueValues();
  },

  _getFillFixedValues: function () {
    var colorOmitAttributes = [
      'createContentView',
      'selected',
      'type',
      'image',
      'marker',
      'range'
    ];

    var imageOmitAttributes = [
      'createContentView',
      'selected',
      'type',
      'fixed',
      'range'
    ];

    var colorAttributes = _.omit(this._fixedColorInputModel.toJSON(), colorOmitAttributes);
    var imageAttributes = _.omit(this._imageInputModel.toJSON(), imageOmitAttributes);
    var values = _.extend({}, imageAttributes, colorAttributes);

    this._fixedColorInputModel.set(values);
    this._imageInputModel.set(values);

    return values;
  },

  _getFillByValueValues: function () {
    var colorOmitAttributes = [
      'createContentView',
      'selected',
      'type'
    ];

    var values = _.omit(this._valueColorInputModel.toJSON(), colorOmitAttributes);

    this._valueColorInputModel.set(values);

    return values;
  }
});
<|endoftext|>


<commit_before>'use strict';
/*global module*/
var pkgData = require('./package.json');
module.exports = function(grunt) {
  grunt.initConfig({
    pkg: '<json:package.json>',
    jshint: {
      all: ['./stampit.js', './test/stampit-specs.js'],
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        nonew: true,
        noarg: true,
        sub: true,
        undef: true,
        unused: true,
        eqnull: true,
        node: true,
        strict: true,
        boss: false
      }
    },

    lexicon: {
      all: {
        src: ["stampit.js"],
        dest: "doc",
        options: {
          title: "Stampit API",
          format: "markdown"
        }
      }
    },

    connect: {
      server: {
        options: {
          port: process.env.sauceport,
          base: './'
        }
      }
    },

    'saucelabs-qunit': {
      all: {
        options: {
          username: process.env.sauceuser,
          key: process.env.saucekey,
          urls: ['http://localhost:' +
            process.env.sauceport + '/test/index.html'],
          tunnelTimeout: ['10000'],
          testname: pkgData.name,
          tags: [''],
          browsers: [
            {
              browserName: 'chrome'
            },
            {
              browserName: 'internet explorer',
              platform: 'Windows 2003',
              version: '8'
            },
            {
              browserName: 'internet explorer'
            },
            {
              browserName: 'firefox'
            },
            {
              browserName: 'android',
              platform: 'Linux',
              version: '4'
            },
            {
              browserName: 'safari',
              platform: 'Mac 10.8',
              version: '6'
            },
            {
              browserName: 'safari',
              platform: 'Mac 10.6',
              version: 5
            }
          ]
        }
      }
    },

    browserify: {
      'dist/stampit.js': ['./stampit.js'],
      'test/stampit.js': ['./stampit.js'],
      options: {
        standalone: 'stampit'
      }
    },

    uglify: {
      dist: {
          src: 'dist/stampit.js',
          dest: 'dist/stampit.min.js'
      }
    },

    watch: {
      options: {
        livereload: true
      },
      scripts: {
        files: ['./stampit.js', './test/stampit-specs.js', './mixer.js', './merger.js'],
        tasks: ['default']
      }
    }
  });

  grunt.loadNpmTasks('grunt-saucelabs');
  grunt.loadNpmTasks('grunt-browserify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  // grunt.loadNpmTasks('grunt-lexicon');

  grunt.registerTask('hint', ['jshint']);
  grunt.registerTask('default', ['jshint', 'browserify', 'uglify']);
  grunt.registerTask('test', ['jshint', 'browserify', 'connect', 'saucelabs-qunit']);
};
<commit_msg>Remove non existing file from gruntfile.js.<commit_after>'use strict';
/*global module*/
var pkgData = require('./package.json');
module.exports = function(grunt) {
  grunt.initConfig({
    pkg: '<json:package.json>',
    jshint: {
      all: ['./stampit.js', './test/stampit-specs.js'],
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        nonew: true,
        noarg: true,
        sub: true,
        undef: true,
        unused: true,
        eqnull: true,
        node: true,
        strict: true,
        boss: false
      }
    },

    lexicon: {
      all: {
        src: ["stampit.js"],
        dest: "doc",
        options: {
          title: "Stampit API",
          format: "markdown"
        }
      }
    },

    connect: {
      server: {
        options: {
          port: process.env.sauceport,
          base: './'
        }
      }
    },

    'saucelabs-qunit': {
      all: {
        options: {
          username: process.env.sauceuser,
          key: process.env.saucekey,
          urls: ['http://localhost:' +
            process.env.sauceport + '/test/index.html'],
          tunnelTimeout: ['10000'],
          testname: pkgData.name,
          tags: [''],
          browsers: [
            {
              browserName: 'chrome'
            },
            {
              browserName: 'internet explorer',
              platform: 'Windows 2003',
              version: '8'
            },
            {
              browserName: 'internet explorer'
            },
            {
              browserName: 'firefox'
            },
            {
              browserName: 'android',
              platform: 'Linux',
              version: '4'
            },
            {
              browserName: 'safari',
              platform: 'Mac 10.8',
              version: '6'
            },
            {
              browserName: 'safari',
              platform: 'Mac 10.6',
              version: 5
            }
          ]
        }
      }
    },

    browserify: {
      'dist/stampit.js': ['./stampit.js'],
      'test/stampit.js': ['./stampit.js'],
      options: {
        standalone: 'stampit'
      }
    },

    uglify: {
      dist: {
          src: 'dist/stampit.js',
          dest: 'dist/stampit.min.js'
      }
    },

    watch: {
      options: {
        livereload: true
      },
      scripts: {
        files: ['./stampit.js', './test/stampit-specs.js', './mixer.js'],
        tasks: ['default']
      }
    }
  });

  grunt.loadNpmTasks('grunt-saucelabs');
  grunt.loadNpmTasks('grunt-browserify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  // grunt.loadNpmTasks('grunt-lexicon');

  grunt.registerTask('hint', ['jshint']);
  grunt.registerTask('default', ['jshint', 'browserify', 'uglify']);
  grunt.registerTask('test', ['jshint', 'browserify', 'connect', 'saucelabs-qunit']);
};
<|endoftext|>


<commit_before>import tableExtractor from './table-extractor'
import domExtractor from './dom-extractor'
/**
 * @typedef {TabularData} Table data.
 * @property {string[][]} data - Table data.
 * @property {string[]} [header] - Header labels.
 */

/**
 * Extract tabular (rows and columns) from the selection.
 * @param  {DomSelectionRange} domSelectionRange - selection range.
 * @param  {String} currentUrl - Current tab url.
 * @return {TabularData} Tabular data.
 * @throws {Error} If no tabular data was found in the selection.
 */
function getTabularDataFromSelection(domSelectionRange, currentUrl) {
  var tabularData
  try {
    tabularData = tableExtractor.getTabularDataFromSelection(domSelectionRange)
  } catch(any) {
    console.log('Could not get tabular data with table extractor', any)
  }

  try {
    if (tabularData === undefined) {
      tabularData = domExtractor.getTabularDataFromSelection(domSelectionRange)
    }
  } catch(any) {
    console.log('Could not get tabular data with DOM extractor', any)
  }

  if (tabularData === undefined) {
    throw Error('Could not find tabular data.')
  }

  return normalizeTabularData(tabularData)
}

/**
 * Make all the rows of the tabular data have the same number of columns, adding empty cells if necessary.
 * @param  {TabularData} tabularData - Tabular data.
 * @return {TabularData} Normalized tabular data.
 */
function normalizeTabularData(tabularData) {
  var colCountMin, colCountMax, row
  for (var i = 0; i < tabularData.data.length; i++) {
    row = tabularData.data[i]
    if (colCountMin === undefined || colCountMin > row.length) {
      colCountMin = row.length
    }
    if (colCountMax === undefined || colCountMax < row.length) {
      colCountMax = row.length
    }
  }
  if (colCountMin === colCountMax) {
    return tabularData
  }

  let columnInfo = getColumnInfo(tabularData, colCountMax)

  for (var i = 0; i < tabularData.data.length; i++) {
    row = tabularData.data[i]
    if (row.length < colCountMax) {
      tabularData.data[i] = padRow(row, colCountMax, columnInfo)
    }
  }
  return tabularData
}

function getColumnInfo(tabularData, colCount) {
  // initialize with {empty: true}
  let columnInfo = Array.apply(null, {length: colCount}).map(() => { return {empty: true}})

  for (var i = 0; i < tabularData.data.length; i++) {
    var row = tabularData.data[i]
    // ignore rows that need padding
    if (row.length < colCount) {
      continue
    }
    for (var col = 0; col < colCount ; col++) {
      if (!isEmpty(row[col])) {
        columnInfo[col] = {empty: false}
      }
    }
  }
  return columnInfo
}

function padRow(row, size, columnInfo) {
  for (var col = 0; col < size ; col++) {
    // pad completed
    if (row.length === size) {
      break
    }

    // reached end of row and still need to pad
    if (row.length < (col + 1)) {
      row.push('')
      continue
    }

    // reached a cell that should be empty but is not and still need to pad
    let shouldBeEmptyCell = columnInfo[col].empty
    let isEmptyCell = isEmpty(row[col])

    if (shouldBeEmptyCell && !isEmptyCell) {
      row.splice(col, 0, '')
    }
  }
  return row
}

function isEmpty(cell) {
  return cell.replace(/\s/g, '').length <= 0
}

module.exports = {
  getTabularDataFromSelection: getTabularDataFromSelection,
  //private methods exposed for testing only
  _normalizeTabularData: normalizeTabularData,
  _padRow: padRow
}
<commit_msg>Refactor base-extractor<commit_after>import tableExtractor from './table-extractor'
import domExtractor from './dom-extractor'
/**
 * @typedef {TabularData} Table data.
 * @property {string[][]} data - Table data.
 * @property {string[]} [header] - Header labels.
 */

/**
 * Extract tabular (rows and columns) from the selection.
 * @param  {DomSelectionRange} domSelectionRange - selection range.
 * @param  {String} currentUrl - Current tab url.
 * @return {TabularData} Tabular data.
 * @throws {Error} If no tabular data was found in the selection.
 */
function getTabularDataFromSelection(domSelectionRange, currentUrl) {
  var tabularData = extractData(domSelectionRange, currentUrl)
  if (tabularData === undefined) {
    throw Error('Could not find tabular data.')
  }

  return normalizeTabularData(tabularData)
}

/**
 * Try to extract data from the selection.
 * @param  {DomSelectionRange} domSelectionRange - selection range.
 * @param  {String} currentUrl - Current tab url.
 * @return {TabularData|undefined} Tabular data.
 */
function extractData(domSelectionRange, currentUrl) {
  var tabularData
  try {
    return tableExtractor.getTabularDataFromSelection(domSelectionRange)
  } catch(any) {
    console.log('Could not get tabular data with table extractor', any)
  }

  try {
    return domExtractor.getTabularDataFromSelection(domSelectionRange)
  } catch(any) {
    console.log('Could not get tabular data with DOM extractor', any)
  }
  return undefined
}

/**
 * Make all the rows of the tabular data have the same number of columns, adding empty cells if necessary.
 * @param  {TabularData} tabularData - Tabular data.
 * @return {TabularData} Normalized tabular data.
 */
function normalizeTabularData(tabularData) {
  var colCountMin, colCountMax, row
  for (var i = 0; i < tabularData.data.length; i++) {
    row = tabularData.data[i]
    if (colCountMin === undefined || colCountMin > row.length) {
      colCountMin = row.length
    }
    if (colCountMax === undefined || colCountMax < row.length) {
      colCountMax = row.length
    }
  }
  if (colCountMin === colCountMax) {
    return tabularData
  }

  let columnInfo = getColumnInfo(tabularData, colCountMax)

  for (var i = 0; i < tabularData.data.length; i++) {
    row = tabularData.data[i]
    if (row.length < colCountMax) {
      tabularData.data[i] = padRow(row, colCountMax, columnInfo)
    }
  }
  return tabularData
}

function getColumnInfo(tabularData, colCount) {
  // initialize with {empty: true}
  let columnInfo = Array.apply(null, {length: colCount}).map(() => { return {empty: true}})

  for (var i = 0; i < tabularData.data.length; i++) {
    var row = tabularData.data[i]
    // ignore rows that need padding
    if (row.length < colCount) {
      continue
    }
    for (var col = 0; col < colCount ; col++) {
      if (!isEmpty(row[col])) {
        columnInfo[col] = {empty: false}
      }
    }
  }
  return columnInfo
}

function padRow(row, size, columnInfo) {
  for (var col = 0; col < size ; col++) {
    // pad completed
    if (row.length === size) {
      break
    }

    // reached end of row and still need to pad
    if (row.length < (col + 1)) {
      row.push('')
      continue
    }

    // reached a cell that should be empty but is not and still need to pad
    let shouldBeEmptyCell = columnInfo[col].empty
    let isEmptyCell = isEmpty(row[col])

    if (shouldBeEmptyCell && !isEmptyCell) {
      row.splice(col, 0, '')
    }
  }
  return row
}

function isEmpty(cell) {
  return cell.replace(/\s/g, '').length <= 0
}

module.exports = {
  getTabularDataFromSelection: getTabularDataFromSelection,
  //private methods exposed for testing only
  _normalizeTabularData: normalizeTabularData,
  _padRow: padRow
}
<|endoftext|>


<commit_before>/**
 * Created by Michael on 13/04/2016.
 */
var graphs;

var svgContainers = {};
var averages = {};

function addGraphPlaceholders(years) {
    const noOfColumns = 4;
    const columnWidth = 12 / noOfColumns;
    var container = document.getElementById('container');
    for (var i = 0; i < years.length; i++) {
        var year = years[i];
        if (i % noOfColumns === 0) {
            var newRow = document.createElement('div');
            newRow.className = 'row-fluid';
            container.appendChild(newRow);
        }
        container.lastChild.innerHTML += '

';
        document.getElementById('graph-' + year).innerHTML += '
' +
            year +
            ' Score: ' +
            '<button type="button" class="smallButton" id="giveButton-' + year + '">given</button>' +
            '<button type="button" class="smallButton" id="receiveButton-' + year + '">received</button>' +
            '<button type="button" class="smallButton" id="bothButton-' + year + '">both</button>' +
            '
';
        document.getElementById('graph-' + year).innerHTML += '

';
        if (i % noOfColumns == 0 || i == 0) {
            document.getElementById('container').innerHTML += '
'
        }
    }
}

var years = [1957, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967];
var selectedCountryIndex = 0;

addGraphPlaceholders(years);

years.forEach(function (d) {
    drawCluster(d);
});

function removeEverything() {
    years.forEach(function (year) {
        d3.selectAll("#receiveMid-" + year).remove();
        d3.selectAll("#receive-" + year).remove();
        d3.selectAll("#giveMid-" + year).remove();
        d3.selectAll("#give-" + year).remove();

    });
    d3.selectAll(".node").remove();
}

function drawCluster(chartYear) {
    var chartId = "#draw-" + chartYear;
    //var width = $(document).width();
    var width = d3.select(chartId).node().getBoundingClientRect().width;
    //var height = $(document).height();
    var height = d3.select(chartId).node().getBoundingClientRect().height;
    console.log("Row - Width: " + width + " height: " + height);
    var middlePoint = {X: width / 2, Y: height / 2};

    var countries = [];
    var nodesData = [];
    var selectedCountry;
    var scores = [[]];

    const giveColour = "#082f6d";
    const receiveColour = "#cd0027";
    const radiusCenter = 15;
    const radiusOuter = 10;
    const buffer1 = 25; // buffer between outer nodes
    const buffer2 = 25; // buffer between mid circle and outer circles
    var radius = radiusOuter + radiusCenter + buffer2; // radius of circle on which outer nodes should be drawn

    var countriesData;
    var scoresData;

    if (!(chartYear in svgContainers)) {
        var tempSvg = d3.select(chartId)
            .append("svg")
            .attr("width", width)
            .attr("height", height);
        svgContainers[chartYear] = tempSvg;
    }

    var svgContainer = svgContainers[chartYear];

    var sortMethod = 1; //0 = none; 1 = neighbours ; 2 = score

    //load data from multiple json files async
    d3_queue.queue()
        .defer(d3.json, 'data/countries.json')
        .defer(d3.json, 'data/scores.json')
        .await(makeGraph);

    function calcGivenAverage(scoresData) {
        var total = 0;
        var amount = 0;
        scoresData.scores.forEach(function (generalScoreInfo) {
            generalScoreInfo.scores.forEach(function (arrayWithScores) {
                arrayWithScores.forEach(function (score) {
                    // if (score != 0) {
                    total += parseInt(score);
                    amount += 1;
                    //}
                })
            })
            averages[chartYear] = total / amount;
            //console.log(chartYear + ": " + total / amount)
            total = 0;
            amount = 0;
        })

    }

    function makeGraph(error, countriesData, scoresData) {
        if (error) throw error;

        if (typeof averages !== 'undefined') {
            calcGivenAverage(scoresData);
        }

        //Get the results for the given year
        var yearResult = scoresData.scores.find(function (s) {
            return s.year == chartYear;
        });

        //Get the countries that participate this year
        countries = countriesData.countries.filter(function (c) {
            return yearResult.participants.indexOf(c.countryCode) > -1;
        });

        scores = yearResult.scores;

        //aantal gegeven punten
        var pointsCount = countries.length - 1;

        // hoek tussen landen
        var slice = 2 * Math.PI / pointsCount;

        //dynamically changes the radius
        var temp = pointsCount * (buffer1 + radiusOuter * 2);
        while (radius * Math.PI * 2 < temp) {
            radius += 20;
        }

        var links = [];

        //function sortCountries() {
        //    if (sortMethod == 0)
        //        countries.sort();
        //    else
        //        countries.sort(function (c1, c2) {
        //            if (sortMethod == 1) {
        //                //neighbours
        //                return selectedCountry.country.neighbours.indexOf(c1.countryCode) > -1 ? -1 : 1
        //            } else {
        //                //score
        //                //TODO
        //            }
        //        });
        //}
        //
        //sortCountries();

        selectedCountry = {
            country: countries[selectedCountryIndex],
            X: middlePoint.X,
            Y: middlePoint.Y,
            R: radiusCenter
        };

        nodesData.push(selectedCountry);

        var i = 0, j = 0;

        var temp = countries.slice();
        temp.splice(selectedCountryIndex, 1);

        temp.sort(function (c) {
            //sorteren op neighbors
            if (selectedCountry.country.neighbours.indexOf(c.countryCode) > -1) {
                return -1;
            }
            return 1;
        }).forEach(
            function (c) {
                if (i == selectedCountryIndex)
                    i++;

                var angle = slice * (j);
                var isNeighour = selectedCountry.country.neighbours.indexOf(c.countryCode) > -1;

                var outerCenterX = middlePoint.X + (isNeighour ? radius * .6 : radius) * Math.cos(angle);
                var outerCenterY = middlePoint.Y + (isNeighour ? radius * .6 : radius) * Math.sin(angle);

                var outerLinkX = middlePoint.X + ((isNeighour ? radius * .6 : radius) - radiusOuter) * Math.cos(angle);
                var outerLinkY = middlePoint.Y + ((isNeighour ? radius * .6 : radius) - radiusOuter) * Math.sin(angle);

                var innerLinkX = middlePoint.X + radiusCenter * Math.cos(angle);
                var innerLinkY = middlePoint.Y + radiusCenter * Math.sin(angle);

                // center between 2 links; x = (x1+x2)/2; y = (y1+y2)/2
                var centerLinkX = (innerLinkX + outerLinkX) / 2;
                var centerLinkY = (innerLinkY + outerLinkY) / 2;

                nodesData.push({country: countries[i], X: outerCenterX, Y: outerCenterY, R: radiusOuter});

                links.push({
                    innerLinkX: innerLinkX,
                    innerLinkY: innerLinkY,
                    outerLinkX: outerLinkX,
                    outerLinkY: outerLinkY,
                    centerLinkX: centerLinkX,
                    centerLinkY: centerLinkY,
                    scoreGiven: scores[j][selectedCountryIndex],
                    scoreReceived: scores[selectedCountryIndex][j],
                    isNeighbor: isNeighour
                });

                j++;
                i++;
            });

        var lineFunction = d3.svg.line()
            .x(function (d) {
                return d.X;
            })
            .y(function (d) {
                return d.Y;
            });

        var layer1 = svgContainer.append('g');

        function drawLinks(visibility) {
            //remove the current lines
            d3.selectAll("#receiveMid-" + chartYear).remove();
            d3.selectAll("#receive-" + chartYear).remove();
            d3.selectAll("#giveMid-" + chartYear).remove();
            d3.selectAll("#give-" + chartYear).remove();

            switch (visibility) {
                //give
                case 0:
                    links.forEach(function (item, index) {
                        layer1.append("path")
                            .attr("id", "give-" + chartYear)
                            .attr("d", lineFunction([
                                {X: item.innerLinkX, Y: item.innerLinkY},
                                {X: item.outerLinkX, Y: item.outerLinkY}
                            ]))
                            .attr("stroke", function () {
                                var avg = averages[chartYear];
                                if (parseFloat(item.scoreGiven) < averages[chartYear]) {
                                    //rood
                                    return "#C05746";
                                } else {
                                    return "#69995D";
                                }
                            })
                            .attr("stroke-width", 4)
                            .attr("fill", "none")
                            .attr("marker-end", "url(#giveArrowHead)")
                            .on("mouseover", function () {
                                document.getElementById("scoreText-" + chartYear).innerHTML = item.scoreGiven;
                            })
                    });
                    break;
                //receive
                case 1:
                    links.forEach(function (item, index) {
                        layer1.append("path")
                            .attr("id", "receive-" + chartYear)
                            .attr("d", lineFunction([
                                {X: item.outerLinkX, Y: item.outerLinkY},
                                {X: item.innerLinkX, Y: item.innerLinkY}
                            ]))
                            .attr("stroke", function () {
                                var avg = averages[chartYear];
                                if (parseFloat(item.scoreReceived) < averages[chartYear]) {
                                    //rood
                                    return "#C05746";
                                } else {
                                    return "#69995D";
                                }
                            })
                            .attr("stroke-width", 4)
                            .attr("fill", "none")
                            .attr("marker-end", "url(#receiveArrowHead)")
                            .on("mouseover", function () {
                                document.getElementById("scoreText-" + chartYear).innerHTML = item.scoreGiven;
                            });
                    });
                    break;
                //both
                case  2:
                    links.forEach(function (item, index) {
                        //give
                        layer1.append("path")
                            .attr("id", "give-" + chartYear)
                            .attr("d", lineFunction([
                                {X: item.innerLinkX, Y: item.innerLinkY},
                                {X: item.centerLinkX, Y: item.centerLinkY}
                            ]))
                            .attr("stroke", giveColour)
                            .attr("stroke-width", 4)
                            .attr("fill", "none")
                            .attr("marker-end", "url(#giveArrowHead)");
                        //receive
                        layer1.append("path")
                            .attr("id", "receive-" + chartYear)
                            .attr("d", lineFunction([
                                {X: item.outerLinkX, Y: item.outerLinkY},
                                {X: item.centerLinkX, Y: item.centerLinkY}
                            ]))
                            .attr("stroke", receiveColour)
                            .attr("stroke-width", 4)
                            .attr("fill", "none")
                            .attr("marker-end", "url(#receiveArrowHead)");
                    });
                    break;
            }

        }

        drawLinks(0);//draws the links; default is given

        var nodes = svgContainer.selectAll("node")
            .data(nodesData);

        var defs = nodes.enter().append('defs');

        defs.append('pattern')
            .attr('id', function (d) {
                return (d.country.countryCode + "-icon");
            })
            .attr('class', "countryNodes")
            .attr('width', 1)
            .attr('height', 1)
            .attr('patternContentUnits', 'objectBoundingBox')
            .append("image")
            .attr("xlink:xlink:href", function (d) {
                return ("./images/flags/" + d.country.image);
            })
            .attr("height", 1)
            .attr("width", 1)
            .attr("preserveAspectRatio", "xMinYMin slice");

        defs.append("marker")
            .attr("id", "giveArrowHead")
            .attr("refX", 4) /*must be smarter way to calculate shift*/
            .attr("refY", 0)
            .attr("markerWidth", 6)
            .attr("markerHeight", 4)
            .attr("orient", "auto")
            .attr("viewBox", "-5 -5 10 10")
            .append("path")
            .attr("d", "M 0,0 m -5,-5 L 5,0 L -5,5 Z")
            .attr("fill", giveColour);

        defs.append("marker")
            .attr("id", "receiveArrowHead")
            .attr("refX", 4) /*must be smarter way to calculate shift*/
            .attr("refY", 0)
            .attr("markerWidth", 6)
            .attr("markerHeight", 4)
            .attr("orient", "auto")
            .attr("viewBox", "-5 -5 10 10")
            .append("path")
            .attr("d", "M 0,0 m -5,-5 L 5,0 L -5,5 Z")
            .attr("fill", receiveColour);

        nodes.enter().append("circle")
            .attr("class", "node")
            .attr("cx", function (d) {
                return d.X
            })
            .on("click", switchSelectedOnClick)
            .attr("cy", function (d) {
                return d.Y
            })
            .attr("r", function (d) {
                return d.R + 3.5
            })
            .style("fill", function (d) {
                return ("url(#" + d.country.countryCode + "-icon)");
            })
            .style("stroke", "10px solid black");

        //calcAndDraw(selectedCountryIndex);

        function switchSelectedOnClick(flag) {
            var country = flag.country;
            /* VB:
             country = Object {countryCode: "IT", name: "Italië", neighbours: Array[6], image: "Italy.png"}
             */
            selectedCountryIndex = getCountryIndex(flag.country.countryCode);
            removeEverything();
            years.forEach(function (d) {
                drawCluster(d);
            });
        }

        var getCountryIndex = function (countryCode) {
            for (var intIndex = 0; intIndex < countries.length; intIndex++) {
                if (countries[intIndex].countryCode == countryCode) {
                    return intIndex;
                }
            }
        }

        //adds the buttons to choose the visible lines
        document.getElementById("giveButton-" + chartYear).onclick = function () {
            drawLinks(0);
        };
        document.getElementById("receiveButton-" + chartYear).onclick = function () {
            drawLinks(1);
        };
        document.getElementById("bothButton-" + chartYear).onclick = function () {
            drawLinks(2);
        };
    }

}<commit_msg>countries hun order gefixt<commit_after>/**
 * Created by Michael on 13/04/2016.
 */
var graphs;

var svgContainers = {};
var averages = {};

function addGraphPlaceholders(years) {
    const noOfColumns = 4;
    const columnWidth = 12 / noOfColumns;
    var container = document.getElementById('container');
    for (var i = 0; i < years.length; i++) {
        var year = years[i];
        if (i % noOfColumns === 0) {
            var newRow = document.createElement('div');
            newRow.className = 'row-fluid';
            container.appendChild(newRow);
        }
        container.lastChild.innerHTML += '

';
        document.getElementById('graph-' + year).innerHTML += '
' +
            year +
            ' Score: ' +
            '<button type="button" class="smallButton" id="giveButton-' + year + '">given</button>' +
            '<button type="button" class="smallButton" id="receiveButton-' + year + '">received</button>' +
            '<button type="button" class="smallButton" id="bothButton-' + year + '">both</button>' +
            '
';
        document.getElementById('graph-' + year).innerHTML += '

';
        if (i % noOfColumns == 0 || i == 0) {
            document.getElementById('container').innerHTML += '
'
        }
    }
}

var years = [1957, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967];
var selectedCountryIndex = 0;

addGraphPlaceholders(years);

years.forEach(function (d) {
    drawCluster(d);
});

function removeEverything() {
    years.forEach(function (year) {
        d3.selectAll("#receiveMid-" + year).remove();
        d3.selectAll("#receive-" + year).remove();
        d3.selectAll("#giveMid-" + year).remove();
        d3.selectAll("#give-" + year).remove();

    });
    d3.selectAll(".node").remove();
}

function drawCluster(chartYear) {
    var chartId = "#draw-" + chartYear;
    //var width = $(document).width();
    var width = d3.select(chartId).node().getBoundingClientRect().width;
    //var height = $(document).height();
    var height = d3.select(chartId).node().getBoundingClientRect().height;
    console.log("Row - Width: " + width + " height: " + height);
    var middlePoint = {X: width / 2, Y: height / 2};

    var countries = [];
    var nodesData = [];
    var selectedCountry;
    var scores = [[]];

    const giveColour = "#082f6d";
    const receiveColour = "#cd0027";
    const radiusCenter = 15;
    const radiusOuter = 10;
    const buffer1 = 25; // buffer between outer nodes
    const buffer2 = 25; // buffer between mid circle and outer circles
    var radius = radiusOuter + radiusCenter + buffer2; // radius of circle on which outer nodes should be drawn

    var countriesData;
    var scoresData;

    if (!(chartYear in svgContainers)) {
        var tempSvg = d3.select(chartId)
            .append("svg")
            .attr("width", width)
            .attr("height", height);
        svgContainers[chartYear] = tempSvg;
    }

    var svgContainer = svgContainers[chartYear];

    var sortMethod = 1; //0 = none; 1 = neighbours ; 2 = score

    //load data from multiple json files async
    d3_queue.queue()
        .defer(d3.json, 'data/countries.json')
        .defer(d3.json, 'data/scores.json')
        .await(makeGraph);

    function calcGivenAverage(scoresData) {
        var total = 0;
        var amount = 0;
        scoresData.scores.forEach(function (generalScoreInfo) {
            generalScoreInfo.scores.forEach(function (arrayWithScores) {
                arrayWithScores.forEach(function (score) {
                    // if (score != 0) {
                    total += parseInt(score);
                    amount += 1;
                    //}
                })
            })
            averages[chartYear] = total / amount;
            //console.log(chartYear + ": " + total / amount)
            total = 0;
            amount = 0;
        })

    }

    function makeGraph(error, countriesData, scoresData) {
        if (error) throw error;

        if (typeof averages !== 'undefined') {
            calcGivenAverage(scoresData);
        }

        //Get the results for the given year
        var yearResult = scoresData.scores.find(function (s) {
            return s.year == chartYear;
        });

        //Get the countries that participate this year
        countries = [];
        countriesData.countries.forEach(function (c) {
            var index = yearResult.participants.indexOf(c.countryCode);
            if (index > -1)
                countries[index] = c;
        });

        scores = yearResult.scores;

        //aantal gegeven punten
        var pointsCount = countries.length - 1;

        // hoek tussen landen
        var slice = 2 * Math.PI / pointsCount;

        //dynamically changes the radius
        var temp = pointsCount * (buffer1 + radiusOuter * 2);
        while (radius * Math.PI * 2 < temp) {
            radius += 20;
        }

        var links = [];

        //function sortCountries() {
        //    if (sortMethod == 0)
        //        countries.sort();
        //    else
        //        countries.sort(function (c1, c2) {
        //            if (sortMethod == 1) {
        //                //neighbours
        //                return selectedCountry.country.neighbours.indexOf(c1.countryCode) > -1 ? -1 : 1
        //            } else {
        //                //score
        //                //TODO
        //            }
        //        });
        //}
        //
        //sortCountries();

        selectedCountry = {
            country: countries[selectedCountryIndex],
            X: middlePoint.X,
            Y: middlePoint.Y,
            R: radiusCenter
        };

        nodesData.push(selectedCountry);

        var i = 0, j = 0;

        var temp = countries.slice();
        temp.splice(selectedCountryIndex, 1);

        temp.sort(function (c) {
            //sorteren op neighbors
            if (selectedCountry.country.neighbours.indexOf(c.countryCode) > -1) {
                return -1;
            }
            return 1;
        }).forEach(
            function (c) {
                if (i == selectedCountryIndex)
                    i++;

                var angle = slice * (j);
                var isNeighour = selectedCountry.country.neighbours.indexOf(c.countryCode) > -1;

                var outerCenterX = middlePoint.X + (isNeighour ? radius * .6 : radius) * Math.cos(angle);
                var outerCenterY = middlePoint.Y + (isNeighour ? radius * .6 : radius) * Math.sin(angle);

                var outerLinkX = middlePoint.X + ((isNeighour ? radius * .6 : radius) - radiusOuter) * Math.cos(angle);
                var outerLinkY = middlePoint.Y + ((isNeighour ? radius * .6 : radius) - radiusOuter) * Math.sin(angle);

                var innerLinkX = middlePoint.X + radiusCenter * Math.cos(angle);
                var innerLinkY = middlePoint.Y + radiusCenter * Math.sin(angle);

                // center between 2 links; x = (x1+x2)/2; y = (y1+y2)/2
                var centerLinkX = (innerLinkX + outerLinkX) / 2;
                var centerLinkY = (innerLinkY + outerLinkY) / 2;

                nodesData.push({country: countries[i], X: outerCenterX, Y: outerCenterY, R: radiusOuter});

                links.push({
                    innerLinkX: innerLinkX,
                    innerLinkY: innerLinkY,
                    outerLinkX: outerLinkX,
                    outerLinkY: outerLinkY,
                    centerLinkX: centerLinkX,
                    centerLinkY: centerLinkY,
                    scoreGiven: scores[j][selectedCountryIndex],
                    scoreReceived: scores[selectedCountryIndex][j],
                    isNeighbor: isNeighour
                });

                j++;
                i++;
            });

        var lineFunction = d3.svg.line()
            .x(function (d) {
                return d.X;
            })
            .y(function (d) {
                return d.Y;
            });

        var layer1 = svgContainer.append('g');

        function drawLinks(visibility) {
            //remove the current lines
            d3.selectAll("#receiveMid-" + chartYear).remove();
            d3.selectAll("#receive-" + chartYear).remove();
            d3.selectAll("#giveMid-" + chartYear).remove();
            d3.selectAll("#give-" + chartYear).remove();

            switch (visibility) {
                //give
                case 0:
                    links.forEach(function (item, index) {
                        layer1.append("path")
                            .attr("id", "give-" + chartYear)
                            .attr("d", lineFunction([
                                {X: item.innerLinkX, Y: item.innerLinkY},
                                {X: item.outerLinkX, Y: item.outerLinkY}
                            ]))
                            .attr("stroke", function () {
                                var avg = averages[chartYear];
                                if (parseFloat(item.scoreGiven) < averages[chartYear]) {
                                    //rood
                                    return "#C05746";
                                } else {
                                    return "#69995D";
                                }
                            })
                            .attr("stroke-width", 4)
                            .attr("fill", "none")
                            .attr("marker-end", "url(#giveArrowHead)")
                            .on("mouseover", function () {
                                document.getElementById("scoreText-" + chartYear).innerHTML = item.scoreGiven;
                            })
                    });
                    break;
                //receive
                case 1:
                    links.forEach(function (item, index) {
                        layer1.append("path")
                            .attr("id", "receive-" + chartYear)
                            .attr("d", lineFunction([
                                {X: item.outerLinkX, Y: item.outerLinkY},
                                {X: item.innerLinkX, Y: item.innerLinkY}
                            ]))
                            .attr("stroke", function () {
                                var avg = averages[chartYear];
                                if (parseFloat(item.scoreReceived) < averages[chartYear]) {
                                    //rood
                                    return "#C05746";
                                } else {
                                    return "#69995D";
                                }
                            })
                            .attr("stroke-width", 4)
                            .attr("fill", "none")
                            .attr("marker-end", "url(#receiveArrowHead)")
                            .on("mouseover", function () {
                                document.getElementById("scoreText-" + chartYear).innerHTML = item.scoreGiven;
                            });
                    });
                    break;
                //both
                case  2:
                    links.forEach(function (item, index) {
                        //give
                        layer1.append("path")
                            .attr("id", "give-" + chartYear)
                            .attr("d", lineFunction([
                                {X: item.innerLinkX, Y: item.innerLinkY},
                                {X: item.centerLinkX, Y: item.centerLinkY}
                            ]))
                            .attr("stroke", giveColour)
                            .attr("stroke-width", 4)
                            .attr("fill", "none")
                            .attr("marker-end", "url(#giveArrowHead)");
                        //receive
                        layer1.append("path")
                            .attr("id", "receive-" + chartYear)
                            .attr("d", lineFunction([
                                {X: item.outerLinkX, Y: item.outerLinkY},
                                {X: item.centerLinkX, Y: item.centerLinkY}
                            ]))
                            .attr("stroke", receiveColour)
                            .attr("stroke-width", 4)
                            .attr("fill", "none")
                            .attr("marker-end", "url(#receiveArrowHead)");
                    });
                    break;
            }

        }

        drawLinks(0);//draws the links; default is given

        var nodes = svgContainer.selectAll("node")
            .data(nodesData);

        var defs = nodes.enter().append('defs');

        defs.append('pattern')
            .attr('id', function (d) {
                return (d.country.countryCode + "-icon");
            })
            .attr('class', "countryNodes")
            .attr('width', 1)
            .attr('height', 1)
            .attr('patternContentUnits', 'objectBoundingBox')
            .append("image")
            .attr("xlink:xlink:href", function (d) {
                return ("./images/flags/" + d.country.image);
            })
            .attr("height", 1)
            .attr("width", 1)
            .attr("preserveAspectRatio", "xMinYMin slice");

        defs.append("marker")
            .attr("id", "giveArrowHead")
            .attr("refX", 4) /*must be smarter way to calculate shift*/
            .attr("refY", 0)
            .attr("markerWidth", 6)
            .attr("markerHeight", 4)
            .attr("orient", "auto")
            .attr("viewBox", "-5 -5 10 10")
            .append("path")
            .attr("d", "M 0,0 m -5,-5 L 5,0 L -5,5 Z")
            .attr("fill", giveColour);

        defs.append("marker")
            .attr("id", "receiveArrowHead")
            .attr("refX", 4) /*must be smarter way to calculate shift*/
            .attr("refY", 0)
            .attr("markerWidth", 6)
            .attr("markerHeight", 4)
            .attr("orient", "auto")
            .attr("viewBox", "-5 -5 10 10")
            .append("path")
            .attr("d", "M 0,0 m -5,-5 L 5,0 L -5,5 Z")
            .attr("fill", receiveColour);

        nodes.enter().append("circle")
            .attr("class", "node")
            .attr("cx", function (d) {
                return d.X
            })
            .on("click", switchSelectedOnClick)
            .attr("cy", function (d) {
                return d.Y
            })
            .attr("r", function (d) {
                return d.R + 3.5
            })
            .style("fill", function (d) {
                return ("url(#" + d.country.countryCode + "-icon)");
            })
            .style("stroke", "10px solid black");

        //calcAndDraw(selectedCountryIndex);

        function switchSelectedOnClick(flag) {
            var country = flag.country;
            /* VB:
             country = Object {countryCode: "IT", name: "Italië", neighbours: Array[6], image: "Italy.png"}
             */
            selectedCountryIndex = getCountryIndex(flag.country.countryCode);
            removeEverything();
            years.forEach(function (d) {
                drawCluster(d);
            });
        }

        var getCountryIndex = function (countryCode) {
            for (var intIndex = 0; intIndex < countries.length; intIndex++) {
                if (countries[intIndex].countryCode == countryCode) {
                    return intIndex;
                }
            }
        }

        //adds the buttons to choose the visible lines
        document.getElementById("giveButton-" + chartYear).onclick = function () {
            drawLinks(0);
        };
        document.getElementById("receiveButton-" + chartYear).onclick = function () {
            drawLinks(1);
        };
        document.getElementById("bothButton-" + chartYear).onclick = function () {
            drawLinks(2);
        };
    }

}<|endoftext|>


<commit_before>var Data = {

  starts : [
    "Experiential truth ",
    "Coffee ",
    "Geopolitics ",
    "Javascript ",
    "Glory ",
    "Espresso ",
    "Heuristic thought ",
    "Absinthe ",
    "Cave dwelling ",
    "Cuthbertine ",
    "Autonomous solace ",
    "Equestrian ",
    "Salacilic ",
    "Glitch Mob ",
    "Surrogate birth ",
    "Scurrilous ",
    "Rishathra ",
    "Irradiation ",
    "Megalomania ",
    "Solar radiation ",
    "Autosomy ",
    "Boba tea ",
    "Domain-specific languages ",
    "Practical economics ",
    "Activism ",
    "Dental plaque ",
    "Consternation ",
    "Vanilla nougat ",
    "The physical world ",
    "Sadness ",
    "Chicken ",
    "Non-judgment ",
    "Parsimony ",
    "Hodor ",
    "Salacity ",
    "Grunge music ",
    "Clarity ",
    "Antagonism ",
    "Heterodoxity ",
    "Erudition ",
    "Amalgamation ",
    "Remuneration ",
    "Primacy ",
    "Bran Van 3000 ",
    "The empty set ",
    "Bergamot marmalade ",
    "Amelioration ",
    "Apostasy ",
    "Reprobacy ",
    "Aquaculture ",
    "Infinity ",
    "Rubric ",
    "Email ",
    "Calamity ",
    "Loquacity ",
    "Honesty ",
    "Cosmology ",
    "Aperture science ",
    "Temporal quaquaversality ",
    "Derrida ",
    "Mellow vibe ",
    "Prosody ",
    "Selectivity ",
    "Unity ",
    "Good health ",
    "A quantum leap ",    // thanks Francis Veilleux-Gaboury
    "A clean brain ",
    "Entreaty ",
    "Brusque temperment ",
    "A flexible thought pattern ",
    "Insightful visage ",
    "Mindfulness in action ",
    "Automated translation ",
    "Facebook ",
    "Compassion ",
    "Altruism ",
    "Totality ",
    "Rhetorical training ",
    "Insoucinace ",
    "Dynamic mutative creation ",
    "The graspably non-considerable ",
    "Social science ",
    "Stone age philosophy ",
    "Interpretive dance ",
    "Meditative physics ",
    "Rambunctious cause ",
    "Biology ",
    "Multitudinality ",
    "Nascent luminence ",
    "True randomness ",
    "Deconstrutionist wisdom ",
    "Science intersecting religion ",
    "The role of a leader ",
    "The soul of a calm person ",
    "The idea of God ",
    "Mechanistic reaction ",
    "Semiotic involvement ",
    "Herotodeus ",
    "Quantum physics ",
    "Cerebrolinguistics ",
    "Dubstep as a metaphor for liberty "
  ],

  middles : [
    "nurtures ",
    "colocates by way of ",
    "unifies ",
    "stymies ",
    "separates ",
    "distributes widely ",
    "appreciates ",
    "deprecates ",
    "conglomerates ",
    "gives meaning to ",
    "displays ",
    "projects ",
    "permeates ",
    "eviscerates ",
    "clarifies ",
    "macerates ",
    "asceticizes ",
    "recapitulates ",
    "satisfies ",
    "sanctifies via ",
    "trivializes ",
    "justifies with ",
    "rarifies ",
    "enjoins ",
    "codifies ",
    "socializes by way of ",
    "promulgates ",
    "reclaims ",
    "disintegrates ",
    "integrates ",
    "racemizes ",
    "reduces ",
    "explores ",
    "dissociates from within ",
    "cosequences ",
    "exposes ",
    "masticates ",
    "builds, using ",
    "teaches through ",
    "projects onto ",
    "imparts reality to ",
    "colloquializes ",
    "constructs with "
  ],

  qualifiers : [
    "abundance of ",
    "ostentatious ",
    "the barrier of ",
    "self-righteous ",
    "collective ",
    "species specific ",
    "heterodynamic ",
    "clarity within ",
    "epistemological ",
    "synchronistic ",
    "timely ",
    "unpredictable ",
    "unassailable ",
    "glassy eyed ",
    "dishonest ",
    "indefatigable ",
    "factual ",
    "highly descriptive ",
    "location based ",
    "describably pure ",
    "bounded ",
    "unbounded ",
    "trans-boundary ",
    "expedient ",
    "ontogenous ",
    "parallelizes ",
    "serendipitous ",
    "geopolitical ",
    "popular ",
    "advocatory ",
    "pluripotentialistic ",
    "atomized ",
    "rhythmatic ",
    "dimensional ",
    "sophist ",
    "Etruscan ",
    "reliquary ",
    "escapist ",
    "aerated ",
    "anarchist ",
    "conformist ",
    "erudite ",
    "epistemic ",
    "cromulent ",
    "poker faced ",
    "miniscule ",
    "Manichean ",
    "Hadrean ",
    "media driven ",
    "global ",
    "local ",
    "post-",
    "hyper-",
    "trans-",
    "extra-",
    "super-",
    "supra-",
    "world regarding ",
    "provably optimal ",
    "potential ",
    "munctional "
  ],

  finishes : [
    "marvel.",
    "choices.",
    "harmony.",
    "phylogeny.",
    "disharmony.",
    "traversal.",
    "ostracism.",
    "semiotics.",
    "deconstructionism.",
    "post-logic.",
    "escapism.",
    "criarchy.",
    "permaculture.",
    "platitudinality.",
    "creosophy.",
    "journalism.",
    "preternaturality.",
    "glossolalia.",
    "idolatry.",
    "conscience confluence.",
    "hapto-ergonomics.",
    "mental rigor.",
    "spiritual fortitude.",
    "wisdom.",
    "secret genius.",
    "inner brilliance.",
    "unseen internal gift.",
    "combobulation.",
    "transdoctrinal inference.",
    "creativity.",
    "significance.",
    "materialization.",
    "generosity.",
    "infinitude.",
    "plurality.",
    "asceticism.",
    "truism.",
    "horizontal scaling.",
    "monopoly.",
    "temerity.",
    "neo-Platonism."
    "monosophism.",
    "polyarchy.",
    "heredity.",
    "togetherness.",
    "voluminous reaction.",
    "joyous revelation.",
    "stimulation.",
    "numbing.",
    "intuition.",
    "actions."
  ]

};

function randFrom(X) {
  return X[Math.floor(Math.random() * X.length)];
}

function makeDC() {
  return randFrom(Data.starts) + randFrom(Data.middles) + randFrom(Data.qualifiers) + randFrom(Data.finishes);
}

function go() {
  document.getElementById('txt').innerHTML = '"' + makeDC() + '"';
}
<commit_msg>loftializes<commit_after>var Data = {

  starts : [
    "Experiential truth ",
    "Coffee ",
    "Geopolitics ",
    "Javascript ",
    "Glory ",
    "Espresso ",
    "Heuristic thought ",
    "Absinthe ",
    "Cave dwelling ",
    "Cuthbertine ",
    "Autonomous solace ",
    "Equestrian ",
    "Salacilic ",
    "Glitch Mob ",
    "Surrogate birth ",
    "Scurrilous ",
    "Rishathra ",
    "Irradiation ",
    "Megalomania ",
    "Solar radiation ",
    "Autosomy ",
    "Boba tea ",
    "Domain-specific languages ",
    "Practical economics ",
    "Activism ",
    "Dental plaque ",
    "Consternation ",
    "Vanilla nougat ",
    "The physical world ",
    "Sadness ",
    "Chicken ",
    "Non-judgment ",
    "Parsimony ",
    "Hodor ",
    "Salacity ",
    "Grunge music ",
    "Clarity ",
    "Antagonism ",
    "Heterodoxity ",
    "Erudition ",
    "Amalgamation ",
    "Remuneration ",
    "Primacy ",
    "Bran Van 3000 ",
    "The empty set ",
    "Bergamot marmalade ",
    "Amelioration ",
    "Apostasy ",
    "Reprobacy ",
    "Aquaculture ",
    "Infinity ",
    "Rubric ",
    "Email ",
    "Calamity ",
    "Loquacity ",
    "Honesty ",
    "Cosmology ",
    "Aperture science ",
    "Temporal quaquaversality ",
    "Derrida ",
    "Mellow vibe ",
    "Prosody ",
    "Selectivity ",
    "Unity ",
    "Good health ",
    "A quantum leap ",    // thanks Francis Veilleux-Gaboury
    "A clean brain ",
    "Entreaty ",
    "Brusque temperment ",
    "A flexible thought pattern ",
    "Insightful visage ",
    "Mindfulness in action ",
    "Automated translation ",
    "Facebook ",
    "Compassion ",
    "Altruism ",
    "Totality ",
    "Rhetorical training ",
    "Insoucinace ",
    "Dynamic mutative creation ",
    "The graspably non-considerable ",
    "Social science ",
    "Stone age philosophy ",
    "Interpretive dance ",
    "Meditative physics ",
    "Rambunctious cause ",
    "Biology ",
    "Multitudinality ",
    "Nascent luminence ",
    "True randomness ",
    "Deconstrutionist wisdom ",
    "Science intersecting religion ",
    "The role of a leader ",
    "The soul of a calm person ",
    "The idea of God ",
    "Mechanistic reaction ",
    "Semiotic involvement ",
    "Herotodeus ",
    "Quantum physics ",
    "Cerebrolinguistics ",
    "Dubstep as a metaphor for liberty "
  ],

  middles : [
    "nurtures ",
    "colocates by way of ",
    "unifies ",
    "stymies ",
    "separates ",
    "distributes widely ",
    "appreciates ",
    "deprecates ",
    "conglomerates ",
    "gives meaning to ",
    "displays ",
    "projects ",
    "permeates ",
    "eviscerates ",
    "clarifies ",
    "macerates ",
    "asceticizes ",
    "recapitulates ",
    "satisfies ",
    "sanctifies via ",
    "trivializes ",
    "justifies with ",
    "rarifies ",
    "enjoins ",
    "codifies ",
    "socializes by way of ",
    "promulgates ",
    "reclaims ",
    "disintegrates ",
    "integrates ",
    "racemizes ",
    "reduces ",
    "explores ",
    "dissociates from within ",
    "cosequences ",
    "exposes ",
    "masticates ",
    "builds, using ",
    "teaches through ",
    "projects onto ",
    "imparts reality to ",
    "colloquializes ",
    "loftializes ",
    "constructs with "
  ],

  qualifiers : [
    "abundance of ",
    "ostentatious ",
    "the barrier of ",
    "self-righteous ",
    "collective ",
    "species specific ",
    "heterodynamic ",
    "clarity within ",
    "epistemological ",
    "synchronistic ",
    "timely ",
    "unpredictable ",
    "unassailable ",
    "glassy eyed ",
    "dishonest ",
    "indefatigable ",
    "factual ",
    "highly descriptive ",
    "location based ",
    "describably pure ",
    "bounded ",
    "unbounded ",
    "trans-boundary ",
    "expedient ",
    "ontogenous ",
    "parallelizes ",
    "serendipitous ",
    "geopolitical ",
    "popular ",
    "advocatory ",
    "pluripotentialistic ",
    "atomized ",
    "rhythmatic ",
    "dimensional ",
    "sophist ",
    "Etruscan ",
    "reliquary ",
    "escapist ",
    "aerated ",
    "anarchist ",
    "conformist ",
    "erudite ",
    "epistemic ",
    "cromulent ",
    "poker faced ",
    "miniscule ",
    "Manichean ",
    "Hadrean ",
    "media driven ",
    "global ",
    "local ",
    "post-",
    "hyper-",
    "trans-",
    "extra-",
    "super-",
    "supra-",
    "world regarding ",
    "provably optimal ",
    "potential ",
    "munctional "
  ],

  finishes : [
    "marvel.",
    "choices.",
    "harmony.",
    "phylogeny.",
    "disharmony.",
    "traversal.",
    "ostracism.",
    "semiotics.",
    "deconstructionism.",
    "post-logic.",
    "escapism.",
    "criarchy.",
    "permaculture.",
    "platitudinality.",
    "creosophy.",
    "journalism.",
    "preternaturality.",
    "glossolalia.",
    "idolatry.",
    "conscience confluence.",
    "hapto-ergonomics.",
    "mental rigor.",
    "spiritual fortitude.",
    "wisdom.",
    "secret genius.",
    "inner brilliance.",
    "unseen internal gift.",
    "combobulation.",
    "transdoctrinal inference.",
    "creativity.",
    "significance.",
    "materialization.",
    "generosity.",
    "infinitude.",
    "plurality.",
    "asceticism.",
    "truism.",
    "horizontal scaling.",
    "monopoly.",
    "temerity.",
    "neo-Platonism."
    "monosophism.",
    "polyarchy.",
    "heredity.",
    "togetherness.",
    "voluminous reaction.",
    "joyous revelation.",
    "stimulation.",
    "numbing.",
    "intuition.",
    "actions."
  ]

};

function randFrom(X) {
  return X[Math.floor(Math.random() * X.length)];
}

function makeDC() {
  return randFrom(Data.starts) + randFrom(Data.middles) + randFrom(Data.qualifiers) + randFrom(Data.finishes);
}

function go() {
  document.getElementById('txt').innerHTML = '"' + makeDC() + '"';
}
<|endoftext|>


<commit_before>/* ----:[ Activity Calendar ]:---- */
// http://jsfiddle.net/3g3tusuq/
var width = 960,
    height = 136,
    cellSize = 17, // cell size
    today = new Date(),
    lastyear = new Date();
    lastyear.setFullYear(lastyear.getFullYear() - 1);

var day = function(d) { return (d.getDay() + 6) % 7; },
    week = d3.time.format("%W"),
    year = d3.time.format("%Y"),
    format = d3.time.format("%Y-%m-%d"),
    parseDate = d3.time.format("%Y-%m-%dT%H:%M:%SZ").parse;

var color = d3.scale.quantize()
    .domain([0, 30])  // TODO: Make this dynamic and dependent on my longest run in the dataset
    .range(d3.range(5).map(function(d) { return "q" + d + "-5"; }));

var svg = d3.select("#activity-calendar").selectAll("svg")
    //.data(d3.range(2015, 2016)) // This doesn't need to be a range, just an array
    .data([1])  // An array with one element
  .enter().append("svg")
    .attr("width", width)
    .attr("height", height)
    .attr("class", "RdYlGn")
  //.append("g")  /* Padding for year label */
  //  .attr("transform", "translate(" + ((width - cellSize * 53) / 2) + "," + (height - cellSize * 7 - 1) + ")");

// Year label
/* svg.append("text")
    .attr("transform", "translate(-6," + cellSize * 3.5 + ")rotate(-90)")
    .style("text-anchor", "middle")
    .text(function(d) { return d; });
*/

// Month label
/* TODO
svg.append("text")
  .attr("class", "graph-label")
  .attr("x", function(d) { return 0; })
  .attr("y", function(d) { return -5; })
  .text("JAN FEB MAR APR MAY");
*/

// Draw out each day square
var rect = svg.selectAll(".day")
    //.data(function(d) { return d3.time.days(new Date(d, 0, 1), new Date(d + 1, 0, 1)); })
    .data(function(d) { return d3.time.days(lastyear, today); })
  .enter().append("rect")
    .attr("class", "day")
    .attr("width", cellSize)
    .attr("height", cellSize)
    //.attr("x", function(d) { return week(d) * cellSize; })
    .attr("x", function(d) {
        var offset = 54 - +week(today);

        if (+week(d) <= +week(today) && +year(d) == +year(today))  {
            return ((+week(d) + offset) * cellSize) - (2 * cellSize);
        } else {
            return ((+week(d) + offset - 54) * cellSize);
        }
    })
    .attr("y", function(d) { return day(d) * cellSize; })
    .datum(format);

// Day tooltip
rect.append("title")
    .text(function(d) { return d; });

// Border around each month
/* svg.selectAll(".month")
    .data(function(d) { return d3.time.months(new Date(d, 0, 1), new Date(d + 1, 0, 1)); })
  .enter().append("path")
    .attr("class", "month")
    .attr("d", monthPath);
*/

//var url = "simple.json";
var url = "200.json";
d3.json(url, function(error, json) {
  if (error) return console.warn(error);

  // Map the json data to date & distance
  // TODO: cater for days where I run more than once.
  var data = d3.nest()
    .key(function (d) {return format(parseDate(d.start_date_local));})
    .rollup(function (d) {var dist = 0;
        d.forEach(function(e) {
            dist += +e.distance;
        })
        return +dist/1000;
      })
    .map(json);

  // Each Day tooltip & colouring
  rect.filter(function (d) {return d in data;})
    .attr("class", function (d) {return "day " + color(data[d]);})
    .select("title")
    .text(function (d) {return d + ": " + Math.round(data[d]) + "km";});
})
<commit_msg>Remove count todo<commit_after>/* ----:[ Activity Calendar ]:---- */
// http://jsfiddle.net/3g3tusuq/
var width = 960,
    height = 136,
    cellSize = 17, // cell size
    today = new Date(),
    lastyear = new Date();
    lastyear.setFullYear(lastyear.getFullYear() - 1);

var day = function(d) { return (d.getDay() + 6) % 7; },
    week = d3.time.format("%W"),
    year = d3.time.format("%Y"),
    format = d3.time.format("%Y-%m-%d"),
    parseDate = d3.time.format("%Y-%m-%dT%H:%M:%SZ").parse;

var color = d3.scale.quantize()
    .domain([0, 30])  // TODO: Make this dynamic and dependent on my longest run in the dataset
    .range(d3.range(5).map(function(d) { return "q" + d + "-5"; }));

var svg = d3.select("#activity-calendar").selectAll("svg")
    //.data(d3.range(2015, 2016)) // This doesn't need to be a range, just an array
    .data([1])  // An array with one element
  .enter().append("svg")
    .attr("width", width)
    .attr("height", height)
    .attr("class", "RdYlGn")
  //.append("g")  /* Padding for year label */
  //  .attr("transform", "translate(" + ((width - cellSize * 53) / 2) + "," + (height - cellSize * 7 - 1) + ")");

// Year label
/* svg.append("text")
    .attr("transform", "translate(-6," + cellSize * 3.5 + ")rotate(-90)")
    .style("text-anchor", "middle")
    .text(function(d) { return d; });
*/

// Month label
/* TODO
svg.append("text")
  .attr("class", "graph-label")
  .attr("x", function(d) { return 0; })
  .attr("y", function(d) { return -5; })
  .text("JAN FEB MAR APR MAY");
*/

// Draw out each day square
var rect = svg.selectAll(".day")
    //.data(function(d) { return d3.time.days(new Date(d, 0, 1), new Date(d + 1, 0, 1)); })
    .data(function(d) { return d3.time.days(lastyear, today); })
  .enter().append("rect")
    .attr("class", "day")
    .attr("width", cellSize)
    .attr("height", cellSize)
    //.attr("x", function(d) { return week(d) * cellSize; })
    .attr("x", function(d) {
        var offset = 54 - +week(today);

        if (+week(d) <= +week(today) && +year(d) == +year(today))  {
            return ((+week(d) + offset) * cellSize) - (2 * cellSize);
        } else {
            return ((+week(d) + offset - 54) * cellSize);
        }
    })
    .attr("y", function(d) { return day(d) * cellSize; })
    .datum(format);

// Day tooltip
rect.append("title")
    .text(function(d) { return d; });

// Border around each month
/* svg.selectAll(".month")
    .data(function(d) { return d3.time.months(new Date(d, 0, 1), new Date(d + 1, 0, 1)); })
  .enter().append("path")
    .attr("class", "month")
    .attr("d", monthPath);
*/

//var url = "simple.json";
var url = "200.json";
d3.json(url, function(error, json) {
  if (error) return console.warn(error);

  // Map the json data to date & distance
  var data = d3.nest()
    .key(function (d) {return format(parseDate(d.start_date_local));})
    .rollup(function (d) {var dist = 0;
        d.forEach(function(e) {
            dist += +e.distance;
        })
        return +dist/1000;
      })
    .map(json);

  // Each Day tooltip & colouring
  rect.filter(function (d) {return d in data;})
    .attr("class", function (d) {return "day " + color(data[d]);})
    .select("title")
    .text(function (d) {return d + ": " + Math.round(data[d]) + "km";});
})
<|endoftext|>


<commit_before>var min = 1;
var sec = 11;
var ideas = null; // array of ideas from db
var numIdeasCompleted = 0;

function isWithinOneHour(now, start) {
  var diff = start.getTime() - now.getTime();
  return diff >= 0 && diff < 3600000; // 1hr in ms
}

/* Init for stage 1 (definition) */
function initBeginClock(startDate, startTime, duration) {
  var now = new Date();
  var start = new Date(startDate+","+startTime);
  var diff = start.getTime() - now.getTime();

  if (diff < 0) { // session already started
  	finishStage();
  } else if (diff < 6000000) {
    min = Math.floor(diff/1000/60);
    sec = Math.floor((diff/1000) % 60)
    startClock();
  } else {
  	min = 99;
  	sec = 99;
    $("#clock").html(getTimeString());
  }
}

/* init for stage 2 (ideation) */
function initIdeationClock(startDate, startTime, duration) {
  min = 0;
  sec = 20;
  startClock();
}

function initDiscussionClock(startDate, startTime, duration) {
  min = 0;
  sec = 5;

  $("#clock").html(getTimeString());
  updateDiscussionClock(); // run once to start
  intervalID = setInterval(updateDiscussionClock,1000);
}

function updateDiscussionClock() {
  if (min == 0 && sec == 0 && ideas === null) {
  	fetchIdeas();
  } else if (min == 0 && sec == 0 && !isDiscussionDone()) {
    displayNextIdea();
    min = 0;
    sec = 10;
    $("#clock").html(getTimeString());
  } else if (min == 0 && sec == 0 && isDiscussionDone()) {
  	finishStage();
  } else {
	sec -= 1;
	if (sec < 0) {
	  min -= 1;
	  sec = 59;
	}
	$("#clock").html(getTimeString());
  }
}

/* Loads the ideas from the db and assigns them to 'ideas' var */
function fetchIdeas() {
  var key = getFirebaseKey();
  var ref = new Firebase(getSessionUrl(key));
  ref.once("value", function(snapshot) {
    var session = snapshot.val();
    ideas = session.ideas;
  }, function (errorObject) {
    console.log("The read failed: " + errorObject.code);
  });
}

/* Replace the title and description with the next one */
function displayNextIdea() {
  var currIdea = ideas[numIdeasCompleted];
  $("#title").html(currIdea.title);
  $("#description").html(currIdea.description);
  numIdeasCompleted += 1;
}

/* Returns true if every topic has been discussed */
function isDiscussionDone() {
  return numIdeasCompleted > ideas.length;
}

/* route the appropriate finish function */
function finishStage() {
  clearInterval(intervalID);
  var stage = getCurrentStage();
  if (stage === "begin")
  	finishBegin();
  else if (stage === "ideation")
  	finishIdeation();
  else if (stage === "discussion")
  	finishDiscussion();
  else if (stage === "decision")
  	finishDecision();
  else
  	alert("Sorry, an error occured");
}

function finishBegin() {
  var key = getFirebaseKey();
  if (isDeployed())
    window.location.replace("http://www.willhennessy.com/storm/ideation?session="+key);
  else
  	window.location.replace("/Users/willhennessy/Documents/CS%20598%20-%20Social/storm/ideation.html?&session="+key);
}

function finishIdeation() {
  submitToFirebase();

  return;

  var key = getFirebaseKey();
  if (isDeployed())
    window.location.replace("http://www.willhennessy.com/storm/discussion?session="+key);
  else
  	window.location.replace("/Users/willhennessy/Documents/CS%20598%20-%20Social/storm/discussion.html?&session="+key);
}

function finishDiscussion() {
  return;
}

function finishDecision() {
  return;
}

function startClock() {
  $("#clock").html(getTimeString());
  updateClock(); // run once to start
  intervalID = setInterval(updateClock,1000);
}

function updateClock() {
  if (min == 0 && sec == 0) {
  	finishStage();
  	return;
  }

  sec -= 1;
  if (sec < 0) {
  	min -= 1;
  	sec = 59;
  }

  $("#clock").html(getTimeString());
}

function getTimeString() {
  if (min < 10)
    var m = "0" + min;
  else
  	var m = min.toString();
  if (sec < 10)
  	var s = "0" + sec;
  else
  	var s = sec.toString();

  return m + ":" + s;
}
<commit_msg>Bug fixes<commit_after>var min = 99;
var sec = 99;
var ideas = null; // array of ideas from db
var numIdeasCompleted = 0;
var intervalID = 0;

function isWithinOneHour(now, start) {
  var diff = start.getTime() - now.getTime();
  return diff >= 0 && diff < 3600000; // 1hr in ms
}

/* Init for stage 1 (definition) */
function initBeginClock(startDate, startTime, duration) {
  var now = new Date();
  var start = new Date(startDate+","+startTime);
  var diff = start.getTime() - now.getTime();

  if (diff < 0) { // session already started
  	finishStage();
  } else if (diff < 6000000) {
    min = Math.floor(diff/1000/60);
    sec = Math.floor((diff/1000) % 60)
    startClock();
  } else {
  	min = 99;
  	sec = 99;
    $("#clock").html(getTimeString());
  }
}

/* init for stage 2 (ideation) */
function initIdeationClock(startDate, startTime, duration) {
  min = 0;
  sec = 20;
  startClock();
}

function initDiscussionClock(startDate, startTime, duration) {
  min = 0;
  sec = 5;

  $("#clock").html(getTimeString());
  updateDiscussionClock(); // run once to start
  intervalID = setInterval(updateDiscussionClock,1000);
}

function updateDiscussionClock() {
  if (min == 0 && sec == 0 && ideas === null) {
  	fetchIdeas();
  } else if (min == 0 && sec == 0 && !isDiscussionDone()) {
    displayNextIdea();
    min = 90;
    sec = 0;
    $("#clock").html(getTimeString());
  } else if (min == 0 && sec == 0 && isDiscussionDone()) {
  	finishStage();
  } else {
	sec -= 1;
	if (sec < 0) {
	  min -= 1;
	  sec = 59;
	}
	$("#clock").html(getTimeString());
  }
}

/* Loads the ideas from the db and assigns them to 'ideas' var */
function fetchIdeas() {
  var key = getFirebaseKey();
  var ref = new Firebase(getSessionUrl(key));
  ref.once("value", function(snapshot) {
    var session = snapshot.val();
    ideas = session.ideas;
  }, function (errorObject) {
    console.log("The read failed: " + errorObject.code);
  });
}

/* Replace the title and description with the next one */
function displayNextIdea() {
  var currIdea = ideas[numIdeasCompleted];
  $("#title").html(currIdea.title);
  $("#description").html(currIdea.description);
  numIdeasCompleted += 1;
}

/* Returns true if every topic has been discussed */
function isDiscussionDone() {
  return numIdeasCompleted >= ideas.length;
}

/* route the appropriate finish function */
function finishStage() {
  clearInterval(intervalID);
  var stage = getCurrentStage();
  if (stage === "begin")
  	finishBegin();
  else if (stage === "ideation")
  	finishIdeation();
  else if (stage === "discussion")
  	finishDiscussion();
  else if (stage === "decision")
  	finishDecision();
  else
  	alert("Sorry, an error occured");
}

function finishBegin() {
  var key = getFirebaseKey();
  if (isDeployed())
    window.location.replace("http://www.willhennessy.com/storm/ideation?session="+key);
  else
  	window.location.replace("/Users/willhennessy/Documents/CS%20598%20-%20Social/storm/ideation.html?&session="+key);
}

function finishIdeation() {
  submitToFirebase();
}

function finishDiscussion() {
  if (isDeployed()) {
    window.location.replace("http://www.willhennessy.com/storm/ideation?session="+getFirebaseKey());
  } else {
    window.location.replace("/Users/willhennessy/Documents/CS%20598%20-%20Social/storm/ideation.html?creator=1&session="+getFirebaseKey());
  }
}

function finishDecision() {
  return;
}

function startClock() {
  $("#clock").html(getTimeString());
  updateClock(); // run once to start
  intervalID = setInterval(updateClock,1000);
}

function updateClock() {
  if (min == 0 && sec == 0) {
  	finishStage();
  	return;
  }

  sec -= 1;
  if (sec < 0) {
  	min -= 1;
  	sec = 59;
  }

  $("#clock").html(getTimeString());
}

function getTimeString() {
  if (min < 10)
    var m = "0" + min;
  else
  	var m = min.toString();
  if (sec < 10)
  	var s = "0" + sec;
  else
  	var s = sec.toString();

  return m + ":" + s;
}
<|endoftext|>