<commit_before>$(function () {
    const property = 'hc-key';

    const visited_countries = [
        'in',  // India
        'np',  // Nepal
        'th',  // Thailand
        'sg',  // Singapore
        'my',  // Malaysia
        'ch',  // Switzerland
        'de',  // Germany
        'fr',  // France
        'au',   // Australia

    ]

    const visited_states_in_india = [
        'in-wb',
        'in-pb',
        'in-ga',
        'in-2984',
        'in-jk',
        'in-hr',
        'in-tn',
        'in-ap',
        'in-ka',
        'in-mh',
        'in-or',
        'in-dl',
        'in-hp',
        'in-rj',
        'in-up',
        'in-ut',
        'in-jh',
        'in-ch',
        'in-br'
    ]

    const visited_states_in_us = [
        'us-ma',
        'us-ca',
        'us-wa',
        'us-or',
        'us-wi',
        'us-nv',
        'us-sc',
        'us-ny',
        'us-nj',
        'us-fl',
        'us-ga',
        'us-az'
    ];

    function getDrilldown(data, visited) {
        $.each(data, function(i) {
            this.value = visited.indexOf(this.properties[property]);
        });
        return data;
    }

    // Fetch data
    var world_data =  Highcharts.geojson(Highcharts.maps['custom/world']);

    var us_data =  Highcharts.geojson(Highcharts.maps['countries/us/us-all']);

    var india_data =  Highcharts.geojson(Highcharts.maps['countries/in/custom/in-all-disputed']);

    console.log(india_data);

    // Set drilldown pointers
    $.each(world_data, function (i) {

        if (this.properties[property] == 'us') {
            this.drilldown = getDrilldown(
                us_data,
                visited_states_in_us);
            this.drilldownLabel = 'United States of America';
        } else if (this.properties[property] == 'in') {
            this.drilldown = getDrilldown(
                india_data,
                visited_states_in_india);
            this.drilldownLabel = 'India';
        }

        this.value = visited_countries.indexOf(this.properties[property]);
    });

    // Instanciate the map
    $('#container').highcharts('Map', {
        chart: {
            spacingBottom: 20,
            events: {
                drilldown: function (e) {
                    if (!e.seriesOptions) {
                        var chart = this;
                        var data = e.point.drilldown;
                        var label = e.point.drilldownLabel;

                        chart.addSeriesAsDrilldown(e.point, {
                            name: label,
                            data: data,
                            dataLabels: {
                                enabled: true,
                                format: '{point.name}'
                            },
                            tooltip: {
                                headerFormat: '',
                                pointFormat: '{point.name}'
                            }
                        });
                    }
                    chart.setTitle(null, { text: label });
                },
                drillup: function () {
                    this.setTitle(null, { text: 'World' });
                }
            }
        },
        title : {
            text : 'Around the world!!',
        },

        subtitle: {
            text: 'World',
        },

        mapNavigation: {
            enabled: true,
            enableMouseWheelZoom: false,
            buttonOptions: {
                verticalAlign: 'bottom'
            }
        },

        colorAxis: {
            dataClasses: [{
                from: -100,
                to: 0,
                color: '#E5F5E0',
                name: 'Pending'
            }, {
                from: 0,
                to: 100,
                color: '#31A354',
                name: 'Visited'
            }]
        },

        plotOptions: {
            map: {
                states: {
                    hover: {
                        color: '#EEDD66'
                    }
                }
            }
        },

        series : [{
            name: 'World',
            data: world_data,
            dataLabels: {
                enabled: true,
                format: '{point.name}'
            },
            tooltip: {
                headerFormat: '',
                pointFormat: '{point.name}'
            }
        }],

        drilldown: {
            activeDataLabelStyle: {
                color: '#FFFFFF',
                textDecoration: 'none',
                textShadow: '0 0 3px #000000'
            },
            drillUpButton: {
                relativeTo: 'spacingBox',
                position: {
                    x: 0,
                    y: 60
                }
            }
        }
    });
});
<commit_msg>Update index.js<commit_after>$(function () {
    const property = 'hc-key';

    const visited_countries = [
        'in',  // India
        'bt',  //bhutan
        'sg',  // Singapore
        'vn',  // vietnam
        'id',   // Indonesia

    ]

    const visited_states_in_india = [
        'in-wb',
        'in-pb',
        'in-ga',
        'in-2984',
        'in-jk',
        'in-hr',
        'in-tn',
        'in-ap',
        'in-ka',
        'in-mh',
        'in-or',
        'in-dl',
        'in-hp',
        'in-rj',
        'in-up',
        'in-ut',
        'in-jh',
        'in-ch',
        'in-br'
    ]
    function getDrilldown(data, visited) {
        $.each(data, function(i) {
            this.value = visited.indexOf(this.properties[property]);
        });
        return data;
    }

    // Fetch data
    var world_data =  Highcharts.geojson(Highcharts.maps['custom/world']);

    var us_data =  Highcharts.geojson(Highcharts.maps['countries/us/us-all']);

    var india_data =  Highcharts.geojson(Highcharts.maps['countries/in/custom/in-all-disputed']);

    console.log(india_data);

    // Set drilldown pointers
    $.each(world_data, function (i) {

        if (this.properties[property] == 'us') {
            this.drilldown = getDrilldown(
                us_data,
                visited_states_in_us);
            this.drilldownLabel = 'United States of America';
        } else if (this.properties[property] == 'in') {
            this.drilldown = getDrilldown(
                india_data,
                visited_states_in_india);
            this.drilldownLabel = 'India';
        }

        this.value = visited_countries.indexOf(this.properties[property]);
    });

    // Instanciate the map
    $('#container').highcharts('Map', {
        chart: {
            spacingBottom: 20,
            events: {
                drilldown: function (e) {
                    if (!e.seriesOptions) {
                        var chart = this;
                        var data = e.point.drilldown;
                        var label = e.point.drilldownLabel;

                        chart.addSeriesAsDrilldown(e.point, {
                            name: label,
                            data: data,
                            dataLabels: {
                                enabled: true,
                                format: '{point.name}'
                            },
                            tooltip: {
                                headerFormat: '',
                                pointFormat: '{point.name}'
                            }
                        });
                    }
                    chart.setTitle(null, { text: label });
                },
                drillup: function () {
                    this.setTitle(null, { text: 'World' });
                }
            }
        },
        title : {
            text : 'Around the world!!',
        },

        subtitle: {
            text: 'World',
        },

        mapNavigation: {
            enabled: true,
            enableMouseWheelZoom: false,
            buttonOptions: {
                verticalAlign: 'bottom'
            }
        },

        colorAxis: {
            dataClasses: [{
                from: -100,
                to: 0,
                color: '#E5F5E0',
                name: 'Pending'
            }, {
                from: 0,
                to: 100,
                color: '#31A354',
                name: 'Visited'
            }]
        },

        plotOptions: {
            map: {
                states: {
                    hover: {
                        color: '#EEDD66'
                    }
                }
            }
        },

        series : [{
            name: 'World',
            data: world_data,
            dataLabels: {
                enabled: true,
                format: '{point.name}'
            },
            tooltip: {
                headerFormat: '',
                pointFormat: '{point.name}'
            }
        }],

        drilldown: {
            activeDataLabelStyle: {
                color: '#FFFFFF',
                textDecoration: 'none',
                textShadow: '0 0 3px #000000'
            },
            drillUpButton: {
                relativeTo: 'spacingBox',
                position: {
                    x: 0,
                    y: 60
                }
            }
        }
    });
});
<|endoftext|>


<commit_before>'use strict';

angular.module('angularRestfulAuth')
    .factory('Main', ['$http', '$localStorage', function($http, $localStorage) {
        var baseUrl = 'http://localhost:3000/api';

        function buildRequest(method, url, data, token) {
            var requestData = {
                method: method,
                url: url,
                data: data
            };
            if (token) {
                requestData.headers = { 'Authorization': 'Token ' + token };
            }
            return requestData;
        }

        function changeUser(user) {
            angular.extend(currentUser, user);
        }

        function urlBase64Decode(str) {
            var output = str.replace('-', '+').replace('_', '/');
            switch (output.length % 4) {
                case 0:
                    break;
                case 2:
                    output += '==';
                    break;
                case 3:
                    output += '=';
                    break;
                default:
                    throw 'Illegal base64url string!';
            }
            return window.atob(output);
        }

        function getUserFromToken() {
            var token = $localStorage.token;
            var user = {};
            if (typeof token !== 'undefined') {
                var encoded = token.split('.')[1];
                user = JSON.parse(urlBase64Decode(encoded));
            }
            return user;
        }

        var currentUser = getUserFromToken();
        return {
            register: function(data, success, error) {
                $http.post(baseUrl + '/register', data).success(success).error(error);
            },
            signin: function(data, success, error) {
                $http.post(baseUrl + '/signin', data).success(success).error(error);
            },
            me: function(data, success, error) {
                $http.get(baseUrl + '/me').success(success).error(error);
            },
            logout: function(success) {
                changeUser({});
                delete $localStorage.token;
                success();
            },
            getPrograms: function(token, success, err) {
                $http.get(baseUrl + '/programs').success(success).error(err);
            },
            getUserFromToken: getUserFromToken,
            changeUser: changeUser,
            getClasses: function(token, success, err) {
                $http.get(baseUrl + '/classes/', {
                    headers: {
                        'Authorization': 'Basic ' + token
                    }
                }).success(success).error(err);
            },
            saveClass: function(data, token, success, err) {
                console.log('Saving data...');
                console.log(JSON.stringify(data));
                $http.post(baseUrl + '/classes/', data, {
                    headers: {
                        'Authorization': 'Basic ' + token
                    }
                }).success(success).error(err);
            }
        }
    }]);
<commit_msg>Changed the way I'm detecting whether a token is valid<commit_after>'use strict';

angular.module('angularRestfulAuth')
    .factory('Main', ['$http', '$localStorage', function($http, $localStorage) {
        var baseUrl = 'http://localhost:3000/api';

        function buildRequest(method, url, data, token) {
            var requestData = {
                method: method,
                url: url,
                data: data
            };
            if (token) {
                requestData.headers = { 'Authorization': 'Token ' + token };
            }
            return requestData;
        }

        function changeUser(user) {
            angular.extend(currentUser, user);
        }

        function urlBase64Decode(str) {
            var output = str.replace('-', '+').replace('_', '/');
            switch (output.length % 4) {
                case 0:
                    break;
                case 2:
                    output += '==';
                    break;
                case 3:
                    output += '=';
                    break;
                default:
                    throw 'Illegal base64url string!';
            }
            return window.atob(output);
        }

        function getUserFromToken() {
            var token = $localStorage.token;
            var user = {};
            if (typeof token === "string") {
                var encoded = token.split('.')[1];
                user = JSON.parse(urlBase64Decode(encoded));
            }
            return user;
        }

        var currentUser = getUserFromToken();
        return {
            register: function(data, success, error) {
                $http.post(baseUrl + '/users/register', data).success(success).error(error);
            },
            signin: function(data, success, error) {
                $http.post(baseUrl + '/users/signin', data).success(success).error(error);
            },
            me: function(data, success, error) {
                $http.get(baseUrl + '/users/me').success(success).error(error);
            },
            logout: function(success) {
                changeUser({});
                delete $localStorage.token;
                success();
            },
            getPrograms: function(token, success, err) {
                $http.get(baseUrl + '/programs').success(success).error(err);
            },
            getUserFromToken: getUserFromToken,
            changeUser: changeUser,
            getClasses: function(token, success, err) {
                console.log(getUserFromToken(token));
                $http.get(baseUrl + '/classes/', {
                    headers: {
                        'Authorization': 'Basic ' + token
                    }
                }).success(success).error(err);
            },
            saveClass: function(data, token, success, err) {
                console.log('Saving data...');
                console.log(JSON.stringify(data));
                $http.post(baseUrl + '/classes/', data, {
                    headers: {
                        'Authorization': 'Basic ' + token
                    }
                }).success(success).error(err);
            }
        }
    }]);
<|endoftext|>


<commit_before>;(function () {
	// level caps
	var stageCollections = [
		{
			levelCap: 10,
			stageUrl: 'pb'
		},
		{
			levelCap: 20,
			stageUrl: 'sb'
		},
		{
			levelCap: 30,
			stageUrl: 'nf'
		},
		{
			levelCap: 45,
			stageUrl: 'ia'
		},
		{
			levelCap: 60,
			stageUrl: 'rp'
		},
		{
			levelCap: 75,
			stageUrl: 'gr'
		},
		{
			levelCap: 90,
			stageUrl: 'ss'
		},
		{
			levelCap: 105,
			stageUrl: 'sm'
		},
		{
			levelCap: 120,
			stageUrl: 'mv'
		},
		{
			levelCap: 135,
			stageUrl: 'cn'
		},
		{
			levelCap: 150,
			stageUrl: 'jv'
		},
		{
			levelCap: 180,
			stageUrl: 'ww'
		},
		{
			levelCap: 210,
			stageUrl: 'pv'
		},
		{
			levelCap: 240,
			stageUrl: 'at'
		},
		{
			levelCap: 300,
			stageUrl: 'rc'
		},
		{
			levelCap: 350,
			stageUrl: 'du'
		},
		{
			levelCap: 400,
			stageUrl: 'vp'
		},
		{
			levelCap: 450,
			stageUrl: 'bs'
		}
	];

	// setup stage divisions
	var pokemonCollectionUrl = 'https://rawgit.com/shelune/poke-shuffle-guide/master/app/scripts/assets/pokemonCollection.json';
	var pokemonCollection;
	$.getJSON(pokemonCollectionUrl, function (data) {
		pokemonCollection = data;
	});

	// setup stage id
	function getStage(stageId) {
		var stageUrls = [];
		stageCollections.forEach(function (stages){
			if (stageId <= stages.levelCap) {
				stageUrls.push('https://rawgit.com/shelune/poke-shuffle-guide/master/app/scripts/assets/stageGuides/' + stages.stageUrl + '.json');
			}
		});
		if (stageUrls.length >= 1) {
			return stageUrls.shift();
		}
		return "";
	}

	var stageId = $('body').attr('stage-data-id');
	var stageUrl = getStage(stageId);
	console.log(stageUrl);

	// variables for individual stage info
	var currentArea, stageIcon, hitPoints, stageName, stageType, stageMoves,
			boardLayout, disruptions, disruptionInit, disruptionBoard, disruptionTimer,
			basePower, ability, captureRate,
			recommendedParty, srankStrat, clearStrat, teamLimit;

	var splitBreakLine = function (data) {
		return data.split('\n');
	}

	var splitPeriod = function(data) {
		return data.split('.');
	}

	var splitSlash = function(data) {
		return data.split('/');
	}

	var getPokemonDivisions = function(stageDivisionUrl) {
		$.getJSON(stageDivisionUrl, function (data) {
			return data;
		});
	};

	// handle stage selection
	$('.stage-selector').change(function () {
		console.log($(this).val());
		$('body').attr('stage-data-id', $(this).val());
		stageId = $('body').attr('stage-data-id');
		var stageUrl = getStage(stageId);
		resetData();
		loadStageData(stageUrl);
	});

	// handle HP
	var handleHP = function(hitPts) {
		var hitpointsDisplay = $('[data-attr="stage-hp"]');
		hitpointsDisplay.text(hitPts);
		if (hitpointsDisplay.text().includes('\n')) {
			var nerfs = hitpointsDisplay.text().split('\n');
			hitpointsDisplay.html('' + nerfs[0] + ' ' + nerfs[1]);
		}
	}

	// handle capture rate display
	var handleCaptureRate = function (captureRate) {
		if (captureRate.length < 2) {
			$('[data-attr="stage-capture"]').text('N/A');
			$('[data-attr="stage-capture-bonus"]').text('N/A');
		} else {
			var captureRateInit = parseInt(captureRate[0].slice(5, -1));
			var captureRateBonus = parseInt(captureRate[1].slice(6, -1));
			if (isNaN(captureRateInit) || isNaN(captureRateBonus)) {
				$('[data-attr="stage-capture"]').text('N/A');
				$('[data-attr="stage-capture-bonus"]').text(captureRateBonus);
			} else {
				$('[data-attr="stage-capture"]').text(captureRateInit);
				$('[data-attr="stage-capture-bonus"]').text(captureRateBonus);
			}
		}
	};

	// handle stage icon display
	var handleStageIcon = function(stageIcon) {
		$('[data-attr="stage-thumbnail"]').attr('src', 'images/icons/icon_' + stageIcon + '.png');
	};

	// handle board layout display
	var handleStageLayout = function(stageLayoutUrl) {
		$('[data-attr="stage-setup-layout"]').attr('src', stageLayoutUrl);
	};

	// handle clearing strategy display
	var handleStageClearing = function(stageClearing) {
		$('[data-attr="stage-strategy-clearing"]').text(stageClearing);
	};

	// handle srank strategy & moves display
	var handleStageSRank = function(stageSRank) {
		var strat = stageSRank.split('\n');
		strat.shift();
		$('[data-attr="stage-strategy-srank"]').text(strat.join(' '));
	};

	// handle base power
	var handleBasePower = function(basePower) {
		if (isNaN(basePower)) {
			$('[data-attr="stage-power"]').text('N/A');
		} else {
			$('[data-attr="stage-power"]').text(basePower);
		}
	};

	// handle ability
	var handleAbility = function(ability) {
		if (ability.includes(':')) {
			ability = ability.slice(14, -1);
		}
		$('[data-attr="stage-ability"]').text(ability);
	};

	// TODO : better formatting without having format the source data
	var handleDisruptions = function(disruptions) {
		var disruptionArr = disruptions.split(/\n/);
		var disruptionArrBoard = [], disruptionArrInit = [], disruptionArrTimer = [];

		if (disruptionArr.length <= 1) {
			disruptionBoard = 'None';
			disruptionInit = 'None';
			disruptionTimer = 'None';
		} else {
			$.each(disruptionArr, function(line, value) {
				if (value.toLowerCase().startsWith('board') && value.length > value.indexOf(':')) {
					var separator = value.indexOf(':');
					disruptionBoard = value.slice(separator + 1, value.length);
				} else if (value.toLowerCase().startsWith('initial') && value.length > value.indexOf(':')) {
					var separator = value.indexOf(':');
					disruptionInit = value.slice(separator + 1, value.length);
				} else if (value.toLowerCase().startsWith('timer') && value.length > value.indexOf(':')) {
					var separator = value.indexOf(':');
					disruptionTimer = value.slice(separator + 1, value.length);
				}
			});
		}

		disruptionArrTimer = splitPeriod(disruptionTimer);
		disruptionArrInit = splitPeriod(disruptionInit);
		disruptionArrBoard = splitPeriod(disruptionBoard);

		$.each(disruptionArrTimer, function(index, value) {
			value = value + '.';
			$('[data-attr="stage-disruption-timer"]').append('
' + value.trim() + '
');
		});

		$.each(disruptionArrInit, function(index, value) {
			value = value + '.';
			$('[data-attr="stage-disruption-init"]').append('
' + value.trim() + '
');
		});

		$.each(disruptionArrBoard, function(index, value) {
			value = value + '.';
			$('[data-attr="stage-disruption-board"]').append('
' + value.trim() + '
');
		});

		//console.log(disruptionBoard);
		//console.log(disruptionInit);
		//console.log(disruptionArrTimer);
	};

	// handle recommended team
	var handleParty = function(recommendedParty) {
		var choices = recommendedParty.split('\n');
		var results = [];

		// split & put each pokemon into a new array
		choices.forEach(function (choice) {
			if (choice.includes('/')) {
				var tempChoices = choice.split('/');
				results = results.concat(tempChoices);
			}
			else if (choice.includes(',')) {
				var tempChoices = choice.split(',');
				results = results.concat(tempChoices);
			}
			else {
				results.push(choice);
			}
		});

		// filter out empty & duplicate values
		results = unique(results).filter(function (value) {
			return value != "";
		});

		// match pokemon with its icon to display out on recommended party
		results.forEach(function (result) {
			if (result.startsWith('[')) {
				result = result.slice(1, -1).toLowerCase();
				pokemonCollection['mega'].forEach(function (referencePoke) {
					if (referencePoke.pokemonName.toLowerCase().includes(result) && !referencePoke.pokemonName.includes(' X')) {
						$('[data-attr="stage-slots-mega"]').append('');
					}
				});
			} else {
				for (var key in pokemonCollection) {
					var division = pokemonCollection[key];
					division.forEach(function (referencePoke) {
						if (referencePoke.pokemonName.toLowerCase().startsWith(result.toLowerCase()) && result.trim().length > 0) {
							$('[data-attr="stage-slots-' + key + '"]').append('');
						}
					});
				}
			}
		});
		console.log(results);
	};

	var handleStageType = function (stageType) {
		$('[data-attr="stage-type"]').text(stageType);
	};

	var handleStageLimit = function (stageLimit) {
		$('[data-attr="stage-limit"]').text(stageLimit);
	};

	var handleStageMoves = function (stageMoves, stageSRank) {
		var movesInitPos = stageSRank.indexOf('least');
		var movesLastPos = stageSRank.indexOf('left');
		var movesSRank = stageSRank.slice(movesInitPos + 6, movesLastPos - 6);

		$('[data-attr="stage-srank-moves"]').text(movesSRank);
		$('[data-attr="stage-moves"]').text(stageMoves);
	};

	var handleStageName = function (stageName) {
		$('[data-attr="stage-name"]').text(stageName);
	};

	var resetData = function() {
		$('ul[data-attr^="stage-disruption"]').empty();
		$('span[data-attr^="stage-"]').text('---');
		$('div[data-attr^="stage-slots-"]').empty();
	};

	function unique(list) {
	  var result = [];
	  $.each(list, function(i, e) {
	    if ($.inArray(e, result) == -1) result.push(e);
	  });
	  return result;
	}

	var loadStageData = function (stageUrl) {

		$.getJSON(stageUrl, function (data) {
		// get the area name
			currentArea = data.shift()['stageNo'];
			console.log(currentArea);

			data.map(function (item) {

				if (item['stageNo'].toString() === stageId) {
					stageIcon = item['icon'];
					hitPoints = item['hitPts'];
					stageName = item['name'];
					stageType = item['type'];
					stageMoves = item['moves'];
					boardLayout = item['initialBoardSetup'];
					teamLimit = item['pokemon'];
					recommendedParty = item['recommendedParty'];
					captureRate = splitBreakLine(item['captureRate']);
					srankStrat = item['srankingStrategy'];
					clearStrat = item['clearingStrategy'];
					disruptions = item['disruptions'];
					basePower = item['basePower'];
					ability = item['ability'];

					handleStageType(stageType);
					handleStageLimit(teamLimit);
					handleStageMoves(stageMoves, srankStrat);
					handleStageName(stageName);

					handleHP(hitPoints);
					handleStageIcon(stageIcon);
					handleCaptureRate(captureRate);
					handleBasePower(basePower);
					handleAbility(ability);
					handleStageLayout(boardLayout);
					handleStageClearing(clearStrat);
					handleStageSRank(srankStrat);

					handleDisruptions(disruptions);
					handleParty(recommendedParty);
				}
			});
		});
	};

	resetData();
	loadStageData(stageUrl);

	/*
	*********
	Horsey Autocomplete
	*********
	*/

	horsey(document.querySelector('#stage-selector'), {
		source: [{ list: ['banana', 'apple', 'orange'] }]
	});

})();<commit_msg>fixed formes display as well<commit_after>;(function () {
	// level caps
	var stageCollections = [
		{
			levelCap: 10,
			stageUrl: 'pb'
		},
		{
			levelCap: 20,
			stageUrl: 'sb'
		},
		{
			levelCap: 30,
			stageUrl: 'nf'
		},
		{
			levelCap: 45,
			stageUrl: 'ia'
		},
		{
			levelCap: 60,
			stageUrl: 'rp'
		},
		{
			levelCap: 75,
			stageUrl: 'gr'
		},
		{
			levelCap: 90,
			stageUrl: 'ss'
		},
		{
			levelCap: 105,
			stageUrl: 'sm'
		},
		{
			levelCap: 120,
			stageUrl: 'mv'
		},
		{
			levelCap: 135,
			stageUrl: 'cn'
		},
		{
			levelCap: 150,
			stageUrl: 'jv'
		},
		{
			levelCap: 180,
			stageUrl: 'ww'
		},
		{
			levelCap: 210,
			stageUrl: 'pv'
		},
		{
			levelCap: 240,
			stageUrl: 'at'
		},
		{
			levelCap: 300,
			stageUrl: 'rc'
		},
		{
			levelCap: 350,
			stageUrl: 'du'
		},
		{
			levelCap: 400,
			stageUrl: 'vp'
		},
		{
			levelCap: 450,
			stageUrl: 'bs'
		}
	];

	// setup stage divisions
	var pokemonCollectionUrl = 'https://rawgit.com/shelune/poke-shuffle-guide/master/app/scripts/assets/pokemonCollection.json';
	var pokemonCollection;
	$.getJSON(pokemonCollectionUrl, function (data) {
		pokemonCollection = data;
	});

	// setup stage id
	function getStage(stageId) {
		var stageUrls = [];
		stageCollections.forEach(function (stages){
			if (stageId <= stages.levelCap) {
				stageUrls.push('https://rawgit.com/shelune/poke-shuffle-guide/master/app/scripts/assets/stageGuides/' + stages.stageUrl + '.json');
			}
		});
		if (stageUrls.length >= 1) {
			return stageUrls.shift();
		}
		return "";
	}

	var stageId = $('body').attr('stage-data-id');
	var stageUrl = getStage(stageId);

	// variables for individual stage info
	var currentArea, stageIcon, hitPoints, stageName, stageType, stageMoves,
			boardLayout, disruptions, disruptionInit, disruptionBoard, disruptionTimer,
			basePower, ability, captureRate,
			recommendedParty, srankStrat, clearStrat, teamLimit;

	var splitBreakLine = function (data) {
		return data.split('\n');
	}

	var splitPeriod = function(data) {
		return data.split('.');
	}

	var splitSlash = function(data) {
		return data.split('/');
	}

	var getPokemonDivisions = function(stageDivisionUrl) {
		$.getJSON(stageDivisionUrl, function (data) {
			return data;
		});
	};

	// handle stage selection
	$('.stage-selector').change(function () {
		console.log($(this).val());
		$('body').attr('stage-data-id', $(this).val());
		stageId = $('body').attr('stage-data-id');
		var stageUrl = getStage(stageId);
		resetData();
		loadStageData(stageUrl);
	});

	// handle HP
	var handleHP = function(hitPts) {
		var hitpointsDisplay = $('[data-attr="stage-hp"]');
		hitpointsDisplay.text(hitPts);
		if (hitpointsDisplay.text().includes('\n')) {
			var nerfs = hitpointsDisplay.text().split('\n');
			hitpointsDisplay.html('' + nerfs[0] + ' ' + nerfs[1]);
		}
	}

	// handle capture rate display
	var handleCaptureRate = function (captureRate) {
		if (captureRate.length < 2) {
			$('[data-attr="stage-capture"]').text('N/A');
			$('[data-attr="stage-capture-bonus"]').text('N/A');
		} else {
			var captureRateInit = parseInt(captureRate[0].slice(5, -1));
			var captureRateBonus = parseInt(captureRate[1].slice(6, -1));
			if (isNaN(captureRateInit) || isNaN(captureRateBonus)) {
				$('[data-attr="stage-capture"]').text('N/A');
				$('[data-attr="stage-capture-bonus"]').text(captureRateBonus);
			} else {
				$('[data-attr="stage-capture"]').text(captureRateInit);
				$('[data-attr="stage-capture-bonus"]').text(captureRateBonus);
			}
		}
	};

	// handle stage icon display
	var handleStageIcon = function(stageIcon) {
		$('[data-attr="stage-thumbnail"]').attr('src', 'images/icons/icon_' + stageIcon + '.png');
	};

	// handle board layout display
	var handleStageLayout = function(stageLayoutUrl) {
		$('[data-attr="stage-setup-layout"]').attr('src', stageLayoutUrl);
	};

	// handle clearing strategy display
	var handleStageClearing = function(stageClearing) {
		$('[data-attr="stage-strategy-clearing"]').text(stageClearing);
	};

	// handle srank strategy & moves display
	var handleStageSRank = function(stageSRank) {
		var strat = stageSRank.split('\n');
		strat.shift();
		$('[data-attr="stage-strategy-srank"]').text(strat.join(' '));
	};

	// handle base power
	var handleBasePower = function(basePower) {
		if (isNaN(basePower)) {
			$('[data-attr="stage-power"]').text('N/A');
		} else {
			$('[data-attr="stage-power"]').text(basePower);
		}
	};

	// handle ability
	var handleAbility = function(ability) {
		if (ability.includes(':')) {
			ability = ability.slice(14, -1);
		}
		$('[data-attr="stage-ability"]').text(ability);
	};

	// TODO : better formatting without having format the source data
	var handleDisruptions = function(disruptions) {
		var disruptionArr = disruptions.split(/\n/);
		var disruptionArrBoard = [], disruptionArrInit = [], disruptionArrTimer = [];

		if (disruptionArr.length <= 1) {
			disruptionBoard = 'None';
			disruptionInit = 'None';
			disruptionTimer = 'None';
		} else {
			$.each(disruptionArr, function(line, value) {
				if (value.toLowerCase().startsWith('board') && value.length > value.indexOf(':')) {
					var separator = value.indexOf(':');
					disruptionBoard = value.slice(separator + 1, value.length);
				} else if (value.toLowerCase().startsWith('initial') && value.length > value.indexOf(':')) {
					var separator = value.indexOf(':');
					disruptionInit = value.slice(separator + 1, value.length);
				} else if (value.toLowerCase().startsWith('timer') && value.length > value.indexOf(':')) {
					var separator = value.indexOf(':');
					disruptionTimer = value.slice(separator + 1, value.length);
				}
			});
		}

		disruptionArrTimer = splitPeriod(disruptionTimer);
		disruptionArrInit = splitPeriod(disruptionInit);
		disruptionArrBoard = splitPeriod(disruptionBoard);

		$.each(disruptionArrTimer, function(index, value) {
			value = value + '.';
			$('[data-attr="stage-disruption-timer"]').append('
' + value.trim() + '
');
		});

		$.each(disruptionArrInit, function(index, value) {
			value = value + '.';
			$('[data-attr="stage-disruption-init"]').append('
' + value.trim() + '
');
		});

		$.each(disruptionArrBoard, function(index, value) {
			value = value + '.';
			$('[data-attr="stage-disruption-board"]').append('
' + value.trim() + '
');
		});

		//console.log(disruptionBoard);
		//console.log(disruptionInit);
		//console.log(disruptionArrTimer);
	};

	// handle recommended team
	var handleParty = function(recommendedParty) {
		var choices = recommendedParty.split('\n');
		var results = [];

		// split & put each pokemon into a new array
		choices.forEach(function (choice) {
			if (choice.includes('/')) {
				var tempChoices = choice.split('/');
				results = results.concat(tempChoices);
			}
			else if (choice.includes(',')) {
				var tempChoices = choice.split(',');
				results = results.concat(tempChoices);
			}
			else {
				results.push(choice);
			}
		});

		// filter out empty & duplicate values
		results = unique(results).filter(function (value) {
			return value != "";
		});

		// match pokemon with its icon to display out on recommended party
		results.forEach(function (result) {
			if (result.startsWith('[')) {
				result = result.slice(1, -1).toLowerCase();
				pokemonCollection['mega'].forEach(function (referencePoke) {
					if (referencePoke.pokemonName.toLowerCase().includes(result.toLowerCase()) && !referencePoke.pokemonName.includes(' X')) {
						$('[data-attr="stage-slots-mega"]').append('');
					}
				});
			} else {
				for (var key in pokemonCollection) {
					var division = pokemonCollection[key];
					division.forEach(function (referencePoke) {
						if (result.trim().toLowerCase().startsWith(referencePoke.pokemonName.toLowerCase()) && result.trim().length > 0) {
							$('[data-attr="stage-slots-' + key + '"]').append('');
						}
					});
				}
			}
		});
		console.log(results);
	};

	var handleStageType = function (stageType) {
		$('[data-attr="stage-type"]').text(stageType);
	};

	var handleStageLimit = function (stageLimit) {
		$('[data-attr="stage-limit"]').text(stageLimit);
	};

	var handleStageMoves = function (stageMoves, stageSRank) {
		var movesInitPos = stageSRank.indexOf('least');
		var movesLastPos = stageSRank.indexOf('left');
		var movesSRank = stageSRank.slice(movesInitPos + 6, movesLastPos - 6);

		$('[data-attr="stage-srank-moves"]').text(movesSRank);
		$('[data-attr="stage-moves"]').text(stageMoves);
	};

	var handleStageName = function (stageName) {
		$('[data-attr="stage-name"]').text(stageName);
	};

	var resetData = function() {
		$('ul[data-attr^="stage-disruption"]').empty();
		$('span[data-attr^="stage-"]').text('---');
		$('div[data-attr^="stage-slots-"]').empty();
	};

	function unique(list) {
	  var result = [];
	  $.each(list, function(i, e) {
	    if ($.inArray(e, result) == -1) result.push(e);
	  });
	  return result;
	}

	var loadStageData = function (stageUrl) {

		$.getJSON(stageUrl, function (data) {
		// get the area name
			currentArea = data.shift()['stageNo'];
			console.log(stageUrl);
			console.log(currentArea);

			data.map(function (item) {

				if (item['stageNo'].toString() === stageId) {
					stageIcon = item['icon'];
					hitPoints = item['hitPts'];
					stageName = item['name'];
					stageType = item['type'];
					stageMoves = item['moves'];
					boardLayout = item['initialBoardSetup'];
					teamLimit = item['pokemon'];
					recommendedParty = item['recommendedParty'];
					captureRate = splitBreakLine(item['captureRate']);
					srankStrat = item['srankingStrategy'];
					clearStrat = item['clearingStrategy'];
					disruptions = item['disruptions'];
					basePower = item['basePower'];
					ability = item['ability'];

					handleStageType(stageType);
					handleStageLimit(teamLimit);
					handleStageMoves(stageMoves, srankStrat);
					handleStageName(stageName);

					handleHP(hitPoints);
					handleStageIcon(stageIcon);
					handleCaptureRate(captureRate);
					handleBasePower(basePower);
					handleAbility(ability);
					handleStageLayout(boardLayout);
					handleStageClearing(clearStrat);
					handleStageSRank(srankStrat);

					handleDisruptions(disruptions);
					handleParty(recommendedParty);
				}
			});
		});
	};

	resetData();
	loadStageData(stageUrl);

	/*
	*********
	Horsey Autocomplete
	*********
	*/

	horsey(document.querySelector('#stage-selector'), {
		source: [{ list: ['banana', 'apple', 'orange'] }]
	});

})();<|endoftext|>


<commit_before><commit_msg>Updated homepage title<commit_after><|endoftext|>


<commit_before>// Dependencies
var express = require('express');
var MongoClient = require('mongodb').MongoClient;
var crypto = require('crypto');
var nconf = require('nconf');
var path = require('path');
var icalendar = require('icalendar');
var request = require('request');
var async = require('async');

//
var app = express();

// Configuration
nconf
    .argv()
    .env()
    .file('custom', __dirname+'/config.json')
    .file(__dirname+'/default.config.json');

// Optionally serve the public front-end app
if (nconf.get('server:publicDir')) {
    app.use(express.static( path.resolve(__dirname, nconf.get('server:publicDir') )));
}

// API for Browser App
/**
Main
*/
MongoClient.connect('mongodb://'+nconf.get('database:hostname')+':'+nconf.get('database:port')+'/'+nconf.get('database:name'), function(err, db) {
    if(err) throw err;

    var collection = db.collection(nconf.get('database:collection'));

    // Setup Express server
    app.use(express.bodyParser());

    /**
    =========================================================================
    API
    */
    app.get('/api/uniapi', function(req, res) {
      res.json({
        "protocol": nconf.get('uniapi:protocol'),
        "hostname": nconf.get('uniapi:hostname'),
        "port": nconf.get('uniapi:port')
      });
    });

    var saveCalendar = function(calendarId, courses, collection, callback) {
        var data = {
            calendarId: calendarId,
            courses: courses
        };
        collection.update({ 'calendarId': calendarId }, data, {upsert: true}, function(err, docs) {
            //console.log(err, docs);
            callback(err, docs);
        });
    };

    // Create Calendar
    app.post('/api/calendar', function(req, res) {
        console.log(req.body);

        var courses = JSON.parse(req.body.courses);

        if (courses.length > 0) {

            // Create secure CalendarId
            var timestamp = (+(new Date()))+"";
            var temp = (timestamp + nconf.get('secret'));
            console.log(temp);
            var digest = "hex"
            var calendarId = crypto.createHash('md5').update(temp).digest(digest);
            console.log(calendarId);

            saveCalendar(calendarId, courses, collection, function(err, docs) {
                console.log('Saved Courses');

                var url = "/calendar/"+calendarId+"/calendar.ics";
                res.json({
                    'url': url,
                    'courses': courses
                }, 201);

            });

        } else {
            res.json({
                'error': "No courses were found."
            }, 204);
        }

    });

    // Stats
    app.get('/api/stats.json', function(req, res) {
        // Count
        collection.count(function(err, count) {
            res.json({ 'calendars': count }, 200);
        });

    });

    // var timeFromStr = function(str) {
    //     // Ex: "1245"
    //     //console.log('timeFromStr: ', str);
    //     var n = parseInt(str);
    //     var hours = parseInt(n/100);
    //     var minutes = n - hours*100;
    //     return {
    //         "hours": hours,
    //         "minutes": minutes
    //     };
    // };

    var jsonToEvent = function(json) {
        //console.log('jsonToEvent: ', json);
        var vevent = new icalendar.VEvent("event-"+json.crn);
        var summary = json.Subj_code + " " + json.Crse_numb + " - " + json.Crse_title;
        vevent.setSummary(summary);

        var location = json.Bldg_code + " " + json.Room_code;
        vevent.setDescription(location);
        // Calculate date and event length
        var startDate = new Date(json.Start_date);
        var startTime = json.Begin_time;
        startDate.setHours(startTime.hours, startTime.minutes);

        var endTime = json.End_time;
        var endDate = new Date(json.Start_date);
        endDate.setHours(endTime.hours, endTime.minutes);
        // console.log(startDate, endDate);
        vevent.setDate(startDate, endDate);

        var days = [];
        if (json.Mon_day) {
            days.push("MO");
        }
        if (json.Tue_day) {
            days.push("TU");
        }
        if (json.Wed_day) {
            days.push("WE");
        }
        if (json.Thu_day) {
            days.push("TH");
        }
        if (json.Fri_day) {
            days.push("FR");
        }
        if (json.Sat_day) {
            days.push("SA");
        }
        if (json.Sun_day) {
            days.push("SU");
        }
        // console.log(days);
        vevent.addProperty('RRULE', { FREQ: 'WEEKLY', BYDAY: days.join(','), UNTIL: new Date(json.End_date) });
        vevent.addProperty('LOCATION', json.Bldg_code +" "+json.Room_code);
        return vevent;
    };

    var coursesToCalendar = function(courses, callback) {
        //console.log(courses);
        // Generate iCalendar file
        var calendar = new icalendar.iCalendar();
        // Replace PRODID
        calendar.properties.PRODID = [];
        calendar.addProperty('PRODID',"-//Saint Mary's University//Calendar//EN");
        // Add events to calendar
        for (var i=0, len=courses.length; i<len; i++)
        {
            var course = courses[i];
            if (course.Begin_time && course.End_time)
            {
              var vevent = jsonToEvent(course);
              calendar.addComponent(vevent);
            }
        }
        return callback(calendar);
    };

    var reloadCourses = function(courses, callback) {

        async.map(courses, function(course, cb) {
            var baseurl = nconf.get('uniapi:protocol')+"://"+nconf.get('uniapi:hostname')+":"+nconf.get('uniapi:port');
            var url = baseurl + "/api/v1/courses/"+course._id;
            request(url, function(error, response, body) {
                console.log(error, body);
                try {
                    if (!error && !!body) {
                        var temp = JSON.parse(body);
                        course = temp;
                    }
                } catch (e) {
                    //
                }
                return cb(null, course);
            });
        }, function(err, results) {
            return callback && callback(results);
        });
    };

    // Calendar
    app.get('/calendar/:calendarId/calendar.ics', function(req, res) {
        console.log('Calendar', req.params);
        var calendarId = req.params.calendarId;

        // Locate all the entries using find
        collection.find({'calendarId': calendarId }).toArray(function(err, results) {
            console.dir(results);
            var result = results[0] || { 'courses': [] };
            var courses = result.courses;

            try {
                reloadCourses(courses, function(courses) {
                    coursesToCalendar(courses, function(calendar) {
                        res.header("Content-Type", "text/calendar; charset=utf-8");
                        res.header("Content-Disposition", "inline; filename=calendar.ics");
                        res.end(calendar.toString());
                    });
                })
            } catch (e) {
                res.json({"error": e.message });
            }

        });

    });

    // Start server
    app.listen(process.env.PORT || nconf.get('server:port'), function() {
        console.log('iCal-Sync Server is listening on '+nconf.get('server:port')+'.');
    });

});
<commit_msg>Set Event location to class room location, and add Instructor in event notes<commit_after>// Dependencies
var express = require('express');
var MongoClient = require('mongodb').MongoClient;
var crypto = require('crypto');
var nconf = require('nconf');
var path = require('path');
var icalendar = require('icalendar');
var request = require('request');
var async = require('async');

//
var app = express();

// Configuration
nconf
    .argv()
    .env()
    .file('custom', __dirname+'/config.json')
    .file(__dirname+'/default.config.json');

// Optionally serve the public front-end app
if (nconf.get('server:publicDir')) {
    app.use(express.static( path.resolve(__dirname, nconf.get('server:publicDir') )));
}

// API for Browser App
/**
Main
*/
MongoClient.connect('mongodb://'+nconf.get('database:hostname')+':'+nconf.get('database:port')+'/'+nconf.get('database:name'), function(err, db) {
    if(err) throw err;

    var collection = db.collection(nconf.get('database:collection'));

    // Setup Express server
    app.use(express.bodyParser());

    /**
    =========================================================================
    API
    */
    app.get('/api/uniapi', function(req, res) {
      res.json({
        "protocol": nconf.get('uniapi:protocol'),
        "hostname": nconf.get('uniapi:hostname'),
        "port": nconf.get('uniapi:port')
      });
    });

    var saveCalendar = function(calendarId, courses, collection, callback) {
        var data = {
            calendarId: calendarId,
            courses: courses
        };
        collection.update({ 'calendarId': calendarId }, data, {upsert: true}, function(err, docs) {
            //console.log(err, docs);
            callback(err, docs);
        });
    };

    // Create Calendar
    app.post('/api/calendar', function(req, res) {
        console.log(req.body);

        var courses = JSON.parse(req.body.courses);

        if (courses.length > 0) {

            // Create secure CalendarId
            var timestamp = (+(new Date()))+"";
            var temp = (timestamp + nconf.get('secret'));
            console.log(temp);
            var digest = "hex"
            var calendarId = crypto.createHash('md5').update(temp).digest(digest);
            console.log(calendarId);

            saveCalendar(calendarId, courses, collection, function(err, docs) {
                console.log('Saved Courses');

                var url = "/calendar/"+calendarId+"/calendar.ics";
                res.json({
                    'url': url,
                    'courses': courses
                }, 201);

            });

        } else {
            res.json({
                'error': "No courses were found."
            }, 204);
        }

    });

    // Stats
    app.get('/api/stats.json', function(req, res) {
        // Count
        collection.count(function(err, count) {
            res.json({ 'calendars': count }, 200);
        });

    });

    // var timeFromStr = function(str) {
    //     // Ex: "1245"
    //     //console.log('timeFromStr: ', str);
    //     var n = parseInt(str);
    //     var hours = parseInt(n/100);
    //     var minutes = n - hours*100;
    //     return {
    //         "hours": hours,
    //         "minutes": minutes
    //     };
    // };

    var jsonToEvent = function(json) {
        //console.log('jsonToEvent: ', json);
        var vevent = new icalendar.VEvent("event-"+json.crn);
        var summary = json.Subj_code + " " + json.Crse_numb + " - " + json.Crse_title;
        vevent.setSummary(summary);

        vevent.setDescription(json.faculty);
        // Calculate date and event length
        var startDate = new Date(json.Start_date);
        var startTime = json.Begin_time;
        startDate.setHours(startTime.hours, startTime.minutes);

        var endTime = json.End_time;
        var endDate = new Date(json.Start_date);
        endDate.setHours(endTime.hours, endTime.minutes);
        // console.log(startDate, endDate);
        vevent.setDate(startDate, endDate);

        var days = [];
        if (json.Mon_day) {
            days.push("MO");
        }
        if (json.Tue_day) {
            days.push("TU");
        }
        if (json.Wed_day) {
            days.push("WE");
        }
        if (json.Thu_day) {
            days.push("TH");
        }
        if (json.Fri_day) {
            days.push("FR");
        }
        if (json.Sat_day) {
            days.push("SA");
        }
        if (json.Sun_day) {
            days.push("SU");
        }
        // console.log(days);
        vevent.addProperty('RRULE', { FREQ: 'WEEKLY', BYDAY: days.join(','), UNTIL: new Date(json.End_date) });
        var location = json.Bldg_code + " " + json.Room_code;
        vevent.addProperty('LOCATION', location);
        return vevent;
    };

    var coursesToCalendar = function(courses, callback) {
        //console.log(courses);
        // Generate iCalendar file
        var calendar = new icalendar.iCalendar();
        // Replace PRODID
        calendar.properties.PRODID = [];
        calendar.addProperty('PRODID',"-//Saint Mary's University//Calendar//EN");
        // Add events to calendar
        for (var i=0, len=courses.length; i<len; i++)
        {
            var course = courses[i];
            if (course.Begin_time && course.End_time)
            {
              var vevent = jsonToEvent(course);
              calendar.addComponent(vevent);
            }
        }
        return callback(calendar);
    };

    var reloadCourses = function(courses, callback) {

        async.map(courses, function(course, cb) {
            var baseurl = nconf.get('uniapi:protocol')+"://"+nconf.get('uniapi:hostname')+":"+nconf.get('uniapi:port');
            var url = baseurl + "/api/v1/courses/"+course._id;
            request(url, function(error, response, body) {
                console.log(error, body);
                try {
                    if (!error && !!body) {
                        var temp = JSON.parse(body);
                        course = temp;
                    }
                } catch (e) {
                    //
                }
                return cb(null, course);
            });
        }, function(err, results) {
            return callback && callback(results);
        });
    };

    // Calendar
    app.get('/calendar/:calendarId/calendar.ics', function(req, res) {
        console.log('Calendar', req.params);
        var calendarId = req.params.calendarId;

        // Locate all the entries using find
        collection.find({'calendarId': calendarId }).toArray(function(err, results) {
            console.dir(results);
            var result = results[0] || { 'courses': [] };
            var courses = result.courses;

            try {
                reloadCourses(courses, function(courses) {
                    coursesToCalendar(courses, function(calendar) {
                        res.header("Content-Type", "text/calendar; charset=utf-8");
                        res.header("Content-Disposition", "inline; filename=calendar.ics");
                        res.end(calendar.toString());
                    });
                })
            } catch (e) {
                res.json({"error": e.message });
            }

        });

    });

    // Start server
    app.listen(process.env.PORT || nconf.get('server:port'), function() {
        console.log('iCal-Sync Server is listening on '+nconf.get('server:port')+'.');
    });

});
<|endoftext|>


<commit_before>"use strict";

function is_function(fn) {
    return !!(fn && fn.constructor && fn.call && fn.apply);
}

function suppress_event(event) {
    is_function(event.preventDefault) && !event.preventDefault.passive && event.preventDefault();
    event.returnValue = false;
}

var EpubReader = (function() {
    function EpubReader(book_url, zip_source) {
        this.url = new URL(document.URL);
        this.source_url = new URL($('#reader-source-url').val());
        this.currentLocationCfi = new ePub.CFI(this.url.hash.slice(1));

        // epub.js doesn't pass options correctly so we have this ugly hack in
        // out code
        if (this.source_url.href.endsWith('/epub')) {
            let c = this.source_url.href.split('');
            c.splice(this.source_url.href.lastIndexOf('/'), 1, '.');
            this.source_url.href = c.join('');
        }

        // this doesn't work so ugly hack above.
        this.book = ePub(this.source_url.href, {openAs: "epub"});
        this.rendition = this.book.then((book) => {
            return book.renderTo("display", {
                width: "100%",
                height: "100%",
            });
        });
        this.display = null;
    }

    function prev_page(event) {
        return this.rendition.then((rendition) => {
            rendition.prev();
        });
    }

    function next_page(event) {
        return this.rendition.then((rendition) => {
            rendition.next();
        });
    }

    function draw(target) {
        target = target || this.currentLocationCfi.str;

        this.rendition.then(((rendition) => {
            if (target) {
                this.display = rendition.display(target);
            } else {
                this.display = rendition.display();
            }
        }).bind(this));
    }

    EpubReader.prototype = {
        nextPage: next_page,
        prevPage: prev_page,
        draw: draw,
    };

    return EpubReader;
}());

$(document).ready(() => {
    const KBD_ARROW_DIRECTION = {
        rtl: { prev: "ArrowRight", next: "ArrowLeft" },
        ltr: { prev: "ArrowLeft", next: "ArrowRight" },
    };

    let epub_reader = new EpubReader();

    epub_reader.book.then((book) => {
        $("nav").html($("<select/>", {
            id: "toc-selector",
            class: "custom-select custom-control-inline",
            html: book.sections.items.map((section, index) => {
                let toc_entry = book.navigation.toc.find((element) => {
                    let element_href = element.href;
                    if (element_href.indexOf('#') > 0) {
                        element_href = element_href.substring(0, element_href.lastIndexOf('#'));
                    }
                    return decodeURIComponent(element_href) == decodeURIComponent(section.href);
                });

                let title = toc_entry ? toc_entry.title.trim() : "Entry " + index;
                return $("<option/>", {
                    id: "toc-option-" + section.idref,
                    label: title,
                    text: title,
                    value: decodeURIComponent(section.href),
                    'data-section-index': section['index'],
                    'data-section-source': section['source'],
                });
            }),
            change: (event) => {
                epub_reader.draw(event.currentTarget.value);
                suppress_event(event);
            },
        }));
    });

    epub_reader.rendition.then((rendition) => {
        rendition.on("keydown", (event) => {
            parent.$(parent.document).trigger($.Event("keydown", event));
        });
    });

    epub_reader.rendition.then((rendition) => {
        rendition.on("relocated", (location) => {
            let cfi = location.start.cfi;
            epub_reader.currentLocationCfi = new ePub.CFI(cfi);
            window.location = '#' + cfi;
            let $option = $('option[data-section-source="' + location.start.href + '"]');
            if ($option.length > 0) {
                $('option').removeAttr('selected');
                $option.attr('selected', true);
            }
            else {
                console.log('No toc entry found.');
            }
        });
    });

    $(".arrow").on("touchstart mousedown", (event) => {
        let $arrow_button = $(event.currentTarget);
        $arrow_button.css({"opacity": 1});
        $arrow_button.on("touchend mouseup", (event) => {
            setTimeout(() => {$arrow_button.css({"opacity": 0})}, 100);
        });
    });

    $("#prev").on("click", epub_reader.prevPage.bind(epub_reader));
    $("#next").on("click", epub_reader.nextPage.bind(epub_reader));

    $(window).on("keydown", (event) => {
        epub_reader.book.then((book) => {
            let direction = book.manifest.metadata.direction || "ltr";
            switch (event.key) {
            case KBD_ARROW_DIRECTION[direction].prev: epub_reader.prevPage(event); break;
            case KBD_ARROW_DIRECTION[direction].next: epub_reader.nextPage(event); break;
            }
        });
    });

    $(window).on('hashchange', (event) => {
        let current_location_cfi = epub_reader.currentLocationCfi.str;
        let current_window_cfi = new ePub.CFI(window.location.hash.slice(1)).str;
        if (!(current_location_cfi == current_window_cfi)) {
            epub_reader.draw(current_window_cfi);
        }
    });

    epub_reader.draw();
});
<commit_msg>Corrects TOC handling in reader app<commit_after>"use strict";

function is_function(fn) {
    return !!(fn && fn.constructor && fn.call && fn.apply);
}

function suppress_event(event) {
    is_function(event.preventDefault) && !event.preventDefault.passive && event.preventDefault();
    event.returnValue = false;
}

var EpubReader = (function() {
    function EpubReader(book_url, zip_source) {
        this.url = new URL(document.URL);
        this.source_url = new URL($('#reader-source-url').val());
        this.currentLocationCfi = new ePub.CFI(this.url.hash.slice(1));

        // epub.js doesn't pass options correctly so we have this ugly hack in
        // out code
        if (this.source_url.href.endsWith('/epub')) {
            let c = this.source_url.href.split('');
            c.splice(this.source_url.href.lastIndexOf('/'), 1, '.');
            this.source_url.href = c.join('');
        }

        // this doesn't work so ugly hack above.
        this.book = ePub(this.source_url.href, {openAs: "epub"});
        this.rendition = this.book.then((book) => {
            return book.renderTo("display", {
                width: "100%",
                height: "100%",
            });
        });
        this.display = null;
    }

    function prev_page(event) {
        return this.rendition.then((rendition) => {
            rendition.prev();
        });
    }

    function next_page(event) {
        return this.rendition.then((rendition) => {
            rendition.next();
        });
    }

    function draw(target) {
        target = target || this.currentLocationCfi.str;

        this.rendition.then(((rendition) => {
            if (target) {
                this.display = rendition.display(target);
            } else {
                this.display = rendition.display();
            }
        }).bind(this));
    }

    EpubReader.prototype = {
        nextPage: next_page,
        prevPage: prev_page,
        draw: draw,
    };

    return EpubReader;
}());

$(document).ready(() => {
    const KBD_ARROW_DIRECTION = {
        rtl: { prev: "ArrowRight", next: "ArrowLeft" },
        ltr: { prev: "ArrowLeft", next: "ArrowRight" },
    };

    let epub_reader = new EpubReader();

    epub_reader.book.then((book) => {
        let section_keys = {};
        Object.keys(book.sections.spineByHref).forEach((key) => {
            let index = book.sections.spineByHref[key];
            section_keys[index] = section_keys[index] || {}
            section_keys[index][key] = true;
        });

        $("nav").html($("<select/>", {
            id: "toc-selector",
            class: "custom-select custom-control-inline",
            html: book.sections.items.map((section, index) => {
                let toc_entry = book.navigation.toc.find((element) => {
                    let element_href = decodeURIComponent(element.href);
                    if (element_href.indexOf('#') > 0) {
                        element_href = element_href.substring(0, element_href.lastIndexOf('#'));
                    }
                    let possible_keys = section_keys[index];
                    return possible_keys[element_href] || possible_keys[element_href.substring(1)];

                });

                let title = toc_entry ? toc_entry.title.trim() : "Entry " + index;
                return $("<option/>", {
                    id: "toc-option-" + section.idref,
                    label: title,
                    text: title,
                    value: decodeURIComponent(section.href),
                    'data-section-index': section['index'],
                    'data-section-source': section['source'],
                });
            }),
            change: (event) => {
                epub_reader.draw(event.currentTarget.value);
                suppress_event(event);
            },
        }));
    });

    epub_reader.rendition.then((rendition) => {
        rendition.on("keydown", (event) => {
            parent.$(parent.document).trigger($.Event("keydown", event));
        });
    });

    epub_reader.rendition.then((rendition) => {
        rendition.on("relocated", (location) => {
            let cfi = location.start.cfi;
            epub_reader.currentLocationCfi = new ePub.CFI(cfi);
            window.location = '#' + cfi;
            let $option = $('option[data-section-source="' + location.start.href + '"]');
            if ($option.length > 0) {
                $('option').removeAttr('selected');
                $option.attr('selected', true);
            }
            else {
                console.log('No toc entry found.');
            }
        });
    });

    $(".arrow").on("touchstart mousedown", (event) => {
        let $arrow_button = $(event.currentTarget);
        $arrow_button.css({"opacity": 1});
        $arrow_button.on("touchend mouseup", (event) => {
            setTimeout(() => {$arrow_button.css({"opacity": 0})}, 100);
        });
    });

    $("#prev").on("click", epub_reader.prevPage.bind(epub_reader));
    $("#next").on("click", epub_reader.nextPage.bind(epub_reader));

    $(window).on("keydown", (event) => {
        epub_reader.book.then((book) => {
            let direction = book.manifest.metadata.direction || "ltr";
            switch (event.key) {
            case KBD_ARROW_DIRECTION[direction].prev: epub_reader.prevPage(event); break;
            case KBD_ARROW_DIRECTION[direction].next: epub_reader.nextPage(event); break;
            }
        });
    });

    $(window).on('hashchange', (event) => {
        let current_location_cfi = epub_reader.currentLocationCfi.str;
        let current_window_cfi = new ePub.CFI(window.location.hash.slice(1)).str;
        if (!(current_location_cfi == current_window_cfi)) {
            epub_reader.draw(current_window_cfi);
        }
    });

    epub_reader.draw();
});
<|endoftext|>


<commit_before>'use strict'

let mori = require('mori')

let Store = require('./store')

let AppDispatcher = require('../dispatcher/app-dispatcher')
let AppConstants = require('../constants/app-constants')
let AppActions = require('../actions/app-actions')
let pairs = require('underscore').pairs

let defer = require('../util/defer')
let env = require('../env')

let state = mori.hashMap(
  'page', 'login',

  'update', mori.hashMap(
    'available', false,
    'downloaded', false
  ),

  'library', mori.hashMap(
    'games', mori.hashMap(),
    'panel', '',
    'collections', mori.hashMap(),
    'caves', mori.hashMap()
  ),

  'login', mori.hashMap(
    'loading', false,
    'errors', null
  ),

  'setup', mori.hashMap(
    'message', '...',
    'icon', 'settings'
  )
)

let AppStore = Object.assign(new Store('app-store', 'renderer'), {
  get_state: function () {
    return state
  }
})

function checking_for_self_update (payload) {
  console.log(`checking for self updates...`)
  state = mori.assocIn(state, ['update', 'checking'], true)
  AppStore.emit_change()
}

function update_not_available (payload) {
  state = mori.assocIn(state, ['update', 'checking'], false)
  state = mori.assocIn(state, ['update', 'uptodate'], true)
  AppStore.emit_change()

  setTimeout(function () {
    state = mori.assocIn(state, ['update', 'uptodate'], false)
    AppStore.emit_change()
  }, 5000)
}

function update_available (payload) {
  console.log(`update available? cool!`)
  state = mori.assocIn(state, ['update', 'checking'], false)
  state = mori.assocIn(state, ['update', 'available'], true)
  AppStore.emit_change()
}

function update_downloaded (payload) {
  console.log(`update downloaded?! uber-cool!`)
  state = mori.assocIn(state, ['update', 'downloaded'], true)
  AppStore.emit_change()
}

function update_error (payload) {
  if (env.name === 'development') {
    console.log(`Ignoring update error ${payload.error} from dev environment`)
    return
  }

  state = mori.assocIn(state, ['update', 'checking'], false)
  state = mori.assocIn(state, ['update', 'error'], payload.message)
  AppStore.emit_change()
}

function dismiss_update_error () {
  state = mori.updateIn(state, ['update'], x => mori.dissoc(x, 'error'))
  AppStore.emit_change()
}

function focus_panel (payload) {
  let panel = payload.panel

  state = mori.assoc(state, 'page', 'library')
  state = mori.assocIn(state, ['library', 'panel'], panel)
  AppStore.emit_change()

  defer(() => {
    AppActions.focus_window()
    AppActions.fetch_games(panel)
  })
}

function switch_page (page) {
  state = mori.assoc(state, 'page', page)
  AppStore.emit_change()
}

function login_attempt (payload) {
  state = mori.assocIn(state, ['login', 'loading'], true)
  state = mori.assocIn(state, ['login', 'errors'], null)
  AppStore.emit_change()
}

function login_failure (payload) {
  let errors = payload.errors
  state = mori.assocIn(state, ['login', 'loading'], false)
  state = mori.assocIn(state, ['login', 'errors'], errors.stack || errors)
  switch_page('login')
}

function no_stored_credentials () {
  switch_page('login')
}

function ready_to_roll (payload) {
  state = mori.assocIn(state, ['login', 'loading'], false)
  state = mori.assocIn(state, ['login', 'errors'], null)

  let me = mori.getIn(state, ['library', 'credentials', 'me'])
  if (mori.get(me, 'developer')) {
    focus_panel({panel: 'dashboard'})
  } else {
    focus_panel({panel: 'owned'})
  }

  defer(() => {
    AppActions.fetch_games('dashboard')
  })
}

function logout () {
  state = mori.assocIn(state, ['library'], mori.hashMap(
    'games', mori.hashMap(),
    'panel', '',
    'collections', mori.hashMap(),
    'caves', mori.hashMap()
  ))
  AppStore.emit_change()
  switch_page('login')
}

function setup_status (payload) {
  let message = payload.message
  let icon = payload.icon
  state = mori.assocIn(state, ['setup', 'message'], message)
  if (icon) {
    state = mori.assocIn(state, ['setup', 'icon'], icon)
  }
  AppStore.emit_change()
}

function setup_wait (payload) {
  switch_page('setup')
}

function cave_progress (payload) {
  for (let pair of pairs(payload.opts)) {
    let k = pair[0]
    let v = pair[1]
    state = mori.assocIn(state, ['library', 'caves', payload.opts.id, k], mori.toClj(v))
  }
  AppStore.emit_change()
}

function cave_implode (payload) {
}

function cave_thrown_into_bit_bucket (payload) {
  state = mori.updateIn(state, ['library', 'caves'], caves => mori.dissoc(caves, payload.id))
  AppStore.emit_change()
  if (mori.getIn(state, ['library', 'panel']) === `caves/${payload.id}`) {
    AppActions.focus_panel('caved')
  }
}

AppDispatcher.register('app-store', Store.action_listeners(on => {
  on(AppConstants.SETUP_STATUS, setup_status)
  on(AppConstants.SETUP_WAIT, setup_wait)

  on(AppConstants.LIBRARY_FOCUS_PANEL, focus_panel)

  on(AppConstants.NO_STORED_CREDENTIALS, no_stored_credentials)
  on(AppConstants.LOGIN_ATTEMPT, login_attempt)
  on(AppConstants.LOGIN_FAILURE, login_failure)
  on(AppConstants.READY_TO_ROLL, ready_to_roll)
  on(AppConstants.LOGOUT, logout)

  on(AppConstants.CAVE_PROGRESS, cave_progress)
  on(AppConstants.CAVE_IMPLODE, cave_implode)

  on(AppConstants.CHECKING_FOR_SELF_UPDATE, checking_for_self_update)
  on(AppConstants.SELF_UPDATE_AVAILABLE, update_available)
  on(AppConstants.SELF_UPDATE_NOT_AVAILABLE, update_not_available)
  on(AppConstants.SELF_UPDATE_DOWNLOADED, update_downloaded)
  on(AppConstants.SELF_UPDATE_ERROR, update_error)
  on(AppConstants.DISMISS_UPDATE_ERROR, dismiss_update_error)
  on(AppConstants.CAVE_THROWN_INTO_BIT_BUCKET, cave_thrown_into_bit_bucket)

  on(AppConstants.GAIN_FOCUS, (payload) => {
    AppActions.fetch_collections()
    let panel = mori.getIn(state, ['library', 'panel'])
    panel && AppActions.fetch_games(panel)
  })
}))

Store.subscribe('game-store', (games) => {
  // state = mori.assocIn(state, ['library', 'games'], mori.toClj(games))
  AppStore.emit_change()
})

Store.subscribe('collection-store', (collections) => {
  state = mori.assocIn(state, ['library', 'collections'], mori.toClj(collections))
  AppStore.emit_change()
})

Store.subscribe('credentials-store', (credentials) => {
  state = mori.assocIn(state, ['library', 'credentials'], mori.toClj(credentials))
  AppStore.emit_change()
})

module.exports = AppStore
<commit_msg>Don't :hankey: everything by leaving test code in<commit_after>'use strict'

let mori = require('mori')

let Store = require('./store')

let AppDispatcher = require('../dispatcher/app-dispatcher')
let AppConstants = require('../constants/app-constants')
let AppActions = require('../actions/app-actions')
let pairs = require('underscore').pairs

let defer = require('../util/defer')
let env = require('../env')

let state = mori.hashMap(
  'page', 'login',

  'update', mori.hashMap(
    'available', false,
    'downloaded', false
  ),

  'library', mori.hashMap(
    'games', mori.hashMap(),
    'panel', '',
    'collections', mori.hashMap(),
    'caves', mori.hashMap()
  ),

  'login', mori.hashMap(
    'loading', false,
    'errors', null
  ),

  'setup', mori.hashMap(
    'message', '...',
    'icon', 'settings'
  )
)

let AppStore = Object.assign(new Store('app-store', 'renderer'), {
  get_state: function () {
    return state
  }
})

function checking_for_self_update (payload) {
  console.log(`checking for self updates...`)
  state = mori.assocIn(state, ['update', 'checking'], true)
  AppStore.emit_change()
}

function update_not_available (payload) {
  state = mori.assocIn(state, ['update', 'checking'], false)
  state = mori.assocIn(state, ['update', 'uptodate'], true)
  AppStore.emit_change()

  setTimeout(function () {
    state = mori.assocIn(state, ['update', 'uptodate'], false)
    AppStore.emit_change()
  }, 5000)
}

function update_available (payload) {
  console.log(`update available? cool!`)
  state = mori.assocIn(state, ['update', 'checking'], false)
  state = mori.assocIn(state, ['update', 'available'], true)
  AppStore.emit_change()
}

function update_downloaded (payload) {
  console.log(`update downloaded?! uber-cool!`)
  state = mori.assocIn(state, ['update', 'downloaded'], true)
  AppStore.emit_change()
}

function update_error (payload) {
  if (env.name === 'development') {
    console.log(`Ignoring update error ${payload.error} from dev environment`)
    return
  }

  state = mori.assocIn(state, ['update', 'checking'], false)
  state = mori.assocIn(state, ['update', 'error'], payload.message)
  AppStore.emit_change()
}

function dismiss_update_error () {
  state = mori.updateIn(state, ['update'], x => mori.dissoc(x, 'error'))
  AppStore.emit_change()
}

function focus_panel (payload) {
  let panel = payload.panel

  state = mori.assoc(state, 'page', 'library')
  state = mori.assocIn(state, ['library', 'panel'], panel)
  AppStore.emit_change()

  defer(() => {
    AppActions.focus_window()
    AppActions.fetch_games(panel)
  })
}

function switch_page (page) {
  state = mori.assoc(state, 'page', page)
  AppStore.emit_change()
}

function login_attempt (payload) {
  state = mori.assocIn(state, ['login', 'loading'], true)
  state = mori.assocIn(state, ['login', 'errors'], null)
  AppStore.emit_change()
}

function login_failure (payload) {
  let errors = payload.errors
  state = mori.assocIn(state, ['login', 'loading'], false)
  state = mori.assocIn(state, ['login', 'errors'], errors.stack || errors)
  switch_page('login')
}

function no_stored_credentials () {
  switch_page('login')
}

function ready_to_roll (payload) {
  state = mori.assocIn(state, ['login', 'loading'], false)
  state = mori.assocIn(state, ['login', 'errors'], null)

  let me = mori.getIn(state, ['library', 'credentials', 'me'])
  if (mori.get(me, 'developer')) {
    focus_panel({panel: 'dashboard'})
  } else {
    focus_panel({panel: 'owned'})
  }

  defer(() => {
    AppActions.fetch_games('dashboard')
  })
}

function logout () {
  state = mori.assocIn(state, ['library'], mori.hashMap(
    'games', mori.hashMap(),
    'panel', '',
    'collections', mori.hashMap(),
    'caves', mori.hashMap()
  ))
  AppStore.emit_change()
  switch_page('login')
}

function setup_status (payload) {
  let message = payload.message
  let icon = payload.icon
  state = mori.assocIn(state, ['setup', 'message'], message)
  if (icon) {
    state = mori.assocIn(state, ['setup', 'icon'], icon)
  }
  AppStore.emit_change()
}

function setup_wait (payload) {
  switch_page('setup')
}

function cave_progress (payload) {
  for (let pair of pairs(payload.opts)) {
    let k = pair[0]
    let v = pair[1]
    state = mori.assocIn(state, ['library', 'caves', payload.opts.id, k], mori.toClj(v))
  }
  AppStore.emit_change()
}

function cave_implode (payload) {
}

function cave_thrown_into_bit_bucket (payload) {
  state = mori.updateIn(state, ['library', 'caves'], caves => mori.dissoc(caves, payload.id))
  AppStore.emit_change()
  if (mori.getIn(state, ['library', 'panel']) === `caves/${payload.id}`) {
    AppActions.focus_panel('caved')
  }
}

AppDispatcher.register('app-store', Store.action_listeners(on => {
  on(AppConstants.SETUP_STATUS, setup_status)
  on(AppConstants.SETUP_WAIT, setup_wait)

  on(AppConstants.LIBRARY_FOCUS_PANEL, focus_panel)

  on(AppConstants.NO_STORED_CREDENTIALS, no_stored_credentials)
  on(AppConstants.LOGIN_ATTEMPT, login_attempt)
  on(AppConstants.LOGIN_FAILURE, login_failure)
  on(AppConstants.READY_TO_ROLL, ready_to_roll)
  on(AppConstants.LOGOUT, logout)

  on(AppConstants.CAVE_PROGRESS, cave_progress)
  on(AppConstants.CAVE_IMPLODE, cave_implode)

  on(AppConstants.CHECKING_FOR_SELF_UPDATE, checking_for_self_update)
  on(AppConstants.SELF_UPDATE_AVAILABLE, update_available)
  on(AppConstants.SELF_UPDATE_NOT_AVAILABLE, update_not_available)
  on(AppConstants.SELF_UPDATE_DOWNLOADED, update_downloaded)
  on(AppConstants.SELF_UPDATE_ERROR, update_error)
  on(AppConstants.DISMISS_UPDATE_ERROR, dismiss_update_error)
  on(AppConstants.CAVE_THROWN_INTO_BIT_BUCKET, cave_thrown_into_bit_bucket)

  on(AppConstants.GAIN_FOCUS, (payload) => {
    AppActions.fetch_collections()
    let panel = mori.getIn(state, ['library', 'panel'])
    panel && AppActions.fetch_games(panel)
  })
}))

Store.subscribe('game-store', (games) => {
  state = mori.assocIn(state, ['library', 'games'], mori.toClj(games))
  AppStore.emit_change()
})

Store.subscribe('collection-store', (collections) => {
  state = mori.assocIn(state, ['library', 'collections'], mori.toClj(collections))
  AppStore.emit_change()
})

Store.subscribe('credentials-store', (credentials) => {
  state = mori.assocIn(state, ['library', 'credentials'], mori.toClj(credentials))
  AppStore.emit_change()
})

module.exports = AppStore
<|endoftext|>


<commit_before>'use strict';

var fs    = require('fs');
var path  = require('path');
var utils = require('mout');

var task = {
    id          : 'init',
    author      : 'Indigo United',
    name        : 'Init',
    description : 'Init an empty autofile.',
    options: {
        name: {
            description: 'The task name.',
            default: 'autofile'
        },
        dst: {
            description: 'Directory in which the task will be created.',
            default: process.cwd()
        }
    },
    setup       : function (opt, ctx, next) {
        var error;

        if (utils.string.endsWith(opt.name, '.js')) {
            opt.name = opt.name.slice(0, -3);
        }
        opt.filename = path.join(opt.dst, opt.name + '.js');
        opt.__dirname = __dirname;

        fs.stat(opt.filename, function (err) {
            if (!err || err.code !== 'ENOENT') {
                error = new Error('EEXIST, file already exists \'' + opt.filename + '\'');
                error.code = 'EXISTS';
                return next(error);
            }

            next();
        });
    },
    tasks     :
    [
        {
            task: 'cp',
            options: {
                files: {
                    '{{__dirname}}/../base_autofile.js': '{{filename}}'
                }
            }
        },
        {
            task: 'scaffolding-replace',
            options: {
                files: '{{filename}}',
                data: {
                    name: '{{name}}'
                }
            }
        }
    ]
};

module.exports = task;<commit_msg>Prevent subtasks description of the init task to be outputted.<commit_after>'use strict';

var fs    = require('fs');
var path  = require('path');
var utils = require('mout');

var task = {
    id          : 'init',
    author      : 'Indigo United',
    name        : 'Init',
    description : 'Init an empty autofile.',
    options: {
        name: {
            description: 'The task name.',
            default: 'autofile'
        },
        dst: {
            description: 'Directory in which the task will be created.',
            default: process.cwd()
        }
    },
    setup       : function (opt, ctx, next) {
        var error;

        if (utils.string.endsWith(opt.name, '.js')) {
            opt.name = opt.name.slice(0, -3);
        }
        opt.filename = path.join(opt.dst, opt.name + '.js');
        opt.__dirname = __dirname;

        fs.stat(opt.filename, function (err) {
            if (!err || err.code !== 'ENOENT') {
                error = new Error('EEXIST, file already exists \'' + opt.filename + '\'');
                error.code = 'EXISTS';
                return next(error);
            }

            next();
        });
    },
    tasks     :
    [
        {
            task: 'cp',
            description: null,
            options: {
                files: {
                    '{{__dirname}}/../base_autofile.js': '{{filename}}'
                }
            }
        },
        {
            task: 'scaffolding-replace',
            description: null,
            options: {
                files: '{{filename}}',
                data: {
                    name: '{{name}}'
                }
            }
        }
    ]
};

module.exports = task;<|endoftext|>


<commit_before>/*
 * grunt-ipfs
 * https://github.com/SafeMarket/grunt-ipfs
 *
 * Copyright (c) 2015 Aakil Fernandes
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  var cp = require('child_process')

  grunt.registerMultiTask('ipfsadd', 'Add file/folder to ipfs', function() {

    var options = this.options()
      ,done = this.async();

    options.bin = options.bin || 'ipfs'

    if(!options.paths || options.paths.length === 0){
      grunt.log.warn('options.paths not set or empty');
      done(false)
    }

    options.flags = options.flags || []

    var flagStr = options.flags.map(function(flag){
      return '-'+flag
    }).join(' ')

    addFirstPathOrDone()

    function addFirstPathOrDone(){
      if(options.paths.length === 0) return done(true)

      var path = options.paths.shift()
        ,cmd = (options.bin+' add '+path+' '+flagStr).trim()

      grunt.log.writeln(cmd)

      var childProcess = cp.exec(cmd)

      childProcess.on('exit', function(code) {
        if (code === 1) {
          grunt.log.error('Fail');
          return done(false);
        }else{
          grunt.log.success('Added');
        }

        addFirstPathOrDone();
      });

    }
  })
};
<commit_msg>option to save hashes<commit_after>/*
 * grunt-ipfs
 * https://github.com/SafeMarket/grunt-ipfs
 *
 * Copyright (c) 2015 Aakil Fernandes
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  var cp = require('child_process')

  grunt.registerMultiTask('ipfsadd', 'Add file/folder to ipfs', function() {

    var options = this.options()
      ,done = this.async();

    options.bin = options.bin || 'ipfs'

    if(!options.paths || options.paths.length === 0){
      grunt.log.warn('options.paths not set or empty');
      done(false)
    }

    options.flags = options.flags || []

    var flagStr = options.flags.map(function(flag){
      return '-'+flag
    }).join(' ')

    addFirstPathOrDone()

    function addFirstPathOrDone(){
      if(options.paths.length === 0)
        if(options.save)
          fs.writeFile(options.save, JSON.stringify(hashes), function(err) {
              if(err) {
                  grunt.log.error('Could not save to '+options.save)
                  return done(false);
              }

              grunt.log.success('Saved to '+options.save);
              done()
          });
        else
          return done()

      var path = options.paths.shift()
        ,cmd = (options.bin+' add '+path+' '+flagStr).trim()
        ,hash = null

      grunt.log.writeln(cmd)

      var childProcess = cp.exec(cmd)

      childProcess.on('exit', function(code) {
        if (code === 1) {
          grunt.log.error('Fail');
          return done(false);
        }else{
          hashes[path] = hash
          grunt.log.success('Added '+hash);
        }

        addFirstPathOrDone();
      });

    }
  })
};
<|endoftext|>


<commit_before>/*
 * grunt
 * http://gruntjs.com/
 *
 * Copyright (c) 2012 "Cowboy" Ben Alman
 * Licensed under the MIT license.
 * http://benalman.com/about/license/
 */

'use strict';

module.exports = function(grunt) {

  // External libs.
  var jshint = require('jshint').JSHINT;

  // ==========================================================================
  // TASKS
  // ==========================================================================

  grunt.registerMultiTask('lint', 'Validate files with JSHint.', function() {
    // Get flags and globals, allowing target-specific options and globals to
    // override the default options and globals.
    var options, globals, tmp;

    // Check for a jshintrc file.
    if (tmp = grunt.config(['jshint', this.target, 'jshintrc'])) {
      // If a target-specific jshintrc file was specified, read it.
      grunt.verbose.writeln('Using "' + this.target + '" jshintrc file.');
      options = grunt.file.readJSON(tmp);
    } else if (tmp = grunt.config('jshint.jshintrc')) {
      // If a global jshintrc file was specified, read it.
      grunt.verbose.writeln('Using master jshintrc file.');
      options = grunt.file.readJSON(tmp);
    }

    if (options) {
      // A jshintrc file was read.
      if (options.predef) {
        // Temp kluge for https://github.com/jshint/node-jshint/issues/104
        globals = {};
        options.predef.forEach(function(key) {
          globals[key] = true;
        });
        delete options.predef;
      }

    } else {
      // No jshintrc file was read.
      tmp = grunt.config(['jshint', this.target, 'options']);
      if (typeof tmp === 'object') {
        grunt.verbose.writeln('Using "' + this.target + '" JSHint options.');
        options = tmp;
      } else {
        grunt.verbose.writeln('Using master JSHint options.');
        options = grunt.config('jshint.options');
      }

      tmp = grunt.config(['jshint', this.target, 'globals']);
      if (typeof tmp === 'object') {
        grunt.verbose.writeln('Using "' + this.target + '" JSHint globals.');
        globals = tmp;
      } else {
        grunt.verbose.writeln('Using master JSHint globals.');
        globals = grunt.config('jshint.globals');
      }
    }

    grunt.verbose.writeflags(options, 'JSHint options');
    grunt.verbose.writeflags(globals, 'JSHint globals');

    // Lint specified files.
    var files = grunt.file.expandFiles(this.file.src);
    files.forEach(function(filepath) {
      grunt.helper('lint', grunt.file.read(filepath), options, globals, filepath);
    });

    // Fail task if errors were logged.
    if (this.errorCount) { return false; }

    // Otherwise, print a success message.
    grunt.log.ok(files.length + ' files lint free.');
  });

  // ==========================================================================
  // HELPERS
  // ==========================================================================

  // No idea why JSHint treats tabs as options.indent # characters wide, but it
  // does. See issue: https://github.com/jshint/jshint/issues/430
  function getTabStr(options) {
    // Do something that's going to error.
    jshint('\tx', options || {});
    // If an error occurred, figure out what character JSHint reported and
    // subtract one.
    var character = jshint.errors && jshint.errors[0] && jshint.errors[0].character - 1;
    // If character is actually a number, use it. Otherwise use 1.
    var tabsize = isNaN(character) ? 1 : character;
    // If tabsize > 1, return something that should be safe to use as a
    // placeholder. \uFFFF repeated 2+ times.
    return tabsize > 1 && grunt.util.repeat(tabsize, '\uFFFF');
  }

  var tabregex = /\t/g;

  // Lint source code with JSHint.
  grunt.registerHelper('lint', function(src, options, globals, extraMsg) {
    // JSHint sometimes modifies objects you pass in, so clone them.
    options = grunt.util._.clone(options);
    globals = grunt.util._.clone(globals);
    // Enable/disable debugging if option explicitly set.
    if (grunt.option('debug') !== undefined) {
      options.devel = options.debug = grunt.option('debug');
      // Tweak a few things.
      if (grunt.option('debug')) {
        options.maxerr = Infinity;
      }
    }
    var msg = 'Linting' + (extraMsg ? ' ' + extraMsg : '') + '...';
    grunt.verbose.write(msg);
    // Tab size as reported by JSHint.
    var tabstr = getTabStr(options);
    var placeholderregex = new RegExp(tabstr, 'g');
    // Lint.
    var result = jshint(src, options || {}, globals || {});
    var data = jshint.data();
    // Attempt to work around JSHint erroneously reporting bugs.
    // if (!result) {
    //   // Filter out errors that shouldn't be reported.
    //   jshint.errors = jshint.errors.filter(function(o) {
    //     return o && o.something === 'something';
    //   });
    //   // If no errors are left, JSHint actually succeeded.
    //   result = jshint.errors.length === 0;
    // }
    if (result && !data.unused) {
      // Success!
      grunt.verbose.ok();
      return;
    }
    // Something went wrong.
    grunt.verbose.or.write(msg);
    grunt.log.error();
    // Iterate over all unused variables
    var varsByLine = {};
    if (data.unused) {
      data.unused.forEach(function(unused) {
        var line = unused.line;
        var vars = varsByLine[line] = varsByLine[line] || [];
        vars.push(unused.name);
      });
      Object.keys(varsByLine).forEach(function(line) {
        // Manually increment errorcount since we're not using grunt.log.error().
        grunt.fail.errorcount++;
        var vars = varsByLine[line];
        grunt.log.writeln('['.red + ('L' + line).yellow + ']'.red +
          (' Unused variable' + (vars.length === 1 ? '' : 's') + ': ').yellow +
          grunt.log.wordlist(vars, {color: false, separator: ', '.yellow}));
      });
    }
    // Iterate over all errors.
    jshint.errors.forEach(function(e) {
      // Sometimes there's no error object.
      if (!e) { return; }
      var pos;
      var evidence = e.evidence;
      var character = e.character;
      if (evidence) {
        // Manually increment errorcount since we're not using grunt.log.error().
        grunt.fail.errorcount++;
        // Descriptive code error.
        pos = '['.red + ('L' + e.line).yellow + ':'.red + ('C' + character).yellow + ']'.red;
        grunt.log.writeln(pos + ' ' + e.reason.yellow);
        // If necessary, eplace each tab char with something that can be
        // swapped out later.
        if (tabstr) {
          evidence = evidence.replace(tabregex, tabstr);
        }
        if (character === 0) {
          // Beginning of line.
          evidence = '?'.inverse.red + evidence;
        } else if (character > evidence.length) {
          // End of line.
          evidence = evidence + ' '.inverse.red;
        } else {
          // Middle of line.
          evidence = evidence.slice(0, character - 1) + evidence[character - 1].inverse.red +
            evidence.slice(character);
        }
        // Replace tab placeholder (or tabs) but with a 2-space soft tab.
        evidence = evidence.replace(tabstr ? placeholderregex : tabregex, '  ');
        grunt.log.writeln(evidence);
      } else {
        // Generic "Whoops, too many errors" error.
        grunt.log.error(e.reason);
      }
    });
    grunt.log.writeln();
  });

};
<commit_msg>Updating lint task to use the new task/target options property.<commit_after>/*
 * grunt
 * http://gruntjs.com/
 *
 * Copyright (c) 2012 "Cowboy" Ben Alman
 * Licensed under the MIT license.
 * http://benalman.com/about/license/
 */

'use strict';

module.exports = function(grunt) {

  // External libs.
  var jshint = require('jshint').JSHINT;

  // ==========================================================================
  // TASKS
  // ==========================================================================

  grunt.registerMultiTask('lint', 'Validate files with JSHint.', function() {
    // Get any task- or target-specific options, using the top-level "jshint"
    // property and its sub-properties (options, globals, jshintrc) as defaults.
    var options = this.options(grunt.config('jshint'));

    // If a jshintrc file was specified, read it.
    var jshintrc;
    if (options.jshintrc) {
      jshintrc = grunt.file.readJSON(options.jshintrc);
      delete options.jshintrc;
      // JSHint options and globals will be read from jshintrc file.
      options.options = jshintrc;
      options.globals = {};
      if (jshintrc.predef) {
        // Temp kluge for https://github.com/jshint/node-jshint/issues/104
        jshintrc.predef.forEach(function(key) {
          options.globals[key] = true;
        });
        delete jshintrc.predef;
      }
    }

    grunt.verbose.writeflags(options.options, 'JSHint options');
    grunt.verbose.writeflags(options.globals, 'JSHint globals');

    // Lint specified files.
    var files = grunt.file.expandFiles(this.file.src);
    files.forEach(function(filepath) {
      grunt.helper('lint', grunt.file.read(filepath), options.options,
        options.globals, filepath);
    });

    // Fail task if errors were logged.
    if (this.errorCount) { return false; }

    // Otherwise, print a success message.
    grunt.log.ok(files.length + ' files lint free.');
  });

  // ==========================================================================
  // HELPERS
  // ==========================================================================

  // No idea why JSHint treats tabs as options.indent # characters wide, but it
  // does. See issue: https://github.com/jshint/jshint/issues/430
  function getTabStr(options) {
    // Do something that's going to error.
    jshint('\tx', options || {});
    // If an error occurred, figure out what character JSHint reported and
    // subtract one.
    var character = jshint.errors && jshint.errors[0] && jshint.errors[0].character - 1;
    // If character is actually a number, use it. Otherwise use 1.
    var tabsize = isNaN(character) ? 1 : character;
    // If tabsize > 1, return something that should be safe to use as a
    // placeholder. \uFFFF repeated 2+ times.
    return tabsize > 1 && grunt.util.repeat(tabsize, '\uFFFF');
  }

  var tabregex = /\t/g;

  // Lint source code with JSHint.
  grunt.registerHelper('lint', function(src, options, globals, extraMsg) {
    // JSHint sometimes modifies objects you pass in, so clone them.
    options = grunt.util._.clone(options);
    globals = grunt.util._.clone(globals);
    // Enable/disable debugging if option explicitly set.
    if (grunt.option('debug') !== undefined) {
      options.devel = options.debug = grunt.option('debug');
      // Tweak a few things.
      if (grunt.option('debug')) {
        options.maxerr = Infinity;
      }
    }
    var msg = 'Linting' + (extraMsg ? ' ' + extraMsg : '') + '...';
    grunt.verbose.write(msg);
    // Tab size as reported by JSHint.
    var tabstr = getTabStr(options);
    var placeholderregex = new RegExp(tabstr, 'g');
    // Lint.
    var result = jshint(src, options || {}, globals || {});
    var data = jshint.data();
    // Attempt to work around JSHint erroneously reporting bugs.
    // if (!result) {
    //   // Filter out errors that shouldn't be reported.
    //   jshint.errors = jshint.errors.filter(function(o) {
    //     return o && o.something === 'something';
    //   });
    //   // If no errors are left, JSHint actually succeeded.
    //   result = jshint.errors.length === 0;
    // }
    if (result && !data.unused) {
      // Success!
      grunt.verbose.ok();
      return;
    }
    // Something went wrong.
    grunt.verbose.or.write(msg);
    grunt.log.error();
    // Iterate over all unused variables
    var varsByLine = {};
    if (data.unused) {
      data.unused.forEach(function(unused) {
        var line = unused.line;
        var vars = varsByLine[line] = varsByLine[line] || [];
        vars.push(unused.name);
      });
      Object.keys(varsByLine).forEach(function(line) {
        // Manually increment errorcount since we're not using grunt.log.error().
        grunt.fail.errorcount++;
        var vars = varsByLine[line];
        grunt.log.writeln('['.red + ('L' + line).yellow + ']'.red +
          (' Unused variable' + (vars.length === 1 ? '' : 's') + ': ').yellow +
          grunt.log.wordlist(vars, {color: false, separator: ', '.yellow}));
      });
    }
    // Iterate over all errors.
    jshint.errors.forEach(function(e) {
      // Sometimes there's no error object.
      if (!e) { return; }
      var pos;
      var evidence = e.evidence;
      var character = e.character;
      if (evidence) {
        // Manually increment errorcount since we're not using grunt.log.error().
        grunt.fail.errorcount++;
        // Descriptive code error.
        pos = '['.red + ('L' + e.line).yellow + ':'.red + ('C' + character).yellow + ']'.red;
        grunt.log.writeln(pos + ' ' + e.reason.yellow);
        // If necessary, eplace each tab char with something that can be
        // swapped out later.
        if (tabstr) {
          evidence = evidence.replace(tabregex, tabstr);
        }
        if (character === 0) {
          // Beginning of line.
          evidence = '?'.inverse.red + evidence;
        } else if (character > evidence.length) {
          // End of line.
          evidence = evidence + ' '.inverse.red;
        } else {
          // Middle of line.
          evidence = evidence.slice(0, character - 1) + evidence[character - 1].inverse.red +
            evidence.slice(character);
        }
        // Replace tab placeholder (or tabs) but with a 2-space soft tab.
        evidence = evidence.replace(tabstr ? placeholderregex : tabregex, '  ');
        grunt.log.writeln(evidence);
      } else {
        // Generic "Whoops, too many errors" error.
        grunt.log.error(e.reason);
      }
    });
    grunt.log.writeln();
  });

};
<|endoftext|>


<commit_before>'use strict'

const path = require('path')

let sourceDirectories = [
  '*.js',
  'bin/**',
  'config/**/*.js',
  'test/**/*.js',
  'src/**/*.js',
  'tasks/**/*.js',
  'examples/**/*.js',
  'benchmarks/**/*.js'
]

// Get custom entry file's directory and add it to the source directories
try {
  const customConfig = require(path.resolve('.aegir.js'))
  if (customConfig.entry) {
    // Get the entry file path and remove the filename from it
    const entryDir = customConfig.entry.split('/').slice(0, -1).join('/')
    if (entryDir !== '') {
      sourceDirectories.push(entryDir + '/**/*.js')
    }
  }
} catch (err) {
}

module.exports = (gulp) => {
  gulp.task('lint', () => {
    const eslint = require('gulp-eslint')

    return gulp.src(sourceDirectories)
      .pipe(eslint(`${__dirname}/../config/eslintrc.yml`))
      .pipe(eslint.format())
      .pipe(eslint.failAfterError())
  })
}
<commit_msg>fix(lint): ignore nested `node_modules` dirs<commit_after>'use strict'

const path = require('path')

let sourceDirectories = [
  '*.js',
  'bin/**',
  'config/**/*.js',
  'test/**/*.js',
  'src/**/*.js',
  'tasks/**/*.js',
  'examples/**/*.js',
  'benchmarks/**/*.js',
  '!**/node_modules/**'
]

// Get custom entry file's directory and add it to the source directories
try {
  const customConfig = require(path.resolve('.aegir.js'))
  if (customConfig.entry) {
    // Get the entry file path and remove the filename from it
    const entryDir = customConfig.entry.split('/').slice(0, -1).join('/')
    if (entryDir !== '') {
      sourceDirectories.push(entryDir + '/**/*.js')
    }
  }
} catch (err) {
}

module.exports = (gulp) => {
  gulp.task('lint', () => {
    const eslint = require('gulp-eslint')

    return gulp.src(sourceDirectories)
      .pipe(eslint(`${__dirname}/../config/eslintrc.yml`))
      .pipe(eslint.format())
      .pipe(eslint.failAfterError())
  })
}
<|endoftext|>