<commit_before>'use strict';

// MODULES //

var tape = require( 'tape' );
var proxyquire = require( 'proxyquire' );
var IS_BROWSER = require( '@stdlib/assert/is-browser' );
var noop = require( '@stdlib/utils/noop' );
var isBuffer = require( '@stdlib/assert/is-buffer' );
var Stream = require( './fixtures/stdin.js' );
var stdin = require( './../lib' );

// VARIABLES //

var opts = {
	'skip': IS_BROWSER
};

// TESTS //

tape( 'main export is a function', opts, function test( t ) {
	t.ok( true, __filename );
	t.equal( typeof stdin, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function throws if provided an `encoding` argument which is not a string', opts, function test( t ) {
	var values;
	var i;

	values = [
		5,
		true,
		null,
		undefined,
		[],
		{},
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws TypeError when provided ' + values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			stdin( value, noop );
		};
	}
});

tape( 'the function throws if provided a `callback` argument which is not a function', opts, function test( t ) {
	var values;
	var i;

	values = [
		'5',
		5,
		true,
		null,
		undefined,
		[],
		{}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue1( values[i] ), TypeError, 'throws TypeError when provided ' + values[i] );
		t.throws( badValue2( values[i] ), TypeError, 'throws TypeError when provided ' + values[i] );
	}
	t.end();

	function badValue1( value ) {
		return function badValue() {
			stdin( value );
		};
	}
	function badValue2( value ) {
		return function badValue() {
			stdin( 'utf8', value );
		};
	}
});

tape( 'if `stdin` is run in TTY mode and the encoding is not set, the function returns an empty buffer', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = true;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( onRead );

	function onRead( error, data ) {
		if ( error ) {
			t.ok( false, error.message );
		}
		t.equal( isBuffer( data ), true, 'returns a buffer' );
		t.equal( data.length, 0, 'buffer is empty' );
		t.end();
	}
});

tape( 'if `stdin` is run in TTY mode and the encoding is set, the function returns an empty string', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = true;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( 'hex', onRead );

	function onRead( error, data ) {
		if ( error ) {
			t.ok( false, error.message );
		}
		t.equal( isBuffer( data ), false, 'does not return a buffer' );
		t.equal( typeof data, 'string', 'returns a string' );
		t.equal( data.length, 0, 'string is empty' );
		t.end();
	}
});

tape( 'if an error is encountered while reading from `stdin`, the error is returned', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = false;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( onRead );

	stream.emit( 'error', new Error( 'beep' ) );

	function onRead( error ) {
		if ( error ) {
			t.equal( error.message, 'beep', 'returns an error' );
		}
		t.end();
	}
});

tape( 'if an error is encountered while reading from `stdin`, the error is returned (encoding set)', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = false;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( 'utf8', onRead );

	stream.emit( 'error', new Error( 'beep' ) );

	function onRead( error ) {
		if ( error ) {
			t.equal( error.message, 'beep', 'returns an error' );
		}
		t.end();
	}
});

tape( 'if the `encoding` argument is not set, the function returns `stdin` data as a `buffer`', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = false;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( onRead );

	stream.push( new Buffer( 'beep' ) );
	stream.push( new Buffer( ' ' ) );
	stream.push( new Buffer( 'boop' ) );
	stream.push( null );

	function onRead( error, data ) {
		if ( error ) {
			t.ok( false, error.message );
		}
		t.equal( isBuffer( data ), true, 'returns a buffer' );
		t.equal( data.toString(), 'beep boop', 'returns `stdin` data' );
		t.end();
	}
});

tape( 'if the `encoding` argument is set, the function returns `stdin` data as a `string`', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = false;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( 'utf8', onRead );

	stream.push( new Buffer( 'beep' ) );
	stream.push( new Buffer( ' ' ) );
	stream.push( new Buffer( 'boop' ) );
	stream.push( null );

	function onRead( error, data ) {
		if ( error ) {
			t.ok( false, error.message );
		}
		t.equal( isBuffer( data ), false, 'does not return a buffer' );
		t.equal( typeof data, 'string', 'returns a string' );
		t.equal( data, 'beep boop', 'returns `stdin` data' );
		t.end();
	}
});

tape( 'if the `encoding` argument is not set and no `stdin` data, the function returns an empty `buffer`', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = false;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( onRead );

	stream.push( null );

	function onRead( error, data ) {
		if ( error ) {
			t.ok( false, error.message );
		}
		t.equal( isBuffer( data ), true, 'returns a buffer' );
		t.equal( data.length, 0, 'returns an empty buffer' );
		t.equal( data.toString(), '', 'buffer is empty' );
		t.end();
	}
});

tape( 'if the `encoding` argument is set and no `stdin` data, the function returns an empty `string`', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = false;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( 'utf8', onRead );

	stream.push( null );

	function onRead( error, data ) {
		if ( error ) {
			t.ok( false, error.message );
		}
		t.equal( isBuffer( data ), false, 'does not return a buffer' );
		t.equal( typeof data, 'string', 'returns a string' );
		t.equal( data, '', 'returns empty string' );
		t.end();
	}
});
<commit_msg>Change headerback to FIXME<commit_after>'use strict';

// MODULES //

var tape = require( 'tape' );
var proxyquire = require( 'proxyquire' );
var IS_BROWSER = require( '@stdlib/assert/is-browser' );
var noop = require( '@stdlib/utils/noop' );
var isBuffer = require( '@stdlib/assert/is-buffer' );
var Stream = require( './fixtures/stdin.js' );
var stdin = require( './../lib' );

// FIXME //

var opts = {
	'skip': IS_BROWSER
};

// TESTS //

tape( 'main export is a function', opts, function test( t ) {
	t.ok( true, __filename );
	t.equal( typeof stdin, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function throws if provided an `encoding` argument which is not a string', opts, function test( t ) {
	var values;
	var i;

	values = [
		5,
		true,
		null,
		undefined,
		[],
		{},
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws TypeError when provided ' + values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			stdin( value, noop );
		};
	}
});

tape( 'the function throws if provided a `callback` argument which is not a function', opts, function test( t ) {
	var values;
	var i;

	values = [
		'5',
		5,
		true,
		null,
		undefined,
		[],
		{}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue1( values[i] ), TypeError, 'throws TypeError when provided ' + values[i] );
		t.throws( badValue2( values[i] ), TypeError, 'throws TypeError when provided ' + values[i] );
	}
	t.end();

	function badValue1( value ) {
		return function badValue() {
			stdin( value );
		};
	}
	function badValue2( value ) {
		return function badValue() {
			stdin( 'utf8', value );
		};
	}
});

tape( 'if `stdin` is run in TTY mode and the encoding is not set, the function returns an empty buffer', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = true;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( onRead );

	function onRead( error, data ) {
		if ( error ) {
			t.ok( false, error.message );
		}
		t.equal( isBuffer( data ), true, 'returns a buffer' );
		t.equal( data.length, 0, 'buffer is empty' );
		t.end();
	}
});

tape( 'if `stdin` is run in TTY mode and the encoding is set, the function returns an empty string', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = true;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( 'hex', onRead );

	function onRead( error, data ) {
		if ( error ) {
			t.ok( false, error.message );
		}
		t.equal( isBuffer( data ), false, 'does not return a buffer' );
		t.equal( typeof data, 'string', 'returns a string' );
		t.equal( data.length, 0, 'string is empty' );
		t.end();
	}
});

tape( 'if an error is encountered while reading from `stdin`, the error is returned', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = false;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( onRead );

	stream.emit( 'error', new Error( 'beep' ) );

	function onRead( error ) {
		if ( error ) {
			t.equal( error.message, 'beep', 'returns an error' );
		}
		t.end();
	}
});

tape( 'if an error is encountered while reading from `stdin`, the error is returned (encoding set)', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = false;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( 'utf8', onRead );

	stream.emit( 'error', new Error( 'beep' ) );

	function onRead( error ) {
		if ( error ) {
			t.equal( error.message, 'beep', 'returns an error' );
		}
		t.end();
	}
});

tape( 'if the `encoding` argument is not set, the function returns `stdin` data as a `buffer`', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = false;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( onRead );

	stream.push( new Buffer( 'beep' ) );
	stream.push( new Buffer( ' ' ) );
	stream.push( new Buffer( 'boop' ) );
	stream.push( null );

	function onRead( error, data ) {
		if ( error ) {
			t.ok( false, error.message );
		}
		t.equal( isBuffer( data ), true, 'returns a buffer' );
		t.equal( data.toString(), 'beep boop', 'returns `stdin` data' );
		t.end();
	}
});

tape( 'if the `encoding` argument is set, the function returns `stdin` data as a `string`', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = false;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( 'utf8', onRead );

	stream.push( new Buffer( 'beep' ) );
	stream.push( new Buffer( ' ' ) );
	stream.push( new Buffer( 'boop' ) );
	stream.push( null );

	function onRead( error, data ) {
		if ( error ) {
			t.ok( false, error.message );
		}
		t.equal( isBuffer( data ), false, 'does not return a buffer' );
		t.equal( typeof data, 'string', 'returns a string' );
		t.equal( data, 'beep boop', 'returns `stdin` data' );
		t.end();
	}
});

tape( 'if the `encoding` argument is not set and no `stdin` data, the function returns an empty `buffer`', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = false;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( onRead );

	stream.push( null );

	function onRead( error, data ) {
		if ( error ) {
			t.ok( false, error.message );
		}
		t.equal( isBuffer( data ), true, 'returns a buffer' );
		t.equal( data.length, 0, 'returns an empty buffer' );
		t.equal( data.toString(), '', 'buffer is empty' );
		t.end();
	}
});

tape( 'if the `encoding` argument is set and no `stdin` data, the function returns an empty `string`', opts, function test( t ) {
	var stream;
	var stdin;

	stream = new Stream();
	stream.isTTY = false;

	stdin = proxyquire( './../lib/read.js', {
		'@stdlib/streams/base/stdin': stream,
		'@noCallThru': true
	});

	stdin( 'utf8', onRead );

	stream.push( null );

	function onRead( error, data ) {
		if ( error ) {
			t.ok( false, error.message );
		}
		t.equal( isBuffer( data ), false, 'does not return a buffer' );
		t.equal( typeof data, 'string', 'returns a string' );
		t.equal( data, '', 'returns empty string' );
		t.end();
	}
});
<|endoftext|>


<commit_before>'use strict';

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import createFragment from 'react-addons-create-fragment';
import PageView from './PageView';
import BreakView from './BreakView';

export default class PaginationBoxView extends Component {
  static propTypes = {
    pageCount             : PropTypes.number.isRequired,
    pageRangeDisplayed    : PropTypes.number.isRequired,
    marginPagesDisplayed  : PropTypes.number.isRequired,
    previousLabel         : PropTypes.node,
    nextLabel             : PropTypes.node,
    breakLabel            : PropTypes.node,
    hrefBuilder           : PropTypes.func,
    onPageChange          : PropTypes.func,
    initialPage           : PropTypes.number,
    forcePage             : PropTypes.number,
    disableInitialCallback: PropTypes.bool,
    containerClassName    : PropTypes.string,
    pageClassName         : PropTypes.string,
    pageLinkClassName     : PropTypes.string,
    activeClassName       : PropTypes.string,
    previousClassName     : PropTypes.string,
    nextClassName         : PropTypes.string,
    previousLinkClassName : PropTypes.string,
    nextLinkClassName     : PropTypes.string,
    disabledClassName     : PropTypes.string,
    breakClassName        : PropTypes.string
  };

  static defaultProps = {
    pageCount             : 10,
    pageRangeDisplayed    : 2,
    marginPagesDisplayed  : 3,
    activeClassName       : "selected",
    previousClassName     : "previous",
    nextClassName         : "next",
    previousLabel         : "Previous",
    nextLabel             : "Next",
    breakLabel            : "...",
    disabledClassName     : "disabled",
    disableInitialCallback: false
  };

  constructor(props) {
    super(props);

    this.state = {
      selected: props.initialPage ? props.initialPage :
                props.forcePage   ? props.forcePage :
                0
    };
  }

  componentDidMount() {
    const { initialPage, disableInitialCallback } = this.props;
    // Call the callback with the initialPage item:
    if (typeof(initialPage) !== 'undefined' && !disableInitialCallback) {
      this.callCallback(initialPage);
    }
  }

  componentWillReceiveProps(nextProps) {
    if (typeof(nextProps.forcePage) !== 'undefined' && this.props.forcePage !== nextProps.forcePage) {
      this.setState({selected: nextProps.forcePage});
    }
  }

  handlePreviousPage = evt => {
    const { selected } = this.state;
    evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
    if (selected > 0) {
      this.handlePageSelected(selected - 1, evt);
    }
  };

  handleNextPage = evt => {
    const { selected } = this.state;
    const { pageCount } = this.props;

    evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
    if (selected < pageCount - 1) {
      this.handlePageSelected(selected + 1, evt);
    }
  };

  handlePageSelected = (selected, evt) => {
    evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);

    if (this.state.selected === selected) return;

    this.setState({selected: selected});

    // Call the callback with the new selected item:
    this.callCallback(selected);
  };

  hrefBuilder(pageIndex) {
    const { hrefBuilder, pageCount } = this.props;
    if (hrefBuilder &&
      pageIndex !== this.state.selected &&
      pageIndex >= 0 &&
      pageIndex < pageCount
    ) {
      return hrefBuilder(pageIndex + 1);
    }
  }

  callCallback = (selectedItem) => {
    if (typeof(this.props.onPageChange) !== "undefined" &&
        typeof(this.props.onPageChange) === "function") {
      this.props.onPageChange({selected: selectedItem});
    }
  };

  getPageElement(index) {
    const { selected } = this.state;
    const {
      pageClassName,
      pageLinkClassName,
      activeClassName,
      extraAriaContext
    } = this.props;

    return <PageView
      onClick={this.handlePageSelected.bind(null, index)}
      selected={selected === index}
      pageClassName={pageClassName}
      pageLinkClassName={pageLinkClassName}
      activeClassName={activeClassName}
      extraAriaContext={extraAriaContext}
      href={this.hrefBuilder(index)}
      page={index + 1} />
  }

  pagination = () => {
    let items = {};
    const {
      pageRangeDisplayed,
      pageCount,
      marginPagesDisplayed,
      breakLabel,
      breakClassName
    } = this.props;

    const {selected } = this.state;

    if (pageCount <= pageRangeDisplayed) {

      for (let index = 0; index < pageCount; index++) {
        items['key' + index] = this.getPageElement(index);
      }

    } else {

      let leftSide  = (pageRangeDisplayed / 2);
      let rightSide = (pageRangeDisplayed - leftSide);

      if (selected > pageCount - pageRangeDisplayed / 2) {
        rightSide = pageCount - selected;
        leftSide  = pageRangeDisplayed - rightSide;
      }
      else if (selected < pageRangeDisplayed / 2) {
        leftSide  = selected;
        rightSide = pageRangeDisplayed - leftSide;
      }

      let index;
      let page;
      let breakView;
      let createPageView = (index) => this.getPageElement(index);

      for (index = 0; index < pageCount; index++) {

        page = index + 1;

        if (page <= marginPagesDisplayed) {
          items['key' + index] = createPageView(index);
          continue;
        }

        if (page > pageCount - marginPagesDisplayed) {
          items['key' + index] = createPageView(index);
          continue;
        }

        if ((index >= selected - leftSide) && (index <= selected + rightSide)) {
          items['key' + index] = createPageView(index);
          continue;
        }

        let keys            = Object.keys(items);
        let breakLabelKey   = keys[keys.length - 1];
        let breakLabelValue = items[breakLabelKey];

        if (breakLabel && breakLabelValue !== breakView) {
          breakView = (
            <BreakView
              breakLabel={breakLabel}
              breakClassName={breakClassName}
            />
          );

          items['key' + index] = breakView;
        }
      }
    }

    return items;
  };

  render() {
    const {
      disabledClassName,
      previousClassName,
      nextClassName,
      pageCount,
      containerClassName,
      previousLinkClassName,
      previousLabel,
      nextLinkClassName,
      nextLabel
    } = this.props;

    const { selected } = this.state;

    let disabled = disabledClassName;
    const previousClasses = classNames(previousClassName,
                                       {[disabled]: selected === 0});

    const nextClasses = classNames(nextClassName,
                                   {[disabled]: selected === pageCount - 1});

    return (

            {previousLabel}

        {createFragment(this.pagination())}

            {nextLabel}

    );
  }
};
<commit_msg>Add missing space<commit_after>'use strict';

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import createFragment from 'react-addons-create-fragment';
import PageView from './PageView';
import BreakView from './BreakView';

export default class PaginationBoxView extends Component {
  static propTypes = {
    pageCount             : PropTypes.number.isRequired,
    pageRangeDisplayed    : PropTypes.number.isRequired,
    marginPagesDisplayed  : PropTypes.number.isRequired,
    previousLabel         : PropTypes.node,
    nextLabel             : PropTypes.node,
    breakLabel            : PropTypes.node,
    hrefBuilder           : PropTypes.func,
    onPageChange          : PropTypes.func,
    initialPage           : PropTypes.number,
    forcePage             : PropTypes.number,
    disableInitialCallback: PropTypes.bool,
    containerClassName    : PropTypes.string,
    pageClassName         : PropTypes.string,
    pageLinkClassName     : PropTypes.string,
    activeClassName       : PropTypes.string,
    previousClassName     : PropTypes.string,
    nextClassName         : PropTypes.string,
    previousLinkClassName : PropTypes.string,
    nextLinkClassName     : PropTypes.string,
    disabledClassName     : PropTypes.string,
    breakClassName        : PropTypes.string
  };

  static defaultProps = {
    pageCount             : 10,
    pageRangeDisplayed    : 2,
    marginPagesDisplayed  : 3,
    activeClassName       : "selected",
    previousClassName     : "previous",
    nextClassName         : "next",
    previousLabel         : "Previous",
    nextLabel             : "Next",
    breakLabel            : "...",
    disabledClassName     : "disabled",
    disableInitialCallback: false
  };

  constructor(props) {
    super(props);

    this.state = {
      selected: props.initialPage ? props.initialPage :
                props.forcePage   ? props.forcePage :
                0
    };
  }

  componentDidMount() {
    const { initialPage, disableInitialCallback } = this.props;
    // Call the callback with the initialPage item:
    if (typeof(initialPage) !== 'undefined' && !disableInitialCallback) {
      this.callCallback(initialPage);
    }
  }

  componentWillReceiveProps(nextProps) {
    if (typeof(nextProps.forcePage) !== 'undefined' && this.props.forcePage !== nextProps.forcePage) {
      this.setState({selected: nextProps.forcePage});
    }
  }

  handlePreviousPage = evt => {
    const { selected } = this.state;
    evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
    if (selected > 0) {
      this.handlePageSelected(selected - 1, evt);
    }
  };

  handleNextPage = evt => {
    const { selected } = this.state;
    const { pageCount } = this.props;

    evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
    if (selected < pageCount - 1) {
      this.handlePageSelected(selected + 1, evt);
    }
  };

  handlePageSelected = (selected, evt) => {
    evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);

    if (this.state.selected === selected) return;

    this.setState({selected: selected});

    // Call the callback with the new selected item:
    this.callCallback(selected);
  };

  hrefBuilder(pageIndex) {
    const { hrefBuilder, pageCount } = this.props;
    if (hrefBuilder &&
      pageIndex !== this.state.selected &&
      pageIndex >= 0 &&
      pageIndex < pageCount
    ) {
      return hrefBuilder(pageIndex + 1);
    }
  }

  callCallback = (selectedItem) => {
    if (typeof(this.props.onPageChange) !== "undefined" &&
        typeof(this.props.onPageChange) === "function") {
      this.props.onPageChange({selected: selectedItem});
    }
  };

  getPageElement(index) {
    const { selected } = this.state;
    const {
      pageClassName,
      pageLinkClassName,
      activeClassName,
      extraAriaContext
    } = this.props;

    return <PageView
      onClick={this.handlePageSelected.bind(null, index)}
      selected={selected === index}
      pageClassName={pageClassName}
      pageLinkClassName={pageLinkClassName}
      activeClassName={activeClassName}
      extraAriaContext={extraAriaContext}
      href={this.hrefBuilder(index)}
      page={index + 1} />
  }

  pagination = () => {
    let items = {};
    const {
      pageRangeDisplayed,
      pageCount,
      marginPagesDisplayed,
      breakLabel,
      breakClassName
    } = this.props;

    const { selected } = this.state;

    if (pageCount <= pageRangeDisplayed) {

      for (let index = 0; index < pageCount; index++) {
        items['key' + index] = this.getPageElement(index);
      }

    } else {

      let leftSide  = (pageRangeDisplayed / 2);
      let rightSide = (pageRangeDisplayed - leftSide);

      if (selected > pageCount - pageRangeDisplayed / 2) {
        rightSide = pageCount - selected;
        leftSide  = pageRangeDisplayed - rightSide;
      }
      else if (selected < pageRangeDisplayed / 2) {
        leftSide  = selected;
        rightSide = pageRangeDisplayed - leftSide;
      }

      let index;
      let page;
      let breakView;
      let createPageView = (index) => this.getPageElement(index);

      for (index = 0; index < pageCount; index++) {

        page = index + 1;

        if (page <= marginPagesDisplayed) {
          items['key' + index] = createPageView(index);
          continue;
        }

        if (page > pageCount - marginPagesDisplayed) {
          items['key' + index] = createPageView(index);
          continue;
        }

        if ((index >= selected - leftSide) && (index <= selected + rightSide)) {
          items['key' + index] = createPageView(index);
          continue;
        }

        let keys            = Object.keys(items);
        let breakLabelKey   = keys[keys.length - 1];
        let breakLabelValue = items[breakLabelKey];

        if (breakLabel && breakLabelValue !== breakView) {
          breakView = (
            <BreakView
              breakLabel={breakLabel}
              breakClassName={breakClassName}
            />
          );

          items['key' + index] = breakView;
        }
      }
    }

    return items;
  };

  render() {
    const {
      disabledClassName,
      previousClassName,
      nextClassName,
      pageCount,
      containerClassName,
      previousLinkClassName,
      previousLabel,
      nextLinkClassName,
      nextLabel
    } = this.props;

    const { selected } = this.state;

    let disabled = disabledClassName;
    const previousClasses = classNames(previousClassName,
                                       {[disabled]: selected === 0});

    const nextClasses = classNames(nextClassName,
                                   {[disabled]: selected === pageCount - 1});

    return (

            {previousLabel}

        {createFragment(this.pagination())}

            {nextLabel}

    );
  }
};
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { chainPropTypes } from '@material-ui/utils';
import withStyles from '../styles/withStyles';
import { capitalize } from '../utils/helpers';

const SIZE = 44;

function getRelativeValue(value, min, max) {
  const clampedValue = Math.min(Math.max(min, value), max);
  return (clampedValue - min) / (max - min);
}

function easeOut(t) {
  t = getRelativeValue(t, 0, 1);
  // https://gist.github.com/gre/1650294
  t = (t -= 1) * t * t + 1;
  return t;
}

function easeIn(t) {
  return t * t;
}

export const styles = theme => ({
  /* Styles applied to the root element. */
  root: {
    display: 'inline-block',
    lineHeight: 1, // Keep the progress centered
  },
  /* Styles applied to the root element if `variant="static"`. */
  static: {
    transition: theme.transitions.create('transform'),
  },
  /* Styles applied to the root element if `variant="indeterminate"`. */
  indeterminate: {
    animation: '$circular-rotate 1.4s linear infinite',
  },
  /* Styles applied to the root element if `color="primary"`. */
  colorPrimary: {
    color: theme.palette.primary.main,
  },
  /* Styles applied to the root element if `color="secondary"`. */
  colorSecondary: {
    color: theme.palette.secondary.main,
  },
  /* Styles applied to the `svg` element. */
  svg: {},
  /* Styles applied to the `circle` svg path. */
  circle: {
    stroke: 'currentColor',
    // Use butt to follow the specification, by chance, it's already the default CSS value.
    // strokeLinecap: 'butt',
  },
  /* Styles applied to the `circle` svg path if `variant="static"`. */
  circleStatic: {
    transition: theme.transitions.create('stroke-dashoffset'),
  },
  /* Styles applied to the `circle` svg path if `variant="indeterminate"`. */
  circleIndeterminate: {
    animation: '$circular-dash 1.4s ease-in-out infinite',
    // Some default value that looks fine waiting for the animation to kicks in.
    strokeDasharray: '80px, 200px',
    strokeDashoffset: '0px', // Add the unit to fix a Edge 16 and below bug.
  },
  '@keyframes circular-rotate': {
    '100%': {
      transform: 'rotate(360deg)',
    },
  },
  '@keyframes circular-dash': {
    '0%': {
      strokeDasharray: '1px, 200px',
      strokeDashoffset: '0px',
    },
    '50%': {
      strokeDasharray: '100px, 200px',
      strokeDashoffset: '-15px',
    },
    '100%': {
      strokeDasharray: '100px, 200px',
      strokeDashoffset: '-125px',
    },
  },
  /* Styles applied to the `circle` svg path if `disableShrink={true}`. */
  circleDisableShrink: {
    animation: 'none',
  },
});

/**
 * ## ARIA
 *
 * If the progress bar is describing the loading progress of a particular region of a page,
 * you should use `aria-describedby` to point to the progress bar, and set the `aria-busy`
 * attribute to `true` on that region until it has finished loading.
 */
const CircularProgress = React.forwardRef(function CircularProgress(props, ref) {
  const {
    classes,
    className,
    color = 'primary',
    disableShrink = false,
    size = 40,
    style,
    thickness = 3.6,
    value = 0,
    variant = 'indeterminate',
    ...other
  } = props;

  const circleStyle = {};
  const rootStyle = {};
  const rootProps = {};

  if (variant === 'determinate' || variant === 'static') {
    const circumference = 2 * Math.PI * ((SIZE - thickness) / 2);
    circleStyle.strokeDasharray = circumference.toFixed(3);
    rootProps['aria-valuenow'] = Math.round(value);

    if (variant === 'static') {
      circleStyle.strokeDashoffset = `${(((100 - value) / 100) * circumference).toFixed(3)}px`;
      rootStyle.transform = 'rotate(-90deg)';
    } else {
      circleStyle.strokeDashoffset = `${(easeIn((100 - value) / 100) * circumference).toFixed(
        3,
      )}px`;
      rootStyle.transform = `rotate(${(easeOut(value / 70) * 270).toFixed(3)}deg)`;
    }
  }

  return (
    <div
      className={clsx(
        classes.root,
        {
          [classes[`color${capitalize(color)}`]]: color !== 'inherit',
          [classes.indeterminate]: variant === 'indeterminate',
          [classes.static]: variant === 'static',
        },
        className,
      )}
      style={{ width: size, height: size, ...rootStyle, ...style }}
      ref={ref}
      role="progressbar"
      {...rootProps}
      {...other}
    >
      <svg className={classes.svg} viewBox={`${SIZE / 2} ${SIZE / 2} ${SIZE} ${SIZE}`}>
        <circle
          className={clsx(classes.circle, {
            [classes.circleIndeterminate]: variant === 'indeterminate',
            [classes.circleStatic]: variant === 'static',
            [classes.circleDisableShrink]: disableShrink,
          })}
          style={circleStyle}
          cx={SIZE}
          cy={SIZE}
          r={(SIZE - thickness) / 2}
          fill="none"
          strokeWidth={thickness}
        />
      </svg>
    </div>
  );
});

CircularProgress.propTypes = {
  /**
   * Override or extend the styles applied to the component.
   * See [CSS API](#css) below for more details.
   */
  classes: PropTypes.object.isRequired,
  /**
   * @ignore
   */
  className: PropTypes.string,
  /**
   * The color of the component. It supports those theme colors that make sense for this component.
   */
  color: PropTypes.oneOf(['primary', 'secondary', 'inherit']),
  /**
   * If `true`, the shrink animation is disabled.
   * This only works if variant is `indeterminate`.
   */
  disableShrink: chainPropTypes(PropTypes.bool, props => {
    if (props.disableShrink && props.variant && props.variant !== 'indeterminate') {
      return new Error(
        'Material-UI: you have provided the `disableShrink` prop ' +
          'with a variant other than `indeterminate`. This will have no effect.',
      );
    }

    return null;
  }),
  /**
   * The size of the circle.
   * If using a number, the pixel unit is assumed.
   * If using a string, you need to provide the CSS unit, e.g '3rem'.
   */
  size: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
  /**
   * @ignore
   */
  style: PropTypes.object,
  /**
   * The thickness of the circle.
   */
  thickness: PropTypes.number,
  /**
   * The value of the progress indicator for the determinate and static variants.
   * Value between 0 and 100.
   */
  value: PropTypes.number,
  /**
   * The variant to use.
   * Use indeterminate when there is no progress value.
   */
  variant: PropTypes.oneOf(['determinate', 'indeterminate', 'static']),
};

export default withStyles(styles, { name: 'MuiCircularProgress', flip: false })(CircularProgress);
<commit_msg>[CircularProgress] Fix centering (#17482)<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { chainPropTypes } from '@material-ui/utils';
import withStyles from '../styles/withStyles';
import { capitalize } from '../utils/helpers';

const SIZE = 44;

function getRelativeValue(value, min, max) {
  const clampedValue = Math.min(Math.max(min, value), max);
  return (clampedValue - min) / (max - min);
}

function easeOut(t) {
  t = getRelativeValue(t, 0, 1);
  // https://gist.github.com/gre/1650294
  t = (t -= 1) * t * t + 1;
  return t;
}

function easeIn(t) {
  return t * t;
}

export const styles = theme => ({
  /* Styles applied to the root element. */
  root: {
    display: 'inline-block',
  },
  /* Styles applied to the root element if `variant="static"`. */
  static: {
    transition: theme.transitions.create('transform'),
  },
  /* Styles applied to the root element if `variant="indeterminate"`. */
  indeterminate: {
    animation: '$circular-rotate 1.4s linear infinite',
  },
  /* Styles applied to the root element if `color="primary"`. */
  colorPrimary: {
    color: theme.palette.primary.main,
  },
  /* Styles applied to the root element if `color="secondary"`. */
  colorSecondary: {
    color: theme.palette.secondary.main,
  },
  /* Styles applied to the `svg` element. */
  svg: {
    display: 'block', // Keeps the progress centered
  },
  /* Styles applied to the `circle` svg path. */
  circle: {
    stroke: 'currentColor',
    // Use butt to follow the specification, by chance, it's already the default CSS value.
    // strokeLinecap: 'butt',
  },
  /* Styles applied to the `circle` svg path if `variant="static"`. */
  circleStatic: {
    transition: theme.transitions.create('stroke-dashoffset'),
  },
  /* Styles applied to the `circle` svg path if `variant="indeterminate"`. */
  circleIndeterminate: {
    animation: '$circular-dash 1.4s ease-in-out infinite',
    // Some default value that looks fine waiting for the animation to kicks in.
    strokeDasharray: '80px, 200px',
    strokeDashoffset: '0px', // Add the unit to fix a Edge 16 and below bug.
  },
  '@keyframes circular-rotate': {
    '100%': {
      transform: 'rotate(360deg)',
    },
  },
  '@keyframes circular-dash': {
    '0%': {
      strokeDasharray: '1px, 200px',
      strokeDashoffset: '0px',
    },
    '50%': {
      strokeDasharray: '100px, 200px',
      strokeDashoffset: '-15px',
    },
    '100%': {
      strokeDasharray: '100px, 200px',
      strokeDashoffset: '-125px',
    },
  },
  /* Styles applied to the `circle` svg path if `disableShrink={true}`. */
  circleDisableShrink: {
    animation: 'none',
  },
});

/**
 * ## ARIA
 *
 * If the progress bar is describing the loading progress of a particular region of a page,
 * you should use `aria-describedby` to point to the progress bar, and set the `aria-busy`
 * attribute to `true` on that region until it has finished loading.
 */
const CircularProgress = React.forwardRef(function CircularProgress(props, ref) {
  const {
    classes,
    className,
    color = 'primary',
    disableShrink = false,
    size = 40,
    style,
    thickness = 3.6,
    value = 0,
    variant = 'indeterminate',
    ...other
  } = props;

  const circleStyle = {};
  const rootStyle = {};
  const rootProps = {};

  if (variant === 'determinate' || variant === 'static') {
    const circumference = 2 * Math.PI * ((SIZE - thickness) / 2);
    circleStyle.strokeDasharray = circumference.toFixed(3);
    rootProps['aria-valuenow'] = Math.round(value);

    if (variant === 'static') {
      circleStyle.strokeDashoffset = `${(((100 - value) / 100) * circumference).toFixed(3)}px`;
      rootStyle.transform = 'rotate(-90deg)';
    } else {
      circleStyle.strokeDashoffset = `${(easeIn((100 - value) / 100) * circumference).toFixed(
        3,
      )}px`;
      rootStyle.transform = `rotate(${(easeOut(value / 70) * 270).toFixed(3)}deg)`;
    }
  }

  return (
    <div
      className={clsx(
        classes.root,
        {
          [classes[`color${capitalize(color)}`]]: color !== 'inherit',
          [classes.indeterminate]: variant === 'indeterminate',
          [classes.static]: variant === 'static',
        },
        className,
      )}
      style={{ width: size, height: size, ...rootStyle, ...style }}
      ref={ref}
      role="progressbar"
      {...rootProps}
      {...other}
    >
      <svg className={classes.svg} viewBox={`${SIZE / 2} ${SIZE / 2} ${SIZE} ${SIZE}`}>
        <circle
          className={clsx(classes.circle, {
            [classes.circleIndeterminate]: variant === 'indeterminate',
            [classes.circleStatic]: variant === 'static',
            [classes.circleDisableShrink]: disableShrink,
          })}
          style={circleStyle}
          cx={SIZE}
          cy={SIZE}
          r={(SIZE - thickness) / 2}
          fill="none"
          strokeWidth={thickness}
        />
      </svg>
    </div>
  );
});

CircularProgress.propTypes = {
  /**
   * Override or extend the styles applied to the component.
   * See [CSS API](#css) below for more details.
   */
  classes: PropTypes.object.isRequired,
  /**
   * @ignore
   */
  className: PropTypes.string,
  /**
   * The color of the component. It supports those theme colors that make sense for this component.
   */
  color: PropTypes.oneOf(['primary', 'secondary', 'inherit']),
  /**
   * If `true`, the shrink animation is disabled.
   * This only works if variant is `indeterminate`.
   */
  disableShrink: chainPropTypes(PropTypes.bool, props => {
    if (props.disableShrink && props.variant && props.variant !== 'indeterminate') {
      return new Error(
        'Material-UI: you have provided the `disableShrink` prop ' +
          'with a variant other than `indeterminate`. This will have no effect.',
      );
    }

    return null;
  }),
  /**
   * The size of the circle.
   * If using a number, the pixel unit is assumed.
   * If using a string, you need to provide the CSS unit, e.g '3rem'.
   */
  size: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
  /**
   * @ignore
   */
  style: PropTypes.object,
  /**
   * The thickness of the circle.
   */
  thickness: PropTypes.number,
  /**
   * The value of the progress indicator for the determinate and static variants.
   * Value between 0 and 100.
   */
  value: PropTypes.number,
  /**
   * The variant to use.
   * Use indeterminate when there is no progress value.
   */
  variant: PropTypes.oneOf(['determinate', 'indeterminate', 'static']),
};

export default withStyles(styles, { name: 'MuiCircularProgress', flip: false })(CircularProgress);
<|endoftext|>


<commit_before>import React from 'react'
import { saveAs } from 'file-saver'

import normalizeWordData from '../../core/normalizeWordData/normalizeWordData'
import makeCard from '../../core/makeCard/makeCard'

import splitByWord from '../../utils/splitByWord/splitByWord'
import maybePluralize from '../../utils/maybePluralize/maybePluralize'
import wordToData from '../../utils/wordToData/wordToData'

import GithubCorner from 'react-github-corner'
// import LinearProgress from '@material-ui/core/LinearProgress'
import Header from '../Header/Header'
import DownloadButton from '../DownloadButton/DownloadButton'
import ResultCards from '../ResultCards/ResultCards'
import UserWords from '../UserWords/UserWords'
import DeckName from '../DeckName/DeckName'

import './App.css'

const template = {
    css: `
			.card { font-family: arial; font-size: 20px; text-align: center; color: black; background-color: white; }
			.lta-example { font-style: italic; }
			.lta-form { font-weight: bold; }
		`
}

export default class App extends React.Component {
    state = {
        words: [],
        inputValue: '',
        wordsCards: {},
        deckName: 'English words'
    }

    componentDidMount() {
        try {
            if (localStorage.state) {
                this.setState(JSON.parse(localStorage.state))
            } else {
                this.setState({ inputValue: localStorage.inputValue })
            }
        } catch (error) {
            console.error(error)
        }
    }

    componentDidUpdate(prevProps, prevState) {
        localStorage.state = JSON.stringify(this.state)
    }

    handleDeckNameChange = event => {
        this.setState({
            deckName: event.target.value
        })
    }

    handleInputChange = async event => {
        this.setState({
            inputValue: event.target.value
        })
    }

    handleDeleteButtonClick = wordToDelete => () => {
        this.setState(prevState => ({
            words: prevState.words.filter(word => word !== wordToDelete),
            wordsCards: { ...prevState.wordsCards, [wordToDelete]: undefined }
        }))
    }

    handleSubmit = event => {
        event.preventDefault()

        if (this.state.inputValue === '') {
            return
        }

        const isMultilineInputValue = /\n/.test(this.state.inputValue)
        const newWords = isMultilineInputValue
            ? splitByWord(this.state.inputValue)
            : [this.state.inputValue]

        this.setState(
            prevState => ({
                words: [...newWords, ...prevState.words],
                inputValue: ''
            }),
            () => {
                this.state.words.map(async word => {
                    const wordData = await wordToData(word)

                    if (!wordData) {
                        this.setState(prevState => ({
                            wordsCards: {
                                ...prevState.wordsCards,
                                [word]: null
                            }
                        }))
                        return
                    }

                    this.setState(prevState => ({
                        wordsCards: {
                            ...prevState.wordsCards,
                            [wordData.headword]: normalizeWordData(wordData)
                        },
                        words: prevState.words.map(
                            item => (item === word ? wordData.headword : item)
                        )
                    }))
                })
            }
        )
    }

    handleDownload = event => {
        event.preventDefault()

        const cardsArr = this.state.words
            .reverse()
            .map(word => this.state.wordsCards[word])
            .reduce((acc, curr) => (curr ? acc.concat(...curr) : acc), [])
            .map(makeCard)

        fetch('https://micro-anki-yakhinvadim.now.sh/', {
            method: 'POST',
            headers: new Headers({ 'Content-Type': 'application/json' }),
            body: JSON.stringify({
                cards: cardsArr,
                deckName: this.state.deckName,
                template: template
            })
        })
            .then(res => res.blob())
            .then(blob => saveAs(blob, `${this.state.deckName}.apkg`))
            .catch(console.error)
    }

    handleEnterPress = event => {
        if (event.key === 'Enter' && event.shiftKey === false) {
            event.preventDefault()
            this.handleSubmit(event)
        }
    }

    render() {
        const wordsTotalNumber = this.state.words.length
        const cardsTotalNumber = Object.values(
            this.state.wordsCards
        ).reduce((acc, curr) => {
            return acc + (curr ? curr.length : 0)
        }, 0)

        const wordsTotal = maybePluralize(wordsTotalNumber, 'word')
        const cardsTotal = maybePluralize(cardsTotalNumber, 'card')

        const totals = `${wordsTotal}, ${cardsTotal}`

        return (

                <GithubCorner
                    href="https://github.com/yakhinvadim/longman-to-anki"
                    bannerColor="#3f51b5"
                />

                <form onSubmit={this.handleSubmit}>
                    <UserWords
                        value={this.state.inputValue}
                        onChange={this.handleInputChange}
                        onKeyDown={this.handleEnterPress}
                    />
                </form>

                {/* <LinearProgress
					mode="determinate"
					value={Object.keys(this.state.wordsCards).length}
					max={this.state.words.length}
				/> */}

                <ResultCards
                    words={this.state.words}
                    wordsCards={this.state.wordsCards}
                    onDeleteButtonClick={this.handleDeleteButtonClick}
                />

                <DeckName
                    value={this.state.deckName}
                    onChange={this.handleDeckNameChange}
                />

                        {totals}

                    <DownloadButton
                        onClick={this.handleDownload}
                        disabled={!cardsTotalNumber}
                    />

        )
    }
}
<commit_msg>feature: add Grid<commit_after>import React from 'react'
import { saveAs } from 'file-saver'

import normalizeWordData from '../../core/normalizeWordData/normalizeWordData'
import makeCard from '../../core/makeCard/makeCard'

import splitByWord from '../../utils/splitByWord/splitByWord'
import maybePluralize from '../../utils/maybePluralize/maybePluralize'
import wordToData from '../../utils/wordToData/wordToData'

import GithubCorner from 'react-github-corner'

import Header from '../Header/Header'
import DownloadButton from '../DownloadButton/DownloadButton'
import ResultCards from '../ResultCards/ResultCards'
import UserWords from '../UserWords/UserWords'
import DeckName from '../DeckName/DeckName'

import Grid from '@material-ui/core/Grid'

import './App.css'

const template = {
	css: `
			.card { font-family: arial; font-size: 20px; text-align: center; color: black; background-color: white; }
			.lta-example { font-style: italic; }
			.lta-form { font-weight: bold; }
		`
}

export default class App extends React.Component {
	state = {
		words: [],
		inputValue: '',
		wordsCards: {},
		deckName: 'English words'
	}

	componentDidMount() {
		try {
			if (localStorage.state) {
				this.setState(JSON.parse(localStorage.state))
			} else {
				this.setState({ inputValue: localStorage.inputValue })
			}
		} catch (error) {
			console.error(error)
		}
	}

	componentDidUpdate(prevProps, prevState) {
		localStorage.state = JSON.stringify(this.state)
	}

	handleDeckNameChange = event => {
		this.setState({
			deckName: event.target.value
		})
	}

	handleInputChange = async event => {
		this.setState({
			inputValue: event.target.value
		})
	}

	handleDeleteButtonClick = wordToDelete => () => {
		this.setState(prevState => ({
			words: prevState.words.filter(word => word !== wordToDelete),
			wordsCards: { ...prevState.wordsCards, [wordToDelete]: undefined }
		}))
	}

	handleSubmit = event => {
		event.preventDefault()

		if (this.state.inputValue === '') {
			return
		}

		const isMultilineInputValue = /\n/.test(this.state.inputValue)
		const newWords = isMultilineInputValue
			? splitByWord(this.state.inputValue)
			: [this.state.inputValue]

		this.setState(
			prevState => ({
				words: [...newWords, ...prevState.words],
				inputValue: ''
			}),
			() => {
				this.state.words.map(async word => {
					const wordData = await wordToData(word)

					if (!wordData) {
						this.setState(prevState => ({
							wordsCards: {
								...prevState.wordsCards,
								[word]: null
							}
						}))
						return
					}

					this.setState(prevState => ({
						wordsCards: {
							...prevState.wordsCards,
							[wordData.headword]: normalizeWordData(wordData)
						},
						words: prevState.words.map(item =>
							item === word ? wordData.headword : item
						)
					}))
				})
			}
		)
	}

	handleDownload = event => {
		event.preventDefault()

		const cardsArr = this.state.words
			.reverse()
			.map(word => this.state.wordsCards[word])
			.reduce((acc, curr) => (curr ? acc.concat(...curr) : acc), [])
			.map(makeCard)

		fetch('https://micro-anki-yakhinvadim.now.sh/', {
			method: 'POST',
			headers: new Headers({ 'Content-Type': 'application/json' }),
			body: JSON.stringify({
				cards: cardsArr,
				deckName: this.state.deckName,
				template: template
			})
		})
			.then(res => res.blob())
			.then(blob => saveAs(blob, `${this.state.deckName}.apkg`))
			.catch(console.error)
	}

	handleEnterPress = event => {
		if (event.key === 'Enter' && event.shiftKey === false) {
			event.preventDefault()
			this.handleSubmit(event)
		}
	}

	render() {
		const wordsTotalNumber = this.state.words.length
		const cardsTotalNumber = Object.values(this.state.wordsCards).reduce(
			(acc, curr) => {
				return acc + (curr ? curr.length : 0)
			},
			0
		)

		const wordsTotal = maybePluralize(wordsTotalNumber, 'word')
		const cardsTotal = maybePluralize(cardsTotalNumber, 'card')

		const totals = `${wordsTotal}, ${cardsTotal}`

		return (

				<GithubCorner
					href="https://github.com/yakhinvadim/longman-to-anki"
					bannerColor="#3f51b5"
				/>

				<Grid container spacing={16}>
					<Grid item item xs={12}>

					</Grid>

					<Grid item item xs={12}>
						<form onSubmit={this.handleSubmit}>
							<UserWords
								value={this.state.inputValue}
								onChange={this.handleInputChange}
								onKeyDown={this.handleEnterPress}
							/>
						</form>
					</Grid>

					<Grid item item xs={12}>
						<ResultCards
							words={this.state.words}
							wordsCards={this.state.wordsCards}
							onDeleteButtonClick={this.handleDeleteButtonClick}
						/>
					</Grid>

					<Grid item item xs={12}>
						<DeckName
							value={this.state.deckName}
							onChange={this.handleDeckNameChange}
						/>
					</Grid>

					<Grid item item xs={12}>

							{totals}
							<DownloadButton
								onClick={this.handleDownload}
								disabled={!cardsTotalNumber}
							/>

					</Grid>
				</Grid>

		)
	}
}
<|endoftext|>


<commit_before>
/**
 * WPCOM module
 */

var WPCOM = require('../');
var Sites = require('../lib/sites');
var Media = require('../lib/media');
var util = require('./util');

/**
 * Testing data
 */

var test = require('./data');

/**
 * WPCOM instance
 */

describe('WPCOM#Sites#Media', function(){

  // Create a new_media before to start the tests

  var new_media;
  before(function(done){
    util.addMedia(function(err, media) {
      if (err) return done(err);

      console.log('-> media -> ', media);
      new_media = media;
      done();
    });
  });

  describe('sync', function(){

    it('should create an `Media` instance from `Sites`', function(){
      var media = WPCOM().sites().media();
      media
        .should.be.an.instanceOf(Media);
    });

  });

});
<commit_msg>test: remove console.log()<commit_after>
/**
 * WPCOM module
 */

var WPCOM = require('../');
var Sites = require('../lib/sites');
var Media = require('../lib/media');
var util = require('./util');

/**
 * Testing data
 */

var test = require('./data');

/**
 * WPCOM instance
 */

describe('WPCOM#Sites#Media', function(){

  // Create a new_media before to start the tests

  var new_media;
  before(function(done){
    util.addMedia(function(err, media) {
      if (err) return done(err);

      new_media = media;
      done();
    });
  });

  describe('sync', function(){

    it('should create an `Media` instance from `Sites`', function(){
      var media = WPCOM().sites().media();
      media
        .should.be.an.instanceOf(Media);
    });

  });

});
<|endoftext|>


<commit_before><commit_msg>disabled failing specs<commit_after><|endoftext|>


<commit_before>/*globals I18n,LoadChartsSettings,StrategyHelper*/

var Transformer = (function () {
    'use strict';

    var currentWeek,
        msInWeek     = 6.048e+8,
        chartLengths = {
            long: 35040,
            short: 8760,
            annual: 365
        };

    function generateCapacity(data, results) {
        var capacity = (data.capacity * (data.units || 1.0)),
            extent   = d3.extent(results[0].values, function (d) { return d.x; });

        return {
            key:      "Capacity",
            type:     "capacity",
            color:    LoadChartsSettings.capacity.color,
            area:     false,
            visible:  LoadChartsSettings.capacity.visible,
            values:   [
                { x: extent[0], y: capacity },
                { x: extent[1], y: capacity },
                { x: extent[0], y: capacity * -1 },
                { x: extent[1], y: capacity * -1 }
            ]
        };
    }

    function fetchLoad() {
        if (this.settings.load) {
            return this.settings.load;
        } else if (StrategyHelper.anyStrategies()) {
            return [{ area: true,  type: 'load_strategies' },
                    { area: false, type: 'load' },
                    { area: true,  type: 'gas_strategies' },
                    { area: false, type: 'gas' },
                    { area: true,  type: 'heat_strategies' },
                    { area: false, type: 'heat' }];
        } else {
            return [{ area: true, type: 'load' },
                    { area: true, type: 'gas' },
                    { area: true, type: 'heat' }];
        }
    }

    function formatDateFromFrame(loads, frame) {
        var multiplier = -1,
            len        = loads.length,
            offset     = currentWeek === 0 ? 0 : (currentWeek - 1) * msInWeek;

        if (len === chartLengths.long || len === 673) {
            multiplier = 900000;
        } else if (len === chartLengths.short) {
            multiplier = 3600000;
        } else if (len === chartLengths.annual) {
            multiplier = 86400000;
        }

        return new Date((frame * multiplier) + offset);
    }

    function formatYvalue(y) {
        if (this.scaling) {
            return ((y * 1000) / this.scaling.unit.power.multiple);
        } else {
            return y;
        }
    }

    function setCoords(loads) {
        return loads.map(function (y, x) {
            return { x: formatDateFromFrame(loads, x), y: formatYvalue.call(this, y) };
        }.bind(this));
    }

    function isStaticLoadOrTotal() {
        return (this.settings.load || this.settings.view_as === 'total');
    }

    function isShown(chartType) {
        var type = this.settings.view_carrier;

        if (this.strategies && StrategyHelper.anyStrategies()) {
            type += "_strategies";
        }

        return isStaticLoadOrTotal.call(this) || chartType === type;
    }

    function setTotalLoad(datum, values) {
        var type     = (datum.type || this.d3Chart.curveType),
            settings = LoadChartsSettings[type];

        if (!settings) {
            throw "No settings available for '" + type + "'";
        }

        return {
            key:     settings.name,
            type:    datum.type,
            values:  setCoords.call(this, values),
            area:    datum.area,
            color:   settings.color,
            visible: settings.visible
        };
    }

    function setLoadsPerTech(values) {
        var tech;

        for (tech in values.tech_loads) {
            if (!LoadChartsSettings[tech]) {
                LoadChartsSettings[tech] = { visible: true };
            }

            this.results.push({
                key:     I18n.translations.en.inputs[tech],
                type:    tech,
                values:  setCoords.call(this, values.tech_loads[tech]),
                area:    (this.settings.view_as === 'stacked'),
                color:   $(".technologies.hidden span." + tech).data('color'),
                visible: LoadChartsSettings[tech].visible
            });
        }
    }

    function setLoad(datum) {
        var values = datum.values || this.data[datum.type];

        if (isShown.call(this, datum.type) && values.total) {
            if (isStaticLoadOrTotal.call(this)) {
                this.results.push(setTotalLoad.call(this, datum, values.total));
            } else {
                setLoadsPerTech.call(this, values);
            }
        }
    }

    return {
        transform: function (d3Chart, thisCurrentWeek) {
            this.results  = [];
            this.data     = d3Chart.lastRequestedData;
            this.settings = d3Chart.settings;
            this.scaling  = d3Chart.scaling;

            currentWeek   = thisCurrentWeek;

            fetchLoad.call(this).forEach(setLoad.bind(this));

            if (this.data.capacity && this.settings.view_as === 'total') {
                this.results.push(generateCapacity(this.data, this.results));
            }

            return this.results;
        }
    };
}());
<commit_msg>Correctly scaling capacity series on load chart<commit_after>/*globals I18n,LoadChartsSettings,StrategyHelper*/

var Transformer = (function () {
    'use strict';

    var currentWeek,
        msInWeek     = 6.048e+8,
        chartLengths = {
            long: 35040,
            short: 8760,
            annual: 365
        };

    function generateCapacity(data, results, scaling) {
        var capacity = (data.capacity * (data.units || 1.0)),
            extent   = d3.extent(results[0].values, function (d) { return d.x; });

        // scale capacity according to the unit being shown.
        capacity = (capacity * 1000) / scaling.unit.power.multiple;

        return {
            key:      "Capacity",
            type:     "capacity",
            color:    LoadChartsSettings.capacity.color,
            area:     false,
            visible:  LoadChartsSettings.capacity.visible,
            values:   [
                { x: extent[0], y: capacity },
                { x: extent[1], y: capacity },
                { x: extent[0], y: capacity * -1 },
                { x: extent[1], y: capacity * -1 }
            ]
        };
    }

    function fetchLoad() {
        if (this.settings.load) {
            return this.settings.load;
        } else if (StrategyHelper.anyStrategies()) {
            return [{ area: true,  type: 'load_strategies' },
                    { area: false, type: 'load' },
                    { area: true,  type: 'gas_strategies' },
                    { area: false, type: 'gas' },
                    { area: true,  type: 'heat_strategies' },
                    { area: false, type: 'heat' }];
        } else {
            return [{ area: true, type: 'load' },
                    { area: true, type: 'gas' },
                    { area: true, type: 'heat' }];
        }
    }

    function formatDateFromFrame(loads, frame) {
        var multiplier = -1,
            len        = loads.length,
            offset     = currentWeek === 0 ? 0 : (currentWeek - 1) * msInWeek;

        if (len === chartLengths.long || len === 673) {
            multiplier = 900000;
        } else if (len === chartLengths.short) {
            multiplier = 3600000;
        } else if (len === chartLengths.annual) {
            multiplier = 86400000;
        }

        return new Date((frame * multiplier) + offset);
    }

    function formatYvalue(y) {
        if (this.scaling) {
            return ((y * 1000) / this.scaling.unit.power.multiple);
        } else {
            return y;
        }
    }

    function setCoords(loads) {
        return loads.map(function (y, x) {
            return { x: formatDateFromFrame(loads, x), y: formatYvalue.call(this, y) };
        }.bind(this));
    }

    function isStaticLoadOrTotal() {
        return (this.settings.load || this.settings.view_as === 'total');
    }

    function isShown(chartType) {
        var type = this.settings.view_carrier;

        if (this.strategies && StrategyHelper.anyStrategies()) {
            type += "_strategies";
        }

        return isStaticLoadOrTotal.call(this) || chartType === type;
    }

    function setTotalLoad(datum, values) {
        var type     = (datum.type || this.d3Chart.curveType),
            settings = LoadChartsSettings[type];

        if (!settings) {
            throw "No settings available for '" + type + "'";
        }

        return {
            key:     settings.name,
            type:    datum.type,
            values:  setCoords.call(this, values),
            area:    datum.area,
            color:   settings.color,
            visible: settings.visible
        };
    }

    function setLoadsPerTech(values) {
        var tech;

        for (tech in values.tech_loads) {
            if (!LoadChartsSettings[tech]) {
                LoadChartsSettings[tech] = { visible: true };
            }

            this.results.push({
                key:     I18n.translations.en.inputs[tech],
                type:    tech,
                values:  setCoords.call(this, values.tech_loads[tech]),
                area:    (this.settings.view_as === 'stacked'),
                color:   $(".technologies.hidden span." + tech).data('color'),
                visible: LoadChartsSettings[tech].visible
            });
        }
    }

    function setLoad(datum) {
        var values = datum.values || this.data[datum.type];

        if (isShown.call(this, datum.type) && values.total) {
            if (isStaticLoadOrTotal.call(this)) {
                this.results.push(setTotalLoad.call(this, datum, values.total));
            } else {
                setLoadsPerTech.call(this, values);
            }
        }
    }

    return {
        transform: function (d3Chart, thisCurrentWeek) {
            this.results  = [];
            this.data     = d3Chart.lastRequestedData;
            this.settings = d3Chart.settings;
            this.scaling  = d3Chart.scaling;

            currentWeek   = thisCurrentWeek;

            fetchLoad.call(this).forEach(setLoad.bind(this));

            if (this.data.capacity && this.settings.view_as === 'total') {
                this.results.push(
                    generateCapacity(this.data, this.results, this.scaling)
                );
            }

            return this.results;
        }
    };
}());
<|endoftext|>


<commit_before>/* eslint-disable max-len, no-else-return */

// the collatz conjecture
// https://youtu.be/VrrnjYgDBEk?t=729
// http://www.cs.utep.edu/vladik/cs2401.10a/Ch_14_Recursion.pdf

// http://www.w3resource.com/javascript-exercises/javascript-recursion-functions-exercises.php
// http://www.w3resource.com/c-programming-exercises/recursion/index.php
// https://roman01la.github.io/recursion-exercises/
// https://cscircles.cemc.uwaterloo.ca/16-recursion/
// http://www.bowdoin.edu/~ltoma/teaching/cs107/spring05/recursion.html
// http://codingbat.com/java/Recursion-1
// http://www.cse.chalmers.se/edu/year/2016/course/TDA555/ex-week2.html
// https://www.inf.unibz.it/~calvanese/teaching/04-05-ip/exercises/recursion/strings/
// http://www.geeksforgeeks.org/category/algorithm/recursion/
// https://www.hackerrank.com/domains/fp/fp-recursion
// http://www.cs.wustl.edu/~kjg/cse131/modules/recursion/lab.html
// http://anandology.com/python-practice-book/functional-programming.html

// Write a recursive function that outputs the range between two positive numbers
// myFunction(1, 5) #=> [1, 2, 3, 4, 5]
export const range = (array) => (
  array
)

// Write a recursive function that outputs the sum of an array of integers
// myFunction([1, 2, 3, 4, 5, 6]) #=> 21
export const sumArray = (array) => {
  if (array.length === 1) {
    return array[0]
  }

  return array.shift() + sumArray(array)
}

// Implement Ruby's `select` in JavaScript recursively.
// Example: iterating over [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and only returning even numbers.
export const arraySelect = (array) => (
  array
)

// Implement Ruby's `drop_while` in JavaScript recursively.
// Example: iterating over [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and only returning integers greater than 7.
// drop_while: http://ruby-doc.org/core-2.2.3/Enumerable.html#method-i-drop
export const dropWhile = (array) => (
  array
)

/**
 * Reverse a string.
 *
 * The substr() method returns the characters in a string beginning at the specified
 * location through the specified number of characters.
 *
 * The charAt() method returns the specified character from a string.
 *
 * So what's happening is that if we aren't at an empty string we are going to recurse
 * reverseString and pass it the a substring sans the first chracter of our current string.
 * We append the current string's character at the first character as well.
 *
 * For the world hello:
 *    recursionReverse('hello')
 *    (recursionReverse('ello') + 'h')
 *    ((recursionReverse('llo') + 'e') + 'h')
 *    (((recursionReverse('lo') + 'l') + 'e') + 'h')
 *    ((((recursionReverse('o') + 'l') + 'l' ) + 'e') + 'h')
 *    (((('o') + 'l') + 'l' ) + 'e') + 'h')
 *
 * s
 *
 * @see http://bit.ly/2v4XBZE
 * @see http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/ *
 * @param {string} string String to reverse.
 * @return {string}
 */
export const reverseString = (string) => {
  if (string.length <= 1) {
    return string
  }

  console.log(string)

  return reverseString(string.substr(1)) + string.charAt(0)
}

/**
 * Reverse a string using a simpler ternary.
 *
 * The substr() method returns the characters in a string beginning at the specified
 * location through the specified number of characters.
 *
 * The charAt() method returns the specified character from a string.
 *
 * So what's happening is that if we aren't at an empty string we are going to recurse
 * reverseString and pass it the a substring sans the first chracter of our current string.
 * We append the current string's character at the first character as well.
 *
 * For the world hello:
 *    recursionReverse('hello')
 *    (recursionReverse('ello') + 'h')
 *    ((recursionReverse('llo') + 'e') + 'h')
 *    (((recursionReverse('lo') + 'l') + 'e') + 'h')
 *    ((((recursionReverse('o') + 'l') + 'l' ) + 'e') + 'h')
 *    (((('o') + 'l') + 'l' ) + 'e') + 'h')
 *
 * @see http://bit.ly/2v4XBZE
 * @see http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/ *
 * @param {string} string String to reverse.
 * @return {string}
 */
export const reverseStringTernary = (string) => (
  (string.length <= 1)
    ? string
    : reverseStringTernary(string.substr(1)) + string.charAt(0)
)
<commit_msg>Comments.<commit_after>/* eslint-disable max-len, no-else-return */

// the collatz conjecture
// https://youtu.be/VrrnjYgDBEk?t=729
// http://www.cs.utep.edu/vladik/cs2401.10a/Ch_14_Recursion.pdf

// http://www.w3resource.com/javascript-exercises/javascript-recursion-functions-exercises.php
// http://www.w3resource.com/c-programming-exercises/recursion/index.php
// https://roman01la.github.io/recursion-exercises/
// https://cscircles.cemc.uwaterloo.ca/16-recursion/
// http://www.bowdoin.edu/~ltoma/teaching/cs107/spring05/recursion.html
// http://codingbat.com/java/Recursion-1
// http://www.cse.chalmers.se/edu/year/2016/course/TDA555/ex-week2.html
// https://www.inf.unibz.it/~calvanese/teaching/04-05-ip/exercises/recursion/strings/
// http://www.geeksforgeeks.org/category/algorithm/recursion/
// https://www.hackerrank.com/domains/fp/fp-recursion
// http://www.cs.wustl.edu/~kjg/cse131/modules/recursion/lab.html
// http://anandology.com/python-practice-book/functional-programming.html

// Write a recursive function that outputs the range between two positive numbers
// myFunction(1, 5) #=> [1, 2, 3, 4, 5]
export const range = (array) => (
  array
)

// Write a recursive function that outputs the sum of an array of integers
// myFunction([1, 2, 3, 4, 5, 6]) #=> 21
export const sumArray = (array) => {
  if (array.length === 1) {
    return array[0]
  }

  return array.shift() + sumArray(array)
}

// Implement Ruby's `select` in JavaScript recursively.
// Example: iterating over [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and only returning even numbers.
export const arraySelect = (array) => (
  array
)

// Implement Ruby's `drop_while` in JavaScript recursively.
// Example: iterating over [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and only returning integers greater than 7.
// drop_while: http://ruby-doc.org/core-2.2.3/Enumerable.html#method-i-drop
export const dropWhile = (array) => (
  array
)

/**
 * Reverse a string.
 *
 * The substr() method returns the characters in a string beginning at the specified
 * location through the specified number of characters.
 *
 * The charAt() method returns the specified character from a string.
 *
 * So what's happening is that if we aren't at an empty string we are going to recurse
 * reverseString and pass it the a substring sans the first chracter of our current string.
 * We append the current string's character at the first character as well.
 *
 * For the world hello:
 *    recursionReverse('hello')
 *    (recursionReverse('ello') + 'h')
 *    ((recursionReverse('llo') + 'e') + 'h')
 *    (((recursionReverse('lo') + 'l') + 'e') + 'h')
 *    ((((recursionReverse('o') + 'l') + 'l' ) + 'e') + 'h')
 *    (((('o') + 'l') + 'l' ) + 'e') + 'h')
 *
 * What is odd is how we're doing the return in the recurisve function. This is often what
 * throws me off. We are passing in a substring for as long as we have a string left and
 * then we call ourself again. What is important here is the string.charAt(0) as this is
 * what we're using to build out the reverse string. until we reach the end. The diagram
 * above explains it best.
 *
 * @see http://bit.ly/2v4XBZE
 * @see http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/ *
 * @param {string} string String to reverse.
 * @return {string}
 */
export const reverseString = (string) => {
  if (string.length === 0) {
    return string
  }

  return reverseString(string.substr(1)) + string.charAt(0)
}

/**
 * Reverse a string using a simpler ternary.
 *
 * The substr() method returns the characters in a string beginning at the specified
 * location through the specified number of characters.
 *
 * The charAt() method returns the specified character from a string.
 *
 * So what's happening is that if we aren't at an empty string we are going to recurse
 * reverseString and pass it the a substring sans the first chracter of our current string.
 * We append the current string's character at the first character as well.
 *
 * For the world hello:
 *    recursionReverse('hello')
 *    (recursionReverse('ello') + 'h')
 *    ((recursionReverse('llo') + 'e') + 'h')
 *    (((recursionReverse('lo') + 'l') + 'e') + 'h')
 *    ((((recursionReverse('o') + 'l') + 'l' ) + 'e') + 'h')
 *    (((('o') + 'l') + 'l' ) + 'e') + 'h')
 *
 * @see http://bit.ly/2v4XBZE
 * @see http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/ *
 * @param {string} string String to reverse.
 * @return {string}
 */
export const reverseStringTernary = (string) => (
  (string.length === 0)
    ? string
    : reverseStringTernary(string.substr(1)) + string.charAt(0)
)
<|endoftext|>


<commit_before>//Marker Icons
var MapObj = new Map();
var StorylineMapObj = new StorylineMap();
var ListPOI = [];
var ListPOT = [];
var baseMaps;
var map;

var markerIconPOIBlue = MapObj.createMarker('images/marker-icon-blue.png', 64, 64, 30, 64, 1, 1);
var markerIconPOIGreen = MapObj.createMarker('images/marker-icon-green.png', 64, 64, 30, 64, 1, 1);
var markerIconPOIRed = MapObj.createMarker('images/marker-icon-red.png', 64, 64, 30, 64, 1, 1);
var markerIconNode = MapObj.createMarker('images/none-marker-icon.png');
var mapMinZoom = 1;
var mapMaxZoom = 5;
var floors = [new Floor(1), new Floor(2), new Floor(3), new Floor(4), new Floor(5)];
var storyline;
var storylineSelectedID;
var lastVisitedNodeID = localStorage.getItem("lastVisitedNodeID");
var navigationPath = new Navigation([], false);
var startNode;

function displayStoryline() {
    //Test - next POI button
    $("#nextBtn").hide();
    $("#scanBtn").hide();

    if (storylineSelectedID == null) {
        storylineSelectedID= "S1";
    }

    $('#currentStoryline').text("Current storyline: " + localStorage.getItem("currentStoryline"));
    $('#previewStoryline').text("Previewing storyline: " + localStorage.getItem("currentStoryline"));
    storylineSelectedID = localStorage.getItem("currentStoryline");

    floors = MapObj.parsePOI(floors);
    floors = MapObj.parsePOT(floors);
    floors = MapObj.createFloorTileLayers(floors, mapMinZoom, mapMaxZoom);
    MapObj.parseEdges();
    storyline = StorylineMapObj.parseStoryline(storylineSelectedID);
    storyline = StorylineMapObj.parseNodePath(storyline);

    //browser testing (default storyline)

    if (lastVisitedNodeID != null && lastVisitedNodeID != storyline.nodePath[0]) {
        //From list of POI & POT & edges, find shortest path
        //Get all nodes(markers) from shortest path and add them to floor object
        //create polyline, groupLayers adn add that to map
        //display title: get to the starting point
        //once first beacon is scanned, clear markers and call functions below to create the new storyline
        var dijkstras = new Dijkstra(ListPOI, ListPOT);
        //start = last visited node, finish = storyline start node
        start = lastVisitedNodeID;
        finish = storyline.nodePath[0];
        var shortestPathID = dijkstras.shortestPath(start, finish);
        navigationPath = new Navigation(shortestPathID, true);
        navigationPath = StorylineMapObj.parseNodePath(navigationPath);
        floors = StorylineMapObj.createPolyline(floors, navigationPath);
        floors = MapObj.groupLayers(floors);
        floors = StorylineMapObj.addPolylines(floors);

        startNode = ListPOI[navigationPath.nodePath[0]];
        $('#currentStoryline').text("Navigate to the start");
    } else {
        floors = StorylineMapObj.createPolyline(floors, storyline);
        floors = MapObj.groupLayers(floors);
        floors = StorylineMapObj.addPolylines(floors);
        startNode = ListPOI[storyline.nodePath[0]];
    }

    //floor radio buttons
    var baseMaps = {
        "1": floors[0].groupLayer,
        "2": floors[1].groupLayer,
        "3": floors[2].groupLayer,
        "4": floors[3].groupLayer,
        "5": floors[4].groupLayer
    };
    //floor overlay radio buttons
    var overlayMaps = {
        //"Markers": floor1Overlay
    };

    //create map
    map = L.map('map', {
        maxZoom: mapMaxZoom,
        minZoom: mapMinZoom,
        crs: L.CRS.Simple,
        layers: floors[0].groupLayer
    });
    map.on("load", function () {
        if (startNode.floorID != 1) {
            map.addLayer(floors[startNode.floorID - 1].groupLayer);
            map.removeLayer(floors[0].groupLayer);
        }
        if (localStorage.getItem("startIsSelected") == "true") {
            localStorage.removeItem("startIsSelected");
            startStoryline();
        }

    });
    map.setView([0, 0], mapMaxZoom);
    //map bounds
    var mapBounds = new L.LatLngBounds(
        map.unproject([0, 6144], mapMaxZoom),
        map.unproject([3072, 0], mapMaxZoom));

    //add bounds to map
    map.fitBounds(mapBounds);
    //Add controls (radio buttons) to map in order to switch between floors
    L.control.layers(baseMaps, overlayMaps, { collapsed: false }).addTo(map).setPosition('bottomright');

}

function endPreview() {
    localStorage.removeItem("currentStoryline");
    window.location.replace("storylines.html");
}

function startStoryline() {
    $("#starBtn").hide();
    $("#backBtn").hide();
    $("#previewStoryline").hide();
    $("#nextBtn").show();
    $("#scanBtn").show();
    focusOnStart();
}

function focusOnStart() {
    if (navigationPath.isNotAtStart) {
        firstNodeID = navigationPath.nodePath[0];
        firstNode = navigationPath.nodes[firstNodeID];
    } else {
        firstNodeID = storyline.nodePath[0];
        firstNode = storyline.nodes[firstNodeID];
    }
    focusOnNode(firstNode, 3);
}

//***TODO***
//When beacon in proximity function is fired, should call this method
//Check whether beacon uuid == next Node.iBeacon.uuid
//if true -> fire popup
function currentPOI(storyline) {
    var node;
    for (i = 0; i < storyline.nodePath.length; i++) {
        //if isPOI
        node = storyline.nodes[storyline.nodePath[i]];
        if (storyline.nodePath[i].charAt(0) == "0" && localStorage.getItem("lastVisitedNodeID") != storyline.nodePath[i]) {
            focusOnNode(node, 3);
            localStorage.setItem("lastVisitedNodeID", storyline.nodePath[i]);
            storyline.nodePath.splice(0, i);
            break;
        } else {
            var marker = floors[node.floorID - 1].markersById[node.id];
            floors[node.floorID - 1].groupLayer.removeLayer(marker);
            map.removeLayer(marker);
            //remove marker from floor.groupLayer too
        }
    }
    floors = StorylineMapObj.createPolyline(floors, storyline);
    map.removeLayer(floors[node.floorID-1].polyline);

    for (i = 0; i < floors.length; i++) {
        floors[i].groupLayer.removeLayer(floors[i].polyline);
        //floors[i].groupLayers();
        floors[i].addPolylineLayer();
    }
    map.addLayer(floors[node.floorID - 1].polyline);
}

function focusOnNode(node, zoom) {
        var floors = $('input[name=leaflet-base-layers]:radio');
        jQuery.each(floors, function (index, radio) {
            if ($(radio).next()[0].innerHTML.trim() == node.floorID+"") {
                if (radio.checked) {
                    map.setView(new L.LatLng(node.y, node.x), zoom, { animate: true });
                } else {
                    $(radio).prop("checked", true).trigger("click");
                    map.panTo(new L.LatLng(node.y, node.x));
                    map.setZoom(zoom);
                }
                //openMarkerPopup(markerId);
                return;
            }
        });
}

//testing
function simulateBeacon() {
    if (navigationPath.isNotAtStart) {
        currentPOI(navigationPath);
        if (localStorage.getItem("lastVisitedNodeID") == storyline.nodePath[0]) {
            navigationPath.isNotAtStart = false;
            localStorage.removeItem("lastVisitedNodeID");
            /*
            var node = navigationPath.nodes[navigationPath.nodePath[navigationPath.nodePath.length - 1]];
            var marker = floors[node.floorID - 1].markersById[node.id];
            floors[node.floorID - 1].groupLayer.removeLayer(marker);
            map.removeLayer(marker);
            map.removeLayer(floors[node.floorID - 1].polyline);
            for (i = 0; i < floors.length; i++) {
                floors[i].groupLayer.removeLayer(floors[i].polyline);
                floors[i].markers = [];
                floors[i].polylineLatLng = [];
                floors[i].polyline = null;
            }*/

            //Readd all markers

            floors = StorylineMapObj.createPolyline(floors, storyline);

            for (i = 0; i < floors.length; i++) {
                for (j = 0; j < floors[i].markers.length; j++) {
                    floors[i].groupLayer.addLayer(floors[i].markers[j]);
                }
            }
            floors = StorylineMapObj.addPolylines(floors);
            focusOnStart();
        }
    } else {
        currentPOI(storyline);
        iBeaconDiscovered(9377, 54177);
    }
}
<commit_msg>XM-17 Cleaned up storyline_map.js<commit_after>//Marker Icons
var MapObj = new Map();
var StorylineMapObj = new StorylineMap();
var ListPOI = [];
var ListPOT = [];
var baseMaps;
var map;

var markerIconPOIBlue = MapObj.createMarker('images/marker-icon-blue.png', 64, 64, 30, 64, 1, 1);
var markerIconPOIGreen = MapObj.createMarker('images/marker-icon-green.png', 64, 64, 30, 64, 1, 1);
var markerIconPOIRed = MapObj.createMarker('images/marker-icon-red.png', 64, 64, 30, 64, 1, 1);
var markerIconNode = MapObj.createMarker('images/none-marker-icon.png');
var mapMinZoom = 1;
var mapMaxZoom = 5;
var floors = [new Floor(1), new Floor(2), new Floor(3), new Floor(4), new Floor(5)];
var storyline;
var storylineSelectedID;
var lastVisitedNodeID = localStorage.getItem("lastVisitedNodeID");
var navigationPath = new Navigation([], false);
var startNode;

function displayStoryline() {
    //Test - next POI button
    $("#nextBtn").hide();

    $("#scanBtn").hide();

    //browser testing (default storyline)
    if (storylineSelectedID == null) {
        storylineSelectedID= "S1";
    }

    $('#currentStoryline').text("Current storyline: " + localStorage.getItem("currentStoryline"));
    $('#previewStoryline').text("Previewing storyline: " + localStorage.getItem("currentStoryline"));
    storylineSelectedID = localStorage.getItem("currentStoryline");

    floors = MapObj.parsePOI(floors);
    floors = MapObj.parsePOT(floors);
    floors = MapObj.createFloorTileLayers(floors, mapMinZoom, mapMaxZoom);
    MapObj.parseEdges();
    storyline = StorylineMapObj.parseStoryline(storylineSelectedID);
    storyline = StorylineMapObj.parseNodePath(storyline);

    if (lastVisitedNodeID != null && lastVisitedNodeID != storyline.nodePath[0]) {
        var dijkstras = new Dijkstra(ListPOI, ListPOT);
        start = lastVisitedNodeID;
        finish = storyline.nodePath[0];
        var shortestPathID = dijkstras.shortestPath(start, finish);
        navigationPath = new Navigation(shortestPathID, true);
        navigationPath = StorylineMapObj.parseNodePath(navigationPath);
        floors = StorylineMapObj.createPolyline(floors, navigationPath);
        floors = MapObj.groupLayers(floors);
        floors = StorylineMapObj.addPolylines(floors);

        startNode = ListPOI[navigationPath.nodePath[0]];
        $('#currentStoryline').text("Navigate to the start");
    } else {
        floors = StorylineMapObj.createPolyline(floors, storyline);
        floors = MapObj.groupLayers(floors);
        floors = StorylineMapObj.addPolylines(floors);
        startNode = ListPOI[storyline.nodePath[0]];
    }

    //floor radio buttons
    var baseMaps = {
        "1": floors[0].groupLayer,
        "2": floors[1].groupLayer,
        "3": floors[2].groupLayer,
        "4": floors[3].groupLayer,
        "5": floors[4].groupLayer
    };
    //floor overlay radio buttons
    var overlayMaps = {
        //"Markers": floor1Overlay
    };

    //create map
    map = L.map('map', {
        maxZoom: mapMaxZoom,
        minZoom: mapMinZoom,
        crs: L.CRS.Simple,
        layers: floors[0].groupLayer
    });
    map.on("load", function () {
        if (startNode.floorID != 1) {
            map.addLayer(floors[startNode.floorID - 1].groupLayer);
            map.removeLayer(floors[0].groupLayer);
        }
        if (localStorage.getItem("startIsSelected") == "true") {
            localStorage.removeItem("startIsSelected");
            startStoryline();
        }

    });
    map.setView([0, 0], mapMaxZoom);
    //map bounds
    var mapBounds = new L.LatLngBounds(
        map.unproject([0, 6144], mapMaxZoom),
        map.unproject([3072, 0], mapMaxZoom));

    //add bounds to map
    map.fitBounds(mapBounds);
    //Add controls (radio buttons) to map in order to switch between floors
    L.control.layers(baseMaps, overlayMaps, { collapsed: false }).addTo(map).setPosition('bottomright');
}

function endPreview() {
    localStorage.removeItem("currentStoryline");
    window.location.replace("storylines.html");
}

function startStoryline() {
    $("#starBtn").hide();
    $("#backBtn").hide();
    $("#previewStoryline").hide();
    $("#nextBtn").show();
    $("#scanBtn").show();
    focusOnStart();
}

function focusOnStart() {
    if (navigationPath.isNotAtStart) {
        firstNodeID = navigationPath.nodePath[0];
        firstNode = navigationPath.nodes[firstNodeID];
    } else {
        firstNodeID = storyline.nodePath[0];
        firstNode = storyline.nodes[firstNodeID];
    }
    focusOnNode(firstNode, 3);
}

//***TODO***
//When beacon in proximity function is fired, should call this method
//Check whether beacon uuid == next Node.iBeacon.uuid
//if true -> fire popup
function currentPOI(storyline) {
    var node;
    for (i = 0; i < storyline.nodePath.length; i++) {
        //if isPOI
        node = storyline.nodes[storyline.nodePath[i]];
        if (storyline.nodePath[i].charAt(0) == "0" && localStorage.getItem("lastVisitedNodeID") != storyline.nodePath[i]) {
            focusOnNode(node, 3);
            localStorage.setItem("lastVisitedNodeID", storyline.nodePath[i]);
            storyline.nodePath.splice(0, i);
            break;
        } else {
            var marker = floors[node.floorID - 1].markersById[node.id];
            floors[node.floorID - 1].groupLayer.removeLayer(marker);
            map.removeLayer(marker);
            //remove marker from floor.groupLayer too
        }
    }
    floors = StorylineMapObj.createPolyline(floors, storyline);
    map.removeLayer(floors[node.floorID-1].polyline);

    for (i = 0; i < floors.length; i++) {
        floors[i].groupLayer.removeLayer(floors[i].polyline);
        //floors[i].groupLayers();
        floors[i].addPolylineLayer();
    }
    map.addLayer(floors[node.floorID - 1].polyline);
}

function focusOnNode(node, zoom) {
        var floors = $('input[name=leaflet-base-layers]:radio');
        jQuery.each(floors, function (index, radio) {
            if ($(radio).next()[0].innerHTML.trim() == node.floorID+"") {
                if (radio.checked) {
                    map.setView(new L.LatLng(node.y, node.x), zoom, { animate: true });
                } else {
                    $(radio).prop("checked", true).trigger("click");
                    map.panTo(new L.LatLng(node.y, node.x));
                    map.setZoom(zoom);
                }
                //openMarkerPopup(markerId);
                return;
            }
        });
}

//testing
function simulateBeacon() {
    if (navigationPath.isNotAtStart) {
        currentPOI(navigationPath);
        if (localStorage.getItem("lastVisitedNodeID") == storyline.nodePath[0]) {
            navigationPath.isNotAtStart = false;
            localStorage.removeItem("lastVisitedNodeID");
            //Readd all markers
            floors = StorylineMapObj.createPolyline(floors, storyline);

            for (i = 0; i < floors.length; i++) {
                for (j = 0; j < floors[i].markers.length; j++) {
                    floors[i].groupLayer.addLayer(floors[i].markers[j]);
                }
            }
            floors = StorylineMapObj.addPolylines(floors);
            focusOnStart();
        }
    } else {
        currentPOI(storyline);
        iBeaconDiscovered(9377, 54177);
    }
}
<|endoftext|>


<commit_before>
<commit_msg>Change image attributes<commit_after>import { StyleSheet, Dimensions } from 'react-native';

export default StyleSheet.create({
  image: {
    height: 150,
    width: 150
  }
})
<|endoftext|>


<commit_before>/* EZ-Emote plugin
 * These are commands that make
 * it easier for people to actually
 * emotes without having to manaully
 * add them every time
 * By: panpawn (inspired by jd's ez-tc plugin)
 */

 var fs = require('fs');
 var serialize = require('node-serialize');
 var emotes = {};

 function loadEmotes() {
	try {
		emotes = serialize.unserialize(fs.readFileSync('config/emotes.json', 'utf8'));
		Object.merge(Core.emoticons, emotes);
	} catch (e) {};
}
setTimeout(function(){loadEmotes();},1000);

function saveEmotes() {
	fs.writeFileSync('config/emotes.json',serialize.serialize(emotes));
	Object.merge(Core.emoticons, emotes);
}

exports.commands = {
	ezemote: function (target, room, user) {
		if (!target) target = 'help';
		var parts = target.split(',');
		for (var u in parts) parts[u] = parts[u].trim();

		switch (parts[0]) {
			case 'add':
				if (!this.can('pban')) return false;
				if (!parts[2]) return this.sendReply("Usage: /ezemote add, [emote], [link]");
				var emoteName = parts[1];
				if (Core.emoticons[emoteName]) return this.sendReplyBox("ERROR: the emote: " + emoteName + " already exists.");
				var link = parts.splice(2, parts.length).join(',');
				emotes[emoteName] = Core.emoticons[emoteName] = link;
				saveEmotes();
				this.sendReply("The emote " + emoteName + " has been added.");
				this.logModCommand(user.name + " added the emote " + emoteName);
				try {
					Rooms.rooms.staff.add(user.name + " added the emote " + emoteName);
				} catch (e) {};
				break;
			case 'rem':
			case 'remove':
			case 'del':
			case 'delete':
				if (!this.can('pban')) return false;
				if (!parts[1]) return this.sendReplyBox('/ezemote remove, [emote]');
				var emoteName = parts[1];
				if (!Core.emoticons[emoteName]) return this.sendReplyBox("ERROR: the emote " + emoteName + " does not exist.");
				Core.emoticons[emoteName] = undefined;
				delete Core.emoticons[emoteName];
				saveEmotes();
				this.sendReply("The emote " + emoteName + " was removed.");
				this.logModCommand("The emote " + emoteName + " was removed by " + user.name);
				try {
					Rooms.rooms.staff.add("The emote " + emoteName + " was removed by " + user.name);
				} catch (e) {};
				break;
			case 'help':
			default:
				if (!this.canBroadcast()) return;
				this.sendReplyBox(
					"EZ-Emote Commands:
" +
					"/ezemote add, [emote], [link] - Adds an emote.
" +
					"/ezemote remove, [emote] - Removes an emote.
" +
					"/ezemote help - Shows this help command.
"
				);
		}
	}
};
<commit_msg>Surround the entire command in a try statement<commit_after>/* EZ-Emote plugin
 * These are commands that make
 * it easier for people to actually
 * emotes without having to manaully
 * add them every time
 * By: panpawn (inspired by jd's ez-tc plugin)
 */

 var fs = require('fs');
 var serialize = require('node-serialize');
 var emotes = {};

 function loadEmotes() {
	try {
		emotes = serialize.unserialize(fs.readFileSync('config/emotes.json', 'utf8'));
		Object.merge(Core.emoticons, emotes);
	} catch (e) {};
}
setTimeout(function(){loadEmotes();},1000);

function saveEmotes() {
	fs.writeFileSync('config/emotes.json',serialize.serialize(emotes));
	Object.merge(Core.emoticons, emotes);
}

exports.commands = {
	ezemote: function (target, room, user) {
		if (!target) target = 'help';
		var parts = target.split(',');
		for (var u in parts) parts[u] = parts[u].trim();
		try {
			switch (parts[0]) {
				case 'add':
					if (!this.can('pban')) return false;
					if (!parts[2]) return this.sendReply("Usage: /ezemote add, [emote], [link]");
					var emoteName = parts[1];
					if (Core.emoticons[emoteName]) return this.sendReplyBox("ERROR: the emote: " + emoteName + " already exists.");
					var link = parts.splice(2, parts.length).join(',');
					emotes[emoteName] = Core.emoticons[emoteName] = link;
					saveEmotes();
					this.sendReply("The emote " + emoteName + " has been added.");
					this.logModCommand(user.name + " added the emote " + emoteName);
					Rooms.rooms.staff.add(user.name + " added the emote " + emoteName);
					break;
				case 'rem':
				case 'remove':
				case 'del':
				case 'delete':
					if (!this.can('pban')) return false;
					if (!parts[1]) return this.sendReplyBox('/ezemote remove, [emote]');
					var emoteName = parts[1];
					if (!Core.emoticons[emoteName]) return this.sendReplyBox("ERROR: the emote " + emoteName + " does not exist.");
					Core.emoticons[emoteName] = undefined;
					delete Core.emoticons[emoteName];
					saveEmotes();
					this.sendReply("The emote " + emoteName + " was removed.");
					this.logModCommand("The emote " + emoteName + " was removed by " + user.name);
					Rooms.rooms.staff.add("The emote " + emoteName + " was removed by " + user.name);
					break;
				case 'help':
				default:
					if (!this.canBroadcast()) return;
					this.sendReplyBox(
						"EZ-Emote Commands:
" +
						"/ezemote add, [emote], [link] - Adds an emote.
" +
						"/ezemote remove, [emote] - Removes an emote.
" +
						"/ezemote help - Shows this help command.
"
					);
			}
		} catch (e) {};
	}
};
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import { Avatar, Flex, Box } from 'rebass'
import { sample } from 'lodash'
import { mx } from '../theme'
import fetch from 'unfetch'

const BUBBLES_URL =
  'https://api.hackclub.com/v1/home/slack_users?page=1&inc=72&res=192'

const Root = Flex.extend.attrs({
  justify: 'center',
  align: 'center',
  px: 3
})`
  position: relative;
  max-width: 100vw;
  height: 100vh;
  overflow-y: hidden;
`

const Fill = Flex.extend.attrs({ justify: 'center', wrap: true })`
  position: absolute;
  top: 0;
  z-index: -1;
`

const Cloud = Box.extend`
  max-width: 32rem;
  margin: auto;
  border-radius: 4rem;
  box-shadow: 0 0 2rem 2rem rgba(250, 250, 250, 0.95);
  background-color: rgba(250, 250, 250, 0.95);
  text-align: center;
  z-index: 2;
  ${mx[1]} {
    max-width: 48rem;
    border-radius: 8rem;
    box-shadow: 0 0 8rem 8rem rgba(250, 250, 250, 0.95);
  }
`

const Bubble = Avatar.extend`
  margin: 0.5em;
  &:nth-child(odd) {
    margin-left: 1.5em;
    margin-top: 0;
  }
  &:nth-child(even) {
    margin-right: 1em;
  }
  &:nth-child(6n) {
    width: 3em;
    height: 3em;
    margin-bottom: 1em;
  }
  &:nth-child(8n) {
    width: 2.5em;
    height: 2.5em;
    margin-left: 1em;
  }
  &:nth-child(13n) {
    width: 1.5em;
    height: 1.5em;
  }
  /* fill gap left by diagonal cutoff */
  ${mx[1]} {
    &:first-child {
      position: absolute;
      width: 48px;
      height: 48px;
      right: 0;
      top: -4rem;
    }
    &:nth-child(2) {
      position: absolute;
      width: 32px;
      height: 32px;
      right: 9rem;
      top: -3rem;
    }
    &:nth-child(3) {
      position: absolute;
      width: 24px;
      height: 24px;
      right: 18rem;
      top: -3rem;
    }
  }
`

class Bubbles extends Component {
  constructor() {
    super()
    this.state = { list: [] }
  }

  componentDidMount() {
    fetch(BUBBLES_URL)
      .then(r => r.json())
      .then(d => d.profile_pictures)
      .then(list => this.setState({ list }))
  }

  render() {
    return (
      <Root>
        <Fill>
          {this.state.list.map((item, i) => (
            <Bubble
              src={item}
              size={sample([28, 32, 48, 56, 64, 72, 84])}
              key={`a-${i}`}
            />
          ))}
        </Fill>
        <Cloud children={this.props.children} />
      </Root>
    )
  }
}

export default Bubbles
<commit_msg>Use local Bubbles<commit_after>import React from 'react'
import { Avatar, Flex, Box } from 'rebass'
import { times, sample } from 'lodash'
import { mx } from '../theme'

const Root = Flex.extend.attrs({
  justify: 'space-around',
  align: 'center',
  pt: 3,
  px: [1, 3]
})`
  position: relative;
  max-width: 100vw;
  height: 100vh;
  overflow-y: hidden;
`

const Fill = Flex.extend.attrs({ justify: 'center', wrap: true })`
  position: absolute;
  top: 0;
  z-index: -1;
`

const Cloud = Box.extend`
  max-width: 32rem;
  margin: auto;
  border-radius: 4rem;
  box-shadow: 0 0 2rem 4rem rgba(250, 250, 250, 0.95);
  background-color: rgba(250, 250, 250, 0.95);
  text-align: center;
  z-index: 2;
  ${mx[1]} {
    max-width: 48rem;
    border-radius: 8rem;
    box-shadow: 0 0 8rem 8rem rgba(250, 250, 250, 0.95);
  }
`

const Bubble = Avatar.extend`
  margin: 0.75em;
  &:nth-child(odd) {
    margin-left: 1.5em;
    margin-top: 0;
  }
  &:nth-child(even) {
    margin-right: 1em;
  }
  &:nth-child(6n) {
    width: 3em;
    height: 3em;
    margin-bottom: 1em;
  }
  &:nth-child(8n) {
    width: 2.5em;
    height: 2.5em;
    margin-left: 1em;
  }
  &:nth-child(13n) {
    width: 1.5em;
    height: 1.5em;
  }
  ${mx[1]} {
    &:first-child {
      margin-left: 6rem;
    }
  }
`

const Bubbles = ({ children }) => (
  <Root>
    <Fill>
      {times(92, i => (
        <Bubble
          src={`/avatars/${i + 1}.jpg`}
          size={sample([48, 56, 64, 72, 84, 96])}
          key={`a-${i}`}
        />
      ))}
    </Fill>
    <Cloud children={children} />
  </Root>
)

export default Bubbles
<|endoftext|>