<commit_before>/**
 * The router module.
 *
 * Router handles app routing and URL parameters and updates Presenter.
 *
 * @return singleton instance of Router class (extends Backbone.Router).
 */
define([
  'underscore',
  'backbone',
  'amplify',
  'map/utils',
  'map/services/PlaceService'
], function(_, Backbone, amplify, utils, PlaceService) {

  'use strict';

  var Router = Backbone.Router.extend({

    // temporary, we will do it with env variables
    _cacheVersion: 20,

    routes: {
      'map(/:zoom)(/:lat)(/:lng)(/:iso)(/:maptype)(/:baselayers)(/:sublayers)(/)': 'map',
      'embed/map(/:zoom)(/:lat)(/:lng)(/:iso)(/:maptype)(/:baselayers)(/:sublayers)(/)': 'embed'
    },

    /**
     * Boot file:
     *
     * @param  {[type]} boot [description]
     */
    initialize: function(mainView) {
      this.bind('all', this._checkForCacheBust());
      this.name = null;
      this.mainView = mainView;
      this.placeService = new PlaceService(this);
    },

    map: function() {
      this.name = 'map';
      this.mainView.setMapMode();
      this.initMap.apply(this, arguments);
    },

    embed: function() {
      this.name = 'embed/map';
      this.initMap.apply(this, arguments);
    },

    initMap: function(zoom, lat, lng, iso, maptype, baselayers, sublayers, subscribe) {
      var params = _.extend({
        zoom: zoom,
        lat: lat,
        lng: lng,
        iso: iso,
        maptype: maptype,
        baselayers: baselayers,
        sublayers: sublayers,
        subscribe_alerts: subscribe
      }, _.parseUrl());
      this.placeService.initPlace(this.name, params);
    },

    /**
     * If the URL contains the cache parameter (e.g., cache=bust), clear all
     * cached values in the browser (e.g., from memory, local storage,
     * session).
     */
    _checkForCacheBust: function() {
      var params = _.parseUrl();
      var localCacheVersion = _.toNumber(
        localStorage.getItem('CACHE_VERSION'));

      if (_.has(params, 'cache') || localCacheVersion !== this._cacheVersion) {
        _.each(amplify.store(), function(value, key) {
          amplify.store(key, null);
        });

        localStorage.setItem('CACHE_VERSION', this._cacheVersion);
      }
    },

    navigateTo: function(route, options) {
      this.navigate(route, options);
    }

  });

  return Router;

});
<commit_msg>cacheversion ++<commit_after>/**
 * The router module.
 *
 * Router handles app routing and URL parameters and updates Presenter.
 *
 * @return singleton instance of Router class (extends Backbone.Router).
 */
define([
  'underscore',
  'backbone',
  'amplify',
  'map/utils',
  'map/services/PlaceService'
], function(_, Backbone, amplify, utils, PlaceService) {

  'use strict';

  var Router = Backbone.Router.extend({

    // temporary, we will do it with env variables
    _cacheVersion: 21,

    routes: {
      'map(/:zoom)(/:lat)(/:lng)(/:iso)(/:maptype)(/:baselayers)(/:sublayers)(/)': 'map',
      'embed/map(/:zoom)(/:lat)(/:lng)(/:iso)(/:maptype)(/:baselayers)(/:sublayers)(/)': 'embed'
    },

    /**
     * Boot file:
     *
     * @param  {[type]} boot [description]
     */
    initialize: function(mainView) {
      this.bind('all', this._checkForCacheBust());
      this.name = null;
      this.mainView = mainView;
      this.placeService = new PlaceService(this);
    },

    map: function() {
      this.name = 'map';
      this.mainView.setMapMode();
      this.initMap.apply(this, arguments);
    },

    embed: function() {
      this.name = 'embed/map';
      this.initMap.apply(this, arguments);
    },

    initMap: function(zoom, lat, lng, iso, maptype, baselayers, sublayers, subscribe) {
      var params = _.extend({
        zoom: zoom,
        lat: lat,
        lng: lng,
        iso: iso,
        maptype: maptype,
        baselayers: baselayers,
        sublayers: sublayers,
        subscribe_alerts: subscribe
      }, _.parseUrl());
      this.placeService.initPlace(this.name, params);
    },

    /**
     * If the URL contains the cache parameter (e.g., cache=bust), clear all
     * cached values in the browser (e.g., from memory, local storage,
     * session).
     */
    _checkForCacheBust: function() {
      var params = _.parseUrl();
      var localCacheVersion = _.toNumber(
        localStorage.getItem('CACHE_VERSION'));

      if (_.has(params, 'cache') || localCacheVersion !== this._cacheVersion) {
        _.each(amplify.store(), function(value, key) {
          amplify.store(key, null);
        });

        localStorage.setItem('CACHE_VERSION', this._cacheVersion);
      }
    },

    navigateTo: function(route, options) {
      this.navigate(route, options);
    }

  });

  return Router;

});
<|endoftext|>


<commit_before>'use strict';

var React = require('react');
var Isvg = require('react-inlinesvg');
var getRiderCSS = require('./getRiderCSS');
import RiderInstance from './RiderInstance'

require('../assets/svg/boshSprite.svg');

var SvgSprite = React.createClass({
  shouldComponentUpdate() {
    return false;
  },

  render() {
    return (
      <g>
        <style dangerouslySetInnerHTML={{ __html: getRiderCSS(this.props.namespace, this.props.i, this.props.flag)}} />
        <foreignObject style={{display: 'none'}}>
          <Isvg src={this.props.src} uniquifyIDs={false} namespace={this.props.namespace}/>
        </foreignObject>
      </g>
    );
  }
});

const OPACITY_DECAY = 1.2
const OPACITY_INIT = 0.5
const OPACITY_MIN = 0.05

// TODO: make Rider not rely on viewbox panning/scaling/outer svg
var Rider = React.createClass({

  getDefaultProps() {
    return {
      riderSpriteSrc: 'svg/boshSprite.svg'
    };
  },

  render() {
    let {
      seed,
      index,
      startIndex,
      rider,
      riders,
      onionSkin
    } = this.props
    let namespace = `__RIDER_SPRITE_${this.props.i}__`;

    let getOpacity = (i) => {
      if (startIndex !== index) {
        i = index - (i + startIndex)
      }
      return OPACITY_INIT * (1 - OPACITY_MIN) * Math.pow(OPACITY_DECAY, -i) + OPACITY_MIN
    }

    return (
      <g id={namespace}>
        <SvgSprite namespace={namespace} i={this.props.i} src={this.props.riderSpriteSrc} flag={this.props.flag}/>
        {
          onionSkin ?
            riders.map((state, i) =>
              startIndex + i === index ? null :
              <g key={startIndex + i} style={{opacity: getOpacity(i)}}>
                <RiderInstance
                  namespace={namespace}
                  i={startIndex + i}
                  {...{seed, index: startIndex + i, rider: state}}
                />
              </g>
            )
          : null
        }
        <RiderInstance i={index} key={index} namespace={namespace} {...{seed, index, rider}}/>
      </g>
    );
  }
});

module.exports = Rider;
<commit_msg>keep main rider i the same<commit_after>'use strict';

var React = require('react');
var Isvg = require('react-inlinesvg');
var getRiderCSS = require('./getRiderCSS');
import RiderInstance from './RiderInstance'

require('../assets/svg/boshSprite.svg');

var SvgSprite = React.createClass({
  shouldComponentUpdate() {
    return false;
  },

  render() {
    return (
      <g>
        <style dangerouslySetInnerHTML={{ __html: getRiderCSS(this.props.namespace, this.props.i, this.props.flag)}} />
        <foreignObject style={{display: 'none'}}>
          <Isvg src={this.props.src} uniquifyIDs={false} namespace={this.props.namespace}/>
        </foreignObject>
      </g>
    );
  }
});

const OPACITY_DECAY = 1.2
const OPACITY_INIT = 0.5
const OPACITY_MIN = 0.05

// TODO: make Rider not rely on viewbox panning/scaling/outer svg
var Rider = React.createClass({

  getDefaultProps() {
    return {
      riderSpriteSrc: 'svg/boshSprite.svg'
    };
  },

  render() {
    let {
      seed,
      index,
      startIndex,
      rider,
      riders,
      onionSkin
    } = this.props
    let namespace = `__RIDER_SPRITE_${this.props.i}__`;

    let getOpacity = (i) => {
      if (startIndex !== index) {
        i = index - (i + startIndex)
      }
      return OPACITY_INIT * (1 - OPACITY_MIN) * Math.pow(OPACITY_DECAY, -i) + OPACITY_MIN
    }

    return (
      <g id={namespace}>
        <SvgSprite namespace={namespace} i={this.props.i} src={this.props.riderSpriteSrc} flag={this.props.flag}/>
        {
          onionSkin ?
            riders.map((state, i) =>
              startIndex + i === index ? null :
              <g key={startIndex + i} style={{opacity: getOpacity(i)}}>
                <RiderInstance
                  namespace={namespace}
                  i={startIndex + i}
                  {...{seed, index: startIndex + i, rider: state}}
                />
              </g>
            )
          : null
        }
        <RiderInstance i={-1} key={index} namespace={namespace} {...{seed, index, rider}}/>
      </g>
    );
  }
});

module.exports = Rider;
<|endoftext|>


<commit_before>/* @flow */

import React, { Component, PropTypes } from 'react';
import ReactNative from 'react-native';
import shallowCompare from 'react-addons-shallow-compare';
import AvatarRound from '../Avatar/AvatarRound';
import ChatBubble from './ChatBubble';
import Embed from '../Embed/Embed';
import Icon from '../Core/Icon';
import Time from '../Core/Time';
import ChatLikeButtonContainer from '../../containers/ChatLikeButtonContainer';
import ChatActionSheetContainer from '../../containers/ChatActionSheetContainer';
import { parseURLs } from '../../../../lib/URL';
import { TAG_POST_HIDDEN } from '../../../../lib/Constants';
import type { Text, TextRel } from '../../../../lib/schemaTypes';

const {
	PixelRatio,
	StyleSheet,
	TouchableOpacity,
	View,
} = ReactNative;

const FADED_GREY = '#b2b2b2';

const styles = StyleSheet.create({
	container: {
		marginVertical: 4,
	},
	chat: {
		flex: 0,
		flexDirection: 'column',
		alignItems: 'flex-end',
	},
	received: {
		alignItems: 'flex-start',
		marginLeft: 44,
	},
	timestamp: {
		flexDirection: 'row',
		marginTop: 4,
	},
	timestampLeft: {
		marginLeft: 52,
	},
	timestampRight: {
		alignSelf: 'flex-end',
	},
	timestampIcon: {
		color: FADED_GREY,
		marginVertical: 2,
	},
	timestampText: {
		color: FADED_GREY,
		fontSize: 12,
		marginHorizontal: 6,
		paddingHorizontal: 8,
	},
	avatar: {
		position: 'absolute',
		top: 0,
		left: -36,
		alignSelf: 'flex-end',
	},
	thumbnail: {
		marginVertical: 4,
	},
	embed: {
		borderColor: 'rgba(0, 0, 0, .24)',
		borderWidth: 1 / PixelRatio.get(),
		padding: 8,
		marginVertical: 4,
		borderRadius: 2,
	},
	embedThumbnail: {
		marginBottom: 8,
	},
	chatReceived: {
		paddingRight: 52,
	},
	chatSent: {
		marginHorizontal: 8,
	},
	hidden: {
		opacity: 0.3,
	},
	like: {
		position: 'absolute',
		top: 0,
		right: 0,
		width: 52,
		alignItems: 'center',
	},
});

type Props = {
	text: Text;
	textrel: ?TextRel;
	previousText: ?Text;
	isLast: ?boolean;
	user: string;
	quoteMessage: Function;
	replyToMessage: Function;
	style?: any;
	onNavigate: Function;
};

type State = {
	actionSheetVisible: boolean;
}

export default class ChatItem extends Component<void, Props, State> {
	static propTypes = {
		text: PropTypes.shape({
			body: PropTypes.string.isRequired,
			creator: PropTypes.string.isRequired,
			createTime: PropTypes.number.isRequired,
			meta: PropTypes.object,
		}).isRequired,
		textrel: PropTypes.object,
		previousText: PropTypes.shape({
			creator: PropTypes.string,
			createTime: PropTypes.number,
		}),
		isLast: PropTypes.bool,
		user: PropTypes.string.isRequired,
		quoteMessage: PropTypes.func.isRequired,
		replyToMessage: PropTypes.func.isRequired,
		style: View.propTypes.style,
		onNavigate: PropTypes.func.isRequired,
	};

	state: State = {
		actionSheetVisible: false,
	};

	shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
		return shallowCompare(this, nextProps, nextState);
	}

	_goToProfile = () => {
		const { text } = this.props;

		this.props.onNavigate({
			type: 'push',
			payload: {
				name: 'profile',
				props: {
					user: text.creator,
				},
			},
		});
	};

	_handleShowMenu = () => {
		this.setState({
			actionSheetVisible: true,
		});
	};

	_handleRequestClose = () => {
		this.setState({
			actionSheetVisible: false,
		});
	};

	render() {
		const {
			text,
			previousText,
			isLast,
			user,
		} = this.props;

		const hidden = text.tags && text.tags.indexOf(TAG_POST_HIDDEN) > -1;
		const received = text.creator !== user;
		const links = text.body ? parseURLs(text.body, 1) : null;

		let cover;

		if (text.meta && text.meta.photo) {
			const { photo } = text.meta;

			cover = (
				<Embed
					url={photo.url}
					data={photo}
					showTitle={false}
					thumbnailStyle={styles.thumbnail}
					openOnPress={false}
				/>
			);
		} else if (links && links.length) {
			cover = (
				<Embed
					url={links[0]}
					style={styles.embed}
					thumbnailStyle={styles.embedThumbnail}
				/>
			);
		}

		let showAuthor = received,
			showTime = isLast;

		if (previousText) {
			if (received) {
				showAuthor = text.creator !== previousText.creator;
			}

			showTime = showTime || (text.createTime - previousText.createTime) > 300000;
		}

		return (
			<View {...this.props} style={[ styles.container, this.props.style ]}>
				<View style={[ styles.chat, received ? styles.received : null, hidden ? styles.hidden : null ]}>
					{received && showAuthor ?
						<TouchableOpacity
							activeOpacity={0.5}
							onPress={this._goToProfile}
							style={styles.avatar}
						>
							<AvatarRound size={36} user={text.creator} />
						</TouchableOpacity> :
						null
					}

					<View style={received ? styles.chatReceived : styles.chatSent}>
						<TouchableOpacity activeOpacity={0.5} onPress={this._handleShowMenu}>
							<ChatBubble
								body={text.meta && text.meta.photo ? null : text.body}
								creator={text.creator}
								type={received ? 'left' : 'right'}
								showAuthor={showAuthor}
								showArrow={received ? showAuthor : true}
							>
								{cover}
							</ChatBubble>
						</TouchableOpacity>

						{received ?
							<ChatLikeButtonContainer
								style={styles.like}
								text={this.props.text}
								textrel={this.props.textrel}
							/> :
							null
						}
					</View>
				</View>

				{showTime ?
					(<View style={[ styles.timestamp, received ? styles.timestampLeft : styles.timestampRight ]}>
						<Icon
							name='access-time'
							style={styles.timestampIcon}
							size={12}
						/>
						<Time
							type='long'
							time={text.createTime}
							style={styles.timestampText}
						/>
					</View>) :
					null
				}

				<ChatActionSheetContainer
					text={text}
					user={user}
					quoteMessage={this.props.quoteMessage}
					replyToMessage={this.props.replyToMessage}
					visible={this.state.actionSheetVisible}
					onRequestClose={this._handleRequestClose}
				/>
			</View>
		);
	}
}
<commit_msg>feat(ui): add like button for own text (#405)<commit_after>/* @flow */

import React, { Component, PropTypes } from 'react';
import ReactNative from 'react-native';
import shallowCompare from 'react-addons-shallow-compare';
import AvatarRound from '../Avatar/AvatarRound';
import ChatBubble from './ChatBubble';
import Embed from '../Embed/Embed';
import Icon from '../Core/Icon';
import Time from '../Core/Time';
import ChatLikeButtonContainer from '../../containers/ChatLikeButtonContainer';
import ChatActionSheetContainer from '../../containers/ChatActionSheetContainer';
import { parseURLs } from '../../../../lib/URL';
import { TAG_POST_HIDDEN } from '../../../../lib/Constants';
import type { Text, TextRel } from '../../../../lib/schemaTypes';

const {
	PixelRatio,
	StyleSheet,
	TouchableOpacity,
	View,
} = ReactNative;

const FADED_GREY = '#b2b2b2';

const styles = StyleSheet.create({
	container: {
		marginVertical: 4,
	},
	chat: {
		flex: 0,
		flexDirection: 'column',
		alignItems: 'flex-end',
	},
	received: {
		alignItems: 'flex-start',
		marginLeft: 44,
	},
	timestamp: {
		flexDirection: 'row',
		marginTop: 4,
	},
	timestampLeft: {
		marginLeft: 52,
	},
	timestampRight: {
		alignSelf: 'flex-end',
	},
	timestampIcon: {
		color: FADED_GREY,
		marginVertical: 2,
	},
	timestampText: {
		color: FADED_GREY,
		fontSize: 12,
		marginHorizontal: 6,
		paddingHorizontal: 8,
	},
	avatar: {
		position: 'absolute',
		top: 0,
		left: -36,
		alignSelf: 'flex-end',
	},
	thumbnail: {
		marginVertical: 4,
	},
	embed: {
		borderColor: 'rgba(0, 0, 0, .24)',
		borderWidth: 1 / PixelRatio.get(),
		padding: 8,
		marginVertical: 4,
		borderRadius: 2,
	},
	embedThumbnail: {
		marginBottom: 8,
	},
	chatReceived: {
		paddingRight: 52,
	},
	chatSent: {
		marginHorizontal: 8,
	},
	hidden: {
		opacity: 0.3,
	},
	like: {
		position: 'absolute',
		top: 0,
		width: 52,
		alignItems: 'center',
	},
	likeReceived: {
		right: 0,
	},
	likeSent: {
		left: -52,
	},
});

type Props = {
	text: Text;
	textrel: ?TextRel;
	previousText: ?Text;
	isLast: ?boolean;
	user: string;
	quoteMessage: Function;
	replyToMessage: Function;
	style?: any;
	onNavigate: Function;
};

type State = {
	actionSheetVisible: boolean;
}

export default class ChatItem extends Component<void, Props, State> {
	static propTypes = {
		text: PropTypes.shape({
			body: PropTypes.string.isRequired,
			creator: PropTypes.string.isRequired,
			createTime: PropTypes.number.isRequired,
			meta: PropTypes.object,
		}).isRequired,
		textrel: PropTypes.object,
		previousText: PropTypes.shape({
			creator: PropTypes.string,
			createTime: PropTypes.number,
		}),
		isLast: PropTypes.bool,
		user: PropTypes.string.isRequired,
		quoteMessage: PropTypes.func.isRequired,
		replyToMessage: PropTypes.func.isRequired,
		style: View.propTypes.style,
		onNavigate: PropTypes.func.isRequired,
	};

	state: State = {
		actionSheetVisible: false,
	};

	shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
		return shallowCompare(this, nextProps, nextState);
	}

	_goToProfile = () => {
		const { text } = this.props;

		this.props.onNavigate({
			type: 'push',
			payload: {
				name: 'profile',
				props: {
					user: text.creator,
				},
			},
		});
	};

	_handleShowMenu = () => {
		this.setState({
			actionSheetVisible: true,
		});
	};

	_handleRequestClose = () => {
		this.setState({
			actionSheetVisible: false,
		});
	};

	render() {
		const {
			text,
			previousText,
			isLast,
			user,
		} = this.props;

		const hidden = text.tags && text.tags.indexOf(TAG_POST_HIDDEN) > -1;
		const received = text.creator !== user;
		const links = text.body ? parseURLs(text.body, 1) : null;

		let cover;

		if (text.meta && text.meta.photo) {
			const { photo } = text.meta;

			cover = (
				<Embed
					url={photo.url}
					data={photo}
					showTitle={false}
					thumbnailStyle={styles.thumbnail}
					openOnPress={false}
				/>
			);
		} else if (links && links.length) {
			cover = (
				<Embed
					url={links[0]}
					style={styles.embed}
					thumbnailStyle={styles.embedThumbnail}
				/>
			);
		}

		let showAuthor = received,
			showTime = isLast;

		if (previousText) {
			if (received) {
				showAuthor = text.creator !== previousText.creator;
			}

			showTime = showTime || (text.createTime - previousText.createTime) > 300000;
		}

		return (
			<View {...this.props} style={[ styles.container, this.props.style ]}>
				<View style={[ styles.chat, received ? styles.received : null, hidden ? styles.hidden : null ]}>
					{received && showAuthor ?
						<TouchableOpacity
							activeOpacity={0.5}
							onPress={this._goToProfile}
							style={styles.avatar}
						>
							<AvatarRound size={36} user={text.creator} />
						</TouchableOpacity> :
						null
					}

					<View style={received ? styles.chatReceived : styles.chatSent}>
						<TouchableOpacity activeOpacity={0.5} onPress={this._handleShowMenu}>
							<ChatBubble
								body={text.meta && text.meta.photo ? null : text.body}
								creator={text.creator}
								type={received ? 'left' : 'right'}
								showAuthor={showAuthor}
								showArrow={received ? showAuthor : true}
							>
								{cover}
							</ChatBubble>
						</TouchableOpacity>

						<ChatLikeButtonContainer
							style={[ styles.like, received ? styles.likeReceived : styles.likeSent ]}
							text={this.props.text}
							textrel={this.props.textrel}
						/>
					</View>
				</View>

				{showTime ?
					(<View style={[ styles.timestamp, received ? styles.timestampLeft : styles.timestampRight ]}>
						<Icon
							name='access-time'
							style={styles.timestampIcon}
							size={12}
						/>
						<Time
							type='long'
							time={text.createTime}
							style={styles.timestampText}
						/>
					</View>) :
					null
				}

				<ChatActionSheetContainer
					text={text}
					user={user}
					quoteMessage={this.props.quoteMessage}
					replyToMessage={this.props.replyToMessage}
					visible={this.state.actionSheetVisible}
					onRequestClose={this._handleRequestClose}
				/>
			</View>
		);
	}
}
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var gulp = require('gulp');
var runSequence = require('run-sequence');
var vinylSourceStream = require('vinyl-source-stream');
var vinylPaths = require('vinyl-paths');
var del = require('del');
var browserify = require('browserify');
var babelify = require('babelify');

var paths = {
  output: path.join(__dirname, 'dist'),
  system: [path.join(__dirname, 'main.js')],
  systemOutput: path.join(__dirname, 'main.js'),
  html: path.join(__dirname, 'index.html')
};
var babelOptions = {
  global: true,
  ignore: /node_modules\/(?!rotorjs)/,
  presets: ['es2015', 'stage-1'],
  plugins: [
    ['transform-react-jsx', {pragma: 'h'}],
    ['transform-runtime']
  ],
  compact: false
};

gulp.task('clean', function() {
  return gulp.src([paths.output])
    .pipe(vinylPaths(del));
});

gulp.task('build-system', function () {
  return browserify(paths.system)
    .transform(babelify, babelOptions)
    .bundle()
    .pipe(vinylSourceStream(paths.systemOutput))
    .pipe(gulp.dest(paths.output));
});

gulp.task('build-html', function () {
  return gulp.src(paths.html)
    .pipe(gulp.dest(paths.output));
});

gulp.task('build', function (callback) {
  return runSequence(
    'clean',
    ['build-system', 'build-html'],
    callback
  );
});
<commit_msg>Example: Add source maps generation<commit_after>'use strict';

var path = require('path');
var gulp = require('gulp');
var runSequence = require('run-sequence');
var vinylSourceStream = require('vinyl-source-stream');
var vinylPaths = require('vinyl-paths');
var del = require('del');
var browserify = require('browserify');
var babelify = require('babelify');

var paths = {
  output: path.join(__dirname, 'dist'),
  system: [path.join(__dirname, 'main.js')],
  systemOutput: path.join(__dirname, 'main.js'),
  html: path.join(__dirname, 'index.html')
};
var babelOptions = {
  global: true,
  ignore: /node_modules\/(?!rotorjs)/,
  presets: ['es2015', 'stage-1'],
  plugins: [
    ['transform-react-jsx', {pragma: 'h'}],
    ['transform-runtime']
  ],
  compact: false
};
var browserifyOptions = {
  debug: true
};

gulp.task('clean', function() {
  return gulp.src([paths.output])
    .pipe(vinylPaths(del));
});

gulp.task('build-system', function () {
  return browserify(paths.system, browserifyOptions)
    .transform(babelify, babelOptions)
    .bundle()
    .pipe(vinylSourceStream(paths.systemOutput))
    .pipe(gulp.dest(paths.output));
});

gulp.task('build-html', function () {
  return gulp.src(paths.html)
    .pipe(gulp.dest(paths.output));
});

gulp.task('build', function (callback) {
  return runSequence(
    'clean',
    ['build-system', 'build-html'],
    callback
  );
});
<|endoftext|>


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

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

function addGraphPlaceholders(years) {
    for (var i = 0; i < years.length; i++) {
        var year = years[i];
        document.getElementById('container').innerHTML += '

';
        document.getElementById('graph-' + year).innerHTML += '

' + year + '

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

';
    }
}

var years = [1957, 1960];
var selectedCountryIndex = 0;

addGraphPlaceholders(years);

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

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

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

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

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

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

    var countriesData;
    var scoresData;

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

    var svgContainer = svgContainers[chartYear];

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

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

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

    }

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

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

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

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

        scores = yearResult.scores;

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

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

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

        var links = [];

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

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

        nodesData.push(selectedCountry);

        var i = 0, j = 0;

        var temp = countries.slice();
        temp.splice(selectedCountryIndex, 1);
        temp.forEach(
            function (c) {
                if (i == selectedCountryIndex)
                    i++;

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

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

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

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

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

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

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

                j++;
                i++;
            });

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

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

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

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

        }

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

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

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

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

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

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

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

        //calcAndDraw(selectedCountryIndex);

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

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

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

}<commit_msg>stroke width nog ff aangepast<commit_after>/**
 * Created by Michael on 13/04/2016.
 */
var graphs;

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

function addGraphPlaceholders(years) {
    for (var i = 0; i < years.length; i++) {
        var year = years[i];
        document.getElementById('container').innerHTML += '

';
        document.getElementById('graph-' + year).innerHTML += '

' + year + '

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

';
    }
}

var years = [1957, 1960];
var selectedCountryIndex = 0;

addGraphPlaceholders(years);

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

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

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

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

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

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

    var countriesData;
    var scoresData;

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

    var svgContainer = svgContainers[chartYear];

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

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

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

    }

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

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

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

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

        scores = yearResult.scores;

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

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

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

        var links = [];

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

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

        nodesData.push(selectedCountry);

        var i = 0, j = 0;

        var temp = countries.slice();
        temp.splice(selectedCountryIndex, 1);
        temp.forEach(
            function (c) {
                if (i == selectedCountryIndex)
                    i++;

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

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

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

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

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

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

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

                j++;
                i++;
            });

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

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

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

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

        }

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

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

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

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

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

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

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

        //calcAndDraw(selectedCountryIndex);

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

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

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

}<|endoftext|>


<commit_before>import { GET_BUDGET } from '../actions/budgetView.action';

const budgetReducer = (state = null, action) => {
  switch (action.type) {
    case GET_BUDGET:

      return action.payload.val();
    default:
      return state;
  }
}

export default budgetReducer;<commit_msg>feat(set budget): added an update budget case to the budget reducer<commit_after>import { GET_BUDGET, UPDATE_BUDGET } from '../actions/budgetView.action';

const budgetReducer = (state = null, action) => {
  switch (action.type) {
    case GET_BUDGET:
      return action.payload.val();
    case UPDATE_BUDGET:
      return action.newBudget;
    default:
      return state;
  }
}

export default budgetReducer;<|endoftext|>


<commit_before>// Eloquent JavaScript

// Run this file in your terminal using `node eloquent.js`. Make sure it works before moving on!

// Program Structure
// Write your own variable and do something to it.
    var modulo = 13 % 2;
    console.log(modulo + 5);  // This produces → 6

    var fruitBasket = "apple";
    var whiteFruit = " banana";
    two = "2";
    console.log(fruitBasket + whiteFruit); //-> This produces apple banana
    console.log(two); //-> This produces 2

// Complete one of the exercises: Looping a Triangle, FizzBuzz, or Chess Board
/*  Pseudocode for FizzBuzz problem.
    The range is from 1 to 100.
    Increment the number with 1 to check all the numbers.
    for numbers divisible by 3, print "Fizz" instead of that number.
    for number divisible by 5, print "Buzz"
    for numbers that are divisible both 3 and 5, then print "FizzBuzz" */

    for (var number = 1; number <= 100; number += 1) {
      if ((number % 3 == 0) && (number % 5 == 0))
      console.log("FizzBuzz")
      else if (number % 3 == 0)
      console.log("Fizz");
      else if (number % 5 ==0)
      console.log("Buzz");
      else
      console.log(number);
    }

// Functions

// Complete the `minimum` exercise.

// Data Structures: Objects and Arrays

// Create an object called "me" that stores your name, age, 3 favorite foods, and a quirk below.

// REFLECTIONS:

// Release 1:

// Introduction
// Did you learn anything new about JavaScript or programming in general?
  //  Programming or Javascript requires less code to do the same operation comparing to the old days coding when there was no programming languages. The current programming logic is less complex and more friendly to programmers. With help of blocks constructed in while, for or if statements, there is no need to jump back or forth within the code, while makes it easier to loop for the block. Web browsers are not the only platforms on which Javascript us used. Some databases, such as MongoDB and CouchDB, use Javascript as their scripting and query language. While I was reading throgh Eloquent Javascript book, I found out that the website enables you to edit and run the code, which was great to see different outputs for different input right away.

// Are there any concepts you feel uncomfortable with?
// Nope.

//Ch.1 Values, Types and Operators
//Identify two similarities and two differences between JavaScript and Ruby syntax with regard to numbers, arithmetic, strings, booleans, and various operators.
  // Values in Javascript is the chunk of the bits that were separated and each represent pieces of information. There are six basic types of values in JavaScript: numbers, strings, Booleans, objects, functions, and undefined values.
  //Let's look at each values in both Javascript and Ruby.
    // 1. Numbers are the numerical values, writen as 10. Numbers vary from whole number, integer or frctional numbers, float. There are 3 special numbers in Javascript which are Infinity, -Infinity, and Infinity-1. In Ruby, I have seen only Infinity which results when you divide any number with `0`.
    //2. Strings are the basic data types that reqpresent the text. They are written in both Ruby and Javascript between quotes. When you want to find out what kind of class type is the string, we find out by "String".class = > string in Ruby; however in Javascript we use `typeof` console.log(typeof "x") → string
    //While we are writing strings, whenever a backslash(\) is found inside quoted text, it indicates that the character after ita has a special meaning, which is called escaping the character. When 'n' character comes after backslash, it interpretes as new line (\n) which is also the same in Ruby. Besides `\n`, Javascript has the same `+` operator that concatenates two strings.
    //3. Booleans are the true and false values which distinguishes two possibilities like `on` or `off`. Boolean values are the same for both in Ruby and Javascript.
    //4. Objects and their associated methods are both included in both Ruby and Javascript, which leads that both are object oriented. A prototype in Javascript is much like a Class in Ruby such as:
          // function Cat(name, age) {
          // this.name = name;
          // this.meow = function() {
          // console.log("My name is" +this.name+!) };
          // };
          // var cuteCat = new Cat("Sandy", "5");
    //The cuteCat object is considered a new instance of the Cat prototype. Prototype is essentially the same as Class in Ruby. Note that this in JavaScript is the same concept as self in Ruby.
    //5. Functions . each method is commonly used in Ruby to iterate through an array. Javascript has each function does the same thing but the syntax is different. Ruby has array.each {|element| block } versus Javascript is array.forEach(function(n)) { console.log(n); }.
    //Ruby Methods
          // def plus_5(num = 0)
          // num + 5
          // end
          // plus_5(10) # This returns to 15
          // using map method:
          // [5, 10, 15].map { |k| plus_5(k) }  // This returns to [10, 15, 20]
    // Javascript Functions
          // function plus_5(num) { return (num || 0) + 5; }
          // plus_5();   //This returns to 5
          // plus_5(10); //This returns to 15
          // [5, 10, 15].map(plus_5); // This returns to [10, 15, 20]
    //6. Undefined values are different. null(nil in Ruby) and false will return false. However, some values in Ruby will return false in JavaScript, like 0, empty strings (""), and undefined.

//Ch.2 Program Structure
//What is an expression?
  //A fragment of a code that produces a value is called expression. Every value that is written literally is an expression. The simpliest kind of statement is an expression with a semicolon after it. A function Expression defines a function as a part of a larger expression syntax (typically a variable assignment ). Functions defined via Functions Expressions can be named or anonymous. Function Expressions must not start with “function”.

//What is the purpose of semicolons in JavaScript? Are they always required?
  //If there is no semicolons in Javascript, the next line will be treated as part of the same statement. Most of the time you need to end the code with semicolons. In some cases, JS allows you to omit the semicolons.

// What causes a variable to return undefined?
  // When the variable equals to false, null, `0` or empty string (""), or variable doesn't have any initial value then a variable returns to undefined.

//Write your own variable and do something to it in the eloquent.js file.
  // Please see top of this page.

// What does console.log do and when would you use it? What Ruby method(s) is this similar to?
  // We will use console.log to indicate what we want to see the result of evaluating some code, the value produced should be shown on the screen, although how it apprears will depend on the Javascript environment you use to run it. The methods that we have in Ruby are puts, and p that those could be written in front of method calling which would executes the methods.
//
// Write a short program that asks for a user to input their favorite food. After they hit return, have the program respond with "Hey! That's my favorite too!" (You will probably need to run this in the Chrome console (Links to an external site.) rather than node since node does not support prompt or alert). Paste your program into the eloquent.js file.
      // The solution is:
      //     prompt("What is your favorite food?"," ");
      //     alert("Hey! That's my favorite too!");

// Describe while and for loop
  // While creates a loop. The loop executes that statement as long as the expression produces a value that is true in Boolean. Looping control flow allows us to go back to some point in the program where we were before and repeat it with current program state.
  // for loops is similar to the while loops. The only change is that all the statements that are related to the “state” of the loop are now grouped together. I mean that the parentheses after a for keyword must contain two semicolons like for (var = 1; counter < 5 ; counter ++). The first part defines the variable, the second part checks if it should continue to loop and the last part updates the state of the loop after every iteration.

//What other similarities or differences between Ruby and JavaScript did you notice in this section?
//Binary operators (+, -, *, /, %) and comparison (==, !=, ===, !==, <, >, <=, >=) are the same in both Ruby and Javascript. Just as a note: upper case letters are always "less" than lowercase ones, so "Z"<"a" is true. There is only one value in JavaScript that is not equal to itself, and that is NaN, which stands for “not a number”.
    //console.log(NaN == NaN)
    // → false
// NaN is supposed to show the result of a nonsensical computation, and as such, it isn’t equal to the result of any other nonsensical computations.
// The other difference is that to increment or decrement by 1 in Javascript, you can write ++ or --, in Ruby that's += or -=.
//Logical(conditional) operator which is tenary, operating on three values. It is written with a question mark and colon, like this:
    // console.log(true? 1 : 2) -> This results 1.
    // console.log(false? 1 : 2) -> This results 2.
//The value on the left of the question mark "picks" which of the other two values will come out. When it is true, the middle value is chosen, when it is false, the value on the right is chosen for output result.

// Complete at least one of the exercises (Looping a Triangle, FizzBuzz, of Chess Board) in the eloquent.js file.
// please see top of the page for the answer of FizzBuzz.

// Ch3. Functions

// What are the differences between local and global variables in JavaScript?
  // When a variable is created inside a function then it is local variable as only the locally running code can see it. A variable can be accessed by any part of the code is called global variable. If you create a variable in the global space (outside of a function scope) then it will be global. If this code is run inside a function then, this variable will be local.

    // To create a local variable is
    //      var variable;
    // To create a global variable is
    //      variable;
    // This variable will be always global, no matter where is created.

// When should you use functions?
// Function is a piece of program that wrapped in a value. Whenever we want to run wrapped program, we can apply functions to variables. You can call a function by putting parentheses after an expression which produces function value. You will directly use the name of the variable that holds the function. The values(these could be strings) between the parentheses are given to the program inside the function. Shortly, functions are the butter and heart of the JavaScript programming.

// What is a function declaration?
// When we are declaring a function, we should have () and {}. The block of code goes between the curly braces. A function declaration defines a named function variable witout requiring variable assignment. The declaration occur as standalone constructs and cannot be nested within non-function blocks. We can think them like siblings of Variable declaration, just as variable declarations must start with "var", function declarations must begin with "function".
      // The synax is : function Identifier ( FormalParameterListopt ) { FunctionBody }
      // function bar() {
      //    return 3;
      // }
      // bar();   // the output is 3
      // bar      //function

Complete the minimum exercise in the eloquent.js file.

Ch.4  Data Structures: Objects and and Arrays

Skip the sections on the Lycanthropes log, Computing Correlations, and sections from Further Arrayology to the Global Object, but read the chapter summary.

What is the difference between using a dot and a bracket to look up a property? Ex. array.max vs array["max"]

Create an object called me that stores your name, age, three favorite foods, and a quirk in your eloquent.js file.
me = {name: Fatma, age: 31, favorite foods: beans, spinach and Turkish soop and quirk: }

What is a JavaScript object with a name and value property similar to in Ruby?

// Release 2:
/*
What are the biggest similarities and differences between JavaScript and Ruby?
I guess syntax, and readability. I think Ruby is more friendly with sytanx since it is very similar as if you are speaking English.
Was some of your Ruby knowledge solidified by learning another language? If so, which concepts?
  Yes, indeed. I think comparison of Javascript and Ruby helped me to solidify few concepts like case condition and for loops.

How do you feel about diving into JavaScript after reading these chapters?
Well, I feel alright.
*/
<commit_msg>Update eloquent file<commit_after>// Eloquent JavaScript

// Run this file in your terminal using `node eloquent.js`. Make sure it works before moving on!

// Program Structure
// Write your own variable and do something to it.
    var modulo = 13 % 2;
    console.log(modulo + 5);  // This produces → 6

    var fruitBasket = "apple";
    var whiteFruit = " banana";
    two = "2";
    console.log(fruitBasket + whiteFruit); //-> This produces apple banana
    console.log(two); //-> This produces 2

// Complete one of the exercises: Looping a Triangle, FizzBuzz, or Chess Board
    var pound = "#"
    for (var counter = 0; counter < 7; counter++) {
      console.log(pound);
      pound += "#";
    }

//  favorite food
    var fav_food = prompt("What is your favorite food?");
    alert("Hey! That's my favorite too!");

/*  //FizzBuzz
    The range is from 1 to 100.
    Increment the number with 1 to check all the numbers.
    for numbers divisible by 3, print "Fizz" instead of that number.
    for number divisible by 5, print "Buzz"
    for numbers that are divisible both 3 and 5, then print "FizzBuzz" */

    for (var number = 1; number <= 100; number += 1) {
      if ((number % 3 == 0) && (number % 5 == 0))
      console.log("FizzBuzz")
      else if (number % 3 == 0)
      console.log("Fizz");
      else if (number % 5 ==0)
      console.log("Buzz");
      else
      console.log(number);
    }

    //Chess Board
    var size = 16
    for (var counter = 0; counter < (size / 2); counter++) {
        console.log("# # # #\n");
        console.log(" # # # #\n");
    }

    // Functions

    // Complete the `minimum` exercise.
    function min(a, b) {
      if (a < b)
        return a;
      else
        return b;
    }
    console.log(min(6,4));

// Data Structures: Objects and Arrays

// Create an object called "me" that stores your name, age, 3 favorite foods, and a quirk below.
var me = {
  name: "Fatma",
  age: 31,
  favoriteFoods: ["bean", "spinach", "Turkish soup"],
  quirk: "Hhmm.."
}
console.log(me)

// REFLECTIONS:

// Release 1:

// Introduction
// Did you learn anything new about JavaScript or programming in general?
  //  Programming or Javascript requires less code to do the same operation comparing to the old days coding when there was no programming languages. The current programming logic is less complex and more friendly to programmers. With help of blocks constructed in while, for or if statements, there is no need to jump back or forth within the code, while makes it easier to loop for the block. Web browsers are not the only platforms on which Javascript us used. Some databases, such as MongoDB and CouchDB, use Javascript as their scripting and query language. While I was reading throgh Eloquent Javascript book, I found out that the website enables you to edit and run the code, which was great to see different outputs for different input right away.

// Are there any concepts you feel uncomfortable with?
// Nope.

//Ch.1 Values, Types and Operators
//Identify two similarities and two differences between JavaScript and Ruby syntax with regard to numbers, arithmetic, strings, booleans, and various operators.
  // Values in Javascript is the chunk of the bits that were separated and each represent pieces of information. There are six basic types of values in JavaScript: numbers, strings, Booleans, objects, functions, and undefined values.
  //Let's look at each values in both Javascript and Ruby.
    // 1. Numbers are the numerical values, writen as 10. Numbers vary from whole number, integer or frctional numbers, float. There are 3 special numbers in Javascript which are Infinity, -Infinity, and Infinity-1. In Ruby, I have seen only Infinity which results when you divide any number with `0`.
    //2. Strings are the basic data types that reqpresent the text. They are written in both Ruby and Javascript between quotes. When you want to find out what kind of class type is the string, we find out by "String".class = > string in Ruby; however in Javascript we use `typeof` console.log(typeof "x") → string
    //While we are writing strings, whenever a backslash(\) is found inside quoted text, it indicates that the character after ita has a special meaning, which is called escaping the character. When 'n' character comes after backslash, it interpretes as new line (\n) which is also the same in Ruby. Besides `\n`, Javascript has the same `+` operator that concatenates two strings.
    //3. Booleans are the true and false values which distinguishes two possibilities like `on` or `off`. Boolean values are the same for both in Ruby and Javascript.
    //4. Objects and their associated methods are both included in both Ruby and Javascript, which leads that both are object oriented. A prototype in Javascript is much like a Class in Ruby such as:
          // function Cat(name, age) {
          // this.name = name;
          // this.meow = function() {
          // console.log("My name is" +this.name+!) };
          // };
          // var cuteCat = new Cat("Sandy", "5");
    //The cuteCat object is considered a new instance of the Cat prototype. Prototype is essentially the same as Class in Ruby. Note that this in JavaScript is the same concept as self in Ruby.
    //5. Functions . each method is commonly used in Ruby to iterate through an array. Javascript has each function does the same thing but the syntax is different. Ruby has array.each {|element| block } versus Javascript is array.forEach(function(n)) { console.log(n); }.
    //Ruby Methods
          // def plus_5(num = 0)
          // num + 5
          // end
          // plus_5(10) # This returns to 15
          // using map method:
          // [5, 10, 15].map { |k| plus_5(k) }  // This returns to [10, 15, 20]
    // Javascript Functions
          // function plus_5(num) { return (num || 0) + 5; }
          // plus_5();   //This returns to 5
          // plus_5(10); //This returns to 15
          // [5, 10, 15].map(plus_5); // This returns to [10, 15, 20]
    //6. Undefined values are different. null(nil in Ruby) and false will return false. However, some values in Ruby will return false in JavaScript, like 0, empty strings (""), and undefined.

//Ch.2 Program Structure
//What is an expression?
  //A fragment of a code that produces a value is called expression. Every value that is written literally is an expression. The simpliest kind of statement is an expression with a semicolon after it. A function Expression defines a function as a part of a larger expression syntax (typically a variable assignment ). Functions defined via Functions Expressions can be named or anonymous. Function Expressions must not start with “function”.

//What is the purpose of semicolons in JavaScript? Are they always required?
  //If there is no semicolons in Javascript, the next line will be treated as part of the same statement. Most of the time you need to end the code with semicolons. In some cases, JS allows you to omit the semicolons.

// What causes a variable to return undefined?
  // When the variable equals to false, null, `0` or empty string (""), or variable doesn't have any initial value then a variable returns to undefined.

//Write your own variable and do something to it in the eloquent.js file.
  // Please see top of this page.

// What does console.log do and when would you use it? What Ruby method(s) is this similar to?
  // We will use console.log to indicate what we want to see the result of evaluating some code, the value produced should be shown on the screen, although how it apprears will depend on the Javascript environment you use to run it. The methods that we have in Ruby are puts, and p that those could be written in front of method calling which would executes the methods.
//
// Write a short program that asks for a user to input their favorite food. After they hit return, have the program respond with "Hey! That's my favorite too!" (You will probably need to run this in the Chrome console (Links to an external site.) rather than node since node does not support prompt or alert). Paste your program into the eloquent.js file.
      // The solution is:
      //     var fav_food = prompt("What is your favorite food?", " ");
      //     alert("Hey! That's my favorite too!");

// Describe while and for loop
  // While creates a loop. The loop executes that statement as long as the expression produces a value that is true in Boolean. Looping control flow allows us to go back to some point in the program where we were before and repeat it with current program state.
  // for loops is similar to the while loops. The only change is that all the statements that are related to the “state” of the loop are now grouped together. I mean that the parentheses after a for keyword must contain two semicolons like for (var = 1; counter < 5 ; counter ++). The first part defines the variable, the second part checks if it should continue to loop and the last part updates the state of the loop after every iteration.

//What other similarities or differences between Ruby and JavaScript did you notice in this section?
//Binary operators (+, -, *, /, %) and comparison (==, !=, ===, !==, <, >, <=, >=) are the same in both Ruby and Javascript. Just as a note: upper case letters are always "less" than lowercase ones, so "Z"<"a" is true. There is only one value in JavaScript that is not equal to itself, and that is NaN, which stands for “not a number”.
    //console.log(NaN == NaN)
    // → false
// NaN is supposed to show the result of a nonsensical computation, and as such, it isn’t equal to the result of any other nonsensical computations.
// The other difference is that to increment or decrement by 1 in Javascript, you can write ++ or --, in Ruby that's += or -=.
//Logical(conditional) operator which is tenary, operating on three values. It is written with a question mark and colon, like this:
    // console.log(true? 1 : 2) -> This results 1.
    // console.log(false? 1 : 2) -> This results 2.
//The value on the left of the question mark "picks" which of the other two values will come out. When it is true, the middle value is chosen, when it is false, the value on the right is chosen for output result.

// Complete at least one of the exercises (Looping a Triangle, FizzBuzz, of Chess Board) in the eloquent.js file.
// please see top of the page for the answer of FizzBuzz.

// Ch3. Functions

// What are the differences between local and global variables in JavaScript?
  // When a variable is created inside a function then it is local variable as only the locally running code can see it. A variable can be accessed by any part of the code is called global variable. If you create a variable in the global space (outside of a function scope) then it will be global. If this code is run inside a function then, this variable will be local.

    // To create a local variable is
    //      var variable;
    // To create a global variable is
    //      variable;
    // This variable will be always global, no matter where is created.

// When should you use functions?
// Function is a piece of program that wrapped in a value. Whenever we want to run wrapped program, we can apply functions to variables. You can call a function by putting parentheses after an expression which produces function value. You will directly use the name of the variable that holds the function. The values(these could be strings) between the parentheses are given to the program inside the function. Shortly, functions are the butter and heart of the JavaScript programming.

// What is a function declaration?
// When we are declaring a function, we should have () and {}. The block of code goes between the curly braces. A function declaration defines a named function variable witout requiring variable assignment. The declaration occur as standalone constructs and cannot be nested within non-function blocks. We can think them like siblings of Variable declaration, just as variable declarations must start with "var", function declarations must begin with "function".
      // The synax is : function Identifier ( FormalParameterListopt ) { FunctionBody }
      // function bar() {
      //    return 3;
      // }
      // bar();   // the output is 3
      // bar      //function

// Complete the minimum exercise in the eloquent.js file.
// Please see top of the page.

//Ch.4  Data Structures: Objects and and Arrays

//What is the difference between using a dot and a bracket to look up a property? Ex. array.max vs array["max"]
  //Accessing members with . is dot notation and accessing with [] is bracket notation. To start with dot notation, it only works with property names. Bracket notation expects an experssion which evaluates to a string, so so you can use any character sequenceas poperty name.

// Create an object called me that stores your name, age, three favorite foods, and a quirk in your eloquent.js file.
// please see top of the page.

//What is a JavaScript object with a name and value property similar to in Ruby?
//Numbers, Booleans, and strings are the bricks that data structures are built from. But you cant make much of a house out of a single brick. Objects allow programmers to group values such as numbers, strings, Booleans including other objects together to build more complex structure.

// Release 2:
/*
What are the biggest similarities and differences between JavaScript and Ruby?
I guess syntax, and readability. I think Ruby is more friendly with sytanx since it is very similar as if you are speaking English.
Was some of your Ruby knowledge solidified by learning another language? If so, which concepts?
  Yes, indeed. I think comparison of Javascript and Ruby helped me to solidify few concepts like case condition and for loops.

How do you feel about diving into JavaScript after reading these chapters?
Well, I feel alright.
*/
<|endoftext|>


<commit_before>/*
 * jQuery File Upload Plugin JS Example 8.8.2
 * https://github.com/blueimp/jQuery-File-Upload
 *
 * Copyright 2010, Sebastian Tschan
 * https://blueimp.net
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 */

/*jslint nomen: true, regexp: true */
/*global $, window, blueimp */
'use strict';

let dominator = {

  init: function(DOMelement) {
    this.el = DOMelement;
    this.files = new Map();   // Metadata related to uploaded files
    this.queueFiles = 0;      // Files in the process queue
    this.queueReady = false;
    this.processedFiles = 0;  // Number of succesfully processed files
  },

  /**
   * Callback function triggered when files have been added to upload queue
   */
  add: (e, data) => {
    dominator.queueFiles++
    let element = $('select#' + data.files[0].name.split('.')[0]);
    if(dominator.queueFiles <= 2) {
      dominator.files.set(element[0].id,
        {
          type: ''
        }
      );
      element.on('change', (e) => {
        dominator.setType(element[0].id, e.currentTarget.value);
      });
    } else {
      console.log('aborta mision');
      data.abort(); // TODO make it abort add
    }
    if(dominator.queueFiles == 2) {
      // TODO I thougt I could re-enable buttons here but no
    }
  },

  beforeUpload: data => {
    if(dominator.queueFiles == 2) {
      let name = data.get('file').name.split('.')[0];
      let file_type = dominator.files.get(name).type;
      data.set('file_type', file_type);
      $('button.process').removeAttr('disabled');
    } else {
      alert('There must be at least 2 files to upload!');
    }
    return data;
  },

  /**
   * Callback function to send uploaded files to processing in sqlizer
   */
  processFiles: data => {
    let key = undefined;
    let file = data.result.files[0];
    $.get('/process/' + file.resource_id,
      {},
      function(response) {
        if(response.Status === 'Complete') {
          if(dominator.processedFiles < 2) {
            dominator.files.get(response.FileName.split('.')[0]).data = response
            dominator.processedFiles++;
          }
          if(dominator.processedFiles == 2) {
            //Send only file type and name of the table created.
            let data = {};
            dominator.files.forEach((k, v) => {
              data[k.type] = k.data.TableName;
            });
            dominator.processed(data);
          }
        }
    });
  },

  /**
   * Callback funtion that triggers when each file returns a succesful state
   * from sqlizer
   */
  processed: data => {
    console.log('FALTA BLOQUEAR PANTALLA');
    $.get('/postproc/',
      data,
      function(response) {
        console.log(response);
    });
    console.log('LIBERAR PANTALLA');
  },

  /**
   * Mutex function for file types
   */
  setType: (file_id, file_type) => {
    if(dominator.files.has(file_id)) {
      dominator.files.get(file_id).type = file_type;
    }
console.log(dominator.files.get(file_id).type);
    let count = 0;
    dominator.files.forEach((v, k) => {
      let sel = $('select#' + file_id);
      console.log(sel.val() +' '+ sel.val().length +' '+typeof(sel.val()));
      if(sel.val() != file_type
        && (sel.val() != undefined || sel.val().length > 0)) {
        sel.val(file_type);
        if(v.type != undefined && v.type.length != 0
          && dominator.queueFiles == 2) {
          count++;
          if(count == 2) {
          // Enable start upoad button only when files have file type
            dominator.queueReady = true;
            $('button.start').removeAttr('disabled');
          }
        }
      }
    });
  },

}

$(function () {
  'use strict';

  dominator.init($('#fileupload')); // Initialize the dominator

    // Initialize the jQuery File Upload widget:
    $('#fileupload').fileupload({
      uploadTemplate: dominator.uploadTemplate
    })
    .on('fileuploadadded', dominator.add)
    .on('fileuploadsend', function(e, data) {
      console.log(data.data.values());
     data.data = dominator.beforeUpload(data.data);
      console.log(data.data.values());
    })
    .on('fileuploadcompleted', function(e, data) {
      $('#fileupload_control .process').on('click',
        dominator.processFiles(data));
    });

    // Enable iframe cross-domain access via redirect option:
    $('#fileupload').fileupload(
        'option',
        'redirect',
        window.location.href.replace(
            /\/[^\/]*$/,
            '/cors/result.html?%s'
        )
    );
});
<commit_msg>WIP fixing type of file<commit_after>/*
 * jQuery File Upload Plugin JS Example 8.8.2
 * https://github.com/blueimp/jQuery-File-Upload
 *
 * Copyright 2010, Sebastian Tschan
 * https://blueimp.net
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 */

/*jslint nomen: true, regexp: true */
/*global $, window, blueimp */
'use strict';

let dominator = {

  init: function(DOMelement) {
    this.el = DOMelement;
    this.files = new Map();   // Metadata related to uploaded files
    this.queueFiles = 0;      // Files in the process queue
    this.queueReady = false;
    this.processedFiles = 0;  // Number of succesfully processed files
  },

  /**
   * Callback function triggered when files have been added to upload queue
   */
  add: (e, data) => {
    dominator.queueFiles++
    let element = $('select#' + data.files[0].name.split('.')[0]);
    if(dominator.queueFiles <= 2) {
      dominator.files.set(element[0].id,
        {
          type: ''
        }
      );
      element.on('change', (e) => {
        dominator.setType(element[0].id, e.currentTarget.value);
      });
    } else {
      console.log('aborta mision');
      data.abort(); // TODO make it abort add
    }
    if(dominator.queueFiles == 2) {
      // TODO I thougt I could re-enable buttons here but no
    }
  },

  beforeUpload: data => {
    if(dominator.queueFiles == 2) {
      let name = data.get('file').name.split('.')[0];
      let file_type = dominator.files.get(name).type;
      data.set('file_type', file_type);
      $('button.process').removeAttr('disabled');
    } else {
      alert('There must be at least 2 files to upload!');
    }
    return data;
  },

  /**
   * Callback function to send uploaded files to processing in sqlizer
   */
  processFiles: data => {
    let key = undefined;
    let file = data.result.files[0];
    $.get('/process/' + file.resource_id,
      {},
      function(response) {
        if(response.Status === 'Complete') {
          if(dominator.processedFiles < 2) {
            dominator.files.get(response.FileName.split('.')[0]).data = response
            dominator.processedFiles++;
          }
          if(dominator.processedFiles == 2) {
            //Send only file type and name of the table created.
            let data = {};
            dominator.files.forEach((k, v) => {
              data[k.type] = k.data.TableName;
            });
            dominator.processed(data);
          }
        }
    });
  },

  /**
   * Callback funtion that triggers when each file returns a succesful state
   * from sqlizer
   */
  processed: data => {
    console.log('FALTA BLOQUEAR PANTALLA');
    $.get('/postproc/',
      data,
      function(response) {
        console.log(response);
    });
    console.log('LIBERAR PANTALLA');
  },

  /**
   * Mutex function for file types
   */
  setType: (file_id, file_type) => {
    let count = 0;
    let sel = $('select#' + file_id);

    dominator.files.forEach((v, k) => {
      if(sel.val() != undefined || sel.val().length > 0) {
        // Check values in select to be different
        if(file_id !== k) {
          console.log('el otro');
          if(dominator.files.get(k).type === sel.val()) {
            sel.val("");
            dominator.files.get(file_id).type = "";
            alert("File can't be of the same type");
            return;
          }
        }
        dominator.files.get(file_id).type = file_type;
        if(v.type != undefined && v.type.length != 0
          && dominator.queueFiles == 2) {
          count++;
          if(count == 2) {
          // Enable start upoad button only when files have file type
            dominator.queueReady = true;
            $('button.start').removeAttr('disabled');
          }
        }

      }

    });
  },

}

$(function () {
  'use strict';

  dominator.init($('#fileupload')); // Initialize the dominator

    // Initialize the jQuery File Upload widget:
    $('#fileupload').fileupload({
      uploadTemplate: dominator.uploadTemplate
    })
    .on('fileuploadadded', dominator.add)
    .on('fileuploadsend', function(e, data) {
      console.log(data.data.values());
     data.data = dominator.beforeUpload(data.data);
      console.log(data.data.values());
    })
    .on('fileuploadcompleted', function(e, data) {
      $('#fileupload_control .process').on('click',
        dominator.processFiles(data));
    });

    // Enable iframe cross-domain access via redirect option:
    $('#fileupload').fileupload(
        'option',
        'redirect',
        window.location.href.replace(
            /\/[^\/]*$/,
            '/cors/result.html?%s'
        )
    );
});
<|endoftext|>


<commit_before>/* global tests */
tests.addSuite([
    function() {
        //Test if the method Utils.adjacentCells exists

        tests.isA(Utils.adjacentCells, 'function');
    },
    function() {
        //Test if the method Utils.inArray exists

        tests.isA(Utils.inArray, 'function');
    },
    function() {
        //Test Utils.inArray

        //Test if an element is in an empty array
        tests.equals(Utils.inArray(1, []), false);

        //Test if an element is not in an array
        tests.equals(Utils.inArray(1, [2, 3]), false);

        //Test if an element is in an array
        tests.equals(Utils.inArray(1, [1, 2]), true);

        //Test if an element is in an array but with a different type
        tests.equals(Utils.inArray(1, ['1', 2]), false);
    }
]);
<commit_msg>comment added - #71<commit_after>/* global tests */
tests.addSuite([
        //Test if the method Utils.inArray exists

        tests.isA(Utils.inArray, 'function');
    },
    function() {
        //Test Utils.inArray

        //Test if an element is in an empty array
        tests.equals(Utils.inArray(1, []), false);

        //Test if an element is not in an array
        tests.equals(Utils.inArray(1, [2, 3]), false);

        //Test if an element is in an array
        tests.equals(Utils.inArray(1, [1, 2]), true);

        //Test if an element is in an array but with a different type
        tests.equals(Utils.inArray(1, ['1', 2]), false);
    }
]);
<|endoftext|>


<commit_before>/** 插入自定义html模块 (可用于插入广告模块等)
 * {
 *   homeSidebarB: htmlString, 首页侧边栏底部
 *
 *   sidebarT: htmlString, 全局左侧边栏顶部
 *   sidebarB: htmlString, 全局左侧边栏底部
 *
 *   pageT: htmlString, 全局页面顶部
 *   pageB: htmlString, 全局页面底部
 *   pageTshowMode: string, 页面顶部-显示方式：未配置默认全局；'article' => 仅文章页①； 'custom' => 仅自定义页①
 *   pageBshowMode: string, 页面底部-显示方式：未配置默认全局；'article' => 仅文章页①； 'custom' => 仅自定义页①
 *
 *   windowLB: htmlString, 全局左下角②
 *   windowRB: htmlString, 全局右下角②
 * }
 *
 * ①注：在.md文件front matter配置`article: false`的页面是自定义页，未配置的默认是文章页（首页除外）。
 * ②注：windowLB 和 windowRB：1.展示区块宽高最大是200*200px。2.请给自定义元素定一个不超过200px的固定宽高。3.在屏宽小于960px时无论如何都不会显示。
 */

module.exports = {
  homeSidebarB:
    `

    `,
  // sidebarT:
  //   `
  //
  //     `,
  sidebarB:
    `

      `,
  pageT: //
    `

      `,
  // pageTshowMode: 'article',
  pageB:
    `

      `,
  // pageBshowMode: 'article',
  // windowLB: // 遮挡部分侧边栏
  //   `
  //
  //     `,
  windowRB:
     `

      `,
}

// module.exports = {
//   homeSidebarB: `<div style="width:100%;height:100px;color:#fff;background: #eee;">自定义模块测试</div>`,
//   sidebarT: `<div style="width:100%;height:100px;color:#fff;background: #eee;">自定义模块测试</div>`,
//   sidebarB: `<div style="width:100%;height:100px;color:#fff;background: #eee;">自定义模块测试</div>`,
//   pageT: `<div style="width:100%;height:100px;color:#fff;background: #eee;">自定义模块测试</div>`,
//   pageB: `<div style="width:100%;height:100px;color:#fff;background: #eee;">自定义模块测试</div>`,
//   windowLB: `<div style="width:100%;height:100px;color:#fff;background: #eee;">自定义模块测试</div>`,
//   windowRB: `<div style="width:100%;height:100px;color:#fff;background: #eee;">自定义模块测试</div>`,
// }
<commit_msg>更新html模块<commit_after>/** 插入自定义html模块 (可用于插入广告模块等)
 * {
 *   homeSidebarB: htmlString, 首页侧边栏底部
 *
 *   sidebarT: htmlString, 全局左侧边栏顶部
 *   sidebarB: htmlString, 全局左侧边栏底部
 *
 *   pageT: htmlString, 全局页面顶部
 *   pageB: htmlString, 全局页面底部
 *   pageTshowMode: string, 页面顶部-显示方式：未配置默认全局；'article' => 仅文章页①； 'custom' => 仅自定义页①
 *   pageBshowMode: string, 页面底部-显示方式：未配置默认全局；'article' => 仅文章页①； 'custom' => 仅自定义页①
 *
 *   windowLB: htmlString, 全局窗口左下角②
 *   windowRB: htmlString, 全局窗口右下角②
 * }
 *
 * ①注：在.md文件front matter配置`article: false`的页面是自定义页，未配置的默认是文章页（首页除外）。
 * ②注：windowLB 和 windowRB：1.展示区块宽高最大是200*200px。2.请给自定义元素定一个不超过200px的固定宽高。3.在屏宽小于960px时无论如何都不会显示。
 */

module.exports = {
  homeSidebarB:
    `

    `,
  // sidebarT:
  //   `
  //
  //     `,
  sidebarB:
    `

      `,
  pageT: //
    `

      `,
  // pageTshowMode: 'article',
  pageB:
    `

      `,
  // pageBshowMode: 'article',
  // windowLB: // 会遮挡部分侧边栏
  //   `
  //
  //
  //     `,
  windowRB:
     `

      `,
}

// module.exports = {
//   homeSidebarB: `<div style="width:100%;height:100px;color:#fff;background: #eee;">自定义模块测试</div>`,
//   sidebarT: `<div style="width:100%;height:100px;color:#fff;background: #eee;">自定义模块测试</div>`,
//   sidebarB: `<div style="width:100%;height:100px;color:#fff;background: #eee;">自定义模块测试</div>`,
//   pageT: `<div style="width:100%;height:100px;color:#fff;background: #eee;">自定义模块测试</div>`,
//   pageB: `<div style="width:100%;height:100px;color:#fff;background: #eee;">自定义模块测试</div>`,
//   windowLB: `<div style="width:100%;height:100px;color:#fff;background: #eee;">自定义模块测试</div>`,
//   windowRB: `<div style="width:100%;height:100px;color:#fff;background: #eee;">自定义模块测试</div>`,
// }
<|endoftext|>