<commit_before>require("dotenv").config({ path: "./env." + process.env.NODE_ENV });
var request = require("request-promise");
require("cheerio");
var robots = require("robots");
var parser = new robots.RobotsParser(null, {});
var jeopardyParser = require("../lib/JeopardyParser");
const Queries = require("../lib/Queries");

var MongoClient = require("mongodb").MongoClient,
	assert = require("assert");

var url = process.env.DB_URL;
var USER_AGENT = "Alex Pelan (alexpelan@gmail.com)";
var ROBOTS_URL = "http://www.j-archive.com/robots.txt";
const EARLIEST_SEASON = 30;

let requestOptions = {
	url: "",
	headers: {
		"User-Agent": USER_AGENT
	}
};

var seedGame = function(gameId, delay, db) {
	return new Promise(function(resolve) {
		setTimeout(function() {
			var url = process.env.GAME_URL + gameId;
			requestOptions.url = url;
			request(requestOptions).then(function(html) {
				var gameJson = jeopardyParser.parseJeopardyGame(html);
				var gamesCollection = db.collection("games");
				gamesCollection.updateOne({id: gameId}, {$set: gameJson}, function() {
					resolve();
				});
			});
		}, delay * 1000);
	});
};

// gamesJson is an array of arrays of games
var seedGames = function(gamesJson, delayPerRequest, db) {
	var counter = 0;
	var gamePromises = [];
	gamesJson.forEach(function(gamesFromSingleSeason) {

		gamesFromSingleSeason.forEach(function(game) {
			var delay = delayPerRequest * counter;
			counter = counter + 1;
			gamePromises.push(seedGame(game.id, delay, db));
		});

	});

	return gamePromises;
};

var seedSeason = function(seasonId, delay, db, checkForExisting=false) {
	return new Promise(function(resolve) {
		setTimeout(function() {
			var url = process.env.SEASON_URL + seasonId;
			requestOptions.url = url;
			request(requestOptions).then(function(html) {
				var gamesJson = jeopardyParser.parseJeopardySeason(html).games;
				gamesJson.forEach(function(game) {
					game.season = seasonId;
				});

				if (checkForExisting) {
					insertNewGamesMetadata(db, gamesJson).then((gamesToFinish) => resolve(gamesToFinish));
				} else {
					var gamesCollection = db.collection("games");
					gamesCollection.insertMany(gamesJson, function() {
						resolve(gamesJson);
					});
				}
			}).catch(function(error){
				console.log("error requesting ", error);
			});
		}, delay * 1000);
	});
};

var seedSeasons = function(seasonsJson, delayPerRequest, db) {
	var seasonPromises = [];
	seasonsJson.forEach(function(season, index){
		var delay = delayPerRequest * index;
		seasonPromises.push(seedSeason(season.id, delay, db));
	});

	return seasonPromises;
};

var seedListOfSeasons = function(db) {
	var url = process.env.LIST_SEASONS_URL;
	requestOptions.url = url;

	return new Promise(function (resolve) {
		request(requestOptions).then(function(html) {
			const seasonsJson = jeopardyParser.parseSeasonList(html).seasons;
			const filteredSeasonsJson = seasonsJson.filter((season) => {
				return parseInt(season.id) >= EARLIEST_SEASON;
			});
			var seasonsCollection = db.collection("seasons");
			seasonsCollection.insertMany(filteredSeasonsJson, function() {
				resolve(filteredSeasonsJson);
			});
		}).catch(function(error){
			console.log("error requesting ", error);
		});
	});

};

const seedFullDatabase = function(db, delayInSeconds) {
	seedListOfSeasons(db).then(function(seasonsJson) {
		var promises = seedSeasons(seasonsJson, delayInSeconds, db);
		Promise.all(promises).then(function(gamesJson){
			Promise.all(seedGames(gamesJson, delayInSeconds, db)).then(function() {
				db.close();
			}).catch(function(error) {
				console.log("error fetching list of games", error);
			});
		}).catch(function(error){
			console.log("error fetching listOfSeasons ", error);
		});
	});
};

const insertNewGamesMetadata = function(db, gamesJson) {
	return new Promise(function(resolve) {
		///fetch all the games
		const gamesCollection = db.collection("games");
		gamesCollection.find({}).toArray().then((gamesInDb) => {
			// figure out which games aren't in the database.
			let gamesToInsert = gamesJson.filter((game) => {
				return gamesInDb.some((gameInDb) => {
					return gameInDb.id === game.id;
				});
			});

			// insert the ones that aren't
			if (gamesToInsert.length > 0) {
				gamesCollection.insertMany(gamesToInsert, function() {
					resolve(gamesToInsert);
				});
			} else {
				resolve();
			}

		});

	});

};

const checkForUpdates = function(db, delayInSeconds) {
	// first, find any new games in the most recent season in the databse
	Queries.findMostRecentSeason(db).then((result) => {

		const checkForExisting = true;
		seedSeason(result.toString(), delayInSeconds, db, checkForExisting).then((gamesToFinish)  => {
			if (gamesToFinish) {
				Promise.all(seedGames([gamesToFinish], delayInSeconds, db)).then(() => db.close());
			} else {
				// then, check for a new season, and if we find one, seed ALL games from that new season
				db.close();
			}
		});
	});
};

const executeTask = function(taskFunction) {
	MongoClient.connect(url, function(err, db) {
		assert.equal(null, err);

		parser.setUrl(ROBOTS_URL, function(parser, success) {
			if(success) {
				var delayInSeconds = parser.getCrawlDelay(USER_AGENT);
				taskFunction(db, delayInSeconds);
			}
		});
	});
};

const firstTimeSetupEnvironment = function() {
	executeTask(seedFullDatabase);
};

const updateEnvironment = function() {
	executeTask(checkForUpdates);
};

module.exports = {
	seedGame,
	seedListOfSeasons,
	seedSeason,
	firstTimeSetupEnvironment,
	updateEnvironment,
};<commit_msg>Have update script check to see if there is a brand new season<commit_after>require("dotenv").config({ path: "./env." + process.env.NODE_ENV });
var request = require("request-promise");
require("cheerio");
var robots = require("robots");
var parser = new robots.RobotsParser(null, {});
var jeopardyParser = require("../lib/JeopardyParser");
const Queries = require("../lib/Queries");

var MongoClient = require("mongodb").MongoClient,
	assert = require("assert");

var url = process.env.DB_URL;
var USER_AGENT = "Alex Pelan (alexpelan@gmail.com)";
var ROBOTS_URL = "http://www.j-archive.com/robots.txt";
const EARLIEST_SEASON = 30;

let requestOptions = {
	url: "",
	headers: {
		"User-Agent": USER_AGENT
	}
};

var seedGame = function(gameId, delay, db) {
	return new Promise(function(resolve) {
		setTimeout(function() {
			var url = process.env.GAME_URL + gameId;
			requestOptions.url = url;
			request(requestOptions).then(function(html) {
				var gameJson = jeopardyParser.parseJeopardyGame(html);
				var gamesCollection = db.collection("games");
				console.log("updating game ", gameId, " with ", gameJson);
				gamesCollection.updateOne({id: gameId}, {$set: gameJson}, function() {
					resolve();
				});
			});
		}, delay * 1000);
	});
};

// gamesJson is an array of arrays of games
var seedGames = function(gamesJson, delayPerRequest, db) {
	var counter = 0;
	var gamePromises = [];
	gamesJson.forEach(function(gamesFromSingleSeason) {

		gamesFromSingleSeason.forEach(function(game) {
			var delay = delayPerRequest * counter;
			counter = counter + 1;
			gamePromises.push(seedGame(game.id, delay, db));
		});

	});

	return gamePromises;
};

var seedSeason = function(seasonId, delay, db, checkForExisting=false) {
	return new Promise(function(resolve) {
		setTimeout(function() {
			var url = process.env.SEASON_URL + seasonId;
			requestOptions.url = url;
			request(requestOptions).then(function(html) {
				var gamesJson = jeopardyParser.parseJeopardySeason(html).games;
				gamesJson.forEach(function(game) {
					game.season = seasonId;
				});

				if (checkForExisting) {
					insertNewGamesMetadata(db, gamesJson).then((gamesToFinish) => resolve(gamesToFinish));
				} else {
					var gamesCollection = db.collection("games");
					gamesCollection.insertMany(gamesJson, function() {
						resolve(gamesJson);
					});
				}
			}).catch(function(error){
				console.log("error requesting ", error);
			});
		}, delay * 1000);
	});
};

var seedSeasons = function(seasonsJson, delayPerRequest, db) {
	var seasonPromises = [];
	seasonsJson.forEach(function(season, index){
		var delay = delayPerRequest * index;
		seasonPromises.push(seedSeason(season.id, delay, db));
	});

	return seasonPromises;
};

var seedListOfSeasons = function(db) {
	var url = process.env.LIST_SEASONS_URL;
	requestOptions.url = url;

	return new Promise(function (resolve) {
		request(requestOptions).then(function(html) {
			const seasonsJson = jeopardyParser.parseSeasonList(html).seasons;
			const filteredSeasonsJson = seasonsJson.filter((season) => {
				return parseInt(season.id) >= EARLIEST_SEASON;
			});
			var seasonsCollection = db.collection("seasons");
			// always do a complete removal
			seasonsCollection.removeMany({}).then(() => {
				seasonsCollection.insertMany(filteredSeasonsJson, function() {
					resolve(filteredSeasonsJson);
				});
			});
		}).catch(function(error){
			console.log("error requesting ", error);
		});
	});

};

const seedFullDatabase = function(db, delayInSeconds) {
	seedListOfSeasons(db).then(function(seasonsJson) {
		var promises = seedSeasons(seasonsJson, delayInSeconds, db);
		Promise.all(promises).then(function(gamesJson){
			Promise.all(seedGames(gamesJson, delayInSeconds, db)).then(function() {
				db.close();
			}).catch(function(error) {
				console.log("error fetching list of games", error);
			});
		}).catch(function(error){
			console.log("error fetching listOfSeasons ", error);
		});
	});
};

const insertNewGamesMetadata = function(db, gamesJson) {
	return new Promise(function(resolve) {
		///fetch all the games
		const gamesCollection = db.collection("games");
		gamesCollection.find({}).toArray().then((gamesInDb) => {
			// figure out which games aren't in the database.
			let gamesToInsert = gamesJson.filter((game) => {
				return !gamesInDb.some((gameInDb) => {
					return gameInDb.id === game.id;
				});
			});

			// insert the ones that aren't
			if (gamesToInsert.length > 0) {
				gamesCollection.insertMany(gamesToInsert, function() {
					resolve(gamesToInsert);
				});
			} else {
				resolve();
			}

		});

	});

};

const checkForNewSeason = function(db, delayInSeconds) {
	let foundAnySeason = false;
	var url = process.env.LIST_SEASONS_URL;
	requestOptions.url = url;

	return new Promise(function (resolve) {
		setTimeout(() => {
			request(requestOptions).then(function(html) {
				const seasonsJson = jeopardyParser.parseSeasonList(html).seasons;
				const filteredSeasonsJson = seasonsJson.filter((season) => {
					return parseInt(season.id) >= EARLIEST_SEASON;
				});
				var seasonsCollection = db.collection("seasons");
				seasonsCollection.find({}).toArray().then((seasonsInDb) => {
					filteredSeasonsJson.forEach((seasonFromPage) => {
						const foundNewSeason = !seasonsInDb.some((seasonInDb) => seasonInDb.id === seasonFromPage.id);
						if (foundNewSeason) {
							foundAnySeason = true;
							seedListOfSeasons(db).then(() => {
								seedSeason(seasonFromPage.id.toString(), delayInSeconds, db, false).then((gamesJson)  => {
									if (gamesJson) {
										Promise.all(seedGames([gamesJson], delayInSeconds, db)).then(() => {
											db.close();
											resolve();
										});
									}  else {
										resolve();
									}
								});
							});

						}
					});

					if (!foundAnySeason) {
						resolve();
					}
				});
			}).catch(function(error){
				console.log("error requesting ", error);
			});
		}, delayInSeconds * 1000);
	});
};

const checkForUpdates = function(db, delayInSeconds) {
	Queries.findMostRecentSeason(db).then((result) => {

		const checkForExisting = true;
		seedSeason(result.toString(), delayInSeconds, db, checkForExisting).then((gamesToFinish)  => {
			// if there are new games in the most recent season, then add those. otherwise, check for a new season
			if (gamesToFinish) {
				Promise.all(seedGames([gamesToFinish], delayInSeconds, db)).then(() => db.close());
			} else {
				// then, check for a new season, and if we find one, seed ALL games from that new season
				checkForNewSeason(db, delayInSeconds).then(() =>  {
					db.close();
				});
			}
		});
	});
};

const executeTask = function(taskFunction) {
	MongoClient.connect(url, function(err, db) {
		assert.equal(null, err);

		parser.setUrl(ROBOTS_URL, function(parser, success) {
			if(success) {
				var delayInSeconds = parser.getCrawlDelay(USER_AGENT);
				taskFunction(db, delayInSeconds);
			}
		});
	});
};

const firstTimeSetupEnvironment = function() {
	executeTask(seedFullDatabase);
};

const updateEnvironment = function() {
	executeTask(checkForUpdates);
};

module.exports = {
	seedGame,
	seedListOfSeasons,
	seedSeason,
	firstTimeSetupEnvironment,
	updateEnvironment,
};<|endoftext|>


<commit_before>/* Copyright 2013 Chris Wilson

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

window.AudioContext = window.AudioContext || window.webkitAudioContext;

var audioContext = new AudioContext();
var audioInput = null,
    realAudioInput = null,
    inputPoint = null,
    audioRecorder = null;

var rafID = null;
var analyserContext = null;
var canvasWidth, canvasHeight;
var recIndex = 0;

/* TODO:

- offer mono option
- "Monitor input" switch
*/

function saveAudio() {
    audioRecorder.exportWAV( doneEncoding );
    // could get mono instead by saying
    // audioRecorder.exportMonoWAV( doneEncoding );
}

function gotBuffers( buffers ) {
    var canvas = document.getElementById( "wavedisplay" );

    drawBuffer( canvas.width, canvas.height, canvas.getContext('2d'), buffers[0] );

    // the ONLY time gotBuffers is called is right after a new recording is completed -
    // so here's where we should set up the download.
    audioRecorder.exportWAV( doneEncoding );
}

function doneEncoding( blob ) {
    Recorder.setupDownload( blob, "myRecording" + ((recIndex<10)?"0":"") + recIndex + ".wav" );
    recIndex++;
}

function toggleRecording( e ) {
    if (e.classList.contains("recording")) {
       //stop recording
        audioRecorder.stop();
        e.classList.remove("recording");
        audioRecorder.getBuffers( gotBuffers );
		//end timer
        Recordtimer(audioRecorder);
    } else {
        //start recording
        if (!audioRecorder)
            return;
        e.classList.add("recording");
        audioRecorder.clear();
        audioRecorder.record();
		//Start timer
		Recordtimer(audioRecorder);

    }
}

function Recordtimer(audioRecorder){

			if (audioRecorder){
			//to record time
			var Start_time = new Date();

			}
			else {
			//To stop recording
		    var end_time = new Date();
			var recordingtime = end_time - Start_time;
			var seconds = Math.round(Start_time/1000);
			var minutes = Math.round(seconds/60);
			var hours = Math.round(minutes /60);
			document.getElementById("Recordingtime").innerHTML= hours":"minutes":"seconds;
			}
}

function convertToMono( input ) {
    var splitter = audioContext.createChannelSplitter(2);
    var merger = audioContext.createChannelMerger(2);

    input.connect( splitter );
    splitter.connect( merger, 0, 0 );
    splitter.connect( merger, 0, 1 );
    return merger;
}

function cancelAnalyserUpdates() {
    window.cancelAnimationFrame( rafID );
    rafID = null;
}

function updateAnalysers(            ) {
    if (!analyserContext) {
        var canvas = document.getElementById("analyser");
        canvasWidth = canvas.width;
        canvasHeight = canvas.height;
        analyserContext = canvas.getContext('2d');
    }

    // analyzer draw code here
    {
        var SPACING = 3;
        var BAR_WIDTH = 1;
        var numBars = Math.round(canvasWidth / SPACING);
        var freqByteData = new Uint8Array(analyserNode.frequencyBinCount);

        analyserNode.getByteFrequencyData(freqByteData);

        analyserContext.clearRect(0, 0, canvasWidth, canvasHeight);
        analyserContext.fillStyle = '#F6D565';
        analyserContext.lineCap = 'round';
        var multiplier = analyserNode.frequencyBinCount / numBars;

        // Draw rectangle for each frequency bin.
        for (var i = 0; i < numBars; ++i) {
            var magnitude = 0;
            var offset = Math.floor( i * multiplier );
            // gotta sum/average the block, or we miss narrow-bandwidth spikes
            for (var j = 0; j< multiplier; j++)
                magnitude += freqByteData[offset + j];
            magnitude = magnitude / multiplier;
            var magnitude2 = freqByteData[i * multiplier];
            analyserContext.fillStyle = "hsl( " + Math.round((i*360)/numBars) + ", 100%, 50%)";
            analyserContext.fillRect(i * SPACING, canvasHeight, BAR_WIDTH, -magnitude);
        }
    }

    rafID = window.requestAnimationFrame( updateAnalysers );
}

function toggleMono() {
    if (audioInput != realAudioInput) {
        audioInput.disconnect();
        realAudioInput.disconnect();
        audioInput = realAudioInput;
    } else {
        realAudioInput.disconnect();
        audioInput = convertToMono( realAudioInput );
    }

    audioInput.connect(inputPoint);
}

function gotStream(stream) {
    inputPoint = audioContext.createGain();

    // Create an AudioNode from the stream.
    realAudioInput = audioContext.createMediaStreamSource(stream);
    audioInput = realAudioInput;
    audioInput.connect(inputPoint);

//    audioInput = convertToMono( input );

    analyserNode = audioContext.createAnalyser();
    analyserNode.fftSize = 2048;
    inputPoint.connect( analyserNode );

    audioRecorder = new Recorder( inputPoint );

    zeroGain = audioContext.createGain();
    zeroGain.gain.value = 0.0;
    inputPoint.connect( zeroGain );
    zeroGain.connect( audioContext.destination );
    updateAnalysers();
}

function initAudio() {
        if (!navigator.getUserMedia)
            navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
        if (!navigator.cancelAnimationFrame)
            navigator.cancelAnimationFrame = navigator.webkitCancelAnimationFrame || navigator.mozCancelAnimationFrame;
        if (!navigator.requestAnimationFrame)
            navigator.requestAnimationFrame = navigator.webkitRequestAnimationFrame || navigator.mozRequestAnimationFrame;

    navigator.getUserMedia(
        {
            "audio": {
                "mandatory": {
                    "googEchoCancellation": "false",
                    "googAutoGainControl": "false",
                    "googNoiseSuppression": "false",
                    "googHighpassFilter": "false"
                },
                "optional": []
            },
        }, gotStream, function(e) {
            alert('Error getting audio');
            console.log(e);
        });
}

window.addEventListener('load', initAudio );
<commit_msg>Update main.js<commit_after>/* Copyright 2013 Chris Wilson

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

window.AudioContext = window.AudioContext || window.webkitAudioContext;

var audioContext = new AudioContext();
var audioInput = null,
    realAudioInput = null,
    inputPoint = null,
    audioRecorder = null;

var rafID = null;
var analyserContext = null;
var canvasWidth, canvasHeight;
var recIndex = 0;

/* TODO:

- offer mono option
- "Monitor input" switch
*/

function saveAudio() {
    audioRecorder.exportWAV( doneEncoding );
    // could get mono instead by saying
    // audioRecorder.exportMonoWAV( doneEncoding );
}

function gotBuffers( buffers ) {
    var canvas = document.getElementById( "wavedisplay" );

    drawBuffer( canvas.width, canvas.height, canvas.getContext('2d'), buffers[0] );

    // the ONLY time gotBuffers is called is right after a new recording is completed -
    // so here's where we should set up the download.
    audioRecorder.exportWAV( doneEncoding );
}

function doneEncoding( blob ) {
    Recorder.setupDownload( blob, "myRecording" + ((recIndex<10)?"0":"") + recIndex + ".wav" );
    recIndex++;
}

function toggleRecording( e ) {
    if (e.classList.contains("recording")) {
       //stop recording
        audioRecorder.stop();
        e.classList.remove("recording");
        audioRecorder.getBuffers( gotBuffers );
	//end timer
        var end_time = new Date();
	var recordingtime = end_time - StartTime;
	var seconds = Math.round(Start_time/1000);
	var minutes = Math.round(seconds/60);
	var hours = Math.round(minutes /60);
	document.getElementById("Recordingtime").innerHTML= hours +":"+ minutes + ":" + seconds;
    } else {
        //start recording
        if (!audioRecorder)
            return;
        e.classList.add("recording");
        audioRecorder.clear();
        audioRecorder.record();
		//Start timer
	var Start_time = new Date();
	StartTime = Start_time;

    }
}

function Recordtimer(audioRecorder){

			if (audioRecorder){
			//to record time
			var Start_time = new Date();

			}
			else {
			//To stop recording
		    var end_time = new Date();
			var recordingtime = end_time - Start_time;
			var seconds = Math.round(Start_time/1000);
			var minutes = Math.round(seconds/60);
			var hours = Math.round(minutes /60);
			document.getElementById("Recordingtime").innerHTML= hours":"minutes":"seconds;
			}
}

function convertToMono( input ) {
    var splitter = audioContext.createChannelSplitter(2);
    var merger = audioContext.createChannelMerger(2);

    input.connect( splitter );
    splitter.connect( merger, 0, 0 );
    splitter.connect( merger, 0, 1 );
    return merger;
}

function cancelAnalyserUpdates() {
    window.cancelAnimationFrame( rafID );
    rafID = null;
}

function updateAnalysers(            ) {
    if (!analyserContext) {
        var canvas = document.getElementById("analyser");
        canvasWidth = canvas.width;
        canvasHeight = canvas.height;
        analyserContext = canvas.getContext('2d');
    }

    // analyzer draw code here
    {
        var SPACING = 3;
        var BAR_WIDTH = 1;
        var numBars = Math.round(canvasWidth / SPACING);
        var freqByteData = new Uint8Array(analyserNode.frequencyBinCount);

        analyserNode.getByteFrequencyData(freqByteData);

        analyserContext.clearRect(0, 0, canvasWidth, canvasHeight);
        analyserContext.fillStyle = '#F6D565';
        analyserContext.lineCap = 'round';
        var multiplier = analyserNode.frequencyBinCount / numBars;

        // Draw rectangle for each frequency bin.
        for (var i = 0; i < numBars; ++i) {
            var magnitude = 0;
            var offset = Math.floor( i * multiplier );
            // gotta sum/average the block, or we miss narrow-bandwidth spikes
            for (var j = 0; j< multiplier; j++)
                magnitude += freqByteData[offset + j];
            magnitude = magnitude / multiplier;
            var magnitude2 = freqByteData[i * multiplier];
            analyserContext.fillStyle = "hsl( " + Math.round((i*360)/numBars) + ", 100%, 50%)";
            analyserContext.fillRect(i * SPACING, canvasHeight, BAR_WIDTH, -magnitude);
        }
    }

    rafID = window.requestAnimationFrame( updateAnalysers );
}

function toggleMono() {
    if (audioInput != realAudioInput) {
        audioInput.disconnect();
        realAudioInput.disconnect();
        audioInput = realAudioInput;
    } else {
        realAudioInput.disconnect();
        audioInput = convertToMono( realAudioInput );
    }

    audioInput.connect(inputPoint);
}

function gotStream(stream) {
    inputPoint = audioContext.createGain();

    // Create an AudioNode from the stream.
    realAudioInput = audioContext.createMediaStreamSource(stream);
    audioInput = realAudioInput;
    audioInput.connect(inputPoint);

//    audioInput = convertToMono( input );

    analyserNode = audioContext.createAnalyser();
    analyserNode.fftSize = 2048;
    inputPoint.connect( analyserNode );

    audioRecorder = new Recorder( inputPoint );

    zeroGain = audioContext.createGain();
    zeroGain.gain.value = 0.0;
    inputPoint.connect( zeroGain );
    zeroGain.connect( audioContext.destination );
    updateAnalysers();
}

function initAudio() {
        if (!navigator.getUserMedia)
            navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
        if (!navigator.cancelAnimationFrame)
            navigator.cancelAnimationFrame = navigator.webkitCancelAnimationFrame || navigator.mozCancelAnimationFrame;
        if (!navigator.requestAnimationFrame)
            navigator.requestAnimationFrame = navigator.webkitRequestAnimationFrame || navigator.mozRequestAnimationFrame;

    navigator.getUserMedia(
        {
            "audio": {
                "mandatory": {
                    "googEchoCancellation": "false",
                    "googAutoGainControl": "false",
                    "googNoiseSuppression": "false",
                    "googHighpassFilter": "false"
                },
                "optional": []
            },
        }, gotStream, function(e) {
            alert('Error getting audio');
            console.log(e);
        });
}

window.addEventListener('load', initAudio );
<|endoftext|>


<commit_before>/* global d3 */
;(function () {
  'use strict'

  // inspired by http://bl.ocks.org/mbostock/3902569
  ;[
    'repos',
    'events'
  ].forEach(function (type) {
    d3.json('/public/data/' + type + '-per-week.json', function (error, data) {
      if (error) {
        console.log(error)
      }

      var margin = {top: 20, right: 50, bottom: 30, left: 50}
      var width = 960 - margin.left - margin.right
      var height = 500 - margin.top - margin.bottom
      var parseDate = d3.time.format('%d-%b-%y').parse
      var bisectDate = d3.bisector(function (d) { return d.date }).left
      var formatDate = function (d) {
        return d[ type ] + ' ' + type + ' in the week of ' + d.formatted_date
      }

      var x = d3.time.scale().range([0, width])
      var y = d3.scale.linear().range([height, 0])
      var xAxis = d3.svg.axis().scale(x).orient('bottom')
        .tickFormat(function (d) {
          return d.toString().substring(4, 7) + '\'' + d.toString().substring(13, 15)
        })
      var yAxis = d3.svg.axis().scale(y).orient('left')

      var line = d3.svg.line()
        .x(function (d) { return x(d.date) })
        .y(function (d) { return y(d[ type ]) })

      var svg = d3.select('#' + type + '-per-week').append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom)
        .append('g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

      data.forEach(function (d) {
        d.date = parseDate(d.date)
        d[ type ] = +d[ type ]
      })

      data.sort(function (a, b) {
        return a.date - b.date
      })

      x.domain([data[0].date, data[data.length - 1].date])
      y.domain(d3.extent(data, function (d) {
        return d[ type ]
      }))

      svg.append('g')
        .attr('class', 'x axis')
        .attr('transform', 'translate(0,' + height + ')')
        .call(xAxis)

      svg.append('g')
        .attr('class', 'y axis')
        .call(yAxis)
        .append('text')
        .attr('transform', 'rotate(-90)')
        .attr('y', 6)
        .attr('dy', '.71em')
        .style('text-anchor', 'end')
        .text('No. of ' + type)

      svg.append('path')
        .datum(data)
        .attr('class', 'line')
        .attr('d', line)

      var focus = svg.append('g')
        .attr('class', 'focus')
        .style('display', 'block')

      focus.append('circle')
        .attr('r', 7)

      focus.append('text')
        .attr('x', 9)
        .attr('dx', '-8em')
        .attr('dy', '1.5em')

      svg.append('rect')
        .attr('class', 'overlay')
        .attr('width', width)
        .attr('height', height)
        .on('mouseover', function () { focus.style('display', null) })
        .on('mouseout', function () { focus.style('display', 'none') })
        .on('mousemove', mousemove)

      function mousemove () {
        var x0 = x.invert(d3.mouse(this)[0])
        var i = bisectDate(data, x0, 1)
        var d0 = data[i - 1]
        var d1 = data[i]
        var d = x0 - d0.date > d1.date - x0 ? d1 : d0

        focus.attr('transform', 'translate(' + x(d.date) + ',' + y(d[ type ]) + ')')
        focus.select('text').text(formatDate(d)).attr('class', 'label')
      }
    })
  })
})()
<commit_msg>fix: position the hover text differently. close #30<commit_after>/* global d3 */
;(function () {
  'use strict'

  // inspired by http://bl.ocks.org/mbostock/3902569
  ;[
    'repos',
    'events'
  ].forEach(function (type) {
    d3.json('/public/data/' + type + '-per-week.json', function (error, data) {
      if (error) {
        console.log(error)
      }

      var margin = {top: 20, right: 50, bottom: 30, left: 50}
      var width = 960 - margin.left - margin.right
      var height = 500 - margin.top - margin.bottom
      var parseDate = d3.time.format('%d-%b-%y').parse
      var bisectDate = d3.bisector(function (d) { return d.date }).left
      var formatDate = function (d) {
        return d[ type ] + ' ' + type + ' in the week of ' + d.formatted_date
      }

      var x = d3.time.scale().range([0, width])
      var y = d3.scale.linear().range([height, 0])
      var xAxis = d3.svg.axis().scale(x).orient('bottom')
        .tickFormat(function (d) {
          return d.toString().substring(4, 7) + '\'' + d.toString().substring(13, 15)
        })
      var yAxis = d3.svg.axis().scale(y).orient('left')

      var line = d3.svg.line()
        .x(function (d) { return x(d.date) })
        .y(function (d) { return y(d[ type ]) })

      var svg = d3.select('#' + type + '-per-week').append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom)
        .append('g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

      data.forEach(function (d) {
        d.date = parseDate(d.date)
        d[ type ] = +d[ type ]
      })

      data.sort(function (a, b) {
        return a.date - b.date
      })

      x.domain([data[0].date, data[data.length - 1].date])
      y.domain(d3.extent(data, function (d) {
        return d[ type ]
      }))

      svg.append('g')
        .attr('class', 'x axis')
        .attr('transform', 'translate(0,' + height + ')')
        .call(xAxis)

      svg.append('g')
        .attr('class', 'y axis')
        .call(yAxis)
        .append('text')
        .attr('transform', 'rotate(-90)')
        .attr('y', 6)
        .attr('dy', '.71em')
        .style('text-anchor', 'end')
        .text('No. of ' + type)

      svg.append('path')
        .datum(data)
        .attr('class', 'line')
        .attr('d', line)

      var focus = svg.append('g')
        .attr('class', 'focus')
        .style('display', 'block')

      focus.append('circle')
        .attr('r', 7)

      focus.append('text')
        .attr('x', 9)

      svg.append('rect')
        .attr('class', 'overlay')
        .attr('width', width)
        .attr('height', height)
        .on('mouseover', function () { focus.style('display', null) })
        .on('mouseout', function () { focus.style('display', 'none') })
        .on('mousemove', mousemove)

      function mousemove () {
        var x0 = x.invert(d3.mouse(this)[0])
        var i = bisectDate(data, x0, 1)
        var d0 = data[i - 1]
        var d1 = data[i]
        var d = x0 - d0.date > d1.date - x0 ? d1 : d0

        focus.attr('transform', 'translate(' + x(d.date) + ',' + y(d[ type ]) + ')')
        focus.select('text')
          .text(formatDate(d))
          .attr('class', 'label')
          .attr('dx', function () {
            return i / data.length > 0.5 ? '-17em' : '-1em'
          })
          .attr('dy', '1.5em')
      }
    })
  })
})()
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'

class BraintreeDropIn extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      dropInInstance: null,
      isSubmitButtonDisabled: true
    }
  }

  componentDidMount = () => {
    if (!this.props.braintree || this.state.dropInInstance) return
    this.setup()
  }

  componentDidUpdate = (prevProps, prevState) => {
    if (
      this.props.authorizationToken &&
      this.state.dropInInstance &&
      prevProps.authorizationToken !== this.props.authorizationToken
    ) {
      this.tearDown().then(() => {
        this.setState({
          dropInInstance: null,
          isSubmitButtonDisabled: true
        }, () => {
          this.setup()
        })
      }).catch((err) => {
        if (this.props.onError) {
          this.props.onError(err)
        }
      })
    }
  }

  componentWillUnmount = () => {
    if (!this.state.dropInInstance) return

    this.tearDown().catch((err) => {
      if (this.props.onError) {
        this.props.onError(err)
      }
    })
  }

  setup = () => {
    this.props.braintree.create({
      authorization: this.props.authorizationToken,
      container: '.braintree-dropin-react-form',
      locale: this.props.locale,
      paypal: this.props.paypal,
      paypalCredit: this.props.paypalCredit,
      paymentOptionPriority: this.props.paymentOptionPriority,
      card: this.props.card
    }, (err, dropinInstance) => {
      if (err) {
        if (this.props.onError) {
          this.props.onError(err)
        }
        return
      } else {
        if (this.props.onCreate) {
          this.props.onCreate(dropinInstance)
        }
      }

      if (dropinInstance.isPaymentMethodRequestable()) {
        this.setState({
          isSubmitButtonDisabled: false
        })
      }

      dropinInstance.on('paymentMethodRequestable', (event) => {
        this.setState({
          isSubmitButtonDisabled: false
        })
      })

      dropinInstance.on('noPaymentMethodRequestable', () => {
        this.setState({
          isSubmitButtonDisabled: true
        })
      })

      this.setState({
        dropInInstance: dropinInstance
      })
    })
  }

  tearDown = () => {
    if (this.props.onDestroyStart) {
      this.props.onDestroyStart()
    }
    return new Promise((resolve, reject) => {
      this.state.dropInInstance.teardown((err) => {
        if (this.props.onDestroyEnd) {
          this.props.onDestroyEnd(err)
        }
        if (err) {
          return reject(err)
        } else {
          return resolve()
        }
      })
    })
  }

  handleSubmit = (event) => {
    if (this.state.dropInInstance) {
      this.state.dropInInstance.requestPaymentMethod((err, payload) => {
        if (err) {
          if (this.props.onError) {
            this.props.onError(err)
          }
        } else {
          this.props.handlePaymentMethod(payload)
        }
      })
    }
  }

  render = () => {
    return (

          {this.props.renderSubmitButton({
            onClick: this.handleSubmit,
            isDisabled: this.state.isSubmitButtonDisabled,
            text: this.props.submitButtonText
          })}

    )
  }
}

BraintreeDropIn.propTypes = {
  braintree: PropTypes.object.isRequired,
  authorizationToken: PropTypes.string.isRequired,
  handlePaymentMethod: PropTypes.func.isRequired,
  onCreate: PropTypes.func,
  onError: PropTypes.func,
  onDestroyStart: PropTypes.func,
  onDestroyEnd: PropTypes.func,
  locale: PropTypes.string,
  paypal: PropTypes.object,
  paypalCredit: PropTypes.object,
  paymentOptionPriority: PropTypes.array,
  card: PropTypes.object,
  submitButtonText: PropTypes.string,
  className: PropTypes.string,
  renderSubmitButton: PropTypes.func
}

const renderSubmitButton = ({onClick, isDisabled, text}) => {
  return (
    <button
      onClick={onClick}
      disabled={isDisabled}
    >{text}</button>
  )
}

renderSubmitButton.propTypes = {
  onClick: PropTypes.func.isRequired,
  isDisabled: PropTypes.bool.isRequired,
  text: PropTypes.string.isRequired
}

BraintreeDropIn.defaultProps = {
  className: 'braintree-dropin-react',
  submitButtonText: 'Purchase',
  renderSubmitButton
}

export default BraintreeDropIn
<commit_msg>recreate drop-in on locale change<commit_after>import React from 'react'
import PropTypes from 'prop-types'

class BraintreeDropIn extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      dropInInstance: null,
      isSubmitButtonDisabled: true
    }
  }

  componentDidMount = () => {
    if (!this.props.braintree || this.state.dropInInstance) return
    this.setup()
  }

  componentDidUpdate = (prevProps, prevState) => {
    if (
      this.props.authorizationToken &&
      this.state.dropInInstance &&
      (prevProps.authorizationToken !== this.props.authorizationToken || prevProps.locale !== this.props.locale)
    ) {
      this.tearDown().then(() => {
        this.setState({
          dropInInstance: null,
          isSubmitButtonDisabled: true
        }, () => {
          this.setup()
        })
      }).catch((err) => {
        if (this.props.onError) {
          this.props.onError(err)
        }
      })
    }
  }

  componentWillUnmount = () => {
    if (!this.state.dropInInstance) return

    this.tearDown().catch((err) => {
      if (this.props.onError) {
        this.props.onError(err)
      }
    })
  }

  setup = () => {
    this.props.braintree.create({
      authorization: this.props.authorizationToken,
      container: '.braintree-dropin-react-form',
      locale: this.props.locale,
      paypal: this.props.paypal,
      paypalCredit: this.props.paypalCredit,
      paymentOptionPriority: this.props.paymentOptionPriority,
      card: this.props.card
    }, (err, dropinInstance) => {
      if (err) {
        if (this.props.onError) {
          this.props.onError(err)
        }
        return
      } else {
        if (this.props.onCreate) {
          this.props.onCreate(dropinInstance)
        }
      }

      if (dropinInstance.isPaymentMethodRequestable()) {
        this.setState({
          isSubmitButtonDisabled: false
        })
      }

      dropinInstance.on('paymentMethodRequestable', (event) => {
        this.setState({
          isSubmitButtonDisabled: false
        })
      })

      dropinInstance.on('noPaymentMethodRequestable', () => {
        this.setState({
          isSubmitButtonDisabled: true
        })
      })

      this.setState({
        dropInInstance: dropinInstance
      })
    })
  }

  tearDown = () => {
    if (this.props.onDestroyStart) {
      this.props.onDestroyStart()
    }
    return new Promise((resolve, reject) => {
      this.state.dropInInstance.teardown((err) => {
        if (this.props.onDestroyEnd) {
          this.props.onDestroyEnd(err)
        }
        if (err) {
          return reject(err)
        } else {
          return resolve()
        }
      })
    })
  }

  handleSubmit = (event) => {
    if (this.state.dropInInstance) {
      this.state.dropInInstance.requestPaymentMethod((err, payload) => {
        if (err) {
          if (this.props.onError) {
            this.props.onError(err)
          }
        } else {
          this.props.handlePaymentMethod(payload)
        }
      })
    }
  }

  render = () => {
    return (

          {this.props.renderSubmitButton({
            onClick: this.handleSubmit,
            isDisabled: this.state.isSubmitButtonDisabled,
            text: this.props.submitButtonText
          })}

    )
  }
}

BraintreeDropIn.propTypes = {
  braintree: PropTypes.object.isRequired,
  authorizationToken: PropTypes.string.isRequired,
  handlePaymentMethod: PropTypes.func.isRequired,
  onCreate: PropTypes.func,
  onError: PropTypes.func,
  onDestroyStart: PropTypes.func,
  onDestroyEnd: PropTypes.func,
  locale: PropTypes.string,
  paypal: PropTypes.object,
  paypalCredit: PropTypes.object,
  paymentOptionPriority: PropTypes.array,
  card: PropTypes.object,
  submitButtonText: PropTypes.string,
  className: PropTypes.string,
  renderSubmitButton: PropTypes.func
}

const renderSubmitButton = ({onClick, isDisabled, text}) => {
  return (
    <button
      onClick={onClick}
      disabled={isDisabled}
    >{text}</button>
  )
}

renderSubmitButton.propTypes = {
  onClick: PropTypes.func.isRequired,
  isDisabled: PropTypes.bool.isRequired,
  text: PropTypes.string.isRequired
}

BraintreeDropIn.defaultProps = {
  className: 'braintree-dropin-react',
  submitButtonText: 'Purchase',
  renderSubmitButton
}

export default BraintreeDropIn
<|endoftext|>


<commit_before>/* global bundle, $ */

var d3 = require("d3");

var COLOR_TABLE = [
  "#C8D2D9", "#97ABB8", "#FFBEB9", "#FFD1CE"
];

/* This is a poor-man's estimate, given the fact that measuring the
 * actual size of the characters (accounting for kerning) will involve
 * significant DOM mutation. */
var INDIVIDUAL_CHARACTER_SIZE = 7;

/**
 * calculateChartOffset

/**
 * updateGraph
 *
 * Update the graph with some new data and remove the old one.
 *
 * @newData: New tuples of data to update the graph with
 */
function updateGraph(newData) {
  var svg;
  var chartContainer = document.getElementsByClassName("chart")[0];

  /* The individual points of data, not including labels */
  var dataPoints = newData.map(function onEachDataPoint(w) {
    return w.value;
  });

  /* Estimated sizes of the labels and the bars if no scaling was appleid -
   * use this to determine whether an offset should be applied to the chart
   * based on the width of the smallest bar and its corresponding label. If
   * a bar's label size exceeds the size of the bar, we need to make
   * at least enough room on the left hand side for the bar label */
  var offsetAmount = 0;
  var postprocessedData = newData.map(function onEachDataPoint(d) {
    var availableParentWidth = chartContainer.clientWidth * 0.80;
    var x = d3.scaleLinear().domain([0, d3.max(dataPoints)])
                            .range([0, availableParentWidth]);
    var bar = x(d.value);
    var label = 10 + (INDIVIDUAL_CHARACTER_SIZE * d.name.length);
    var isOffset = false;

    if (label > bar) {
      isOffset = true;
      if (offsetAmount < label) {
        offsetAmount = label;
      }
    }

    return {
      name: d.name,
      value: d.value,
      isOffset: isOffset
    };
  });

  /* Drop any existing SVG elements */
  Array.prototype.forEach.call(document.getElementsByClassName("chart"),
                               function dropInnerHTMLOf(element) {
                                 /* Drop everything inside this chart */
                                 element.innerHTML = "";  // eslint-disable-line no-param-reassign
                               });

  svg = d3.select("div.chart")
          .append("svg")
          .attr("class", "svgchart")
          .attr("width", function computeWidth() {
            return this.parentNode.clientWidth * 0.80;
          })
          .attr("height", function computeHeight() {
            return this.parentNode.clientHeight * 0.80;
          })
          .attr("style", function computeTransform() {
            var x = this.parentNode.clientWidth * 0.10;
            var y = this.parentNode.clientHeight * 0.10;
            return ["transform: translate(", x, "px,", y, "px", ")"].join("");
          });

  postprocessedData.forEach(function forEachDataPoint(dataPoint, index) {
    var g = svg.append("g")
               .attr("transform", function computeBarY() {
                 var chartHeight = this.parentNode.clientHeight;
                 var barSpacing = 10;
                 var barHeight = ((chartHeight - (barSpacing *
                                                  postprocessedData.length)) /
                                  postprocessedData.length);

                 var y = (index * barSpacing) + (index * barHeight);
                 return "translate(0.0, " + y + ")";
               });
    g.append("rect")
     .attr("height", function computeBarHeight() {
       var chartHeight = this.parentNode.parentNode.clientHeight;
       var barSpacing = 10;
       return ((chartHeight - (barSpacing * postprocessedData.length)) /
               postprocessedData.length);
     })
     .transition()
     .delay(index * 50)
     .duration(750)
     .ease(d3.easeElastic.period(0.4))
     .attr("width", function computeBarWidth() {
       var parentWidth = (this.parentNode.parentNode.clientWidth -
                          offsetAmount);
       var x = d3.scaleLinear().domain([0, d3.max(dataPoints)])
                               .range([0, parentWidth]);
       return x(dataPoint.value);
     })
     .attr("rx", "15")
     .attr("ry", "15")
     .attr("x", String(offsetAmount))
     .attr("fill", COLOR_TABLE[index % COLOR_TABLE.length]);
    g.append("text")
     .attr("fill", dataPoint.isOffset ? "#000000" : "#ffffff")
     .text(dataPoint.name)
     .attr("y", function computeY() {
       var chartHeight = this.parentNode.parentNode.clientHeight;
       var barSpacing = 10;
       var textHeight = 15;
       return (((chartHeight - (barSpacing * postprocessedData.length)) /
               postprocessedData.length) / 2) + (textHeight / 2);
     })
     .attr("x", dataPoint.isOffset ? 10 : 10 + offsetAmount);
  });
}

/**
 * postGraphUpdateRequest
 *
 * Post a request to the server to get a new graph.
 *
 * @name The chart name to fetch.
 */
function postGraphUpdateRequest(name) {
  $.ajax({
    url: "/get_bar_chart",
    data: {
      name: name
    },
    success: function onXHRSuccess(data) {
      updateGraph(data.data);
    }
  });
}

document.addEventListener("DOMContentLoaded", function onDOMLoaded() {
  $("#chartSelectionDropdown ul li a").click(function onDropdownClick(event) {
    var div = $(this).parent().parent().parent();
    var button = div.find("button");

    button.html(this.text + " ");
    div.removeClass("open");
    event.preventDefault();

    postGraphUpdateRequest($(this).attr("data-selection-id"));
    return false;
  });
});
<commit_msg>retraction: Display a number on the end of every bar indicating what it is<commit_after>/* global bundle, $ */

var d3 = require("d3");

var COLOR_TABLE = [
  "#C8D2D9", "#97ABB8", "#FFBEB9", "#FFD1CE"
];

/* This is a poor-man's estimate, given the fact that measuring the
 * actual size of the characters (accounting for kerning) will involve
 * significant DOM mutation. */
var INDIVIDUAL_CHARACTER_SIZE = 10;

/**
 * calculateChartOffset

/**
 * updateGraph
 *
 * Update the graph with some new data and remove the old one.
 *
 * @newData: New tuples of data to update the graph with
 */
function updateGraph(newData) {
  var svg;
  var chartContainer = document.getElementsByClassName("chart")[0];

  /* The individual points of data, not including labels */
  var dataPoints = newData.map(function onEachDataPoint(w) {
    return w.value;
  });

  /* Estimated sizes of the labels and the bars if no scaling was appleid -
   * use this to determine whether an offset should be applied to the chart
   * based on the width of the smallest bar and its corresponding label. If
   * a bar's label size exceeds the size of the bar, we need to make
   * at least enough room on the left hand side for the bar label */
  var offsetAmount = 0;
  var postprocessedData = newData.map(function onEachDataPoint(d) {
    var availableParentWidth = chartContainer.clientWidth * 0.80;
    var x = d3.scaleLinear().domain([0, d3.max(dataPoints)])
                            .range([0, availableParentWidth]);
    var bar = x(d.value);
    var label = 10 + (INDIVIDUAL_CHARACTER_SIZE * d.name.length);
    var isOffset = false;

    if (label > bar) {
      isOffset = true;
      if (offsetAmount < label) {
        offsetAmount = label;
      }
    }

    return {
      name: d.name,
      value: d.value,
      isOffset: isOffset
    };
  });

  /* Drop any existing SVG elements */
  Array.prototype.forEach.call(document.getElementsByClassName("chart"),
                               function dropInnerHTMLOf(element) {
                                 /* Drop everything inside this chart */
                                 element.innerHTML = "";  // eslint-disable-line no-param-reassign
                               });

  svg = d3.select("div.chart")
          .append("svg")
          .attr("class", "svgchart")
          .attr("width", function computeWidth() {
            return this.parentNode.clientWidth * 0.80;
          })
          .attr("height", function computeHeight() {
            return this.parentNode.clientHeight * 0.80;
          })
          .attr("style", function computeTransform() {
            var x = this.parentNode.clientWidth * 0.10;
            var y = this.parentNode.clientHeight * 0.10;
            return ["transform: translate(", x, "px,", y, "px", ")"].join("");
          });

  postprocessedData.forEach(function forEachDataPoint(dataPoint, index) {
    var computeTextY = function computeTextY() {
      var chartHeight = this.parentNode.parentNode.clientHeight;
      var barSpacing = 10;
      var textHeight = 15;
      return (((chartHeight - (barSpacing * postprocessedData.length)) /
              postprocessedData.length) / 2) + (textHeight / 2);
    };
    var computeBarWidth = function computeBarWidth() {
      var parentWidth = (this.parentNode.parentNode.clientWidth -
                         offsetAmount);
      var x = d3.scaleLinear().domain([0, d3.max(dataPoints)])
                              .range([0, parentWidth]);
      return x(dataPoint.value);
    };
    var g = svg.append("g")
               .attr("transform", function computeBarY() {
                 var chartHeight = this.parentNode.clientHeight;
                 var barSpacing = 10;
                 var barHeight = ((chartHeight - (barSpacing *
                                                  postprocessedData.length)) /
                                  postprocessedData.length);

                 var y = (index * barSpacing) + (index * barHeight);
                 return "translate(0.0, " + y + ")";
               });
    g.append("rect")
     .attr("height", function computeBarHeight() {
       var chartHeight = this.parentNode.parentNode.clientHeight;
       var barSpacing = 10;
       return ((chartHeight - (barSpacing * postprocessedData.length)) /
               postprocessedData.length);
     })
     .transition()
     .delay(index * 50)
     .duration(750)
     .ease(d3.easeElastic.period(0.4))
     .attr("width", computeBarWidth)
     .attr("rx", "15")
     .attr("ry", "15")
     .attr("x", String(offsetAmount))
     .attr("fill", COLOR_TABLE[index % COLOR_TABLE.length]);
    g.append("text")
     .attr("fill", dataPoint.isOffset ? "#000000" : "#ffffff")
     .text(dataPoint.name)
     .attr("y", computeTextY)
     .attr("x", dataPoint.isOffset ? 10 : 10 + offsetAmount);
    g.append("text")
     .attr("fill", "#ffffff")
     .text(dataPoint.value)
     .attr("y", computeTextY)
     .transition()
     .delay(index * 50)
     .duration(750)
     .ease(d3.easeElastic.period(0.4))
     .attr("x", function computeNumberX() {
       var barWidth = computeBarWidth.call(this);
       var label = String(dataPoint.value);
       var labelSize = label.length * INDIVIDUAL_CHARACTER_SIZE;
       return (barWidth - labelSize) + offsetAmount;
     });
  });
}

/**
 * postGraphUpdateRequest
 *
 * Post a request to the server to get a new graph.
 *
 * @name The chart name to fetch.
 */
function postGraphUpdateRequest(name) {
  $.ajax({
    url: "/get_bar_chart",
    data: {
      name: name
    },
    success: function onXHRSuccess(data) {
      updateGraph(data.data);
    }
  });
}

document.addEventListener("DOMContentLoaded", function onDOMLoaded() {
  $("#chartSelectionDropdown ul li a").click(function onDropdownClick(event) {
    var div = $(this).parent().parent().parent();
    var button = div.find("button");

    button.html(this.text + " ");
    div.removeClass("open");
    event.preventDefault();

    postGraphUpdateRequest($(this).attr("data-selection-id"));
    return false;
  });
});
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import PropTypes from 'prop-types'
import {View, StyleSheet, Animated} from 'react-native';

import Expo, { Svg } from 'expo';
const AnimatedSvg = Animated.createAnimatedComponent(Svg);
const {interpolate} = require('d3-interpolate');

export default class SvgAnimatedLinearGradient extends Component {
    constructor(props) {
        super(props);

        this.state = {
            offsetValues: [
                '-2', '-1.5', '-1'
            ],
            offsets: [
                '0', '0', '0'
            ],
            frequence: props.duration / 2
        }
        this._animate = new Animated.Value(0)
        this.loopAnimation = this
            .loopAnimation
            .bind(this)
    }
    offsetValueBound(x) {
        if (x > 1) {
            return '1'
        }
        if (x < 0) {
            return '0'
        }
        return x
    }
    componentDidMount(props) {
        this.loopAnimation()
    }

    loopAnimation() {

        // setup interpolate
        let interpolator = interpolate(this.state, {
            offsetValues: ['1', '1.5', '2']
        });

        // start animation
        let start = Date.now();
        this._animation = () => {
            const now = Date.now();
            let t = (now - start) / this.props.duration;
            if (t > 1) {
                t = 1
            }

            let newState = interpolator(t);
            let offsetValues = [];
            offsetValues[0] = this.offsetValueBound(newState.offsetValues[0]);
            offsetValues[1] = this.offsetValueBound(newState.offsetValues[1]);
            offsetValues[2] = this.offsetValueBound(newState.offsetValues[2]);
            this.setState({offsets: offsetValues});
            if (t < 1) {
                requestAnimationFrame(this._animation);
            }
        }
        requestAnimationFrame(this._animation);

        // Setup loop animation
        Animated.sequence([
            Animated.timing(this._animate, {
                toValue: 1,
                duration: this.state.frequence
            }),
            Animated.timing(this._animate, {
                toValue: 0,
                duration: this.state.frequence
            })
        ]).start((event) => {
            if (event.finished) {
                this.loopAnimation()
            }
        })
    }
    render() {

        return (
            <AnimatedSvg height={this.props.height} width={this.props.width}>
                <Svg.Defs>
                    <Svg.LinearGradient id="grad" x1={this.props.x1} y1={this.props.y1} x2={this.props.x2} y2={this.props.y2}>
                        <Svg.Stop
                            offset={this.state.offsets[0]}
                            stopColor={this.props.primaryColor}
                            stopOpacity="1"/>
                        <Svg.Stop
                            offset={this.state.offsets[1]}
                            stopColor={this.props.secondaryColor}
                            stopOpacity="1"/>
                        <Svg.Stop
                            offset={this.state.offsets[2]}
                            stopColor={this.props.primaryColor}
                            stopOpacity="1"/>
                    </Svg.LinearGradient>
                    <Svg.ClipPath id="clip">
                        <Svg.G>
                            {this.props.children}
                        </Svg.G>
                    </Svg.ClipPath>
                </Svg.Defs>

                <Svg.Rect
                    x="0"
                    y="0"
                    height={this.props.height}
                    width={this.props.width}
                    fill="url(#grad)"
                    clipPath="url(#clip)"/>
            </AnimatedSvg>
        );
    }
}
SvgAnimatedLinearGradient.propTypes = {
    primaryColor: PropTypes.string,
    secondaryColor: PropTypes.string,
    duration: PropTypes.number,
    width: PropTypes.number,
    height: PropTypes.number,
    x1: PropTypes.string,
    y1: PropTypes.string,
    x2: PropTypes.string,
    y2: PropTypes.string,
}
SvgAnimatedLinearGradient.defaultProps = {
    primaryColor: '#eeeeee',
    secondaryColor: '#dddddd',
    duration: 2000,
    width: 300,
    height: 200,
    x1: '0',
    y1: '0',
    x2: '100%',
    y2: '0'

}
<commit_msg>Check if mounted before continuing loop<commit_after>import React, {Component} from 'react';
import PropTypes from 'prop-types'
import {View, StyleSheet, Animated} from 'react-native';

import Expo, { Svg } from 'expo';
const AnimatedSvg = Animated.createAnimatedComponent(Svg);
const {interpolate} = require('d3-interpolate');

export default class SvgAnimatedLinearGradient extends Component {
    constructor(props) {
        super(props);

        this.state = {
            offsetValues: [
                '-2', '-1.5', '-1'
            ],
            offsets: [
                '0', '0', '0'
            ],
            frequence: props.duration / 2
        }
        this._isMounted = false;
        this._animate = new Animated.Value(0)
        this.loopAnimation = this
            .loopAnimation
            .bind(this)
    }
    offsetValueBound(x) {
        if (x > 1) {
            return '1'
        }
        if (x < 0) {
            return '0'
        }
        return x
    }
    componentDidMount(props) {
        this._isMounted = true
        this.loopAnimation()
    }
    componentWillUnmount() {
        this._isMounted = false
    }
    loopAnimation() {
        if (!this._isMounted) return;
        // setup interpolate
        let interpolator = interpolate(this.state, {
            offsetValues: ['1', '1.5', '2']
        });

        // start animation
        let start = Date.now();
        this._animation = () => {
            const now = Date.now();
            let t = (now - start) / this.props.duration;
            if (t > 1) {
                t = 1
            }

            let newState = interpolator(t);
            let offsetValues = [];
            offsetValues[0] = this.offsetValueBound(newState.offsetValues[0]);
            offsetValues[1] = this.offsetValueBound(newState.offsetValues[1]);
            offsetValues[2] = this.offsetValueBound(newState.offsetValues[2]);
            this.setState({offsets: offsetValues});
            if (t < 1) {
                requestAnimationFrame(this._animation);
            }
        }
        requestAnimationFrame(this._animation);

        // Setup loop animation
        Animated.sequence([
            Animated.timing(this._animate, {
                toValue: 1,
                duration: this.state.frequence
            }),
            Animated.timing(this._animate, {
                toValue: 0,
                duration: this.state.frequence
            })
        ]).start((event) => {
            if (event.finished) {
                this.loopAnimation()
            }
        })
    }
    render() {

        return (
            <AnimatedSvg height={this.props.height} width={this.props.width}>
                <Svg.Defs>
                    <Svg.LinearGradient id="grad" x1={this.props.x1} y1={this.props.y1} x2={this.props.x2} y2={this.props.y2}>
                        <Svg.Stop
                            offset={this.state.offsets[0]}
                            stopColor={this.props.primaryColor}
                            stopOpacity="1"/>
                        <Svg.Stop
                            offset={this.state.offsets[1]}
                            stopColor={this.props.secondaryColor}
                            stopOpacity="1"/>
                        <Svg.Stop
                            offset={this.state.offsets[2]}
                            stopColor={this.props.primaryColor}
                            stopOpacity="1"/>
                    </Svg.LinearGradient>
                    <Svg.ClipPath id="clip">
                        <Svg.G>
                            {this.props.children}
                        </Svg.G>
                    </Svg.ClipPath>
                </Svg.Defs>

                <Svg.Rect
                    x="0"
                    y="0"
                    height={this.props.height}
                    width={this.props.width}
                    fill="url(#grad)"
                    clipPath="url(#clip)"/>
            </AnimatedSvg>
        );
    }
}
SvgAnimatedLinearGradient.propTypes = {
    primaryColor: PropTypes.string,
    secondaryColor: PropTypes.string,
    duration: PropTypes.number,
    width: PropTypes.number,
    height: PropTypes.number,
    x1: PropTypes.string,
    y1: PropTypes.string,
    x2: PropTypes.string,
    y2: PropTypes.string,
}
SvgAnimatedLinearGradient.defaultProps = {
    primaryColor: '#eeeeee',
    secondaryColor: '#dddddd',
    duration: 2000,
    width: 300,
    height: 200,
    x1: '0',
    y1: '0',
    x2: '100%',
    y2: '0'

}
<|endoftext|>


<commit_before>(function($){
    $.fn.paulund_modal_box = function(prop){

      var options = $.extend({
        height : "250",
        width : "500",
        top: "20%",
        left: "30%",
      },prop);

      return this.click(function(e){
        add_block_page();
        add_popup_box();
        add_styles();

        $('.paulund_modal_box').fadeIn();
      });

       function add_styles(){
        $('.paulund_modal_box').css({
          'position':'absolute',
          'left':options.left,
          'top':options.top,
          'display':'none',
          'height': options.height + 'px',
          'width': options.width + 'px',
          'border':'1px solid #fff',
          'box-shadow': '0px 2px 7px #292929',
          '-moz-box-shadow': '0px 2px 7px #292929',
          '-webkit-box-shadow': '0px 2px 7px #292929',
          'border-radius':'10px',
          '-moz-border-radius':'10px',
          '-webkit-border-radius':'10px',
          'background': '#f2f2f2',
          'z-index':'50',
        });
        $('.paulund_modal_close').css({
          'position':'relative',
          'top':'-25px',
          'left':'20px',
          'float':'right',
          'display':'block',
          'height':'50px',
          'width':'50px',
          'background': 'url(images/close.png) no-repeat',
        });

        var pageHeight = $(document).height();
        var pageWidth = $(window).width();

        $('.paulund_block_page').css({
          'position':'absolute',
          'top':'0',
          'left':'0',
          'background-color':'rgba(0,0,0,0.6)',
          'height':pageHeight,
          'width':pageWidth,
          'z-index':'10'
        });
        $('.paulund_inner_modal_box').css({
          'background-color':'#fff',
          'height':(options.height - 50) + 'px',
          'width':(options.width - 50) + 'px',
          'padding':'10px',
          'margin':'15px',
          'border-radius':'10px',
          '-moz-border-radius':'10px',
          '-webkit-border-radius':'10px'
        });
      }

       function add_block_page(){
        var block_page = $('

');

        $(block_page).appendTo('.container');
      }

       function add_popup_box(){
         var pop_up = template.addModal();
         $(pop_up).appendTo('.paulund_block_page');
         $('#modal_content').focus();
         controller.wordCount();

         $('.paulund_modal_close').click(function(){
          $(this).parent().fadeOut().remove();
          $('.paulund_block_page').fadeOut().remove();
         });
      }

      return this;
    };

})(jQuery);

// $(document).ready(function(){
//   $('.paulund_modal').paulund_modal_box();
// });
<commit_msg>JAYME IS A FUCKING WIZARD<commit_after>(function($){
    $.fn.paulund_modal_box = function(prop){

      var options = $.extend({
        height : "250",
        width : "500",
        top: "20%",
        left: "30%",
      },prop);

      return this.click(function(e){
        add_block_page();
        add_popup_box();
        add_styles();

        $('.paulund_modal_box').fadeIn();
      });

       function add_styles(){
        $('.paulund_modal_box').css({
          'position':'absolute',
          'left':options.left,
          'top':options.top,
          'display':'none',
          'height': options.height + 'px',
          'width': options.width + 'px',
          'border':'1px solid #fff',
          'box-shadow': '0px 2px 7px #292929',
          '-moz-box-shadow': '0px 2px 7px #292929',
          '-webkit-box-shadow': '0px 2px 7px #292929',
          'border-radius':'10px',
          '-moz-border-radius':'10px',
          '-webkit-border-radius':'10px',
          'background': '#f2f2f2',
          'z-index':'50',
        });
        $('.paulund_modal_close').css({
          'position':'relative',
          'top':'-25px',
          'left':'20px',
          'float':'right',
          'display':'block',
          'height':'50px',
          'width':'50px',
          'background': 'url(images/close.png) no-repeat',
        });

        var pageHeight = $(document).height();
        var pageWidth = $(window).width();

        $('.paulund_block_page').css({
          'position':'absolute',
          'top':'0',
          'left':'0',
          'background-color':'rgba(0,0,0,0.6)',
          'height':pageHeight,
          'width':pageWidth,
          'z-index':'10'
        });
        $('.paulund_inner_modal_box').css({
          'background-color':'#fff',
          'height':(options.height - 50) + 'px',
          'width':(options.width - 50) + 'px',
          'padding':'10px',
          'margin':'15px',
          'border-radius':'10px',
          '-moz-border-radius':'10px',
          '-webkit-border-radius':'10px'
        });
      }

       function add_block_page(){
        var block_page = $('

');

        $(block_page).appendTo('body');
      }

       function add_popup_box(){
         var pop_up = template.addModal();
         $(pop_up).appendTo('.paulund_block_page');
         $('#modal_content').focus();
         controller.wordCount();

         $('.paulund_modal_close').click(function(){
          $(this).parent().fadeOut().remove();
          $('.paulund_block_page').fadeOut().remove();
         });
      }

      return this;
    };

})(jQuery);

// $(document).ready(function(){
//   $('.paulund_modal').paulund_modal_box();
// });
<|endoftext|>


<commit_before>'use strict';
const fetch = require('node-fetch');
const fs = require('fs');
const path = require('path');
const xhrProxy = fs.readFileSync(path.resolve(__dirname, './script/xhr-proxy.js'), {
    encoding: 'utf8'
}).replace(`'use strict';`, '');
const utils = require('./utils');
const COOKIE_KEY = 'forward_html';
const emptyFunc = x => x;
module.exports = function forward({
    router,
    prefix = '/__forward',
    filterHtml = emptyFunc,
    filterCookie = emptyFunc,
    filterJs = emptyFunc
} = {}) {
    const bindRouter = function(router) {
        if (router && router.all) {
            router.get(`${prefix}/html`, forwardHtml(prefix, filterHtml));
            router.all(`${prefix}/ajax/*`, forwardAjax(prefix, filterCookie));
            router.get(`${prefix}/js`, forwardJs(prefix, filterCookie, filterJs));
        }
    }
    if (router) {
        bindRouter(router);
    } else {
        return function(req, res, next) {
            bindRouter(req.app);
            next();
        };
    }
}

function forwardHtml(prefix, filterHtml) {
    return function(req, res, next) {
        let url = req.query.url;
        let options = {
            credentials: 'include',
            headers: {
                'Connection': 'keep-alive',
                'Pragma': 'no-cache',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36'
            }
        };
        let platform = req.query.m;
        let mobile = (platform === 'H5' ? true : false);
        if (mobile || (/\/\/m\./.test(url) && !mobile)) {
            if (mobile) {
                options.headers['User-Agent'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1';
            }
            options.redirect = 'manual';
            // 先请求一次，探查真实地址
            fetchProcess().then(function(result) {
                let relocation;
                if ((relocation = result.headers._headers) && (relocation = relocation.location) && (relocation = relocation[0]) && (relocation !== url)) {
                    url = relocation;
                    if (!mobile) {
                        platform = 'PC';
                    }
                    options.redirect = 'follow';
                    fetchProcess().then((result) => postProcess(result))
                } else {
                    postProcess(result);
                }
            });
        } else {
            fetchProcess().then((result) => postProcess(result))
        }

        function fetchProcess() {
            return fetch(encodeURI(url), options);
        }

        function postProcess(result) {
            let rawcookie = result.headers;
            if ((rawcookie = rawcookie._headers) && (rawcookie = rawcookie['set-cookie'])) {
                res.append('Set-Cookie', rawcookie);
            }
            return Promise.resolve(result.text()).then(function(html) {
                return processHtml(html);
            }).catch(err => handleError(err, res));
        }

        function processHtml(html) {
            // const id = Date.now() + Math.floor(Math.random() * 10000);
            let origin = url.replace(/\/[^\/]*?$/, '');
            let host = utils.getHost(origin);
            let time = new Date();
            time.setTime(Date.now() + 86400000);
            res.append('Set-Cookie', `${COOKIE_KEY}=${url};expires=${time.toUTCString()}`);
            // 添加自定义脚本
            let proxytext = `<script>(${xhrProxy}('${url}', '${platform}', '${origin}', '${prefix}'))</script>`;
            res.append('Content-Type', 'text/html; charset=utf-8');
            res.end(filterHtml(html)
                .replace('<head>', '<head>' + proxytext)
                .replace(/(href|src)\s*=\s*"\s*((?!http|\/\/|javascript)[^"\s]+?)\s*"/g, function(m, p1, p2) {
                    if (p2.indexOf('.') === 0) {
                        return `${p1}="${origin}/${p2}"`;
                    } else if (p2.indexOf('/') === 0) {
                        return `${p1}="${host}${p2}"`;
                    } else {
                        return `${p1}="${host}/${p2}"`;
                    }
                })
            );
        }
    }
}

function forwardAjax(prefix, filterCookie) {
    return function(req, res, next) {
        let htmlurl = utils.getCookie(req.headers.cookie, COOKIE_KEY);
        let {
            method,
            url,
            query,
            body,
            headers
        } = req;
        let host = utils.getHost(htmlurl) || url;
        let newurl = url.replace(`${prefix}/ajax`, host);
        headers.origin && (delete headers.origin);
        let newheaders = Object.assign(headers, {
            'cookie': filterCookie(headers.cookie),
            'host': host.replace(/https?:\/\//, ''),
            'referer': encodeURI(htmlurl)
        });
        if (body) {
            for (let key in body) {
                let oldval = body[key]
                body[key] = encodeURI(oldval);
            }
            if (newheaders['content-type'] && newheaders['content-type'].indexOf('x-www-form-urlencoded') > -1) {
                let qstr = '';
                for (let key in body) {
                    qstr += `${key}=${body[key]}&`
                }
                body = qstr.slice(0, -1);
            } else {
                body = JSON.stringify(body);
            }
        }
        let option = {
            method,
            headers: newheaders,
            body,
            credentials: 'include'
        };
        fetch(newurl, option)
            .then(function(result) {
                return result.text();
            }).then(function(json) {
                res.send(json);
            }).catch(err => handleError(err, res));
    }
}

function forwardJs(prefix, filterCookie, filterJs) {
    return function(req, res, next) {
        let {
            query
        } = req;
        let method = 'get';
        let newurl = query.url;
        let host = newurl.match(/https?:\/\/(.+?)\//)[1];
        let newheaders = {
            host
        }
        fetch(newurl, {
                method,
                headers: newheaders,
                cookie: filterCookie(headers.cookie),
                credentials: 'include'
            })
            .then(function(result) {
                return result.text();
            }).then(function(js) {
                res.send(filterJs(js));
            }).catch(err => handleError(err, res));
    }
}

function handleError(e, res) {
    console.log(e);
    res.end(e.toString());
    // next(e);
}
<commit_msg>change api<commit_after>'use strict';
const fetch = require('node-fetch');
const fs = require('fs');
const path = require('path');
const xhrProxy = fs.readFileSync(path.resolve(__dirname, './script/xhr-proxy.js'), {
    encoding: 'utf8'
}).replace(`'use strict';`, '');
const utils = require('./utils');
const COOKIE_KEY = 'forward_html';
const emptyFunc = x => x;
module.exports = function forward({
    prefix = '/__forward',
    filterHtml = emptyFunc,
    filterCookie = emptyFunc,
    filterJs = emptyFunc
} = {}) {
    return function(router) {
        if (router && router.all) {
            router.get(`${prefix}/html`, forwardHtml(prefix, filterHtml));
            router.all(`${prefix}/ajax/*`, forwardAjax(prefix, filterCookie));
            router.get(`${prefix}/js`, forwardJs(prefix, filterCookie, filterJs));
        } else {
            throw new TypeError('The param is not express instance or router!');
        }
    }
}

function forwardHtml(prefix, filterHtml) {
    return function(req, res, next) {
        let url = req.query.url;
        let options = {
            credentials: 'include',
            headers: {
                'Connection': 'keep-alive',
                'Pragma': 'no-cache',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36'
            }
        };
        let platform = req.query.m;
        let mobile = (platform === 'H5' ? true : false);
        if (mobile || (/\/\/m\./.test(url) && !mobile)) {
            if (mobile) {
                options.headers['User-Agent'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1';
            }
            options.redirect = 'manual';
            // 先请求一次，探查真实地址
            fetchProcess().then(function(result) {
                let relocation;
                if ((relocation = result.headers._headers) && (relocation = relocation.location) && (relocation = relocation[0]) && (relocation !== url)) {
                    url = relocation;
                    if (!mobile) {
                        platform = 'PC';
                    }
                    options.redirect = 'follow';
                    fetchProcess().then((result) => postProcess(result))
                } else {
                    postProcess(result);
                }
            });
        } else {
            fetchProcess().then((result) => postProcess(result))
        }

        function fetchProcess() {
            return fetch(encodeURI(url), options);
        }

        function postProcess(result) {
            let rawcookie = result.headers;
            if ((rawcookie = rawcookie._headers) && (rawcookie = rawcookie['set-cookie'])) {
                res.append('Set-Cookie', rawcookie);
            }
            return Promise.resolve(result.text()).then(function(html) {
                return processHtml(html);
            }).catch(err => handleError(err, res));
        }

        function processHtml(html) {
            // const id = Date.now() + Math.floor(Math.random() * 10000);
            let origin = url.replace(/\/[^\/]*?$/, '');
            let host = utils.getHost(origin);
            let time = new Date();
            time.setTime(Date.now() + 86400000);
            res.append('Set-Cookie', `${COOKIE_KEY}=${url};expires=${time.toUTCString()}`);
            // 添加自定义脚本
            let proxytext = `<script>(${xhrProxy}('${url}', '${platform}', '${origin}', '${prefix}'))</script>`;
            res.append('Content-Type', 'text/html; charset=utf-8');
            res.end(filterHtml(html)
                .replace('<head>', '<head>' + proxytext)
                .replace(/(href|src)\s*=\s*"\s*((?!http|\/\/|javascript)[^"\s]+?)\s*"/g, function(m, p1, p2) {
                    if (p2.indexOf('.') === 0) {
                        return `${p1}="${origin}/${p2}"`;
                    } else if (p2.indexOf('/') === 0) {
                        return `${p1}="${host}${p2}"`;
                    } else {
                        return `${p1}="${host}/${p2}"`;
                    }
                })
            );
        }
    }
}

function forwardAjax(prefix, filterCookie) {
    return function(req, res, next) {
        let htmlurl = utils.getCookie(req.headers.cookie, COOKIE_KEY);
        let {
            method,
            url,
            query,
            body,
            headers
        } = req;
        let host = utils.getHost(htmlurl) || url;
        let newurl = url.replace(`${prefix}/ajax`, host);
        headers.origin && (delete headers.origin);
        let newheaders = Object.assign(headers, {
            'cookie': filterCookie(headers.cookie),
            'host': host.replace(/https?:\/\//, ''),
            'referer': encodeURI(htmlurl)
        });
        if (body) {
            for (let key in body) {
                let oldval = body[key]
                body[key] = encodeURI(oldval);
            }
            if (newheaders['content-type'] && newheaders['content-type'].indexOf('x-www-form-urlencoded') > -1) {
                let qstr = '';
                for (let key in body) {
                    qstr += `${key}=${body[key]}&`
                }
                body = qstr.slice(0, -1);
            } else {
                body = JSON.stringify(body);
            }
        }
        let option = {
            method,
            headers: newheaders,
            body,
            credentials: 'include'
        };
        fetch(newurl, option)
            .then(function(result) {
                return result.text();
            }).then(function(json) {
                res.send(json);
            }).catch(err => handleError(err, res));
    }
}

function forwardJs(prefix, filterCookie, filterJs) {
    return function(req, res, next) {
        let {
            query
        } = req;
        let method = 'get';
        let newurl = query.url;
        let host = newurl.match(/https?:\/\/(.+?)\//)[1];
        let newheaders = {
            host
        }
        fetch(newurl, {
                method,
                headers: newheaders,
                cookie: filterCookie(headers.cookie),
                credentials: 'include'
            })
            .then(function(result) {
                return result.text();
            }).then(function(js) {
                res.send(filterJs(js));
            }).catch(err => handleError(err, res));
    }
}

function handleError(e, res) {
    console.log(e);
    res.end(e.toString());
    // next(e);
}
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import matchMedia from 'matchmediaquery'
import hyphenate  from 'hyphenate-style-name'
import mediaQuery from './mediaQuery'
import toQuery  from './toQuery'

const defaultTypes = {
  component: PropTypes.node,
  query: PropTypes.string,
  values: PropTypes.shape(mediaQuery.matchers),
  children: PropTypes.oneOfType([ PropTypes.node, PropTypes.func ]),
  onChange: PropTypes.func,
  onBeforeChange: PropTypes.func
}
const mediaKeys = Object.keys(mediaQuery.all)
const excludedQueryKeys = Object.keys(defaultTypes)
const excludedPropKeys = excludedQueryKeys.concat(mediaKeys)

function omit(object, keys) {
  const newObject = { ...object }
  keys.forEach(key => delete newObject[key])
  return newObject
}

class MediaQuery extends React.Component {
  static displayName = 'MediaQuery'
  static defaultProps = {
    values: {}
  }

  state = { matches: false }

  componentWillMount() {
    this.updateQuery(this.props)
  }

  componentWillReceiveProps(nextProps) {
    this.updateQuery(nextProps)
  }

  updateQuery(props) {
    let values
    if (props.query) {
      this.query = props.query
    } else {
      this.query = toQuery(omit(props, excludedQueryKeys))
    }

    if (!this.query) {
      throw new Error('Invalid or missing MediaQuery!')
    }

    if (props.values) {
      values = Object.keys(props.values)
        .reduce(function (result, key) {
          result[hyphenate(key)] = props.values[key]
          return result
        }, {})
    }

    this.removeMql()

    this._mql = matchMedia(this.query, values)
    this._mql.addListener(this.updateMatches)
    this.updateMatches()
  }

  componentWillUpdate(_, nextState) {
    if(this.props.onBeforeChange && this.state.matches !== nextState.matches) {
      this.props.onBeforeChange(this.state.matches)
    }
  }

  componentDidUpdate(_, prevState) {
    if(this.props.onChange && prevState.matches !== this.state.matches) {
      this.props.onChange(this.state.matches)
    }
  }

  componentWillUnmount() {
    this.removeMql()
  }

  updateMatches = () => {
    if (this._mql.matches === this.state.matches) {
      return
    }
    this.setState({
      matches: this._mql.matches
    })
  }

  removeMql = () => {
    if (this._mql) {
      this._mql.removeListener(this.updateMatches)
      this._mql.dispose()
    }
  }

  render() {
    if(typeof this.props.children === 'function') {
      return this.props.children(this.state.matches)
    }

    if (this.state.matches === false) {
      return null
    }
    const props = omit(this.props, excludedPropKeys)
    const hasMergeProps = Object.keys(props).length > 0
    const childrenCount = React.Children.count(this.props.children)
    const wrapChildren = this.props.component ||
      childrenCount > 1 ||
      typeof this.props.children === 'string' ||
      Array.isArray(this.props.children) && childrenCount == 1 ||
      this.props.children === undefined
    if (wrapChildren) {
      return React.createElement(
        this.props.component || 'div',
        props,
        this.props.children
      )
    } else if (hasMergeProps) {
      return React.cloneElement(
        this.props.children,
        props
      )
    } else if (childrenCount) {
      return this.props.children
    }
    else {
      return null
    }
  }
}

export {
  MediaQuery as default,
  toQuery
};

<commit_msg>Lint (remove semicolon)<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import matchMedia from 'matchmediaquery'
import hyphenate  from 'hyphenate-style-name'
import mediaQuery from './mediaQuery'
import toQuery  from './toQuery'

const defaultTypes = {
  component: PropTypes.node,
  query: PropTypes.string,
  values: PropTypes.shape(mediaQuery.matchers),
  children: PropTypes.oneOfType([ PropTypes.node, PropTypes.func ]),
  onChange: PropTypes.func,
  onBeforeChange: PropTypes.func
}
const mediaKeys = Object.keys(mediaQuery.all)
const excludedQueryKeys = Object.keys(defaultTypes)
const excludedPropKeys = excludedQueryKeys.concat(mediaKeys)

function omit(object, keys) {
  const newObject = { ...object }
  keys.forEach(key => delete newObject[key])
  return newObject
}

class MediaQuery extends React.Component {
  static displayName = 'MediaQuery'
  static defaultProps = {
    values: {}
  }

  state = { matches: false }

  componentWillMount() {
    this.updateQuery(this.props)
  }

  componentWillReceiveProps(nextProps) {
    this.updateQuery(nextProps)
  }

  updateQuery(props) {
    let values
    if (props.query) {
      this.query = props.query
    } else {
      this.query = toQuery(omit(props, excludedQueryKeys))
    }

    if (!this.query) {
      throw new Error('Invalid or missing MediaQuery!')
    }

    if (props.values) {
      values = Object.keys(props.values)
        .reduce(function (result, key) {
          result[hyphenate(key)] = props.values[key]
          return result
        }, {})
    }

    this.removeMql()

    this._mql = matchMedia(this.query, values)
    this._mql.addListener(this.updateMatches)
    this.updateMatches()
  }

  componentWillUpdate(_, nextState) {
    if(this.props.onBeforeChange && this.state.matches !== nextState.matches) {
      this.props.onBeforeChange(this.state.matches)
    }
  }

  componentDidUpdate(_, prevState) {
    if(this.props.onChange && prevState.matches !== this.state.matches) {
      this.props.onChange(this.state.matches)
    }
  }

  componentWillUnmount() {
    this.removeMql()
  }

  updateMatches = () => {
    if (this._mql.matches === this.state.matches) {
      return
    }
    this.setState({
      matches: this._mql.matches
    })
  }

  removeMql = () => {
    if (this._mql) {
      this._mql.removeListener(this.updateMatches)
      this._mql.dispose()
    }
  }

  render() {
    if(typeof this.props.children === 'function') {
      return this.props.children(this.state.matches)
    }

    if (this.state.matches === false) {
      return null
    }
    const props = omit(this.props, excludedPropKeys)
    const hasMergeProps = Object.keys(props).length > 0
    const childrenCount = React.Children.count(this.props.children)
    const wrapChildren = this.props.component ||
      childrenCount > 1 ||
      typeof this.props.children === 'string' ||
      Array.isArray(this.props.children) && childrenCount == 1 ||
      this.props.children === undefined
    if (wrapChildren) {
      return React.createElement(
        this.props.component || 'div',
        props,
        this.props.children
      )
    } else if (hasMergeProps) {
      return React.cloneElement(
        this.props.children,
        props
      )
    } else if (childrenCount) {
      return this.props.children
    }
    else {
      return null
    }
  }
}

export {
  MediaQuery as default,
  toQuery
}

<|endoftext|>