<commit_before>( function( window, undefined ){

	window.MarioGolf = function( code ){
		var tmp = [];
		if( !code || !( code = code.match( /(?:^|[\r\n])([MLPBTYK]+)\|(?:(.*)\|)?([OQ|\-1RNM])(?:$|[\r\n])/ ) ) )
		{
			throw new SyntaxError( 'Expecting identifier, got ' + (code? 'invalid program' : '0-length code' ) + '.', 'code', 0 );
		}
		/*All credits due to @Jens (http://stackoverflow.com/users/276070/jens) for the trick:
		 *\+(?=([^"]*"[^"]*")*[^"]*$) - matches any + not inside quotes
		 *Question: http://stackoverflow.com/questions/6462578/alternative-to-regex-match-all-instances-not-inside-quotes
		 */
		else if( code[2] != undefined && ( tmp[0] = code[2].match( /\{(?=([^"]*"[^"]*")*[^"]*$)/g ) || [] ).length != ( tmp[1] = code[2].match( /\}(?=([^"]*"[^"]*")*[^"]*$)/g ) || [] ).length )
		{
			throw new SyntaxError( 'Missing "' + ( tmp[0] < tmp[1] ? '{' : '}' ) + '" before the last identifier.', 'code', 0 );
		}

		var memory = {
			code:code,
			return:'',
			input:'',
			stack:[],
			registers:{R:0,I:0,P:0,L:0,Z:0},
			vars:{},
			output:''
		},

		/*All credits due to @BenAlpert (http://stackoverflow.com/users/49485/ben-alpert) for this implementation
		 *Original code: s.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);});
		 *Also, the use @ledlogic (http://stackoverflow.com/users/987044/ledlogic) made a general rot# function:
		 *function rot(s,i){return s.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+i)?c:c-26);});}
		 *The latest is available on http://jsfiddle.net/ledlogic/tC7qe/
		 */
		rot13 = function(s){return s.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);});},

		/*All credits due to @Jeff (http://stackoverflow.com/users/353278) for this function
		 *Original source: http://snippets.dzone.com/posts/show/849
		 *http://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array-in-javascript
		 */
		shuffle = function(o){
			for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
			return o;
		},

		//tries to parse or get a value from a piece of code
		fetchValue = function( code ){
			var currentChar = code.charAt(0), nextChar = code.charAt(1)
			switch( currentChar )
			{
				case '\'':
					return nextChar;

				case '"':
					if( ~code.indexOf('"',1) )
					{
						return code.substring(1, code.indexOf('"',1)-1 );
					}
					else
					{
						throw new SyntaxError( 'Missing " before the end of the code', 'code', 0 );
					}
					break;

				case '|':
					if( /[a-zRIPLZ]/.test( nextChar ) )
					{
						if( nextChar < 'a')
						{
							return memory.registers[nextChar];
						}
						else
						{
							return memory.vars[nextChar] === undefined ? 0 : memory.vars[nextChar];
						}
					}
					else
					{
						throw new ReferenceError( 'Undefined register "'+nextChar+'"', 'code', 0 );
					}
					break;

				case '{':
					return runBlock( code );

				default:

					if( /[a-z\d]/.test(currentChar) )
					{
						return code.match( /(^[a-z\d]+)/ )[1] || 0;
					}
					else
					{
						return;
					}
			}

		},

		runBlock = function( block ){
			for( var i = 0, l = block.length, c, Return; i<l; i++)
			{
				switch(c = block.charAt(i))
				{

					/*******Arithmetic*******/

					case '+':
						Return = (memory.registers.R / 1 || 0 ) + fetchValue( block.slice(i) );
						break;
					case '/':
						Return = ( (memory.registers.R / 1 || 0 ) / fetchValue( block.slice(i) ) ) >> 0;
						break;
					case '\\':
						Return = ( memory.registers.R / 1 || 0 ) % fetchValue( block.slice(i) );
						break;
					case '-':
						Return = memory.registers.R - fetchValue( block.slice(i) );
						break;
					case '^':
						Return = Math.pow( memory.registers.R, fetchValue( block.slice(i) ) );
						break;
					case '«':
						Return = ( memory.registers.R / 1 || 0 ) << ( fetchValue( block.slice(i) ) & 32 );
						break;
					case '»':
						Return = ( memory.registers.R / 1 || 0 ) >> ( fetchValue( block.slice(i) ) & 32 );
						break;
					case '~':
						Return = ~ ( memory.registers.R / 1 || 0 );
						break;

					/*******   Stack   *******/

					case '<':
						var tmp = fetchValue( block.slice(i) );
						if( tmp / 1 == tmp / 1)
						{
							Return = memory.stack[memory.stack.length] = tmp >> 0;
						}
						else
						{
							for(var j = 0, k = tmp.length; j<k; j++)
							{
								memory.stack[memory.stack.length] = tmp.charAt(i);
							}
						}
						memory.registers.R = memory.stack[0];
						memory.registers.L = memory.stack.length;
						break;
				}
			}
		},

		outputHandler = window.console.log;

		return {
			run: function( input ){
				memory = {
					code:memory.code,
					return:'',
					input:input,
					stack:[],
					registers:{R:0,I:memory.code.index,P:0,L:0,Z:0},
					vars:{},
					output:''
				};

				var negative = true;

				for(var i = 0, l = memory.code[1].length, c; i<l; i++)
				{
					switch(c = memory.code[1].charAt(i))
					{
						case 'M': //loads all the characters to the stack
							memory.stack = (input || '').split('');break;
						case 'L': //same as M, but reverses
							memory.stack = input ? (input + '').reverse().split('') : [];break;
						case 'P': //disables negatives
							negative = false;break;
						case 'B': //EVERYTHING is a negative number
							memory.stack = [];
							if( input )
							{
								for(var j = 0, k = input.length; j<k; j++)
								{
									memory.stack[j] = -input.charAt(j);
								}
							}
							break;
						case 'T': //shuffles the stack
							memory.stack = shuffle( memory.stack );break;
						case 'Y':break; //empty stack
						case 'K': //places a quine into the stack
							memory.stack = memory.code[0].replace(/^\s+/,'').split('');break;
						default:
							throw new ReferenceError('Unknown identifier "'+c+'"');
					}
				}

				memory.registers.L = memory.stack.length;

				if( memory.code[3].indexOf('Q') == -1 && memory.code[2] )
				{
					memory.return = runBlock( memory.code[2] );
				}

				for(var i = 0, l = memory.code[3].length, c; i<l; i++)
				{
					switch(c = memory.code[3].charAt(i))
					{
						case '-': //destroy the return
							memory.return = undefined;
						case 'O': //display the content
							outputHandler.call( window, [memory.output = memory.stack.join('')] );break;
						case 'Q': //quine
							outputHandler.call( window, [memory.output = memory.code[0].replace(/^\s+/,'')] );break;
						case '|': //doesn't display anything, returns the stack
							memory.return = memory.stack;break;
						case '1': //displays the content as rot13
							outputHandler.call( window, [memory.output = rot13( memory.stack.join('')] ) );break;
						case 'R': //displays reversed
							outputHandler.call( window, [memory.output = memory.stack.join('').split('').reverse().join('')] );break;
						case 'N': //outputs line by line, returns array
							outputHandler.call( window, [memory.output = memory.stack.join('').split('').join('\r\n')] );
							memory.return = memory.output.split('\r\n');break;
						case 'M': //outputs numbers line-by-line, returns array
							memory.return = [];
							if( memory.stack.length )
							{
								for(var j = 0, k = memory.stack.length; j<k; j++)
								{
									memory.return[j] = 'string' == typeof memory.stack[j] ? memory.stack[j] : String.fromCharCode(memory.stack[j]);
								}
							}
							outputHandler.call( window, [memory.output = memory.return.join('\r\n')] );break;
						default:
							throw new ReferenceError('Unknown identifier "'+c+'"');
					}
				}

				return memory.return;
			},
			getStack: function(){ return memory.stack; },
			getReturn: function(){ return memory.return; },
			getVars: function(){ return memory.vars; },
			getOutput: function(){ return memory.output; },
			getMemory: function(){ return memory; },
			setOutputHandler: function( fn ){
				if( fn instanceof window.Function)
				{
					outputHandler = fn;
					return true;
				}
				else
				{
					return false;
				}
			}
		};

	};

} )( Function('return this')() );
<commit_msg>Fixed the output handler throwing errors.<commit_after>( function( window, undefined ){

	window.MarioGolf = function( code ){
		var tmp = [];
		if( !code || !( code = code.match( /(?:^|[\r\n])([MLPBTYK]+)\|(?:(.*)\|)?([OQ|\-1RNM])(?:$|[\r\n])/ ) ) )
		{
			throw new SyntaxError( 'Expecting identifier, got ' + (code? 'invalid program' : '0-length code' ) + '.', 'code', 0 );
		}
		/*All credits due to @Jens (http://stackoverflow.com/users/276070/jens) for the trick:
		 *\+(?=([^"]*"[^"]*")*[^"]*$) - matches any + not inside quotes
		 *Question: http://stackoverflow.com/questions/6462578/alternative-to-regex-match-all-instances-not-inside-quotes
		 */
		else if( code[2] != undefined && ( tmp[0] = code[2].match( /\{(?=([^"]*"[^"]*")*[^"]*$)/g ) || [] ).length != ( tmp[1] = code[2].match( /\}(?=([^"]*"[^"]*")*[^"]*$)/g ) || [] ).length )
		{
			throw new SyntaxError( 'Missing "' + ( tmp[0] < tmp[1] ? '{' : '}' ) + '" before the last identifier.', 'code', 0 );
		}

		var memory = {
			code:code,
			return:'',
			input:'',
			stack:[],
			registers:{R:0,I:0,P:0,L:0,Z:0},
			vars:{},
			output:''
		},

		/*All credits due to @BenAlpert (http://stackoverflow.com/users/49485/ben-alpert) for this implementation
		 *Original code: s.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);});
		 *Also, the use @ledlogic (http://stackoverflow.com/users/987044/ledlogic) made a general rot# function:
		 *function rot(s,i){return s.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+i)?c:c-26);});}
		 *The latest is available on http://jsfiddle.net/ledlogic/tC7qe/
		 */
		rot13 = function(s){return s.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);});},

		/*All credits due to @Jeff (http://stackoverflow.com/users/353278) for this function
		 *Original source: http://snippets.dzone.com/posts/show/849
		 *http://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array-in-javascript
		 */
		shuffle = function(o){
			for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
			return o;
		},

		//tries to parse or get a value from a piece of code
		fetchValue = function( code ){
			var currentChar = code.charAt(0), nextChar = code.charAt(1)
			switch( currentChar )
			{
				case '\'':
					return nextChar;

				case '"':
					if( ~code.indexOf('"',1) )
					{
						return code.substring(1, code.indexOf('"',1)-1 );
					}
					else
					{
						throw new SyntaxError( 'Missing " before the end of the code', 'code', 0 );
					}
					break;

				case '|':
					if( /[a-zRIPLZ]/.test( nextChar ) )
					{
						if( nextChar < 'a')
						{
							return memory.registers[nextChar];
						}
						else
						{
							return memory.vars[nextChar] === undefined ? 0 : memory.vars[nextChar];
						}
					}
					else
					{
						throw new ReferenceError( 'Undefined register "'+nextChar+'"', 'code', 0 );
					}
					break;

				case '{':
					return runBlock( code );

				default:

					if( /[a-z\d]/.test(currentChar) )
					{
						return code.match( /(^[a-z\d]+)/ )[1] || 0;
					}
					else
					{
						return;
					}
			}

		},

		runBlock = function( block ){
			for( var i = 0, l = block.length, c, Return; i<l; i++)
			{
				switch(c = block.charAt(i))
				{

					/*******Arithmetic*******/

					case '+':
						Return = (memory.registers.R / 1 || 0 ) + fetchValue( block.slice(i) );
						break;
					case '/':
						Return = ( (memory.registers.R / 1 || 0 ) / fetchValue( block.slice(i) ) ) >> 0;
						break;
					case '\\':
						Return = ( memory.registers.R / 1 || 0 ) % fetchValue( block.slice(i) );
						break;
					case '-':
						Return = memory.registers.R - fetchValue( block.slice(i) );
						break;
					case '^':
						Return = Math.pow( memory.registers.R, fetchValue( block.slice(i) ) );
						break;
					case '«':
						Return = ( memory.registers.R / 1 || 0 ) << ( fetchValue( block.slice(i) ) & 32 );
						break;
					case '»':
						Return = ( memory.registers.R / 1 || 0 ) >> ( fetchValue( block.slice(i) ) & 32 );
						break;
					case '~':
						Return = ~ ( memory.registers.R / 1 || 0 );
						break;

					/*******   Stack   *******/

					case '<':
						var tmp = fetchValue( block.slice(i) );
						if( tmp / 1 == tmp / 1)
						{
							Return = memory.stack[memory.stack.length] = tmp >> 0;
						}
						else
						{
							for(var j = 0, k = tmp.length; j<k; j++)
							{
								memory.stack[memory.stack.length] = tmp.charAt(i);
							}
						}
						memory.registers.R = memory.stack[0];
						memory.registers.L = memory.stack.length;
						break;
				}
			}
		},

		outputHandler = window.console.log;

		return {
			run: function( input ){
				memory = {
					code:memory.code,
					return:'',
					input:input,
					stack:[],
					registers:{R:0,I:memory.code.index,P:0,L:0,Z:0},
					vars:{},
					output:''
				};

				var negative = true;

				for(var i = 0, l = memory.code[1].length, c; i<l; i++)
				{
					switch(c = memory.code[1].charAt(i))
					{
						case 'M': //loads all the characters to the stack
							memory.stack = (input || '').split('');break;
						case 'L': //same as M, but reverses
							memory.stack = input ? (input + '').reverse().split('') : [];break;
						case 'P': //disables negatives
							negative = false;break;
						case 'B': //EVERYTHING is a negative number
							memory.stack = [];
							if( input )
							{
								for(var j = 0, k = input.length; j<k; j++)
								{
									memory.stack[j] = -input.charAt(j);
								}
							}
							break;
						case 'T': //shuffles the stack
							memory.stack = shuffle( memory.stack );break;
						case 'Y':break; //empty stack
						case 'K': //places a quine into the stack
							memory.stack = memory.code[0].replace(/^\s+/,'').split('');break;
						default:
							throw new ReferenceError('Unknown identifier "'+c+'"');
					}
				}

				memory.registers.L = memory.stack.length;

				if( memory.code[3].indexOf('Q') == -1 && memory.code[2] )
				{
					memory.return = runBlock( memory.code[2] );
				}

				for(var i = 0, l = memory.code[3].length, c; i<l; i++)
				{
					switch(c = memory.code[3].charAt(i))
					{
						case '-': //destroy the return
							memory.return = undefined;
						case 'O': //display the content
							outputHandler.call( window.console, [memory.output = memory.stack.join('')] );break;
						case 'Q': //quine
							outputHandler.call( window.console, [memory.output = memory.code[0].replace(/^\s+/,'')] );break;
						case '|': //doesn't display anything, returns the stack
							memory.return = memory.stack;break;
						case '1': //displays the content as rot13
							outputHandler.call( window.console, [memory.output = rot13( memory.stack.join('')] ) );break;
						case 'R': //displays reversed
							outputHandler.call( window.console, [memory.output = memory.stack.join('').split('').reverse().join('')] );break;
						case 'N': //outputs line by line, returns array
							outputHandler.call( window.console, [memory.output = memory.stack.join('').split('').join('\r\n')] );
							memory.return = memory.output.split('\r\n');break;
						case 'M': //outputs numbers line-by-line, returns array
							memory.return = [];
							if( memory.stack.length )
							{
								for(var j = 0, k = memory.stack.length; j<k; j++)
								{
									memory.return[j] = 'string' == typeof memory.stack[j] ? memory.stack[j] : String.fromCharCode(memory.stack[j]);
								}
							}
							outputHandler.call( window.console, [memory.output = memory.return.join('\r\n')] );break;
						default:
							throw new ReferenceError('Unknown identifier "'+c+'"');
					}
				}

				return memory.return;
			},
			getStack: function(){ return memory.stack; },
			getReturn: function(){ return memory.return; },
			getVars: function(){ return memory.vars; },
			getOutput: function(){ return memory.output; },
			getMemory: function(){ return memory; },
			setOutputHandler: function( fn ){
				if( fn instanceof window.Function)
				{
					outputHandler = fn;
					return true;
				}
				else
				{
					return false;
				}
			}
		};

	};

} )( Function('return this')() );
<|endoftext|>


<commit_before>iD.ui.userpanel = function(connection) {
    var event = d3.dispatch('logout', 'login');

    function user(selection) {
        function update() {
            selection.html('');
            if (connection.authenticated()) {
                selection.style('display', 'block');
                connection.userDetails(function(user_details) {

                    // Link
                    var userLink = selection.append('a')
                            .attr('href', connection.url() + '/user/' +
                                  user_details.display_name)
                            .attr('target', '_blank')

                    // Add thumbnail or dont
                        if (user_details.image_url) {
                            userLink.append('img')
                                .attr('class', 'icon icon-pre-text')
                                .attr('src', user_details.image_url);
                        } else {
                            userLink.append('span')
                                .attr('class','icon avatar icon-pre-text');
                        }

                    // Add user name
                    userLink.append('span').attr('class','label').text(user_details.display_name);

                    selection
                        .append('a')
                        .attr('class', 'logout')
                        .attr('href', '#')
                        .text('logout')
                        .on('click.logout', function() {
                            d3.event.preventDefault();
                            event.logout();
                        });
                });
            } else {
                selection.html('').style('display', 'none');
            }
        }
        connection.on('auth', update);
        update();
    }

    return d3.rebind(user, event, 'on');
};
<commit_msg>Fix race condition in user panel. Fixes #515<commit_after>iD.ui.userpanel = function(connection) {
    var event = d3.dispatch('logout', 'login');

    function user(selection) {
        function update() {
            if (connection.authenticated()) {
                selection.style('display', 'block');
                connection.userDetails(function(user_details) {

                    selection.html('');

                    // Link
                    var userLink = selection.append('a')
                            .attr('href', connection.url() + '/user/' +
                                  user_details.display_name)
                            .attr('target', '_blank');

                    // Add thumbnail or dont
                    if (user_details.image_url) {
                        userLink.append('img')
                            .attr('class', 'icon icon-pre-text')
                            .attr('src', user_details.image_url);
                    } else {
                        userLink.append('span')
                            .attr('class','icon avatar icon-pre-text');
                    }

                    // Add user name
                    userLink.append('span')
                        .attr('class','label')
                        .text(user_details.display_name);

                    selection
                        .append('a')
                        .attr('class', 'logout')
                        .attr('href', '#')
                        .text('logout')
                        .on('click.logout', function() {
                            d3.event.preventDefault();
                            event.logout();
                        });
                });
            } else {
                selection.html('').style('display', 'none');
            }
        }
        connection.on('auth', update);
        update();
    }

    return d3.rebind(user, event, 'on');
};
<|endoftext|>


<commit_before>XHRShaper.useGlobal();

var DEFAULT_URL = "http://www.streambox.fr/playlists/test_001/stream_110k_48k_416x234_000.ts";

var stats;
var requestActive = false;

function resetStats() {
	stats = {
		timestamps: [],
		bytes: [],
		t0: null,
		totalDuration: null,
		throughput: null
	};
}

function pushStats(bytes, total) {

	document.querySelector('#progress').value = bytes;
	document.querySelector('#progress').max = total;

	if (stats.t0 === null) {
		stats.t0 = Date.now();
	}

    stats.timestamps.push(Date.now() - stats.t0);
    stats.bytes.push(bytes);
}

function onRequestDone(xhr) {

	requestActive = false;

	var el = document.querySelector('#graph');

	Plotly.plot(el, [{
	    	x: stats.timestamps,
	    	y: stats.bytes
		}],
		{
    		margin: { t: 0 }
    	}
   	);

   	document.querySelector('#throughput').innerHTML = stats.throughput;
   	document.querySelector('#duration').innerHTML = stats.totalDuration;

   	document.querySelector('#status').innerHTML = 'Ready';
}

function onClickLoad() {

	if (requestActive) {
		console.warn('Request currently happening, please wait until done');
		return;
	}

	var minLatency = parseInt(document.querySelector('#latency').value);
	var maxBandwidth = parseInt(document.querySelector('#bandwidth').value);

	if (isNaN(minLatency) || minLatency < 0) {
		minLatency = 0;
		document.querySelector('#latency').value = minLatency;
	}

	if (isNaN(maxBandwidth) || maxBandwidth <= 0) {
		maxBandwidth = Infinity;
		document.querySelector('#bandwidth').value = maxBandwidth;
	}

	document.querySelector('#status').innerHTML = 'Loading';

	makeRequest(DEFAULT_URL, onRequestDone, minLatency, maxBandwidth);
}

function makeRequest(url, done, minLatency, maxBandwidth) {
  var loaded, total;

  console.log('url:', url);

  requestActive = true;

  var xhr = new XMLHttpRequest();

  xhr.shaper.minLatency = minLatency;
  xhr.shaper.maxBandwidth = maxBandwidth;

  xhr.onreadystatechange = function(e) {
    console.log('readyState: ' + xhr.readyState);

    if (xhr.readyState === 4) {
      doneTime = Date.now();
      var duration = doneTime - reqTime;
      var bitrate = Math.round(8 * total / duration);

      stats.totalDuration = duration;
      stats.throughput = bitrate;

      console.log('Loaded ' + total + ' bytes in ' + duration + ' ms, computed bitrate: ' + bitrate + ' kbps');
    }
  };
  xhr.onprogress = function(e) {
    loaded = e.loaded;
    total = e.total;

    pushStats(e.loaded, e.total);

    console.log('Progress: ' + e.loaded + ' of ' + e.total);
  };

  xhr.onload = function(e) {

    if (xhr.readyState < 4) {
      console.warn('onload called with readyState:', xhr.readyState, ' id:', xhr.id);
      return;
    }

    console.log('Loading done');
    //console.log(e);

    console.log('readyState:', xhr.readyState);

    if (xhr.response.byteLength < 1024) {
      console.log(new TextDecoder("utf-8").decode(xhr.response));
    }

    done(xhr);
  }

  xhr.onloadend = function(e) {
    console.log('Loading ended');
    //console.log(e);
  }

  xhr.withCredentials = false;
  xhr.open('GET', url, true);
  xhr.responseType = 'arraybuffer';

  console.debug('Max bandwidth: ' + xhr.shaper.maxBandwidth);
  console.debug('Min latency: ' + xhr.shaper.minLatency);

  var reqTime = Date.now(), doneTime;

  xhr.send();

  resetStats();
  pushStats(0, 0);

  return xhr;
}<commit_msg>code cosmetics in demo<commit_after>XHRShaper.useGlobal();

var DEFAULT_URL = "http://www.streambox.fr/playlists/test_001/stream_110k_48k_416x234_000.ts";

var stats;
var requestActive = false;

function resetStats() {
	stats = {
		timestamps: [],
		bytes: [],
		t0: null,
		totalDuration: null,
		throughput: null
	};
}

function pushStats(bytes, total) {

	document.querySelector('#progress').value = bytes;
	document.querySelector('#progress').max = total;

	if (stats.t0 === null) {
		stats.t0 = Date.now();
	}

	stats.timestamps.push(Date.now() - stats.t0);
	stats.bytes.push(bytes);

	console.log('stats pushed:', stats);
}

function onRequestDone(xhr) {

	requestActive = false;

	var el = document.querySelector('#graph');

	Plotly.plot(
		el,
		[{
				x: stats.timestamps,
				y: stats.bytes
		}],
		{
			margin: { t: 0 }
		}
	);

	document.querySelector('#throughput').innerHTML = stats.throughput;
	document.querySelector('#duration').innerHTML = stats.totalDuration;

	document.querySelector('#status').innerHTML = 'Ready';
}

function onClickLoad() {

	if (requestActive) {
		console.warn('Request currently happening, please wait until done');
		return;
	}

	var minLatency = parseInt(document.querySelector('#latency').value);
	var maxBandwidth = parseInt(document.querySelector('#bandwidth').value);

	if (isNaN(minLatency) || minLatency < 0) {
		minLatency = 0;
		document.querySelector('#latency').value = minLatency;
	}

	if (isNaN(maxBandwidth) || maxBandwidth <= 0) {
		maxBandwidth = Infinity;
		document.querySelector('#bandwidth').value = maxBandwidth;
	}

	document.querySelector('#status').innerHTML = 'Loading';

	makeRequest(DEFAULT_URL, onRequestDone, minLatency, maxBandwidth);
}

function makeRequest(url, onRequestDone, minLatency, maxBandwidth) {
	var loaded, total;

	console.log('url:', url);

	requestActive = true;

	var xhr = new XMLHttpRequest();

	xhr.caching = false;

	xhr.shaper.minLatency = minLatency;
	xhr.shaper.maxBandwidth = maxBandwidth;

	xhr.onreadystatechange = function(e) {
		console.log('readyState changed: ' + xhr.readyState);

		if (xhr.readyState === 4) {
			doneTime = Date.now();
			var duration = doneTime - reqTime;
			var bitrate = Math.round(8 * total / duration);

			stats.totalDuration = duration;
			stats.throughput = bitrate;

			console.log('Loaded ' + total + ' bytes in ' + duration + ' ms, computed bitrate: ' + bitrate + ' kbps');
		}
	};
	xhr.onprogress = function(e) {
		loaded = e.loaded;
		total = e.total;

		pushStats(e.loaded, e.total);

		console.log('Progress: ' + e.loaded + ' of ' + e.total);
	};

	xhr.onload = function(e) {

		if (xhr.readyState < 4) {
			console.warn('onload called with readyState:', xhr.readyState, ' id:', xhr.id);
			return;
		}

		console.log('Loading done');
		//console.log(e);

		console.log('readyState:', xhr.readyState);

		if (xhr.response.byteLength < 1024) {
			console.log(new TextDecoder("utf-8").decode(xhr.response));
		}

	}

	xhr.onloadend = function(e) {
		console.log('Loading ended');

		pushStats(loaded, total);

		onRequestDone(xhr);
	}

	xhr.withCredentials = false;
	xhr.open('GET', url, true);
	xhr.responseType = 'arraybuffer';

	console.debug('Max bandwidth: ' + xhr.shaper.maxBandwidth);
	console.debug('Min latency: ' + xhr.shaper.minLatency);

	var reqTime = Date.now(), doneTime;

	xhr.send();

	resetStats();
	pushStats(0, 0);

	return xhr;
}<|endoftext|>


<commit_before>//     oblo-util.js 0.3.1

//     (c) 2013-2011 Martijn M. Schrage, Oblomomov Systems
//     Oblo-util may be freely distributed under the MIT license.
//     For all details and documentation:
//     https://github.com/oblosys/oblo-util

(function(util){ // Cannot have '-' in name, so use 'util' rather than the verbose 'oblo_util'

  // Notes: basic modules, no active importing, mainly experiment for using npm also on client
  // needs to be defined before we call it.
  // NOTE: on client, use last elt of path for object ref, goes wrong with -'s in name.., so need to specify it in that case
  if (typeof window != 'undefined') // on client, NOTE: we have to manually include the required module scripts in the HTML
    window.require = function(moduleName, clientModuleObject) {
      return window[clientModuleObject ? clientModuleObject : moduleName.split('/').pop()];
    };

  var _ = require('underscore', '_'); // underscore calls itself '_' on client

  util.debug = true; // set this to false on deployment

  // Call console.log with all parameters, but only when util.debug == true
  util.log = function() {
    if (util.debug && typeof console != 'undefined')
      var log = Function.prototype.bind.call(console.log, console);
      log.apply(null, Array.prototype.slice.call(arguments));
  };

  // Constrain x to the interval [min .. max]
  util.clip = function(min, max, x) {
    return Math.max(min, Math.min(x, max));
  };

  util.square = function(x) {
    return x*x;
  };

  // NOTE: replicated objects are only cloned on top-level
  util.replicate = function(n,x) {
    var xs = [];
    for (var i=0; i<n; i++)
      xs.push(_.clone(x));
    return xs;
  };

  // pad integer with leading 0's when necessary
  util.padZero = function(l, n) {
    var nrOfZeros = Math.max(0, l-(''+n).length);
    return util.replicate(nrOfZeros,'0').join('')+n;
  };

  // depth is to prevent hanging on circular objects
  util.showJSON = function(json,indent,depth) {
    indent = indent || '';
    depth = depth || 0;
    var str = '';

    if (!json) {
      str += 'null';
    } else if (depth>=10) { // max depth
      str += typeof json != 'object' ? json : Array.isArray(json) ? '[...]' : '{...}';
    } else if (Array.isArray(json)) {
      if (json.length ==0 )
        str += '[]';
      else {
        for (var i = 0; i<json.length; i++)
          str += (i==0?'[ ':indent + ', ') + util.showJSON(json[i],'  '+indent, depth+1)+'\n';
        str += indent + ']';
      }
    } else if (typeof json == 'object') {
      console.log('json: '+json);
      var keys = Object.keys(json); // TODO: use underscore version for safety
      if (keys.length ==0 )
        str += '{}';
      else {
        for (var i = 0; i<keys.length; i++)
          str += (i==0?'{ ':indent + ', ') + keys[i] + ':' +
          (typeof json[keys[i]] == 'object' ? '\n' + indent +'  ' : ' ') + // for object children start new line
          util.showJSON(json[keys[i]],'  '+indent, depth+1)+'\n';
        str += indent + '}';
      }
    } else {
      str += json;
    }
    return str;
  };

  util.showTime = function(date) {
    return util.padZero(2, date.getHours()) + ':' + util.padZero(2, date.getMinutes()) + ':' + util.padZero(2, date.getSeconds());
  };

  util.showDate = function(date) {
    return util.padZero(2, date.getDate()) + '-' + util.padZero(2, date.getMonth()+1) + '-' + util.padZero(4, date.getFullYear());
  };

  util.readDate = function(dateStr) {
    var parts = dateStr.split('-');
    if (parts.length == 3)
      return new Date(parts[2], parts[1]-1, parts[0]);
    else
      throw 'Exception: Incorrect date: "'+dateStr+'"';
  };

  /* Set boolean DOM attribute for jQuery object $elt according to HTML standard.
   * (absence denotes false, attrName=AttrName denotes true) */
  util.setAttr = function($elt, attrName, isSet) {
    if (isSet)
      $elt.attr(attrName, attrName);
    else
      $elt.removeAttr(attrName);
  };

})(typeof exports == 'undefined' ? this.util={} : exports); // pass exports if we're on the server, otherwise, create object util
<commit_msg>Handle undefined in util.showJSON + Change parameter order<commit_after>//     oblo-util.js 0.3.1

//     (c) 2013-2011 Martijn M. Schrage, Oblomomov Systems
//     Oblo-util may be freely distributed under the MIT license.
//     For all details and documentation:
//     https://github.com/oblosys/oblo-util

(function(util){ // Cannot have '-' in name, so use 'util' rather than the verbose 'oblo_util'

  // Notes: basic modules, no active importing, mainly experiment for using npm also on client
  // needs to be defined before we call it.
  // NOTE: on client, use last elt of path for object ref, goes wrong with -'s in name.., so need to specify it in that case
  if (typeof window != 'undefined') // on client, NOTE: we have to manually include the required module scripts in the HTML
    window.require = function(moduleName, clientModuleObject) {
      return window[clientModuleObject ? clientModuleObject : moduleName.split('/').pop()];
    };

  var _ = require('underscore', '_'); // underscore calls itself '_' on client

  util.debug = true; // set this to false on deployment

  // Call console.log with all parameters, but only when util.debug == true
  util.log = function() {
    if (util.debug && typeof console != 'undefined')
      var log = Function.prototype.bind.call(console.log, console);
      log.apply(null, Array.prototype.slice.call(arguments));
  };

  // Constrain x to the interval [min .. max]
  util.clip = function(min, max, x) {
    return Math.max(min, Math.min(x, max));
  };

  util.square = function(x) {
    return x*x;
  };

  // NOTE: replicated objects are only cloned on top-level
  util.replicate = function(n,x) {
    var xs = [];
    for (var i=0; i<n; i++)
      xs.push(_.clone(x));
    return xs;
  };

  // pad integer with leading 0's when necessary
  util.padZero = function(l, n) {
    var nrOfZeros = Math.max(0, l-(''+n).length);
    return util.replicate(nrOfZeros,'0').join('')+n;
  };

  // depth is to prevent hanging on circular objects
  util.showJSON = function(json,depth,indent) {
    indent = indent || '';
    depth = depth || 0;
    var str = '';

    if (typeof json == 'undefined') {
      str += 'undefined';
    } else if (!json) {
      str += 'null';
    } else if (depth>=10) { // max depth
      str += typeof json != 'object' ? json : Array.isArray(json) ? '[...]' : '{...}';
    } else if (Array.isArray(json)) {
      if (json.length ==0 )
        str += '[]';
      else {
        for (var i = 0; i<json.length; i++)
          str += (i==0?'[ ':indent + ', ') + util.showJSON(json[i], depth+1,indent+'  ')+'\n';
        str += indent + ']';
      }
    } else if (typeof json == 'object') {
      var keys = Object.keys(json); // TODO: use underscore version for safety
      if (keys.length ==0 )
        str += '{}';
      else {
        for (var i = 0; i<keys.length; i++)
          str += (i==0?'{ ':indent + ', ') + keys[i] + ':' +
          (typeof json[keys[i]] == 'object' ? '\n' + indent +'  ' : ' ') + // for object children start new line
          util.showJSON(json[keys[i]], depth+1,indent+'  ')+'\n';
        str += indent + '}';
      }
    } else {
      str += json;
    }
    return str;
  };

  util.showTime = function(date) {
    return util.padZero(2, date.getHours()) + ':' + util.padZero(2, date.getMinutes()) + ':' + util.padZero(2, date.getSeconds());
  };

  util.showDate = function(date) {
    return util.padZero(2, date.getDate()) + '-' + util.padZero(2, date.getMonth()+1) + '-' + util.padZero(4, date.getFullYear());
  };

  util.readDate = function(dateStr) {
    var parts = dateStr.split('-');
    if (parts.length == 3)
      return new Date(parts[2], parts[1]-1, parts[0]);
    else
      throw 'Exception: Incorrect date: "'+dateStr+'"';
  };

  /* Set boolean DOM attribute for jQuery object $elt according to HTML standard.
   * (absence denotes false, attrName=AttrName denotes true) */
  util.setAttr = function($elt, attrName, isSet) {
    if (isSet)
      $elt.attr(attrName, attrName);
    else
      $elt.removeAttr(attrName);
  };

})(typeof exports == 'undefined' ? this.util={} : exports); // pass exports if we're on the server, otherwise, create object util
<|endoftext|>


<commit_before>/*
 * Route for creating survey
 *
 * @exports {function}
 * @param   {object}    server     server instance
 */
var _ = require("lodash");
var when = require("when");
var utils = require("../lib/utils");

module.exports = function (server) {

  // Create batch of surveys from array of survey objects
  server.route({
    method: "POST",
    path: "/surveys/batch",
    handler: function (req, res) {
      var surveys = req.payload;
      var models = req.server.plugins.sqlModels.models;
      var batchId;

      // Wrap in transaction. If promise chain err's
      // then transaction rolled back automatically
      // If succeeds then committed
      models.sqlize.transaction(function () {
        // First create a batch number
        return models.SurveyBatch.create()
          // Then create the survey records
          // and response records
          .then(function (batch) {
            batchId = batch.get("id");

            return when.all(_.map(surveys, function (survey) {
              return utils.createSurvey(_.extend(survey, {
                SurveyBatchId: batchId
              }), models);
            }));
          })
          // Fetch all newly created surveys joined to new responses
          // and create resonse object
          .then(function () {
            return utils.batchResponse(batchId, models);
          })
          .then(function (responseBody) {
            return res(responseBody);
          });
      })
        // If catch then transaction will have been rolled back
        .catch(utils.handleWriteErr(req, res));
    }
  });

  // Get all surveys and responses for a given batch number
  server.route({
    method: "GET",
    path: "/surveys/batch/{number}",
    handler: function (req, res) {
      var models = req.server.plugins.sqlModels.models;

      utils.batchResponse(req.params.number, models)
        .then(function (responseBody) {
          res(responseBody);
        })
        .catch(utils.handleWriteErr(req, res));
    }
  });

  // Get all surveys and responses for a given periodEnd date
  server.route({
    method: "GET",
    path: "/surveys/{periodEnd}",
    handler: function (req, res) {
      var models = req.server.plugins.sqlModels.models;
      var periodEnd = req.params.periodEnd;

      models.Survey.findAll({
        where: {
          periodEnd: periodEnd
        },
        include: [models.Response]
      })
      .then(function (responseBody) {
        res(responseBody);
      })
      .catch(utils.handleWriteErr(req, res));
    }
  });
};
<commit_msg>add hapi date validation<commit_after>/*
 * Route for creating survey
 *
 * @exports {function}
 * @param   {object}    server     server instance
 */
var _ = require("lodash");
var when = require("when");
var utils = require("../lib/utils");
var Joi = require("joi");

module.exports = function (server) {

  // Create batch of surveys from array of survey objects
  server.route({
    method: "POST",
    path: "/surveys/batch",
    handler: function (req, res) {
      var surveys = req.payload;
      var models = req.server.plugins.sqlModels.models;
      var batchId;

      // Wrap in transaction. If promise chain err's
      // then transaction rolled back automatically
      // If succeeds then committed
      models.sqlize.transaction(function () {
        // First create a batch number
        return models.SurveyBatch.create()
          // Then create the survey records
          // and response records
          .then(function (batch) {
            batchId = batch.get("id");

            return when.all(_.map(surveys, function (survey) {
              return utils.createSurvey(_.extend(survey, {
                SurveyBatchId: batchId
              }), models);
            }));
          })
          // Fetch all newly created surveys joined to new responses
          // and create resonse object
          .then(function () {
            return utils.batchResponse(batchId, models);
          })
          .then(function (responseBody) {
            return res(responseBody);
          });
      })
        // If catch then transaction will have been rolled back
        .catch(utils.handleWriteErr(req, res));
    }
  });

  // Get all surveys and responses for a given batch number
  server.route({
    method: "GET",
    path: "/surveys/batch/{number}",
    handler: function (req, res) {
      var models = req.server.plugins.sqlModels.models;

      utils.batchResponse(req.params.number, models)
        .then(function (responseBody) {
          res(responseBody);
        })
        .catch(utils.handleWriteErr(req, res));
    }
  });

  // Get all surveys and responses for a given periodEnd date
  server.route({
    method: "GET",
    path: "/surveys/{periodEnd}",
    handler: function (req, res) {
      var models = req.server.plugins.sqlModels.models;
      var periodEnd = req.params.periodEnd;

      models.Survey.findAll({
        where: {
          periodEnd: periodEnd
        },
        include: [models.Response]
      })
      .then(function (responseBody) {
        res(responseBody);
      })
      .catch(utils.handleWriteErr(req, res));
    },
    config: {
      validate: {
        params: {
          periodEnd: Joi.date().format("YYYYMMDD")
        }
      }
    }
  });
};
<|endoftext|>


<commit_before>import firebase from '../database';
import alt from '../lib/alt';

class UserActions {
  get(userId) {
    firebase.database.ref(`users/${userId}`).once('value', (snap) => {
      if (snap.val()) {
        this.getSuccess(snap.val());
      } else {
        this.getError();
      }
    });

    return true;
  }

  update(user, fields) {
    let update = fields || user;
    update.lastSeenAt = Date.now();
    if (user.id) {
      firebase.database.ref(`users/${user.id}`).update(update,
        (error) => {
          if (error) {
            this.updateError(error);
          } else {
            this.updateSuccess(user);
          }
        });
      } else {
      this.updateError({
          message: 'No user ID present'
      });
    }

    return true;
  }

  set(user, key, value) {
    firebase.database.ref(`users/${user.id}/${key}`).set(value);
    return true;
  }

  getSuccess(user) {
    return user;
  }

  getError() {
    return 'User not found';
  }

  updateSuccess(user) {
    return user;
  }

  updateError(error) {
    return {
      error
    };
  }
}

export default alt.createActions(UserActions);
<commit_msg>[Delivers #124125321] Nullify store before fetching new data<commit_after>import firebase from '../database';
import alt from '../lib/alt';

class UserActions {
  get(userId) {
    this.getSuccess(null);
    firebase.database.ref(`users/${userId}`).once('value', (snap) => {
      if (snap.val()) {
        this.getSuccess(snap.val());
      } else {
        this.getError();
      }
    });

    return true;
  }

  update(user, fields) {
    let update = fields || user;
    update.lastSeenAt = Date.now();
    if (user.id) {
      firebase.database.ref(`users/${user.id}`).update(update,
        (error) => {
          if (error) {
            this.updateError(error);
          } else {
            this.updateSuccess(user);
          }
        });
      } else {
      this.updateError({
          message: 'No user ID present'
      });
    }

    return true;
  }

  set(user, key, value) {
    firebase.database.ref(`users/${user.id}/${key}`).set(value);
    return true;
  }

  getSuccess(user) {
    return user;
  }

  getError() {
    return 'User not found';
  }

  updateSuccess(user) {
    return user;
  }

  updateError(error) {
    return {
      error
    };
  }
}

export default alt.createActions(UserActions);
<|endoftext|>


<commit_before>/* ========================================================================
 * Ratchet Plus: Infinite-scroll.js v1.0.0
 * http://rc.kimsq.com/controls/infinite-scroll/
/*=======================================================================
 * Fuel UX Infinite Scroll (Need Above loader plugin )
 * https://github.com/ExactTarget/fuelux/blob/master/js/infinite-scroll.js
 *
 * Copyright (c) 2014 ExactTarget
 * Licensed under the BSD New license.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
        disclaimer.

    2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
        following disclaimer in the documentation and/or other materials provided with the distribution.

    3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
        products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *========================================================================*/

;(function ( $, window, document, undefined ) {

	var old = $.fn.infinitescroll;

	// INFINITE SCROLL CONSTRUCTOR AND PROTOTYPE

	var InfiniteScroll = function (element, options) {
		this.$element = $(element);
		this.$appendToEle=options.appendToEle;
		this.$element.addClass('infinitescroll');
		this.options = $.extend({}, $.fn.infinitescroll.defaults, options);

		this.curScrollTop = this.$element.scrollTop();
		this.curPercentage = this.getPercentage();
		this.fetchingData = false;

		this.$element.on('scroll.fu.infinitescroll', $.proxy(this.onScroll, this));
		this.onScroll();
	};

    // require tab.js & history.js & utilty.js
    if (!$.fn.loader=="undefined") throw new Error('infinite-scroll requires loader.js')

	InfiniteScroll.prototype = {

		constructor: InfiniteScroll,

		destroy: function () {
			this.$element.remove();
			// any external bindings
			// [none]

			// empty elements to return to original markup
			this.$element.empty();

			return this.$element[0].outerHTML;
		},

		disable: function () {
			this.$element.off('scroll.fu.infinitescroll');
		},

		enable: function () {
			this.$element.on('scroll.fu.infinitescroll', $.proxy(this.onScroll, this));
		},

		end: function (content) {
			var end = $('

');
			if (content) {
				end.append(content);
			} else {
				end.append('---------');
			}

			this.$element.append(end);
			this.disable();
		},

		getPercentage: function () {
			var height = (this.$element.css('box-sizing') === 'border-box') ? this.$element.outerHeight() : this.$element.height();
			var scrollHeight = this.$element.get(0).scrollHeight;
			return (scrollHeight > height) ? ((height / (scrollHeight - this.curScrollTop)) * 100) : 0;
		},

		fetchData: function (force) {
			var load = $('

');
			var self = this;
			var moreBtn;

			var fetch = function () {
				var helpers = {
					percentage: self.curPercentage,
					scrollTop: self.curScrollTop
				};
				//var $loader = $('

');
				var $loader=$('

');
				load.append($loader);
				//$loader.loader();
				$loader.loader()
				if (self.options.dataSource) {
					self.options.dataSource(helpers, function (resp) {
						var end;
						load.remove();
						if (resp.content) {
							self.$appendToEle.append(resp.content);
						}

						if (resp.end) {
							end = (resp.end !== true) ? resp.end : undefined;
							self.end(end);
						}

						self.fetchingData = false;
					});
				}
			};

			this.fetchingData = true;
			this.$element.append(load);
			if (this.options.hybrid && force !== true) {
				moreBtn = $('<button type="button" class="btn btn-primary">more</button>');
				if (typeof this.options.hybrid === 'object') {
					moreBtn.append(this.options.hybrid.label);
				} else {
					moreBtn.append('');
				}

				moreBtn.on('click.fu.infinitescroll', function () {
					moreBtn.remove();
					fetch();
				});
				load.append(moreBtn);
			} else {
				fetch();
			}
		},

		onScroll: function (e) {
			this.curScrollTop = this.$element.scrollTop();
			this.curPercentage = this.getPercentage();
			if (!this.fetchingData && this.curPercentage >= this.options.percentage) {
				this.fetchData();
			}
		}
	};

	// INFINITE SCROLL PLUGIN DEFINITION

	$.fn.infinitescroll = function (option) {
		var args = Array.prototype.slice.call(arguments, 1);
		var methodReturn;

		var $set = this.each(function () {
			var $this = $(this);
			var data = $this.data('fu.infinitescroll');
			var options = typeof option === 'object' && option;

			if (!data) {
				$this.data('fu.infinitescroll', (data = new InfiniteScroll(this, options)));
			}

			if (typeof option === 'string') {
				methodReturn = data[option].apply(data, args);
			}
		});

		return (methodReturn === undefined) ? $set : methodReturn;
	};

	$.fn.infinitescroll.defaults = {
		dataSource: null,
		hybrid: false,//can be true or an object with structure: { 'label': (markup or jQuery obj) }
		percentage: 95//percentage scrolled to the bottom before more is loaded
	};

	$.fn.infinitescroll.Constructor = InfiniteScroll;

	$.fn.infinitescroll.noConflict = function () {
		$.fn.infinitescroll = old;
		return this;
	};

	// NO DATA-API DUE TO NEED OF DATA-SOURCE

	// -- BEGIN UMD WRAPPER AFTERWORD --
})( jQuery, window, document );
// -- END UMD WRAPPER AFTERWORD --<commit_msg>`Loads with button` 템플릿 변경<commit_after>/* ========================================================================
 * Ratchet Plus: Infinite-scroll.js v1.0.0
 * http://rc.kimsq.com/controls/infinite-scroll/
/*=======================================================================
 * Fuel UX Infinite Scroll (Need Above loader plugin )
 * https://github.com/ExactTarget/fuelux/blob/master/js/infinite-scroll.js
 *
 * Copyright (c) 2014 ExactTarget
 * Licensed under the BSD New license.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
        disclaimer.

    2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
        following disclaimer in the documentation and/or other materials provided with the distribution.

    3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
        products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *========================================================================*/

;(function ( $, window, document, undefined ) {

	var old = $.fn.infinitescroll;

	// INFINITE SCROLL CONSTRUCTOR AND PROTOTYPE

	var InfiniteScroll = function (element, options) {
		this.$element = $(element);
		this.$appendToEle=options.appendToEle;
		this.$element.addClass('infinitescroll');
		this.options = $.extend({}, $.fn.infinitescroll.defaults, options);

		this.curScrollTop = this.$element.scrollTop();
		this.curPercentage = this.getPercentage();
		this.fetchingData = false;

		this.$element.on('scroll.fu.infinitescroll', $.proxy(this.onScroll, this));
		this.onScroll();
	};

    // require tab.js & history.js & utilty.js
    if (!$.fn.loader=="undefined") throw new Error('infinite-scroll requires loader.js')

	InfiniteScroll.prototype = {

		constructor: InfiniteScroll,

		destroy: function () {
			this.$element.remove();
			// any external bindings
			// [none]

			// empty elements to return to original markup
			this.$element.empty();

			return this.$element[0].outerHTML;
		},

		disable: function () {
			this.$element.off('scroll.fu.infinitescroll');
		},

		enable: function () {
			this.$element.on('scroll.fu.infinitescroll', $.proxy(this.onScroll, this));
		},

		end: function (content) {
			var end = $('

');
			if (content) {
				end.append(content);
			} else {
				end.append('---------');
			}

			this.$element.append(end);
			this.disable();
		},

		getPercentage: function () {
			var height = (this.$element.css('box-sizing') === 'border-box') ? this.$element.outerHeight() : this.$element.height();
			var scrollHeight = this.$element.get(0).scrollHeight;
			return (scrollHeight > height) ? ((height / (scrollHeight - this.curScrollTop)) * 100) : 0;
		},

		fetchData: function (force) {
			var load = $('

');
			var self = this;
			var moreBtn;

			var fetch = function () {
				var helpers = {
					percentage: self.curPercentage,
					scrollTop: self.curScrollTop
				};
				//var $loader = $('

');
				var $loader=$('

');
				load.append($loader);
				//$loader.loader();
				$loader.loader()
				if (self.options.dataSource) {
					self.options.dataSource(helpers, function (resp) {
						var end;
						load.remove();
						if (resp.content) {
							self.$appendToEle.append(resp.content);
						}

						if (resp.end) {
							end = (resp.end !== true) ? resp.end : undefined;
							self.end(end);
						}

						self.fetchingData = false;
					});
				}
			};

			this.fetchingData = true;
			this.$element.append(load);
			if (this.options.hybrid && force !== true) {
				moreBtn = $('<button type="button" class="btn btn-secondary btn-block">more</button>');
				if (typeof this.options.hybrid === 'object') {
					moreBtn.append(this.options.hybrid.label);
				} else {
					moreBtn.append('');
				}

				moreBtn.on('click.fu.infinitescroll', function () {
					moreBtn.remove();
					fetch();
				});
				load.append(moreBtn);
			} else {
				fetch();
			}
		},

		onScroll: function (e) {
			this.curScrollTop = this.$element.scrollTop();
			this.curPercentage = this.getPercentage();
			if (!this.fetchingData && this.curPercentage >= this.options.percentage) {
				this.fetchData();
			}
		}
	};

	// INFINITE SCROLL PLUGIN DEFINITION

	$.fn.infinitescroll = function (option) {
		var args = Array.prototype.slice.call(arguments, 1);
		var methodReturn;

		var $set = this.each(function () {
			var $this = $(this);
			var data = $this.data('fu.infinitescroll');
			var options = typeof option === 'object' && option;

			if (!data) {
				$this.data('fu.infinitescroll', (data = new InfiniteScroll(this, options)));
			}

			if (typeof option === 'string') {
				methodReturn = data[option].apply(data, args);
			}
		});

		return (methodReturn === undefined) ? $set : methodReturn;
	};

	$.fn.infinitescroll.defaults = {
		dataSource: null,
		hybrid: false,//can be true or an object with structure: { 'label': (markup or jQuery obj) }
		percentage: 95//percentage scrolled to the bottom before more is loaded
	};

	$.fn.infinitescroll.Constructor = InfiniteScroll;

	$.fn.infinitescroll.noConflict = function () {
		$.fn.infinitescroll = old;
		return this;
	};

	// NO DATA-API DUE TO NEED OF DATA-SOURCE

	// -- BEGIN UMD WRAPPER AFTERWORD --
})( jQuery, window, document );
// -- END UMD WRAPPER AFTERWORD --
<|endoftext|>


<commit_before>(function(exports) {

	var Window = new Class({
		initialize: function() {
			this.hasInput = true;
			this.backgroundColor = null;
		},
		connect: function(server) {
			this._server = server;
			this._server.clientConnected(this);
			this._windowId = this._server.createWindow({ hasInput: this.hasInput, backgroundColor: this.backgroundColor });
			this._server.selectInput(this, this._windowId, ["Expose", "ConfigureNotify"]);
		},
		handleEvent: function(event) {
			switch (event.type) {
				case "ConfigureNotify":
					return this.configureNotify(event.x, event.y, event.width, event.height);
				case "Expose":
					return this.expose(event.ctx);
			}
		},
		configureNotify: function(x, y, width, height) {
			this.x = x;
			this.y = y;
			this.width = width;
			this.height = height;
		},
		reparent: function(newParent) {
			this._server.reparentWindow(this._windowId, newParent._windowId);
		},
		expose: function() {
		},
		configure: function(x, y, width, height) {
			x = x === undefined ? this.x : x;
			y = y === undefined ? this.y : y;
			width = width === undefined ? this.width : width;
			height = height === undefined ? this.height : height;
			this._server.configureRequest(this._windowId, x | 0, y | 0, width | 0, height | 0);
		}
	});

	var BackgroundWindow = new Class({
		Extends: Window,
		initialize: function() {
			this.parent();
			this._image = new Image();
			this._image.src = "WoodBackground.jpg";
			this.hasInput = false;
		},
		connect: function(server) {
			this.parent(server);
			this.configure(0, 0, server.width, server.height);
		},
		expose: function(wrapper) {
			wrapper.drawWithContext(function(ctx) {
				ctx.drawImage(this._image, 0, 0, this.width, this.height);
			}.bind(this));
			wrapper.clearDamage();
		},
	});

	var FakeWindow = new Class({
		Extends: Window,
		initialize: function(imageSrc, delay) {
			this.parent();
			this._image = new Image();
			this._image.src = imageSrc;

			// Delay every expose by a bit.
			this.expose = new Task(this._draw.bind(this), delay);
		},
		_draw: function(wrapper) {
			wrapper.drawWithContext(function(ctx) {
				ctx.drawImage(this._image, 0, 0, this.width, this.height);
			}.bind(this));
			wrapper.clearDamage();
			return false;
		},
	});

	var SimpleColorWindow = new Class({
		Extends: Window,
		initialize: function(color) {
			this.backgroundColor = color;
		},
		expose: function(wrapper) {
			// Don't draw anything -- the backgroundColor will take
			// care of it for us.
			wrapper.clearDamage();
		},
	});

	var server = new Server(1024, 768);
	document.querySelector(".server").appendChild(server.elem);

	var w = new BackgroundWindow();
	w.connect(server);

	function animWindow(window, freq, amplitude) {
		var delay = 50;
		var stepsPerSec = 1000 / delay;

		var time = 0;
		var origX = window.x;

		var step = freq * (Math.PI * 2 / stepsPerSec);

		function animate() {
			var offs = Math.sin(time) * amplitude;
			var x = origX + offs;
			window.configure(x, undefined, undefined, undefined);
			time += step;
			return true;
		}
		var task = new Task(animate, delay);
		task();
	}

	var colors = ['red', 'orange', 'yellow', 'lightgreen', 'cyan'];
	for (var i = 0; i < 5; i++) {
		var cascade = 40;
		var windowNumber = i + 1;
		var delay = 40 - windowNumber * 10;
		var w = new FakeWindow("TerminalScreenshot.png", delay);
		w.connect(server);
		w.configure(windowNumber * cascade, windowNumber * cascade, 735, 461);
		var freq = i * 0.25 + 0.5;
		animWindow(w, freq, 40);

		var sub = new SimpleColorWindow(colors[i]);
		sub.connect(server);
		sub.configure(50, 20, 100, 50);
		sub.reparent(w);
		animWindow(sub, freq * 2, 40);
	}

	window.addEventListener("keydown", function(evt) {
		var letter = String.fromCharCode(evt.keyCode);
		if (letter === 'D')
			server.toggleDebug();
		if (letter === 'R')
			server.queueFullRedraw();
	});

})(window);
<commit_msg>Don't delay window exposes anymore<commit_after>(function(exports) {

	var Window = new Class({
		initialize: function() {
			this.hasInput = true;
			this.backgroundColor = null;
		},
		connect: function(server) {
			this._server = server;
			this._server.clientConnected(this);
			this._windowId = this._server.createWindow({ hasInput: this.hasInput, backgroundColor: this.backgroundColor });
			this._server.selectInput(this, this._windowId, ["Expose", "ConfigureNotify"]);
		},
		handleEvent: function(event) {
			switch (event.type) {
				case "ConfigureNotify":
					return this.configureNotify(event.x, event.y, event.width, event.height);
				case "Expose":
					return this.expose(event.ctx);
			}
		},
		configureNotify: function(x, y, width, height) {
			this.x = x;
			this.y = y;
			this.width = width;
			this.height = height;
		},
		reparent: function(newParent) {
			this._server.reparentWindow(this._windowId, newParent._windowId);
		},
		expose: function() {
		},
		configure: function(x, y, width, height) {
			x = x === undefined ? this.x : x;
			y = y === undefined ? this.y : y;
			width = width === undefined ? this.width : width;
			height = height === undefined ? this.height : height;
			this._server.configureRequest(this._windowId, x | 0, y | 0, width | 0, height | 0);
		}
	});

	var BackgroundWindow = new Class({
		Extends: Window,
		initialize: function() {
			this.parent();
			this._image = new Image();
			this._image.src = "WoodBackground.jpg";
			this.hasInput = false;
		},
		connect: function(server) {
			this.parent(server);
			this.configure(0, 0, server.width, server.height);
		},
		expose: function(wrapper) {
			wrapper.drawWithContext(function(ctx) {
				ctx.drawImage(this._image, 0, 0, this.width, this.height);
			}.bind(this));
			wrapper.clearDamage();
		},
	});

	var FakeWindow = new Class({
		Extends: Window,
		initialize: function(imageSrc) {
			this.parent();
			this._image = new Image();
			this._image.src = imageSrc;
		},
		expose: function(wrapper) {
			wrapper.drawWithContext(function(ctx) {
				ctx.drawImage(this._image, 0, 0, this.width, this.height);
			}.bind(this));
			wrapper.clearDamage();
		},
	});

	var SimpleColorWindow = new Class({
		Extends: Window,
		initialize: function(color) {
			this.backgroundColor = color;
		},
		expose: function(wrapper) {
			// Don't draw anything -- the backgroundColor will take
			// care of it for us.
			wrapper.clearDamage();
		},
	});

	var server = new Server(1024, 768);
	document.querySelector(".server").appendChild(server.elem);

	var w = new BackgroundWindow();
	w.connect(server);

	function animWindow(window, freq, amplitude) {
		var delay = 50;
		var stepsPerSec = 1000 / delay;

		var time = 0;
		var origX = window.x;

		var step = freq * (Math.PI * 2 / stepsPerSec);

		function animate() {
			var offs = Math.sin(time) * amplitude;
			var x = origX + offs;
			window.configure(x, undefined, undefined, undefined);
			time += step;
			return true;
		}
		var task = new Task(animate, delay);
		task();
	}

	var colors = ['red', 'orange', 'yellow', 'lightgreen', 'cyan'];
	for (var i = 0; i < 5; i++) {
		var cascade = 40;
		var windowNumber = i + 1;
		var w = new FakeWindow("TerminalScreenshot.png");
		w.connect(server);
		w.configure(windowNumber * cascade, windowNumber * cascade, 735, 461);
		var freq = i * 0.25 + 0.5;
		animWindow(w, freq, 40);

		var sub = new SimpleColorWindow(colors[i]);
		sub.connect(server);
		sub.configure(50, 20, 100, 50);
		sub.reparent(w);
		animWindow(sub, freq * 2, 40);
	}

	window.addEventListener("keydown", function(evt) {
		var letter = String.fromCharCode(evt.keyCode);
		if (letter === 'D')
			server.toggleDebug();
		if (letter === 'R')
			server.queueFullRedraw();
	});

})(window);
<|endoftext|>


<commit_before>import positions from '../constants/positions';
import providers from '../constants/providers';
const samosaSearchAPI = {
    saleList: [],
    i:0,
    neededConfirmations: 3,
    location:{
        lat: 45.50492,
        lon: -73.57616
    },
    defaultLocation:{
        lat: 45.50492,
        lon: -73.57616
    },
    keyMap: {},
    cachedDistances: [],
    getLocation(success, error){
        if(!navigator.geolocation) {
            return null;
        }
        else{
            return navigator.geolocation.getCurrentPosition((pos)=> {
                this.location.lat = pos.coords.latitude;
                this.location.lon = pos.coords.longitude;
                success(pos);
            }, error);
        }
    },
    /**
     * Given a sale List we first get an array-like Object containing unique keys
     * we then return an array generated from such an object
     * @param saleList an array of sales
     * @returns {Array.<T>} an array of {positions,count}
     */
    getTags(saleList){
        let pos = null;
        let length = 0;
        let uniqueKeyCount = saleList.reduce(function(prev, next){
            pos = positions[next.loc];
            // if we have a previous location value, we increment the count there.
            if(prev[next.loc]){
                prev[next.loc].count +=1;
            }
            // Otherwise, we give a new object containing the position and a count of 1
            else{
                prev[next.loc] = {position: {lat: pos.lat, lng: pos.lon}, count: 1};
                length +=1;
            }
            return prev;
        },{});
        uniqueKeyCount.length = length;
        return Array.prototype.slice.call(uniqueKeyCount);
    },
    getMapFromLocation(latitude, longitude, saleList, width, height){
        let httpSrc = 'https://dev.virtualearth.net/REST/V1/Imagery/Map/Road';
        let mapKey = providers.BING_KEY;
        let pos = null;
        let saleLocations = saleList.reduce(function(prev, next){
            pos = positions[next.loc];
            prev[next.loc] = prev[next.loc] || {lat: pos.lat, lon: pos.lon, count: 0};
            prev[next.loc].count += 1;
            return prev;
        },{});
        let loc = null;
        let pushPins = '';
        for(let key in saleLocations){
            if(saleLocations.hasOwnProperty(key)) {
                loc = saleLocations[key];
                pushPins += `&pushpin=${loc.lat}%2C${loc.lon};56;${loc.count}`;
            }
        }
        return `${httpSrc}/${latitude}%2C${longitude}/16?mapSize=${width},${height}&format=png${pushPins}&key=${mapKey}`;
    },
    /**
     * get distances from an array of sales, either from the cache
     * or by making a request to an external server
     * @param arr
     * @returns {*}
     */
    getDistances(arr){
        //we get the unique locations of the given array of sales
        let newKeyMap = this._getUniqueKeys(arr);
        this._prepareMap(newKeyMap);
        //for every location in the new map, we already have a valid location
        //so we use the cache
        if(Object.keys(newKeyMap).every(el => this.keyMap.hasOwnProperty(el))){
            console.log('using cached locations');
            return Promise.resolve(this._setDistances(this.cachedDistances, newKeyMap));
        }
        //we make a request to an external server
        else{
            let locations = this._getPreparedLocations(newKeyMap);
            return this.requestDistances(locations).then((results)=> {
                //we parse the results given by the server to valid distances
                results.one_to_many[0].shift();
                let distances = results.one_to_many[0];
                //we update the cached distances, the keyMap and return the updated keyMap
                this.cachedDistances = distances;
                return this._setDistances(distances, newKeyMap);
            }).catch(err => console.log(err));
        }
    },
    _getUniqueKeys(arr){
        return arr.reduce(function(prev,next){
            prev[next.loc] = true;
            return prev;
        },{});
    },
    _prepareMap(map){
        let index = 0;
        for(let key in map){
            if(map.hasOwnProperty(key)){
                map[key] = index++;
            }
        }
    },
    _getPreparedLocations(map){
        return JSON.stringify(Object.keys(map).reduce(function(prev,next){
            prev.push(positions[map[next]]);
            return prev;
        }, [this.location]));
    },
    _setDistances(distances, map){
        for(let key in map){
            if(map.hasOwnProperty(key)) {
                map[key] = distances[map[key]];
            }
        }
        this.keyMap = map;
        return this.keyMap;
    },
    /**
     * make GET request to an external server and get distances (in km)
     * @param locations String a stringfied array of locations
     * @returns resulting distances in km
     */
    requestDistances(locations){
        let httpSrc = 'https://matrix.mapzen.com/one_to_many?json';
        let key = providers.MAPZEN_MATRIX_KEY;
        let url = `${httpSrc}={"locations":${locations},"costing":"pedestrian"}&id=mosa&api_key=${key}`;

        //perform the actual GET request and parse it
        return fetch(url).then(res=>res.json());
    }
};

export default samosaSearchAPI;<commit_msg>fixed small error when getting tags<commit_after>import positions from '../constants/positions';
import providers from '../constants/providers';
const samosaSearchAPI = {
    saleList: [],
    i:0,
    neededConfirmations: 3,
    location:{
        lat: 45.50492,
        lon: -73.57616
    },
    defaultLocation:{
        lat: 45.50492,
        lon: -73.57616
    },
    keyMap: {},
    cachedDistances: [],
    getLocation(success, error){
        if(!navigator.geolocation) {
            return null;
        }
        else{
            return navigator.geolocation.getCurrentPosition((pos)=> {
                this.location.lat = pos.coords.latitude;
                this.location.lon = pos.coords.longitude;
                success(pos);
            }, error);
        }
    },
    /**
     * Given a sale List we first get an array-like Object containing unique keys
     * we then return an array generated from such an object
     * @param saleList an array of sales
     * @returns {Array.<T>} an array of {positions,count}
     */
    getTags(saleList){
        let pos = null;
        let uniqueKeyCount = saleList.reduce(function(prev, next){
            pos = positions[next.loc];
            // if we have a previous location value, we increment the count there.
            if(prev[next.loc]){
                prev[next.loc].count +=1;
            }
            // Otherwise, we give a new object containing the position and a count of 1
            else{
                prev[next.loc] = {position: {lat: pos.lat, lng: pos.lon}, count: 1};
            }
            return prev;
        },{});
        return Object.keys(uniqueKeyCount).map(key=>uniqueKeyCount[key]);
    },
    getMapFromLocation(latitude, longitude, saleList, width, height){
        let httpSrc = 'https://dev.virtualearth.net/REST/V1/Imagery/Map/Road';
        let mapKey = providers.BING_KEY;
        let pos = null;
        let saleLocations = saleList.reduce(function(prev, next){
            pos = positions[next.loc];
            prev[next.loc] = prev[next.loc] || {lat: pos.lat, lon: pos.lon, count: 0};
            prev[next.loc].count += 1;
            return prev;
        },{});
        let loc = null;
        let pushPins = '';
        for(let key in saleLocations){
            if(saleLocations.hasOwnProperty(key)) {
                loc = saleLocations[key];
                pushPins += `&pushpin=${loc.lat}%2C${loc.lon};56;${loc.count}`;
            }
        }
        return `${httpSrc}/${latitude}%2C${longitude}/16?mapSize=${width},${height}&format=png${pushPins}&key=${mapKey}`;
    },
    /**
     * get distances from an array of sales, either from the cache
     * or by making a request to an external server
     * @param arr
     * @returns {*}
     */
    getDistances(arr){
        //we get the unique locations of the given array of sales
        let newKeyMap = this._getUniqueKeys(arr);
        this._prepareMap(newKeyMap);
        //for every location in the new map, we already have a valid location
        //so we use the cache
        if(Object.keys(newKeyMap).every(el => this.keyMap.hasOwnProperty(el))){
            console.log('using cached locations');
            return Promise.resolve(this._setDistances(this.cachedDistances, newKeyMap));
        }
        //we make a request to an external server
        else{
            let locations = this._getPreparedLocations(newKeyMap);
            return this.requestDistances(locations).then((results)=> {
                //we parse the results given by the server to valid distances
                results.one_to_many[0].shift();
                let distances = results.one_to_many[0];
                //we update the cached distances, the keyMap and return the updated keyMap
                this.cachedDistances = distances;
                return this._setDistances(distances, newKeyMap);
            }).catch(err => console.log(err));
        }
    },
    _getUniqueKeys(arr){
        return arr.reduce(function(prev,next){
            prev[next.loc] = true;
            return prev;
        },{});
    },
    _prepareMap(map){
        let index = 0;
        for(let key in map){
            if(map.hasOwnProperty(key)){
                map[key] = index++;
            }
        }
    },
    _getPreparedLocations(map){
        return JSON.stringify(Object.keys(map).reduce(function(prev,next){
            prev.push(positions[map[next]]);
            return prev;
        }, [this.location]));
    },
    _setDistances(distances, map){
        for(let key in map){
            if(map.hasOwnProperty(key)) {
                map[key] = distances[map[key]];
            }
        }
        this.keyMap = map;
        return this.keyMap;
    },
    /**
     * make GET request to an external server and get distances (in km)
     * @param locations String a stringfied array of locations
     * @returns resulting distances in km
     */
    requestDistances(locations){
        let httpSrc = 'https://matrix.mapzen.com/one_to_many?json';
        let key = providers.MAPZEN_MATRIX_KEY;
        let url = `${httpSrc}={"locations":${locations},"costing":"pedestrian"}&id=mosa&api_key=${key}`;

        //perform the actual GET request and parse it
        return fetch(url).then(res=>res.json());
    }
};

export default samosaSearchAPI;<|endoftext|>


<commit_before>/* Lyle Scott, III
 * lyle@digitalfoo.net
 * http://digitalfoo.net
 */

var KEY_ENTER = 13;
var HOST = 'http://localhost:8080';

function ajaxError(jqXHR, textStatus, errorThrown) {
	// Attempt to gracefully print an error in a jQuery AJAX call.
    if (console && console.log) {
        console.log('jQuery AJAX error:\n' +
        		    textStatus + '\n' +
        		    errorThrown);
    }
}

function getSuggestionAjaxCall(query) {
	// Make an AJAX call to get a list of suggestions.
    $.ajax({
        url: HOST + '',
        data: {'userinput': query, 'cb': 'get_suggestions'},
        datatype: 'jsonp',
        jsonp: 'callback',
        jsonpCallback: 'get_suggestions',
        success: getSuggestionsCallback,
        error: ajaxError
    });
}

function getSuggestionsCallback(data, textStatus, jqXHR) {
	// Parse the returned value as JSON.
    data = data.substring('get_suggestions('.length, data.length);
    data = data.substring(0, data.length-1);

    var html = '';

    try {
        var json = $.parseJSON(data);
        if (json && json.results) {
            html = json.results.join('
');
        }
    } catch (e) {
    	if (console && console.log) {
            console.log('error in the get_suggestions() callback: ' + e);
            console.log(e);
        }
    }

    if (html.length) {
        html = html.replace(/__MARK_START__/g, '');
        html = html.replace(/__MARK_END__/g, '');
        html = '
' + html + '
';
    }

    $('#suggestions').html(html);
}

function submitQueryAjaxCall(query) {
    // Make an AJAX call to get a list of suggestions.
    $.ajax({
        url: HOST,
        data: {'userinput': query, 'cb': 'submit_query'},
        datatype: 'jsonp',
        jsonp: 'callback',
        jsonpCallback: 'submit_query',
        success: submitQueryCallback,
        error: ajaxError
    });
}

function submitQueryCallback(data, textStatus, jqXHR) {
    // Parse the returned value as JSON.
    data = data.substring('submit_query('.length, data.length);
    data = data.substring(0, data.length-1);

    var html = '';

    try {
        var json = $.parseJSON(data);
        if (json) {
        	html = 'query added';
        }
    } catch (e) {
        if (console && console.log) {
        	console.log('error in the submit_query() callback: ' + e);
        	console.log(e);
        }
    }

    $('#status').html(html);
    setTimeout(function() { $('#status').html(''); }, 2000);
}

$(document).ready(function(){

    $("#userinput").bind('keyup', function(event) {

    	// Bail if no input in the text entry.
    	if (!$(this).val()) {
            return;
        }

    	var query = $(this).val();

    	if (event && event.keyCode == KEY_ENTER) {
            // Add the query to the collection of known queries.
            submitQueryAjaxCall(query);
            $(this).val('');
            $('#suggestions').html('');
    	} else {
            // Get suggestions based on what the user is typing.
    		getSuggestionAjaxCall(query);
    	}
    });  // userinput keyup

});  // end document ready
<commit_msg>Don't return results wrapped with paragraph tags.<commit_after>/* Lyle Scott, III
 * lyle@digitalfoo.net
 * http://digitalfoo.net
 */

var KEY_ENTER = 13;
var HOST = 'http://localhost:8080';

function ajaxError(jqXHR, textStatus, errorThrown) {
	// Attempt to gracefully print an error in a jQuery AJAX call.
    if (console && console.log) {
        console.log('jQuery AJAX error:\n' +
        		    textStatus + '\n' +
        		    errorThrown);
    }
}

function getSuggestionAjaxCall(query) {
	// Make an AJAX call to get a list of suggestions.
    $.ajax({
        url: HOST + '',
        data: {'userinput': query, 'cb': 'get_suggestions'},
        datatype: 'jsonp',
        jsonp: 'callback',
        jsonpCallback: 'get_suggestions',
        success: getSuggestionsCallback,
        error: ajaxError
    });
}

function getSuggestionsCallback(data, textStatus, jqXHR) {
	// Parse the returned value as JSON.
    data = data.substring('get_suggestions('.length, data.length);
    data = data.substring(0, data.length-1);

    var html = '';

    try {
        var json = $.parseJSON(data);
        if (json && json.results) {
            html = json.results.join('
');
        }
    } catch (e) {
    	if (console && console.log) {
            console.log('error in the get_suggestions() callback: ' + e);
            console.log(e);
        }
    }

    if (html.length) {
        html = html.replace(/__MARK_START__/g, '');
        html = html.replace(/__MARK_END__/g, '');
    }

    $('#suggestions').html(html);
}

function submitQueryAjaxCall(query) {
    // Make an AJAX call to get a list of suggestions.
    $.ajax({
        url: HOST,
        data: {'userinput': query, 'cb': 'submit_query'},
        datatype: 'jsonp',
        jsonp: 'callback',
        jsonpCallback: 'submit_query',
        success: submitQueryCallback,
        error: ajaxError
    });
}

function submitQueryCallback(data, textStatus, jqXHR) {
    // Parse the returned value as JSON.
    data = data.substring('submit_query('.length, data.length);
    data = data.substring(0, data.length-1);

    var html = '';

    try {
        var json = $.parseJSON(data);
        if (json) {
        	html = 'query added';
        }
    } catch (e) {
        if (console && console.log) {
        	console.log('error in the submit_query() callback: ' + e);
        	console.log(e);
        }
    }

    $('#status').html(html);
    setTimeout(function() { $('#status').html(''); }, 2000);
}

$(document).ready(function(){

    $("#userinput").bind('keyup', function(event) {

    	// Bail if no input in the text entry.
    	if (!$(this).val()) {
            return;
        }

    	var query = $(this).val();

    	if (event && event.keyCode == KEY_ENTER) {
            // Add the query to the collection of known queries.
            submitQueryAjaxCall(query);
            $(this).val('');
            $('#suggestions').html('');
    	} else {
            // Get suggestions based on what the user is typing.
    		getSuggestionAjaxCall(query);
    	}
    });  // userinput keyup

});  // end document ready
<|endoftext|>


<commit_before>var config = require('./config')
var app, express, http, io, server, socket;
var bodyParser = require('body-parser');
var path = require("path");

http = require('http');
io = require('socket.io');
express = require('express');

app = express();

// Configure NodeJS Express server
app.use(bodyParser.json())
app.use(express.static(path.join(__dirname, 'public')));

server = http.createServer(app);

// This is the Express server and Port
// Where the webapp will receive requests
server.listen(config.express.port);

app.get('/', function(req, res) {
	return res.sendFile(__dirname + '/Demo.html');
});

// Set the socket to listen in on the Express port.
socket = io.listen(server);

// Connect to the socket connection to wait for requests from the client
socket.sockets.on('connection', function(client) {
    console.log("A new client has connected");

    client.emit("msg", "Hello there little buddy");
});
<commit_msg>updated config key for socket.io<commit_after>var config = require('./config')
var app, express, http, io, server, socket;
var bodyParser = require('body-parser');
var path = require("path");

http = require('http');
io = require('socket.io');
express = require('express');

app = express();

// Configure NodeJS Express server
app.use(bodyParser.json())
app.use(express.static(path.join(__dirname, 'public')));

server = http.createServer(app);

// This is the Express server and Port
// Where the webapp will receive requests
server.listen(config.socketio.port);

app.get('/', function(req, res) {
	return res.sendFile(__dirname + '/Demo.html');
});

// Set the socket to listen in on the Express port.
socket = io.listen(server);

// Connect to the socket connection to wait for requests from the client
socket.sockets.on('connection', function(client) {
    console.log("A new client has connected");

    client.emit("msg", "Hello there little buddy");
});
<|endoftext|>


<commit_before>import React, {View, Text, TouchableHighlight} from 'react-native';

import ArticleRowStyleSheet from './ArticleRowStyleSheet';
import ArticleActions from './ArticleActions';
import ArticleStore from './ArticleStore';

class ArticleRow extends React.Component {

  constructor(props) {
    super(props);
  }

  onArticleChange() {
    let article = ArticleStore.getArticle(this.props.articleId)
    this.setState({
      article: ArticleStore.getArticle(this.props.articleId)
    });
  }

  componentDidMount() {
    ArticleStore.addArticleChangeListener(this.props.articleId, this.onArticleChange.bind(this));
    ArticleActions.getArticle(this.props.articleId);
  }

  render() {

    let content;
    if (this.state && this.state.article) {
      content = (<Text>{this.state.article.title}</Text>)
    } else {
      content = (<Text>{this.props.articleId}</Text>);
    }

    return (
      <TouchableHighlight
        onPress={this.props.highlightRowFn}
        style={ArticleRowStyleSheet.container}>

        {content}

      </TouchableHighlight>
    );

  }

}

ArticleRow.propTypes = {
  articleId: React.PropTypes.number
}

export default ArticleRow;
<commit_msg>adding light styling to rows<commit_after>import React, {View, Text, TouchableHighlight, TouchableOpacity} from 'react-native';

import ArticleRowStyleSheet from './ArticleRowStyleSheet';
import ArticleActions from './ArticleActions';
import ArticleStore from './ArticleStore';

class ArticleRow extends React.Component {

  constructor(props) {
    super(props);
  }

  onArticleChange() {
    let article = ArticleStore.getArticle(this.props.articleId)
    this.setState({
      article: ArticleStore.getArticle(this.props.articleId)
    });
  }

  componentDidMount() {
    ArticleStore.addArticleChangeListener(this.props.articleId, this.onArticleChange.bind(this));
    ArticleActions.getArticle(this.props.articleId);
  }

  render() {

    let content;
    if (this.state && this.state.article) {
      content = this.state.article.title;
    } else {
      content = this.props.articleId;
    }

    return (
      <TouchableHighlight
        underlayColor="#fffcfa"
        style={[ArticleRowStyleSheet.container, {backgroundColor: '#fbf7f5'}]}>

        <Text style={{fontSize: '15'}}>{content}</Text>

      </TouchableHighlight>
    );

  }

}

ArticleRow.propTypes = {
  articleId: React.PropTypes.number
}

export default ArticleRow;
<|endoftext|>


<commit_before>import {DOM_CHANGED_EVENT} from '../classes/fef-dom-observer';
import {FefResponsiveHelper} from '../classes/fef-responsive-helper';

const ANIMATION_SPEED = 200;
const KEYCODES = {
    'enter': 13,
    'tab': 9,
    'escape': 27
};
const END_OF_MODAL = '.js-end-of-modal';

let existingModals = {};
let scrollbarWidth = 0;

$(window).on(DOM_CHANGED_EVENT, (e) => {
    scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
    $('[data-modal-id]').each((index, element) => {

        $(element).on('click', () => {
            let $caller = $(element);
            let modalId = $caller.attr('data-modal-id');
            let $modalElement = $(`[data-id=${modalId}]`);

            if (existingModals[modalId]) {
                existingModals[modalId].show();
            } else if ($modalElement.length > 0) {
                existingModals[modalId] = new FefModal($modalElement, $caller);
            }
        });
    });
});

/**
 * Handles showing and hiding a modal element
 */
export class FefModal {

    /**
     * @param $element jQuery element
     * @param $caller jQuery element
     */
    constructor($element, $caller) {
        this.$element = $element;
        this.$caller = $caller;
        this.$focusTarget = this.$element.find('.js-focus-target').first();
        this.$mainWrapper = this.$element.find('.js-modal-main-wrapper');
        this.$mainContent = this.$element.find('.js-modal-main-content');
        this.animation = this.$element.attr('data-animation');
        this.previousScrollPosition = null;

        $element.append('');
        this.$mainWrapper.append('Schliessen');

        this.bindEvents();

        if (this.$element.hasClass('js-min-height-of-masthead')) {
            this.$mainContent.css('min-height', $('.js-masthead').outerHeight());
        }

        this.postInit();
    }

    postInit() {
        this.show();
    }

    /**
     * Binds the relevant events for this modal:
     * - Click on a close-button or the overlay
     * - Pressing Escape
     */
    bindEvents() {
        this.$element.find('.js-close-modal, .js-modal-overlay').on('click', () => {
            this.close();
        });

        this.$element.on('keydown', (e) => {
            if (e.keyCode === KEYCODES.escape) {
                this.close();
            }
        });

        // A11Y Helper: when tabbing out of the modal --> on focus, close modal, set focus to the caller
        $(END_OF_MODAL).on('focus', () => {
            this.close();
        });
    }

    /**
     * Show the modal, depending on the provided animation.
     */
    show() {
        const showCallback = () => this.onShowFinished();

        this.$caller.attr({'aria-expanded': true, 'aria-haspopup': true});

        switch (this.animation) {
            case 'scale-from-origin':
                this.scaleFromOrigin(showCallback);
                break;
            case 'fade-in-out':
                this.$element.stop(true, true).fadeIn(ANIMATION_SPEED, showCallback);
                break;
            default:
                this.$element.show(showCallback);
                break;
        }
    }

    onShowFinished() {
        this.preventScrolling();

        if (this.$focusTarget.length === 1) {
            this.setFocus(this.$focusTarget);
        }
    }

    /**
     * Hide the modal, depending on the provided animation.
     */
    close() {
        this.scrollToPreviousPosition();

        this.$caller.attr({'aria-expanded': false, 'aria-haspopup': false});

        switch (this.animation) {
            case 'fade-in-out':
                this.$element.stop(true, true).fadeOut(ANIMATION_SPEED);
                break;
            default:
                this.$element.hide();
                break;
        }

        this.setFocus(this.$caller);
    }

    /**
     * Simply using .focus() doesn't suffice.
     *
     * @param $element jQuery.Element
     */
    setFocus($element) {
        $element.attr('tabindex', -1).on('blur focusout', () => {
            $element.removeAttr('tabindex');
        }).focus();
    }

    /**
     * Fancy menu opening animation:
     * - fades the modal in
     * - 'opens' it from the originating element
     * - fades in the content (otherwise it'll be resized)
     * - calls an optional callback
     *
     * For aesthetical reasons we have to animate to the previous height and not 100% max-height directly.
     */
    scaleFromOrigin(callBack) {
        this.$mainContent.css('opacity', 0);
        this.$element.show();

        let originalHeight = this.$mainWrapper.height();
        let box = this.$caller[0].getBoundingClientRect();
        this.$mainWrapper.css({
            'left': box.left,
            'width': box.width,
            'max-height': box.height,
            'top': box.top,
            'opacity': 0
        }).animate({
            'left': 0,
            'width': '100%',
            'max-height': originalHeight,
            'top': 0,
            'opacity': 1
        }, ANIMATION_SPEED, 'easeInOutSine', () => {
            // remove the scrollbars
            this.$mainWrapper.css({
                'max-height': '100%',
                'width': `calc(100% + ${scrollbarWidth}px)`,
                'margin-right': scrollbarWidth,
                'padding-right': scrollbarWidth
            });
            this.$mainContent.animate({
                'opacity': 1
            }, ANIMATION_SPEED, callBack);
        });
    }

    /**
     * Prevent scrollable page when the modal is open.
     * We achieve this by setting the body to overflow: hidden and setting the height to 100%, thus
     * effectively cutting the rest of the page off. This scrolls to the top of the page, so we
     * also have to save the previous scroll state.
     *
     * We only do this if the modal covers the whole page and on mobile/tablet.
     */
    preventScrolling() {
        if (this.$mainContent.outerHeight() >= $(window).outerHeight() && (FefResponsiveHelper.isTablet() || FefResponsiveHelper.isSmartphone())) {
            this.previousScrollPosition = $(window).scrollTop();
            $('html').addClass('h-prevent-scrolling');
        }
    }

    /**
     * If, upon opening the modal, the ability to scroll was removed, we give it back now. This means:
     * - removing the class that prevents the scrolling
     * - scrolling back to the previously saved scroll position
     *
     * This makes it appear as if we never even scrolled away.
     */
    scrollToPreviousPosition() {
        if (this.previousScrollPosition !== null) {
            $('html').removeClass('h-prevent-scrolling');
            $(window).scrollTop(this.previousScrollPosition);
            this.previousScrollPosition = null;
        }
    }
}
<commit_msg>pr feedback - no arrow function needed here<commit_after>import {DOM_CHANGED_EVENT} from '../classes/fef-dom-observer';
import {FefResponsiveHelper} from '../classes/fef-responsive-helper';

const ANIMATION_SPEED = 200;
const KEYCODES = {
    'enter': 13,
    'tab': 9,
    'escape': 27
};
const END_OF_MODAL = '.js-end-of-modal';

let existingModals = {};
let scrollbarWidth = 0;

$(window).on(DOM_CHANGED_EVENT, (e) => {
    scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
    $('[data-modal-id]').each((index, element) => {

        $(element).on('click', () => {
            let $caller = $(element);
            let modalId = $caller.attr('data-modal-id');
            let $modalElement = $(`[data-id=${modalId}]`);

            if (existingModals[modalId]) {
                existingModals[modalId].show();
            } else if ($modalElement.length > 0) {
                existingModals[modalId] = new FefModal($modalElement, $caller);
            }
        });
    });
});

/**
 * Handles showing and hiding a modal element
 */
export class FefModal {

    /**
     * @param $element jQuery element
     * @param $caller jQuery element
     */
    constructor($element, $caller) {
        this.$element = $element;
        this.$caller = $caller;
        this.$focusTarget = this.$element.find('.js-focus-target').first();
        this.$mainWrapper = this.$element.find('.js-modal-main-wrapper');
        this.$mainContent = this.$element.find('.js-modal-main-content');
        this.animation = this.$element.attr('data-animation');
        this.previousScrollPosition = null;

        $element.append('');
        this.$mainWrapper.append('Schliessen');

        this.bindEvents();

        if (this.$element.hasClass('js-min-height-of-masthead')) {
            this.$mainContent.css('min-height', $('.js-masthead').outerHeight());
        }

        this.postInit();
    }

    postInit() {
        this.show();
    }

    /**
     * Binds the relevant events for this modal:
     * - Click on a close-button or the overlay
     * - Pressing Escape
     */
    bindEvents() {
        this.$element.find('.js-close-modal, .js-modal-overlay').on('click', () => {
            this.close();
        });

        this.$element.on('keydown', (e) => {
            if (e.keyCode === KEYCODES.escape) {
                this.close();
            }
        });

        // A11Y Helper: when tabbing out of the modal --> on focus, close modal, set focus to the caller
        $(END_OF_MODAL).on('focus', () => {
            this.close();
        });
    }

    /**
     * Show the modal, depending on the provided animation.
     */
    show() {
        this.$caller.attr({'aria-expanded': true, 'aria-haspopup': true});

        switch (this.animation) {
            case 'scale-from-origin':
                this.scaleFromOrigin(this.onShowFinished);
                break;
            case 'fade-in-out':
                this.$element.stop(true, true).fadeIn(ANIMATION_SPEED, this.onShowFinished);
                break;
            default:
                this.$element.show(this.onShowFinished);
                break;
        }
    }

    onShowFinished() {
        this.preventScrolling();

        if (this.$focusTarget.length === 1) {
            this.setFocus(this.$focusTarget);
        }
    }

    /**
     * Hide the modal, depending on the provided animation.
     */
    close() {
        this.scrollToPreviousPosition();

        this.$caller.attr({'aria-expanded': false, 'aria-haspopup': false});

        switch (this.animation) {
            case 'fade-in-out':
                this.$element.stop(true, true).fadeOut(ANIMATION_SPEED);
                break;
            default:
                this.$element.hide();
                break;
        }

        this.setFocus(this.$caller);
    }

    /**
     * Simply using .focus() doesn't suffice.
     *
     * @param $element jQuery.Element
     */
    setFocus($element) {
        $element.attr('tabindex', -1).on('blur focusout', () => {
            $element.removeAttr('tabindex');
        }).focus();
    }

    /**
     * Fancy menu opening animation:
     * - fades the modal in
     * - 'opens' it from the originating element
     * - fades in the content (otherwise it'll be resized)
     * - calls an optional callback
     *
     * For aesthetical reasons we have to animate to the previous height and not 100% max-height directly.
     */
    scaleFromOrigin(callBack) {
        this.$mainContent.css('opacity', 0);
        this.$element.show();

        let originalHeight = this.$mainWrapper.height();
        let box = this.$caller[0].getBoundingClientRect();
        this.$mainWrapper.css({
            'left': box.left,
            'width': box.width,
            'max-height': box.height,
            'top': box.top,
            'opacity': 0
        }).animate({
            'left': 0,
            'width': '100%',
            'max-height': originalHeight,
            'top': 0,
            'opacity': 1
        }, ANIMATION_SPEED, 'easeInOutSine', () => {
            // remove the scrollbars
            this.$mainWrapper.css({
                'max-height': '100%',
                'width': `calc(100% + ${scrollbarWidth}px)`,
                'margin-right': scrollbarWidth,
                'padding-right': scrollbarWidth
            });
            this.$mainContent.animate({
                'opacity': 1
            }, ANIMATION_SPEED, callBack);
        });
    }

    /**
     * Prevent scrollable page when the modal is open.
     * We achieve this by setting the body to overflow: hidden and setting the height to 100%, thus
     * effectively cutting the rest of the page off. This scrolls to the top of the page, so we
     * also have to save the previous scroll state.
     *
     * We only do this if the modal covers the whole page and on mobile/tablet.
     */
    preventScrolling() {
        if (this.$mainContent.outerHeight() >= $(window).outerHeight() && (FefResponsiveHelper.isTablet() || FefResponsiveHelper.isSmartphone())) {
            this.previousScrollPosition = $(window).scrollTop();
            $('html').addClass('h-prevent-scrolling');
        }
    }

    /**
     * If, upon opening the modal, the ability to scroll was removed, we give it back now. This means:
     * - removing the class that prevents the scrolling
     * - scrolling back to the previously saved scroll position
     *
     * This makes it appear as if we never even scrolled away.
     */
    scrollToPreviousPosition() {
        if (this.previousScrollPosition !== null) {
            $('html').removeClass('h-prevent-scrolling');
            $(window).scrollTop(this.previousScrollPosition);
            this.previousScrollPosition = null;
        }
    }
}
<|endoftext|>