<commit_before>function generateDashboard(data,activities,geom){
    var map = new lg.map('#map').geojson(geom).nameAttr('NAME').joinAttr('ISO_A3').zoom(2).center([20,-80]);
    console.log(data)
    var status = new lg.column('#status')
                        .label('Status')
                        .domain([0,1])
                        .axisLabels(false)
                        .valueAccessor(function(d){
                            if(d== 'Rojo'){
                                return 1;
                            } else if (d=='Amarillo'){
                                return 0.99999
                            } else if (d== 'Verde'){
                                return 0.99998
                            } else {
                                return null;
                            }
                        })
                        .colorAccessor(function(d,i,max){
                            if(d=='Rojo'){
                                return 2;
                            } else if(d=='Amarillo'){
                                return 1;
                            } else {
                                return 0;
                            }
                        })
                        .colors(['#99d594','#ffcc00','#ff0000']);

    var affected = new lg.column('#affected+total').label('No. Affected').scale(d3.scale.log()).domain([1,1500000])
                        .colors(['#edf8fb','#b3cde3','#8c96c6','#8856a7','#810f7c'])
                        .colorAccessor(
                            function(d,i,max){
                                d=Math.log(d+1);
                                max=Math.log(max);
                                var c = Math.floor(d/max*5);
                                if(c==5){c=4}
                                return c
                            }
                        );

    var affectedper100000 = new lg.column('#affected+percapita').label('Affected per 100,000').scale(d3.scale.log()).domain([1,1000])
                        .colors(['#edf8fb','#b3cde3','#8c96c6','#8856a7','#810f7c'])
                        .colorAccessor(
                            function(d,i,max){
                                d=Math.log(d+1);
                                max=Math.log(max);
                                var c = Math.floor(d/max*5);
                                if(c==5){c=4}
                                return c
                            }
                        );
                        console.log(activities);
    var vAccessor = function(d){
                            if(d== 'true'){
                                return 1;
                            } else {
                                return 0.99999
                            }
                        };

    var cAccessor = function(d,i,max){
                            if(d=='true'){
                                return 0;
                            } else {
                                return 1;
                            }
                        }

    var colors = ['#81C784','#FFCDD2'];

    var riskComms = new lg.column('#activity+riskcomms').label('Risk communication to general public').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var commClean = new lg.column("#activity+cleanup").label('Community clean-up campaigns').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var hhPro = new lg.column("#activity+hhprotection").label('Household and personal protection').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var infoPreg = new lg.column("#activity+infowomen").label('Information and commodities for pregnant women').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var psySup = new lg.column("#activity+pyschosupport").label('Psychosocial support for affected families').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var bloodSafe = new lg.column("#activity+bloodsafety").label('Blood safety').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var chemCont = new lg.column("activity+chemvectorcontrol").label('Chemical vector control').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var protPart = new lg.column("#activity+protectionpartsettings").label('Protection for particular settings').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var commSurv = new lg.column("activity+communitybasedsurveillance").label('Community-based surveillance').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);

    var grid1 = new lg.grid('#grid1')
        .data(data)
        .width($('#grid1').width())
        .height(1200)
        .nameAttr('#country')
        .joinAttr('#country+code')
        .hWhiteSpace(4)
        .vWhiteSpace(4)
        .margins({top: 150, right: 20, bottom: 30, left: 200})
        .columns([status,affected,affectedper100000]);

    var grid2 = new lg.grid('#grid2')
        .data(activities)
        .width($('#grid1').width())
        .height(1200)
        .nameAttr('#country')
        .joinAttr('#country+code')
        .hWhiteSpace(6)
        .vWhiteSpace(6)
        .margins({top: 150, right: 20, bottom: 30, left: 200})
        .columns([riskComms,commClean,hhPro,infoPreg,psySup,bloodSafe,chemCont,protPart,commSurv]);

    lg.init();

    $("#map").width($("#map").width());

}

function hxlProxyToJSON(input,headers){
    var output = [];
    var keys=[]
    input.forEach(function(e,i){
        if(i==0){
            e.forEach(function(e2,i2){
                var parts = e2.split('+');
                var key = parts[0]
                if(parts.length>1){
                    var atts = parts.splice(1,parts.length);
                    atts.sort();
                    atts.forEach(function(att){
                        key +='+'+att
                    });
                }
                keys.push(key);
            });
        } else {
            var row = {};
            e.forEach(function(e2,i2){
                row[keys[i2]] = e2;
            });
            output.push(row);
        }
    });
    return output;
}

function stickydiv(){
    var window_top = $(window).scrollTop();
    var div_top = $('#sticky-anchor').offset().top;
    if (window_top > div_top){
        $('#map-container').addClass('sticky');
    }
    else{
        $('#map-container').removeClass('sticky');
    }
};

$('#grid2').hide();

$('#overviewbutton').on('click',function(){
    $('#grid2').hide();
    $('#grid1').show();
});

$('#activitiesbutton').on('click',function(){
    $('#grid1').hide();
    $('#grid2').show();
});

$(window).scroll(function(){
    stickydiv();
});

//load data

var dataCall = $.ajax({
    type: 'GET',
    url: 'data/dashboard.csv',
    dataType: 'text',
});

var activitiesCall = $.ajax({
    type: 'GET',
    url: 'data/nsactivities.csv',
    dataType: 'text',
});

//load geometry

var geomCall = $.ajax({
    type: 'GET',
    url: 'data/geom.json',
    dataType: 'json',
});

//when both ready construct dashboard

$.when(dataCall, activitiesCall, geomCall).then(function(dataArgs, activitiesArgs, geomArgs){
    geom = topojson.feature(geomArgs[0],geomArgs[0].objects.geom);
    overview = hxlProxyToJSON(Papa.parse(dataArgs[0]).data,false);
    activities = hxlProxyToJSON(Papa.parse(activitiesArgs[0]).data,false);
    overview.forEach(function(d){
        if(d['#population']==0){
            d['#affected+percapita'] = null
        } else {
            d['#affected+percapita'] = d['#affected+total']/d['#population']*100000
        }
    })
    generateDashboard(overview,activities,geom);
});
<commit_msg>added more columns<commit_after>function generateDashboard(data,activities,geom){
    var map = new lg.map('#map').geojson(geom).nameAttr('NAME').joinAttr('ISO_A3').zoom(2).center([20,-80]);
    console.log(data)
    var status = new lg.column('#status')
                        .label('Status')
                        .domain([0,1])
                        .axisLabels(false)
                        .valueAccessor(function(d){
                            if(d== 'Rojo'){
                                return 1;
                            } else if (d=='Amarillo'){
                                return 0.99999
                            } else if (d== 'Verde'){
                                return 0.99998
                            } else {
                                return null;
                            }
                        })
                        .colorAccessor(function(d,i,max){
                            if(d=='Rojo'){
                                return 2;
                            } else if(d=='Amarillo'){
                                return 1;
                            } else {
                                return 0;
                            }
                        })
                        .colors(['#99d594','#ffcc00','#ff0000']);

    max = d3.max(data,function(d){return +d['#affected+total']});
    var affected = new lg.column('#affected+total').label('No. Affected').scale(d3.scale.log()).domain([1,max])
                        .colors(['#edf8fb','#b3cde3','#8c96c6','#8856a7','#810f7c'])
                        .colorAccessor(
                            function(d,i,max){
                                d=Math.log(d+1);
                                max=Math.log(max);
                                var c = Math.floor(d/max*5);
                                if(c==5){c=4}
                                return c
                            }
                        );

    max = d3.max(data,function(d){return +d['#affected+confirmed']});
    var confirmed = new lg.column('#affected+confirmed').label('Confirmed Cases').scale(d3.scale.log()).domain([1,max])
                        .colors(['#edf8fb','#b3cde3','#8c96c6','#8856a7','#810f7c'])
                        .colorAccessor(
                            function(d,i,max){
                                d=Math.log(d+1);
                                max=Math.log(max);
                                var c = Math.floor(d/max*5);
                                if(c==5){c=4}
                                return c
                            }
                        );

    max = d3.max(data,function(d){return +d['#affected+suspected']});
    var suspected = new lg.column('#affected+suspected').label('Suspected Cases').scale(d3.scale.log()).domain([1,max])
                        .colors(['#edf8fb','#b3cde3','#8c96c6','#8856a7','#810f7c'])
                        .colorAccessor(
                            function(d,i,max){
                                d=Math.log(d+1);
                                max=Math.log(max);
                                var c = Math.floor(d/max*5);
                                if(c==5){c=4}
                                return c
                            }
                        );

    var affectedper100000 = new lg.column('#affected+percapita').label('Affected per 100,000').scale(d3.scale.log()).domain([1,1000])
                        .colors(['#edf8fb','#b3cde3','#8c96c6','#8856a7','#810f7c'])
                        .colorAccessor(
                            function(d,i,max){
                                d=Math.log(d+1);
                                max=Math.log(max);
                                var c = Math.floor(d/max*5);
                                if(c==5){c=4}
                                return c
                            }
                        );
                        console.log(activities);
    var vAccessor = function(d){
                            if(d== 'true'){
                                return 1;
                            } else {
                                return 0.99999
                            }
                        };

    var cAccessor = function(d,i,max){
                            if(d=='true'){
                                return 0;
                            } else {
                                return 1;
                            }
                        }

    var colors = ['#81C784','#FFCDD2'];

    var riskComms = new lg.column('#activity+riskcomms').label('Risk communication to general public').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var commClean = new lg.column("#activity+cleanup").label('Community clean-up campaigns').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var hhPro = new lg.column("#activity+hhprotection").label('Household and personal protection').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var infoPreg = new lg.column("#activity+infowomen").label('Information and commodities for pregnant women').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var psySup = new lg.column("#activity+pyschosupport").label('Psychosocial support for affected families').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var bloodSafe = new lg.column("#activity+bloodsafety").label('Blood safety').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var chemCont = new lg.column("activity+chemvectorcontrol").label('Chemical vector control').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var protPart = new lg.column("#activity+protectionpartsettings").label('Protection for particular settings').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);
    var commSurv = new lg.column("activity+communitybasedsurveillance").label('Community-based surveillance').domain([0,1]).axisLabels(false).valueAccessor(vAccessor).colorAccessor(cAccessor).colors(colors);

    var grid1 = new lg.grid('#grid1')
        .data(data)
        .width($('#grid1').width())
        .height(1200)
        .nameAttr('#country')
        .joinAttr('#country+code')
        .hWhiteSpace(4)
        .vWhiteSpace(4)
        .margins({top: 150, right: 20, bottom: 30, left: 200})
        .columns([status,affected,affectedper100000,confirmed,suspected]);

    var grid2 = new lg.grid('#grid2')
        .data(activities)
        .width($('#grid1').width())
        .height(1200)
        .nameAttr('#country')
        .joinAttr('#country+code')
        .hWhiteSpace(6)
        .vWhiteSpace(6)
        .margins({top: 150, right: 20, bottom: 30, left: 200})
        .columns([riskComms,commClean,hhPro,infoPreg,psySup,bloodSafe,chemCont,protPart,commSurv]);

    lg.init();

    $("#map").width($("#map").width());

}

function hxlProxyToJSON(input,headers){
    var output = [];
    var keys=[]
    input.forEach(function(e,i){
        if(i==0){
            e.forEach(function(e2,i2){
                var parts = e2.split('+');
                var key = parts[0]
                if(parts.length>1){
                    var atts = parts.splice(1,parts.length);
                    atts.sort();
                    atts.forEach(function(att){
                        key +='+'+att
                    });
                }
                keys.push(key);
            });
        } else {
            var row = {};
            e.forEach(function(e2,i2){
                row[keys[i2]] = e2;
            });
            output.push(row);
        }
    });
    return output;
}

function stickydiv(){
    var window_top = $(window).scrollTop();
    var div_top = $('#sticky-anchor').offset().top;
    if (window_top > div_top){
        $('#map-container').addClass('sticky');
    }
    else{
        $('#map-container').removeClass('sticky');
    }
};

$('#grid2').hide();

$('#overviewbutton').on('click',function(){
    $('#grid2').hide();
    $('#grid1').show();
});

$('#activitiesbutton').on('click',function(){
    $('#grid1').hide();
    $('#grid2').show();
});

$(window).scroll(function(){
    stickydiv();
});

//load data

var dataCall = $.ajax({
    type: 'GET',
    url: 'data/dashboard.csv',
    dataType: 'text',
});

var activitiesCall = $.ajax({
    type: 'GET',
    url: 'data/nsactivities.csv',
    dataType: 'text',
});

//load geometry

var geomCall = $.ajax({
    type: 'GET',
    url: 'data/geom.json',
    dataType: 'json',
});

//when both ready construct dashboard

$.when(dataCall, activitiesCall, geomCall).then(function(dataArgs, activitiesArgs, geomArgs){
    geom = topojson.feature(geomArgs[0],geomArgs[0].objects.geom);
    overview = hxlProxyToJSON(Papa.parse(dataArgs[0]).data,false);
    activities = hxlProxyToJSON(Papa.parse(activitiesArgs[0]).data,false);
    overview.forEach(function(d){
        if(d['#population']==0){
            d['#affected+percapita'] = null
        } else {
            d['#affected+percapita'] = d['#affected+total']/d['#population']*100000
        }
    })
    generateDashboard(overview,activities,geom);
});
<|endoftext|>


<commit_before>/* Nitro Core
 *
 * Copyright (C) 2012 Caffeinated Code <http://caffeinatedco.de>
 * Copyright (C) 2012 Jono Cooper
 * Copyright (C) 2012 George Czabania
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 * 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.
 * Neither the name of Caffeinated Code 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 OWNER 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.
 */

//Session Vars
sessionStorage.setItem('selected', sessionStorage.getItem('selected') || 'today');

//When everything is ready
$(document).ready(function() {
	//Cache Selectors
	ui.initLoad();
	ui.reload();
});

var ui = {
	initLoad: function() {
		//Buttons
		$('#smartlists').html('
Focus

');
		ui.lists.draw('today');
		ui.lists.draw('next');
		ui.lists.draw('all');

		$$.document.append(ui.buttons.taskAddBTN, $('#tasks .panel'));

		//Splitter
		$('#content').splitter({sizeLeft: true});
		var height = $(window).height(),
			width = $(window).width()

		$(window).resize(function() {
			//Causes lag without it?
			if (height != $(window).height() || width != $(window).width()) {
				//Redefines
				height = $(window).height(),
				width = $(window).width()

				$('#content').trigger('resize');
			}
		});
	},
	reload: function() {
		//Populates Template
		$('#lists').html('
Lists

');
		$$.document.append(ui.buttons.listAddBTN, $('#lists h2'));
		for (var i=0; i<core.storage.lists.order.length; i++) {
			ui.lists.draw(core.storage.lists.order[i]);
		}
		//Simulates Click on selected list
		$('#L' + sessionStorage.getItem('selected')).click();
	},
	lists: {
		//Draws a list to the DOM
		draw: function(listId) {
			if (typeof(listId) == 'string') {
				var obj = $$(ui.templates.listTemplate, {id: listId, name: listId});
				$$.document.append(obj, $('#smartlists ul'));
			} else {
				var obj = $$(ui.templates.listTemplate, {id: listId, name: core.storage.lists.items[listId].name});
				$$.document.append(obj, $('#lists ul'));
			}

			$(obj.view.$()).attr('id', 'L' + obj.model.get('id'))
		}
	},
	templates: {
		taskTemplate: $$({}, '

', {
			'click &': function() {
				$('#tasks .selected').removeClass('selected');
				$(this.view.$()).addClass('selected');
			},
			'dblclick &': function() {
				//Cache the selector
				var view = $(this.view.$());

				//Checks if it's expanded & if it isn't expand it.
				if (!view.hasClass('expanded')) {
					view.addClass('expanded').height(view.height() + view.removeClass('selected').html('New Task

Something
Something Else
Bleh
').children('.hidden').show(0).height());
				} else {
					//Collapses
					view.removeClass('expanded').css('height', '');
					setTimeout(function() {
						view.children('.hidden').remove()
					}, 150);
				}
			}
		}),
		listTemplate: $$({}, '

', {
			'click &': function() {
				//Selected List
				sessionStorage.setItem('selected', this.model.get('id'));
				$('#sidebar .selected').removeClass('selected');
				$(this.view.$()).addClass('selected');

				//Gets list id & populates
				$('#tasks .content').html('
' + this.model.get('name') + '

')
				var tasks = core.list(this.model.get('id')).populate();

				//Loops and adds each task to a tmp view
				var tmpView = $$({});
				for (var i=0; i<tasks.length; i++) {
					tmpView.append($$(ui.templates.taskTemplate, {id: tasks[i], content: core.storage.tasks[tasks[i]].content}));
				}
				$$.document.append(tmpView, $('#tasks ul'));
			}
		})
	},
	buttons: {
		//Buttons
		listAddBTN: $$({name: 'Add List'}, '<button data-bind="name"/>', {
			'click &': function() {
				//Adds a list with the core
				var listId = core.list().add('New List');
				ui.lists.draw(listId);

				//Selects List
				$('#L' + listId).click();
			}
		}),
		taskAddBTN: $$({name: 'Add Task'}, '<button data-bind="name"/>', {
			'click &': function() {
				if (sessionStorage.getItem('selected') != 'all') {
					//Adds a task with the core
					var taskId = core.task().add('New Task', sessionStorage.getItem('selected'));
					$$.document.append($$(ui.templates.taskTemplate, {id: taskId, content: core.storage.tasks[taskId].content}), $('#tasks ul'));
				}
			}
		})
	}
}
<commit_msg>Minor improvements<commit_after>/* Nitro Core
 *
 * Copyright (C) 2012 Caffeinated Code <http://caffeinatedco.de>
 * Copyright (C) 2012 Jono Cooper
 * Copyright (C) 2012 George Czabania
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 * 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.
 * Neither the name of Caffeinated Code 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 OWNER 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.
 */

//Session Vars
sessionStorage.setItem('selected', sessionStorage.getItem('selected') || 'today');

//When everything is ready
$(document).ready(function() {
	//Cache Selectors
	ui.initLoad();
	ui.reload();
});

var ui = {
	initLoad: function() {
		//Buttons
		$('#smartlists').html('
Focus

');
		ui.lists.draw('today');
		ui.lists.draw('next');
		ui.lists.draw('all');

		$$.document.append(ui.buttons.taskAddBTN, $('#tasks .panel'));

		//Splitter
		$('#content').splitter({sizeLeft: true});
		var height = $(window).height(),
			width = $(window).width()

		$(window).resize(function() {
			//Causes lag without it?
			if (height != $(window).height() || width != $(window).width()) {
				//Redefines
				height = $(window).height(),
				width = $(window).width()

				$('#content').trigger('resize');
			}
		});
	},
	reload: function() {
		//Populates Template
		$('#lists').html('
Lists

');
		$$.document.append(ui.buttons.listAddBTN, $('#lists h2'));
		for (var i=0; i<core.storage.lists.order.length; i++) {
			ui.lists.draw(core.storage.lists.order[i]);
		}
		//Simulates Click on selected list
		$('#L' + sessionStorage.getItem('selected')).click();
	},
	lists: {
		//Draws a list to the DOM
		draw: function(listId) {
			if (typeof(listId) == 'string') {
				var obj = $$(ui.templates.listTemplate, {id: listId, name: listId});
				$$.document.append(obj, $('#smartlists ul'));
			} else {
				var obj = $$(ui.templates.listTemplate, {id: listId, name: core.storage.lists.items[listId].name});
				$$.document.append(obj, $('#lists ul'));
			}

			$(obj.view.$()).attr('id', 'L' + obj.model.get('id'))
		}
	},
	templates: {
		taskTemplate: $$({}, '

<textarea></textarea>
', {
			'click &': function() {
				$('#tasks .selected').removeClass('selected');
				$(this.view.$()).addClass('selected');
			},
			'dblclick &': function() {
				//Cache the selector
				var view = $(this.view.$());

				//Checks if it's expanded & if it isn't expand it.
				if (!view.hasClass('expanded')) {
					view.addClass('expanded').height(view.height() + view.removeClass('selected').html('New Task

Something
Something Else
Bleh
').children('.hidden').show(0).height());
				} else {
					//Collapses
					view.removeClass('expanded').css('height', '');
					setTimeout(function() {
						view.children('.hidden').remove()
					}, 150);
				}
			}
		}),
		listTemplate: $$({}, '

', {
			'click &': function() {
				//Selected List
				sessionStorage.setItem('selected', this.model.get('id'));
				$('#sidebar .selected').removeClass('selected');
				$(this.view.$()).addClass('selected');

				//Gets list id & populates
				$('#tasks .content').html('
' + this.model.get('name') + '

')
				var tasks = core.list(this.model.get('id')).populate();

				//Loops and adds each task to a tmp view
				var tmpView = $$({});
				for (var i=0; i<tasks.length; i++) {
					tmpView.append($$(ui.templates.taskTemplate, {id: tasks[i], content: core.storage.tasks[tasks[i]].content}));
				}
				$$.document.append(tmpView, $('#tasks ul'));
			}
		})
	},
	buttons: {
		//Buttons
		listAddBTN: $$({name: 'Add List'}, '<button data-bind="name"/>', {
			'click &': function() {
				//Adds a list with the core
				var listId = core.list().add('New List');
				ui.lists.draw(listId);

				//Selects List
				$('#L' + listId).click();
			}
		}),
		taskAddBTN: $$({name: 'Add Task'}, '<button data-bind="name"/>', {
			'click &': function() {
				var list = sessionStorage.getItem('selected');
				if (list != 'all') {
					//Adds a task with the core
					var taskId = core.task().add('New Task', list);
					$$.document.append($$(ui.templates.taskTemplate, {id: taskId, content: core.storage.tasks[taskId].content}), $('#tasks ul'));
				}
			}
		})
	}
}
<|endoftext|>


<commit_before>console.log('test.js')

if (location.toString().match(/dragongoserver.net\/show_games/)) {
  var gameElems = document.querySelectorAll("a.Button");
  for (var i=0; i<gameElems.length; i++) {
    var elem = gameElems[i];
    var sgf = "http://www.dragongoserver.net/sgf.php?gid=" + elem.text;

    (function(elem, sgf){
      elem.style.display = "inline";
      var newLink = document.createElement('span');
      newLink.style.marginLeft = "5px";
      newLink.style.marginRight = "3px";
      newLink.style.color = "#ff3355";
      newLink.appendChild(document.createTextNode("View"));
      newLink.onclick = function(e) {
        var win = window.open();
        if (win) {
          win.document.write(getWindowContent(sgf));
          win.focus();
          return false;
        } else {
          alert("Please disable popup blocker for this website to allow opening game in a new window.");
          return true;
        }
      }
      elem.parentElement.appendChild(newLink);
    })(elem, sgf);
  }
}

function getWindowContent(game) {
  return "<!DOCTYPE html>" +
    "<link rel='stylesheet' type='text/css' href='http://localhost:8000/jsgameviewer/view4/css/style.css' />" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/js/jquery-1.3.2.min.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/js/en_us.js'></script>" +
    //"<script type='text/javascript' src='http://localhost:8000/jsgameviewer/js/zh_cn.js' charset='utf-8'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/js/base.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/js/model.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/js/parser.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/js/controller.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/view4/js/three/three.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/view4/js/three/OrbitControls.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/view4/fonts/helvetiker_regular.typeface.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/view4/3d_assets/board.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/view4/3d_assets/stone.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/view4/js/view.js' charset='utf-8'></script>" +
    "<script type='text/javascript'>" +
    "var controller = new jsGameViewer.GameController();" +
    "controller.load('" + game + "')" +
    "</script>";
}
<commit_msg>Working on integration with mitbbs<commit_after>console.log('test.js')

if (location.toString().match(/dragongoserver.net\/show_games/)) {
  dgs();
} else if (location.toString().match(/www\.mitbbs\.com\/article_t\/Go/)) {
  mitbbs();
}

function dgs() {
  var gameElems = document.querySelectorAll("a.Button");
  for (var i=0; i<gameElems.length; i++) {
    var elem = gameElems[i];
    var sgf = "http://www.dragongoserver.net/sgf.php?gid=" + elem.text;

    (function(elem, sgf){
      elem.style.display = "inline";
      var newLink = document.createElement('span');
      newLink.style.marginLeft = "5px";
      newLink.style.marginRight = "3px";
      newLink.style.color = "#ff3355";
      newLink.appendChild(document.createTextNode("View"));
      newLink.onclick = function(e) {
        var win = window.open();
        if (win) {
          win.document.write(getWindowContent(sgf));
          win.focus();
          return false;
        } else {
          alert("Please disable popup blocker for this website to allow opening game in a new window.");
          return true;
        }
      }
      elem.parentElement.appendChild(newLink);
    })(elem, sgf);
  }
}
function mitbbs() {
  var dependencyLoaded = false;
  var postElems = document.querySelectorAll("td.jiawenxhang-type");
  for (var i=0; i<postElems.length; i++) {
    var elem = postElems[i];
    var html = elem.innerHTML;
    if (html.indexOf('<<<') >= 0 && html.indexOf('>>>') >= 0) {

    }
  }
}

function getWindowContent(game) {
  return "<!DOCTYPE html>" +
    "<link rel='stylesheet' type='text/css' href='http://localhost:8000/jsgameviewer/view4/css/style.css' />" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/js/jquery-1.3.2.min.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/js/en_us.js'></script>" +
    //"<script type='text/javascript' src='http://localhost:8000/jsgameviewer/js/zh_cn.js' charset='utf-8'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/js/base.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/js/model.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/js/parser.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/js/controller.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/view4/js/three/three.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/view4/js/three/OrbitControls.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/view4/fonts/helvetiker_regular.typeface.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/view4/3d_assets/board.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/view4/3d_assets/stone.js'></script>" +
    "<script type='text/javascript' src='http://localhost:8000/jsgameviewer/view4/js/view.js' charset='utf-8'></script>" +
    "<script type='text/javascript'>" +
    "var controller = new jsGameViewer.GameController();" +
    "controller.load('" + game + "')" +
    "</script>";
}
<|endoftext|>


<commit_before>$(function() {
	// Todo Form Submit Handler
	var handleSubmit = function() {
		console.log('Form was submitted');

		// Get the todo input value

		// Create an list element (li) and append to the unordered list (ul)
	};

	// Setup event handlers
	$('#add-todo-form').submit(handleSubmit);
});<commit_msg>Added todo list starter<commit_after>$(function() {
	// Function to add a todo item
	var addTodoItem(todo) {
		// Create a string with html for a list item

		// Select the unordered list of todo items

		// Append the html to the unordered list of todo items

		// Add a click handler to the delete button in the list item

		// Add a click handler to the input checkbox in the list item

	};

	// Todo Form Submit Handler
	var handleSubmit = function() {
		console.log('Form was submitted');

		// Get the todo input value

		// Add the todo item
	};

	// Setup event handlers
	$('#add-todo-form').submit(handleSubmit);

	// Load initial page with todo items

});<|endoftext|>


<commit_before>/* Copyright 2012 The Go Authors.  All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */
(function() {
"use strict";

var slides, editor, $editor, $output;
var slide = null;
var slidenum = 0;

// manage translations
function L(k) {
	if (tr[k]) {
		return tr[k];
	} else {
		console.log("translation missing for: "+k);
		return "(no translation for "+k+")";
	}
}

function init() {
	var $tocdiv = $('
').insertBefore('#slides').hide();
	$tocdiv.append($('
'+L('toc')+'
'));
	var $toc = $('
').appendTo($tocdiv);
	$("#tocbtn").click(toggleToc);

	slides = $("div.slide");
	slides.each(function(i, slide) {
		var $s = $(slide).hide();

		var $h2 = $s.find("h2").first();
		var $nav;
		if ($h2.length > 0) {
			$("
").addClass("clear").insertAfter($h2);
			$nav = $("
").addClass("nav");
			if (i > 0) {
				$nav.append($("◀").click(function() {
					show(i-1);
					return false;
				}).attr("href", "#"+(i)).attr("title", L('prev')));
			} else {
				$nav.append($("◀"));
			}
			if (i+1 < slides.length) {
				$nav.append($("▶").click(function() {
					show(i+1);
					return false;
				}).attr("href", "#"+(i+2)).attr("title", L('next')));
			} else {
				$nav.append($("▶"));
			}
			$nav.insertBefore($h2);

			var thisI = i;
			var $entry = $("").text($h2.text()).click(function() {
				show(thisI);
			}).attr('href', '#'+(i+1));
			$toc.append($entry);
			$entry.wrap('
');

		}
	});

	// set up playground editor
	editor = CodeMirror.fromTextArea(document.getElementById('editor'), {
		theme: "plain",
		matchBrackets: true,
		indentUnit: 4,
		tabSize: 4,
		indentWithTabs: false,
		mode: "text/x-go",
		lineNumbers: true,
		extraKeys: {
			"Shift-Enter": function() {
				run();
			}
		}
	});
	$editor = $(editor.getWrapperElement()).attr('id', 'code');
	$output = $('#output');

	$('#more').click(function() {
		$('.controls').toggleClass('expanded');
		return false;
	});
	$('html').click(function() {
		$('.controls').removeClass('expanded');
	});

	$('#run').click(function() {
		run();
		$('.controls').removeClass('expanded');
		return false;
	});

	$('#reset').click(function() {
		reset();
		$('.controls').removeClass('expanded');
		return false;
	});

	$('#kill').click(function() {
		kill();
		$('.controls').removeClass('expanded');
		return false;
	});

	$('#format').click(function() {
		format();
		$('.controls').removeClass('expanded');
		return false;
	});

	$('#togglesyntax').click(function() {
		if (editor.getOption('theme') === 'default') {
			editor.setOption('theme', 'plain');
			$('#togglesyntax').text(L('syntax')+': '+L('off'));
		} else {
			editor.setOption('theme', 'default');
			$('#togglesyntax').text(L('syntax')+': '+L('on'));
		}
		setcookie('theme', editor.getOption('theme'), 14);
		$('.controls').removeClass('expanded');
		return false;
	});

	$('#togglelineno').click(function() {
		if (editor.getOption('lineNumbers')) {
			editor.setOption('lineNumbers', false);
			$('#togglelineno').text(L('lineno')+': '+L('off'));
		} else {
			editor.setOption('lineNumbers', true);
			$('#togglelineno').text(L('lineno')+': '+L('on'));
		}
		setcookie('lineno', editor.getOption('lineNumbers'), 14);
		$('.controls').removeClass('expanded');
		return false;
	});

	if (getcookie('lineno') != ""+editor.getOption('lineNumbers')) {
		$('#togglelineno').trigger('click');
	} else {
		$('#togglelineno').text(L('lineno')+': '+L('on'));
	}

	if (getcookie('theme') != ""+editor.getOption('theme')) {
		$('#togglesyntax').trigger('click');
	} else {
		$('#togglesyntax').text(L('syntax')+': '+L('on'));
	}

	// set these according to lang.js
	$('#run').text(L('run'));
	$('#reset').text(L('reset'));
	$('#format').text(L('format'));
	$('#kill').text(L('kill'));
	$('#tocbtn').attr('title', L('toc'));
}

function toggleToc() {
	if ($('#toc').is(':visible')) {
		show(slidenum);
	} else {
		$('#slides, #workspace, #slidenum').hide();
		$('#toc').show();
	}
	return false;
}

function show(i) {
	if(i < 0 || i >= slides.length) {
		return;
	}

	// if a slide is already onscreen, hide it and store its code
	if(slide !== null) {
		var $oldSlide = $(slide).hide();
		if (!$oldSlide.hasClass("nocode")) {
			save(slidenum);
		}
	}

	$('#toc').hide();
	$('#slidenum, #slides').show();

	// switch to new slide
	slidenum = i;
	$("#slidenum").text(i+1);
	slide = slides[i];
	var $s = $(slide).show();

	// load stored code, or hide code box
	if ($s.hasClass("nocode")) {
		$('#workspace').hide();
	} else {
		$('#workspace').show();
		$output.empty();
		editor.setValue(load(i) || $s.find('div.source').text());
		editor.focus();
	}

	// update url fragment
	var url = location.href;
	var j = url.indexOf("#");
	if(j >= 0) {
		url = url.substr(0, j);
	}
	url += "#" + (slidenum+1).toString();
	location.href = url;
}

function reset() {
	editor.setValue($(slide).find('div.source').text());
	save(slidenum);
}

var pageData = {};

function save(page) {
	pageData[page] = editor.getValue();
	return true;
}

function load(page) {
	var data = pageData[page];
	if (data) {
		return data;
	}
	return false;
}

function urlSlideNumber(url) {
	var i = url.indexOf("#");
	if(i < 0) {
		return 0;
	}
	var frag = decodeURIComponent(url.substr(i+1));
	if(/^\d+$/.test(frag)) {
		i = parseInt(frag, 10);
		if(i-1 < 0 || i-1 >= slides.length) {
			return 0;
		}
		return i-1;
	}
	return 0;
}

function pageUpDown(event) {
	var e = window.event || event;
	if (e.keyCode === 33) { // page up
		e.preventDefault();
		show(slidenum-1);
		return false;
	}
	if (e.keyCode === 34) { // page down
		e.preventDefault();
		show(slidenum+1);
		return false;
	}
	return true;
}

$(document).ready(function() {
	init();
	if (location.href.indexOf('#') < 0) {
		show(0);
	} else {
		show(urlSlideNumber(location.href));
	}
	document.onkeydown = pageUpDown;
});

$(window).unload(function() {
	save(slidenum);
});

var runFunc, stopFunc;

function body() {
	return editor.getValue();
}
function loading() {
	$output.html('
'+L('waiting')+'
');
}
function run() {
	$output.empty();
	var $pre = $('
').appendTo($output);
	stopFunc = runFunc(body(), $pre[0]);
}

function kill() {
	if (stopFunc) stopFunc();
}

var seq = 0;

function format() {
	seq++;
	var cur = seq;
	loading();
	$.ajax("/fmt", {
		data: {"body": body()},
		type: "POST",
		dataType: "json",
		success: function(data) {
			if (seq !== cur) {
				return;
			}
			$output.empty();
			if (data.Error) {
				$('
').text(data.Error).appendTo($output);
				highlightErrors(data.Error);
			} else {
				editor.setValue(data.Body);
			}
		},
		error: function() {
			$('
').text(L('errcomm')).appendTo($output);
		}
	});
}

function highlightErrors(text) {
	if (!editor || !text) {
		return;
	}
	var errorRe = /[a-z0-9]+\.go:([0-9]+):/g;
	var result;
	while ((result = errorRe.exec(text)) !== null) {
		var line = result[1]*1-1;
		editor.setLineClass(line, null, 'errLine');
	}
	editor.setOption('onChange', function() {
		for (var i = 0; i < editor.lineCount(); i++) {
			editor.setLineClass(i, null, null);
		}
		editor.setOption('onChange', null);
	});
}

// Nasty hack to make this function available to playground.js and socket.js.
window.highlightErrors = highlightErrors;

function getcookie(name) {
	if (document.cookie.length > 0) {
		var start = document.cookie.indexOf(name + '=');
		if (start >= 0) {
			start += name.length + 1;
			var end = document.cookie.indexOf(';', start);
			if (end < 0) {
				end = document.cookie.length;
			}
			return decodeURIComponent(document.cookie.substring(start, end));
		}
	}
	return null;
}

function setcookie(name, value, expire) {
	var expdate = new Date();
	expdate.setDate(expdate.getDate() + expire);
	document.cookie = name + '=' + encodeURIComponent(value) +
		((expire === undefined) ? '' : ';expires=' + expdate.toGMTString());
}

if (window.connectPlayground) {
	runFunc = window.connectPlayground("ws://localhost:3999/socket");
} else {
	// If this message is logged,
	// we have neglected to include socket.js or playground.js.
	console.log("No playground transport available.");
}

}());
<commit_msg>go-tour: turn syntax highlighting off by default<commit_after>/* Copyright 2012 The Go Authors.  All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */
(function() {
"use strict";

var slides, editor, $editor, $output;
var slide = null;
var slidenum = 0;

// manage translations
function L(k) {
	if (tr[k]) {
		return tr[k];
	} else {
		console.log("translation missing for: "+k);
		return "(no translation for "+k+")";
	}
}

function init() {
	var $tocdiv = $('
').insertBefore('#slides').hide();
	$tocdiv.append($('
'+L('toc')+'
'));
	var $toc = $('
').appendTo($tocdiv);
	$("#tocbtn").click(toggleToc);

	slides = $("div.slide");
	slides.each(function(i, slide) {
		var $s = $(slide).hide();

		var $h2 = $s.find("h2").first();
		var $nav;
		if ($h2.length > 0) {
			$("
").addClass("clear").insertAfter($h2);
			$nav = $("
").addClass("nav");
			if (i > 0) {
				$nav.append($("◀").click(function() {
					show(i-1);
					return false;
				}).attr("href", "#"+(i)).attr("title", L('prev')));
			} else {
				$nav.append($("◀"));
			}
			if (i+1 < slides.length) {
				$nav.append($("▶").click(function() {
					show(i+1);
					return false;
				}).attr("href", "#"+(i+2)).attr("title", L('next')));
			} else {
				$nav.append($("▶"));
			}
			$nav.insertBefore($h2);

			var thisI = i;
			var $entry = $("").text($h2.text()).click(function() {
				show(thisI);
			}).attr('href', '#'+(i+1));
			$toc.append($entry);
			$entry.wrap('
');

		}
	});

	// set up playground editor
	editor = CodeMirror.fromTextArea(document.getElementById('editor'), {
		theme: "default",
		matchBrackets: true,
		indentUnit: 4,
		tabSize: 4,
		indentWithTabs: false,
		mode: "text/x-go",
		lineNumbers: true,
		extraKeys: {
			"Shift-Enter": function() {
				run();
			}
		}
	});
	$editor = $(editor.getWrapperElement()).attr('id', 'code');
	$output = $('#output');

	$('#more').click(function() {
		$('.controls').toggleClass('expanded');
		return false;
	});
	$('html').click(function() {
		$('.controls').removeClass('expanded');
	});

	$('#run').click(function() {
		run();
		$('.controls').removeClass('expanded');
		return false;
	});

	$('#reset').click(function() {
		reset();
		$('.controls').removeClass('expanded');
		return false;
	});

	$('#kill').click(function() {
		kill();
		$('.controls').removeClass('expanded');
		return false;
	});

	$('#format').click(function() {
		format();
		$('.controls').removeClass('expanded');
		return false;
	});

	$('#togglesyntax').click(function() {
		if (editor.getOption('theme') === 'default') {
			editor.setOption('theme', 'plain');
			$('#togglesyntax').text(L('syntax')+': '+L('off'));
		} else {
			editor.setOption('theme', 'default');
			$('#togglesyntax').text(L('syntax')+': '+L('on'));
		}
		setcookie('theme', editor.getOption('theme'), 14);
		$('.controls').removeClass('expanded');
		return false;
	});

	$('#togglelineno').click(function() {
		if (editor.getOption('lineNumbers')) {
			editor.setOption('lineNumbers', false);
			$('#togglelineno').text(L('lineno')+': '+L('off'));
		} else {
			editor.setOption('lineNumbers', true);
			$('#togglelineno').text(L('lineno')+': '+L('on'));
		}
		setcookie('lineno', editor.getOption('lineNumbers'), 14);
		$('.controls').removeClass('expanded');
		return false;
	});

	if (getcookie('lineno') != ""+editor.getOption('lineNumbers')) {
		$('#togglelineno').trigger('click');
	} else {
		$('#togglelineno').text(L('lineno')+': '+L('on'));
	}

	if (getcookie('theme') != ""+editor.getOption('theme')) {
		$('#togglesyntax').trigger('click');
	} else {
		$('#togglesyntax').text(L('syntax')+': '+L('on'));
	}

	// set these according to lang.js
	$('#run').text(L('run'));
	$('#reset').text(L('reset'));
	$('#format').text(L('format'));
	$('#kill').text(L('kill'));
	$('#tocbtn').attr('title', L('toc'));
}

function toggleToc() {
	if ($('#toc').is(':visible')) {
		show(slidenum);
	} else {
		$('#slides, #workspace, #slidenum').hide();
		$('#toc').show();
	}
	return false;
}

function show(i) {
	if(i < 0 || i >= slides.length) {
		return;
	}

	// if a slide is already onscreen, hide it and store its code
	if(slide !== null) {
		var $oldSlide = $(slide).hide();
		if (!$oldSlide.hasClass("nocode")) {
			save(slidenum);
		}
	}

	$('#toc').hide();
	$('#slidenum, #slides').show();

	// switch to new slide
	slidenum = i;
	$("#slidenum").text(i+1);
	slide = slides[i];
	var $s = $(slide).show();

	// load stored code, or hide code box
	if ($s.hasClass("nocode")) {
		$('#workspace').hide();
	} else {
		$('#workspace').show();
		$output.empty();
		editor.setValue(load(i) || $s.find('div.source').text());
		editor.focus();
	}

	// update url fragment
	var url = location.href;
	var j = url.indexOf("#");
	if(j >= 0) {
		url = url.substr(0, j);
	}
	url += "#" + (slidenum+1).toString();
	location.href = url;
}

function reset() {
	editor.setValue($(slide).find('div.source').text());
	save(slidenum);
}

var pageData = {};

function save(page) {
	pageData[page] = editor.getValue();
	return true;
}

function load(page) {
	var data = pageData[page];
	if (data) {
		return data;
	}
	return false;
}

function urlSlideNumber(url) {
	var i = url.indexOf("#");
	if(i < 0) {
		return 0;
	}
	var frag = decodeURIComponent(url.substr(i+1));
	if(/^\d+$/.test(frag)) {
		i = parseInt(frag, 10);
		if(i-1 < 0 || i-1 >= slides.length) {
			return 0;
		}
		return i-1;
	}
	return 0;
}

function pageUpDown(event) {
	var e = window.event || event;
	if (e.keyCode === 33) { // page up
		e.preventDefault();
		show(slidenum-1);
		return false;
	}
	if (e.keyCode === 34) { // page down
		e.preventDefault();
		show(slidenum+1);
		return false;
	}
	return true;
}

$(document).ready(function() {
	init();
	if (location.href.indexOf('#') < 0) {
		show(0);
	} else {
		show(urlSlideNumber(location.href));
	}
	document.onkeydown = pageUpDown;
});

$(window).unload(function() {
	save(slidenum);
});

var runFunc, stopFunc;

function body() {
	return editor.getValue();
}
function loading() {
	$output.html('
'+L('waiting')+'
');
}
function run() {
	$output.empty();
	var $pre = $('
').appendTo($output);
	stopFunc = runFunc(body(), $pre[0]);
}

function kill() {
	if (stopFunc) stopFunc();
}

var seq = 0;

function format() {
	seq++;
	var cur = seq;
	loading();
	$.ajax("/fmt", {
		data: {"body": body()},
		type: "POST",
		dataType: "json",
		success: function(data) {
			if (seq !== cur) {
				return;
			}
			$output.empty();
			if (data.Error) {
				$('
').text(data.Error).appendTo($output);
				highlightErrors(data.Error);
			} else {
				editor.setValue(data.Body);
			}
		},
		error: function() {
			$('
').text(L('errcomm')).appendTo($output);
		}
	});
}

function highlightErrors(text) {
	if (!editor || !text) {
		return;
	}
	var errorRe = /[a-z0-9]+\.go:([0-9]+):/g;
	var result;
	while ((result = errorRe.exec(text)) !== null) {
		var line = result[1]*1-1;
		editor.setLineClass(line, null, 'errLine');
	}
	editor.setOption('onChange', function() {
		for (var i = 0; i < editor.lineCount(); i++) {
			editor.setLineClass(i, null, null);
		}
		editor.setOption('onChange', null);
	});
}

// Nasty hack to make this function available to playground.js and socket.js.
window.highlightErrors = highlightErrors;

function getcookie(name) {
	if (document.cookie.length > 0) {
		var start = document.cookie.indexOf(name + '=');
		if (start >= 0) {
			start += name.length + 1;
			var end = document.cookie.indexOf(';', start);
			if (end < 0) {
				end = document.cookie.length;
			}
			return decodeURIComponent(document.cookie.substring(start, end));
		}
	}
	return null;
}

function setcookie(name, value, expire) {
	var expdate = new Date();
	expdate.setDate(expdate.getDate() + expire);
	document.cookie = name + '=' + encodeURIComponent(value) +
		((expire === undefined) ? '' : ';expires=' + expdate.toGMTString());
}

if (window.connectPlayground) {
	runFunc = window.connectPlayground("ws://localhost:3999/socket");
} else {
	// If this message is logged,
	// we have neglected to include socket.js or playground.js.
	console.log("No playground transport available.");
}

}());
<|endoftext|>


<commit_before>$(document).ready(function(){
	var contacts_div = $('#contacts');
	var transactions_div = $('#transactions');
	var messages_div = $('#messages');

	$.get(contacts_div.data('url'), function(data){
		contacts_div.html(data);
	}).done(function(){
		var $map = $('#map');
		var markers = $map.data('markers');
		var lat = 0;
		var lng = 0;

		$.each(markers, function(index, marker){
			lat = lat + marker.lat;
			lng = lng + marker.lng;
		});

		lat = lat / markers.length;
		lng = lng / markers.length;

		var map = L.map('map').setView([lat, lng], 15);

		L.tileLayer('https://api.mapbox.com/v4/mapbox.streets/{z}/{x}/{y}.png?access_token={accessToken}', {
			attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox',
			maxZoom: 17,
			minZoom: 10,
			accessToken: $map.data('token')
		}).addTo(map);

		$.each(markers, function(id, m){
			L.marker([m.lat, m.lng], {
				riseOnHover: true
			}).addTo(map);
		});
	});

	$.get(transactions_div.data('url'), function(data){
		transactions_div.html(data);
	});

	$.get(messages_div.data('url'), function(data){
		messages_div.html(data);
	});
});
<commit_msg>fix unset markers value<commit_after>$(document).ready(function(){
	var contacts_div = $('#contacts');
	var transactions_div = $('#transactions');
	var messages_div = $('#messages');

	$.get(contacts_div.data('url'), function(data){
		contacts_div.html(data);
	}).done(function(){
		var $map = $('#map');
		var markers = $map.data('markers');
		var lat = 0;
		var lng = 0;

		if (!markers){
			return;
		}

		$.each(markers, function(index, marker){
			lat = lat + marker.lat;
			lng = lng + marker.lng;
		});

		lat = lat / markers.length;
		lng = lng / markers.length;

		var map = L.map('map').setView([lat, lng], 15);

		L.tileLayer('https://api.mapbox.com/v4/mapbox.streets/{z}/{x}/{y}.png?access_token={accessToken}', {
			attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox',
			maxZoom: 17,
			minZoom: 10,
			accessToken: $map.data('token')
		}).addTo(map);

		$.each(markers, function(id, m){
			L.marker([m.lat, m.lng], {
				riseOnHover: true
			}).addTo(map);
		});
	});

	$.get(transactions_div.data('url'), function(data){
		transactions_div.html(data);
	});

	$.get(messages_div.data('url'), function(data){
		messages_div.html(data);
	});
});
<|endoftext|>


<commit_before>$(document).ready(function(){
        // count character on keyup
        function counter(){
            var maxLength     = 140;
            var currentLength = $("#status_textarea").val()
                                                     .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "drry")
                                                     .replace(/[\u0800-\uFFFF]/g, "drr")
                                                     .replace(/[\u0080-\u07FF]/g, "dr")
                                                     .length;
            var remaining = maxLength - currentLength;
            var counter   = $("#counter");
            counter.text(remaining);

            if (remaining <= 0) {
                counter.attr("class", "toomuch");
            } else {
                counter.attr("class", "");
            }
        }

        if ($("#status_textarea").length) {
            $("#status_textarea").bind("keyup", counter);
            // run once in case there's something in there
            counter();
        }
});

function doreply(nick) {
     rgx_username = /^[0-9a-zA-Z\-_.]*$/;
     if (nick.match(rgx_username)) {
          replyto = "@" + nick + " ";
          if ($("#status_textarea")) {
               $("#status_textarea").val(replyto);
               $("#status_textarea").focus();
          }
     }
     return false;
}

<commit_msg>remove hack to count bytes, not chars, in JS, since we now use chars<commit_after>$(document).ready(function(){
        // count character on keyup
        function counter(){
            var maxLength     = 140;
            var currentLength = $("#status_textarea").val().length;
            var remaining = maxLength - currentLength;
            var counter   = $("#counter");
            counter.text(remaining);

            if (remaining <= 0) {
                counter.attr("class", "toomuch");
            } else {
                counter.attr("class", "");
            }
        }

        if ($("#status_textarea").length) {
            $("#status_textarea").bind("keyup", counter);
            // run once in case there's something in there
            counter();
        }
});

function doreply(nick) {
     rgx_username = /^[0-9a-zA-Z\-_.]*$/;
     if (nick.match(rgx_username)) {
          replyto = "@" + nick + " ";
          if ($("#status_textarea")) {
               $("#status_textarea").val(replyto);
               $("#status_textarea").focus();
          }
     }
     return false;
}

<|endoftext|>


<commit_before>/**
* used to story shared functions used in story and comments pages
*/

import APP_CONSTANTS from './app-constants.js';

const util = {};
/**
		* returns object of info about a story based on integer id
		* id		The item's unique id.
		* deleted	true if the item is deleted.
		* type		The type of item. One of "job", "story", "comment", "poll", or "pollopt".
		* by		The username of the item's author.
		* time		Creation date of the item, in Unix Time.
		* text		The comment, story or poll text. HTML.
		* dead		true if the item is dead.
		* parent	The item's parent. For comments, either another comment or the relevant story. For pollopts, the relevant poll.
		* kids		The ids of the item's comments, in ranked display order.
		* url		The URL of the story.
		* score		The story's score, or the votes for a pollopt.
		* title		The title of the story, poll or job.
		* parts		A list of related pollopts, in display order.
		* descendants	In the case of stories or polls, the total comment count.
		*/
util.getItemInfoUrlFromId = function(id){
		return 'https://hacker-news.firebaseio.com/v0/item/' + id + '.json';
	};
/**
* Takes HN.Story object as a parameter and returns the html to display the title and link
*/
util.getStoryTitleHTML = function(story){
	var title = "
" + story.title;
	if(story.urlRoot !== ''){
		title += " " + story.urlRoot + "";
	}
	title += "
";
	return title;
};

/**
* Used for ask pages to display without the link
* Even though code only used on ask pages, is kept here because it should have the same style as getStoryTitleHTML()
*/
util.getAskStoryTitle = function(story){
	return "
" + story.title + "
";
};

/**
* Used for comment HTML text to smarten quotes
* takes html string and returns html string with dumb quotes replaced with smart quotes
* preserves dumbquotes in html attributes
*/
util.smartenQuotesHTML = function(dumbString){
	return util.replaceSmartQuoteEntities(util.transformTextNodes(dumbString, function(text){
		return util.replaceDumbQuotes(text);
	}));
};

/**
* Used to transform just the textNodes in html
* used for smarten quotes
* @element first argument is either the result of document.getElementById()
* or a string of html such as 'text' or 'text
more text
' or '
text
'
* @textTransformFunc is a function used to transform the text nodes
* it should be of the format: function(text){return text.toUpperCase();} or however the text is to be transformed
* @returns either the transformed string if was originally a string or transformed element if was originally an element
*/
util.transformTextNodes = function (element, textTransformFunc) {
    var elementType = typeof element;

    if(elementType === 'string'){
        var div = document.createElement('div');
        div.innerHTML = element;
        element = div;
    }
    try{
	    var walker = document.createTreeWalker(
	        element,
	        NodeFilter.SHOW_TEXT,
	        null,
	        false
	    );
	}
	catch(e){
		console.log(e);
		return element;
	}

    var textNode;

    while(textNode = walker.nextNode()) {
        textNode.nodeValue = textTransformFunc(textNode.nodeValue);
    }
    if(elementType === 'string'){
        return element.innerHTML;
    }
    return element;
};

/**
* Used to replace dumb quotes in a text string
* uses a second replace in the function passed to replace to preserve the non word characters before the quote, such as spaces or parens
*/
util.replaceDumbQuotes = function(dumbString){
	var rightSingleSmartQuote = "’";
	var leftSingleSmartQuote = "‘";
	var rightDoubleSmartQuote = "”";
	var leftDoubleSmartQuote = "“";
	var emDash = "—";
	var ellipsis = "…";
	return dumbString
			   		 .replace(/\b'|[\.?,-\/#!$%\^&\*;:{}<>=|\-_`~()\[\]]'/g, function(match, str, offset){return match.replace(/'/g, rightSingleSmartQuote);})
		       		 .replace(/'/g, leftSingleSmartQuote)
		       		 .replace(/\b"|[\.?,-\/#!$%\^&\*;:{}<>|=\-_`~()\[\]]"/g, function(match, str, offset){return match.replace(/"/g, rightDoubleSmartQuote);})
		       		 .replace(/"/g, leftDoubleSmartQuote)
		       		 .replace(/\D\s+-+\s*\D|\D\s*-+\s+\D|\s*--+\s*/g, function(match, str, offset){return match.replace(/\s*-+\s*/g, emDash);})
		       		 .replace(/\.\s?\.\s?\.\s?/g, ellipsis);
};

/**
* Required because the treeWalker automatically escapes ampersands
*/
util.replaceSmartQuoteEntities = function(string){
	if(typeof string != 'string'){
		return string;
	}
	return string.replace(/&#[\d]{4};/g, function(match, str, offset){
		return match.replace('&', '&');
	});
};

/*
 * Wrapper for ajax
 *
 * @param url - string for url to get request
 * @param success - function to be run on success - takes one argument of the data returned
 * @param failure - function to be run on error - take one argument of error
 * @return null
 */
util.getJSON = function(url, success, failure){
	var request = new XMLHttpRequest();
	request.open('GET', url, true);

	request.onload = function() {
	  if (this.status >= 200 && this.status < 400) {
	    var data = JSON.parse(this.response);
	    success(data);
	  } else {
	    // We reached our target server, but it returned an error
	    failure(this.response);
	  }
	};

	request.onerror = function() {
	  // There was a connection error of some sort
	  failure(this.response);
	};

	request.send();
};

/*
 * Used to iterate over array or array-like collection (e.g. NodeList)
 *
 * @param collection - collection to be iterated over
 * @param action - anynomous function to be called for each item in collection - arguments are item, and (int) index of item
 * @return null
 */

 util.each = function(collection, action){
 	var length = collection.length;
 	for (var i = 0; i < length; i++) {
 		action(collection[i], i);
 	};
 };

/*
* Used for comments to change ycombinator links to hnews links
*/
util.redirectLinks = function(){
	var ycombinatorLink = 'https://news.ycombinator.com/item?id=';
	var links = document.querySelectorAll("#top_list a[href^='" + ycombinatorLink + "']");
	util.each(links, function(link){
		var hrefSplit = link.href.split(ycombinatorLink);
		//make sure it's a comment url
		if(hrefSplit.length !== 2){
			return;
		}
		var commentId = hrefSplit[1];
		//make sure comment id is number
		if(!commentId.match(/^[0-9]*$/)){
			return;
		}
		var hnewsUrl = APP_CONSTANTS.urls.comments + commentId;
		link.setAttribute('href', hnewsUrl);
		link.text = hnewsUrl;
	});
};

export default util;
<commit_msg>Refactor function to rewrite ycombinator links to not need each helper function<commit_after>/**
* used to story shared functions used in story and comments pages
*/

import APP_CONSTANTS from './app-constants.js';

const util = {};
/**
		* returns object of info about a story based on integer id
		* id		The item's unique id.
		* deleted	true if the item is deleted.
		* type		The type of item. One of "job", "story", "comment", "poll", or "pollopt".
		* by		The username of the item's author.
		* time		Creation date of the item, in Unix Time.
		* text		The comment, story or poll text. HTML.
		* dead		true if the item is dead.
		* parent	The item's parent. For comments, either another comment or the relevant story. For pollopts, the relevant poll.
		* kids		The ids of the item's comments, in ranked display order.
		* url		The URL of the story.
		* score		The story's score, or the votes for a pollopt.
		* title		The title of the story, poll or job.
		* parts		A list of related pollopts, in display order.
		* descendants	In the case of stories or polls, the total comment count.
		*/
util.getItemInfoUrlFromId = function(id){
		return 'https://hacker-news.firebaseio.com/v0/item/' + id + '.json';
	};
/**
* Takes HN.Story object as a parameter and returns the html to display the title and link
*/
util.getStoryTitleHTML = function(story){
	var title = "
" + story.title;
	if(story.urlRoot !== ''){
		title += " " + story.urlRoot + "";
	}
	title += "
";
	return title;
};

/**
* Used for ask pages to display without the link
* Even though code only used on ask pages, is kept here because it should have the same style as getStoryTitleHTML()
*/
util.getAskStoryTitle = function(story){
	return "
" + story.title + "
";
};

/**
* Used for comment HTML text to smarten quotes
* takes html string and returns html string with dumb quotes replaced with smart quotes
* preserves dumbquotes in html attributes
*/
util.smartenQuotesHTML = function(dumbString){
	return util.replaceSmartQuoteEntities(util.transformTextNodes(dumbString, function(text){
		return util.replaceDumbQuotes(text);
	}));
};

/**
* Used to transform just the textNodes in html
* used for smarten quotes
* @element first argument is either the result of document.getElementById()
* or a string of html such as 'text' or 'text
more text
' or '
text
'
* @textTransformFunc is a function used to transform the text nodes
* it should be of the format: function(text){return text.toUpperCase();} or however the text is to be transformed
* @returns either the transformed string if was originally a string or transformed element if was originally an element
*/
util.transformTextNodes = function (element, textTransformFunc) {
    var elementType = typeof element;

    if(elementType === 'string'){
        var div = document.createElement('div');
        div.innerHTML = element;
        element = div;
    }
    try{
	    var walker = document.createTreeWalker(
	        element,
	        NodeFilter.SHOW_TEXT,
	        null,
	        false
	    );
	}
	catch(e){
		console.log(e);
		return element;
	}

    var textNode;

    while(textNode = walker.nextNode()) {
        textNode.nodeValue = textTransformFunc(textNode.nodeValue);
    }
    if(elementType === 'string'){
        return element.innerHTML;
    }
    return element;
};

/**
* Used to replace dumb quotes in a text string
* uses a second replace in the function passed to replace to preserve the non word characters before the quote, such as spaces or parens
*/
util.replaceDumbQuotes = function(dumbString){
	var rightSingleSmartQuote = "’";
	var leftSingleSmartQuote = "‘";
	var rightDoubleSmartQuote = "”";
	var leftDoubleSmartQuote = "“";
	var emDash = "—";
	var ellipsis = "…";
	return dumbString
			   		 .replace(/\b'|[\.?,-\/#!$%\^&\*;:{}<>=|\-_`~()\[\]]'/g, function(match, str, offset){return match.replace(/'/g, rightSingleSmartQuote);})
		       		 .replace(/'/g, leftSingleSmartQuote)
		       		 .replace(/\b"|[\.?,-\/#!$%\^&\*;:{}<>|=\-_`~()\[\]]"/g, function(match, str, offset){return match.replace(/"/g, rightDoubleSmartQuote);})
		       		 .replace(/"/g, leftDoubleSmartQuote)
		       		 .replace(/\D\s+-+\s*\D|\D\s*-+\s+\D|\s*--+\s*/g, function(match, str, offset){return match.replace(/\s*-+\s*/g, emDash);})
		       		 .replace(/\.\s?\.\s?\.\s?/g, ellipsis);
};

/**
* Required because the treeWalker automatically escapes ampersands
*/
util.replaceSmartQuoteEntities = function(string){
	if(typeof string != 'string'){
		return string;
	}
	return string.replace(/&#[\d]{4};/g, function(match, str, offset){
		return match.replace('&', '&');
	});
};

/*
 * Wrapper for ajax
 *
 * @param url - string for url to get request
 * @param success - function to be run on success - takes one argument of the data returned
 * @param failure - function to be run on error - take one argument of error
 * @return null
 */
util.getJSON = function(url, success, failure){
	var request = new XMLHttpRequest();
	request.open('GET', url, true);

	request.onload = function() {
	  if (this.status >= 200 && this.status < 400) {
	    var data = JSON.parse(this.response);
	    success(data);
	  } else {
	    // We reached our target server, but it returned an error
	    failure(this.response);
	  }
	};

	request.onerror = function() {
	  // There was a connection error of some sort
	  failure(this.response);
	};

	request.send();
};

/*
* Used for comments to change ycombinator links to hnews links
*/
util.redirectLinks = function(){
	const ycombinatorLink = 'https://news.ycombinator.com/item?id=';
	document.querySelectorAll(`#top_list a[href^="${ycombinatorLink}"]`).forEach((link)=>{
		const hrefSplit = link.href.split(ycombinatorLink);
		//make sure it's a comment url
		if(hrefSplit.length !== 2){
			return;
		}
		const commentId = hrefSplit[1];
		//make sure comment id is number
		if(!commentId.match(/^[0-9]*$/)){
			return;
		}
		const hnewsUrl = APP_CONSTANTS.urls.comments + commentId;
		link.setAttribute('href', hnewsUrl);
		link.text = hnewsUrl;
	});
};

export default util;
<|endoftext|>


<commit_before>const baseKarma = require('./base-karma')

module.exports = function (config) {
  const baseConfig = baseKarma(config)

  config.set(Object.assign(baseConfig, {
    browsers: [
      'bs_firefox_android',
      'bs_firefox_windows',
      'bs_chrome_mac',
      'bs_safari_mac',
      'bs_ie_11',
      'bs_edge'
    ],

    reporters: [
      'mocha', 'BrowserStack'
    ],

    client: {
      mocha: {
        reporter: 'html'
      }
    },

    browserStack: {
      startTunnel: true
    },

    customLaunchers: {
      bs_firefox_android: {
        base: 'BrowserStack',
        browser: 'Android Browser',
        real_mobile: true,
        device: 'Samsung Galaxy S10',
        os: 'android',
        os_version: '9.0'
      },
      bs_firefox_windows: {
        base: 'BrowserStack',
        browser: 'firefox',
        browser_version: '71',
        os: 'Windows',
        os_version: '10'
      },
      bs_chrome_mac: {
        base: 'BrowserStack',
        browser: 'Chrome',
        browser_version: '78',
        os: 'OS X',
        os_version: 'High Sierra'
      },
      bs_safari_mac: {
        base: 'BrowserStack',
        browser: 'Safari',
        browser_version: '13',
        os: 'OS X',
        os_version: 'Catalina'
      },
      bs_ie_11: {
        base: 'BrowserStack',
        browser: 'IE',
        browser_version: '11',
        os: 'Windows',
        os_version: '10'
      },
      bs_edge: {
        base: 'BrowserStack',
        browser: 'Edge',
        browser_version: '18',
        os: 'Windows',
        os_version: '10'
      }
    }
  }))
}
<commit_msg>Update karma browser versions<commit_after>const baseKarma = require('./base-karma')

module.exports = function (config) {
  const baseConfig = baseKarma(config)

  config.set(Object.assign(baseConfig, {
    browsers: [
      'bs_firefox_android',
      'bs_firefox_windows',
      'bs_chrome_mac',
      'bs_safari_mac',
      'bs_ie_11',
      'bs_edge'
    ],

    reporters: [
      'mocha', 'BrowserStack'
    ],

    client: {
      mocha: {
        reporter: 'html'
      }
    },

    browserStack: {
      startTunnel: true
    },

    customLaunchers: {
      bs_firefox_android: {
        base: 'BrowserStack',
        browser: 'Android Browser',
        real_mobile: true,
        device: 'Samsung Galaxy S20',
        os: 'android',
        os_version: '10'
      },
      bs_firefox_windows: {
        base: 'BrowserStack',
        browser: 'firefox',
        browser_version: '75',
        os: 'Windows',
        os_version: '10'
      },
      bs_chrome_mac: {
        base: 'BrowserStack',
        browser: 'Chrome',
        browser_version: '81',
        os: 'OS X',
        os_version: 'High Sierra'
      },
      bs_safari_mac: {
        base: 'BrowserStack',
        browser: 'Safari',
        browser_version: '13',
        os: 'OS X',
        os_version: 'Catalina'
      },
      bs_ie_11: {
        base: 'BrowserStack',
        browser: 'IE',
        browser_version: '11',
        os: 'Windows',
        os_version: '10'
      },
      bs_edge: {
        base: 'BrowserStack',
        browser: 'Edge',
        browser_version: '81',
        os: 'Windows',
        os_version: '10'
      }
    }
  }))
}
<|endoftext|>


<commit_before>import React from 'react';
import {shallow} from 'enzyme';
import {reviewBuilder} from '../builder/pr';

import PullRequestReviewsController from '../../lib/controllers/pr-reviews-controller';

import {PAGE_SIZE, PAGINATION_WAIT_TIME_MS} from '../../lib/helpers';

describe('PullRequestReviewsController', function() {
  function buildApp(opts, overrideProps = {}) {
    const o = {
      relayHasMore: () => { return false; },
      relayLoadMore: () => {},
      relayIsLoading: () => { return false; },
      reviewSpecs: [],
      reviewStartCursor: 0,
      ...opts,
    };

    const reviews = {
      edges: o.reviewSpecs.map((spec, i) => ({
        cursor: `result${i}`,
        node: {
          id: spec.id,
          __typename: 'review',
        },
      })),
      pageInfo: {
        startCursor: `result${o.reviewStartCursor}`,
        endCursor: `result${o.reviewStartCursor + o.reviewSpecs.length}`,
        hasNextPage: o.reviewStartCursor + o.reviewSpecs.length < o.reviewItemTotal,
        hasPreviousPage: o.reviewStartCursor !== 0,
      },
      totalCount: o.reviewItemTotal,
    };

    const props = {
      relay: {
        hasMore: o.relayHasMore,
        loadMore: o.relayLoadMore,
        isLoading: o.relayIsLoading,
      },

      switchToIssueish: () => {},
      getBufferRowForDiffPosition: () => {},
      pullRequest: {reviews},
      ...overrideProps,
    };
    return <PullRequestReviewsController {...props} />;
  }
  it('returns null if props.pullRequest is falsy', function() {
    const wrapper = shallow(buildApp({}, {pullRequest: null}));
    assert.isNull(wrapper.getElement());
  });

  it('returns null if props.pullRequest.reviews is falsy', function() {
    const wrapper = shallow(buildApp({}, {pullRequest: {reviews: null}}));
    assert.isNull(wrapper.getElement());
  });

  it('renders a PullRequestReviewCommentsContainer for every review', function() {
    const review1 = reviewBuilder().build();
    const review2 = reviewBuilder().build();

    const reviewSpecs = [review1, review2];
    const wrapper = shallow(buildApp({reviewSpecs}));
    const containers = wrapper.find('ForwardRef(Relay(BarePullRequestReviewCommentsContainer))');
    assert.strictEqual(containers.length, 2);

    assert.strictEqual(containers.at(0).prop('review').id, review1.id);
    assert.strictEqual(containers.at(1).prop('review').id, review2.id);
  });

  it('renders a PullRequestReviewCommentsView and passes props through', function() {
    const review1 = reviewBuilder().build();
    const review2 = reviewBuilder().build();

    const reviewSpecs = [review1, review2];
    const passThroughProp = 'I only exist for the children';
    const wrapper = shallow(buildApp({reviewSpecs}, {passThroughProp}));
    const view = wrapper.find('PullRequestCommentsView');
    assert.strictEqual(view.length, 1);

    assert.strictEqual(wrapper.instance().props.passThroughProp, view.prop('passThroughProp'));
  });

  describe('collectComments', function() {
    it('sets this.reviewsById with correct data', function() {
      const wrapper = shallow(buildApp());
      const args = {reviewId: 123, submittedAt: '2018-12-27T20:40:55Z', comments: ['a comment',
      ], fetchingMoreComments: true};
      assert.strictEqual(wrapper.instance().reviewsById.size, 0);
      wrapper.instance().collectComments(args);
      const review = wrapper.instance().reviewsById.get(args.reviewId);
      delete args.reviewId;
      assert.deepEqual(review, args);
    });

    it('calls groupCommentsByThread if there are no more reviews or comments to be fetched', function() {
      const wrapper = shallow(buildApp());
      const groupCommentsStub = sinon.stub(wrapper.instance(), 'groupCommentsByThread');
      assert.isFalse(groupCommentsStub.called);
      const args = {reviewId: 123, submittedAt: '2018-12-27T20:40:55Z', comments: ['a comment',
      ], fetchingMoreComments: false};
      wrapper.instance().collectComments(args);
      assert.strictEqual(groupCommentsStub.callCount, 1);
    });
  });

  describe('attemptToLoadMoreReviews', function() {
    let clock;
    beforeEach(function() {
      clock = sinon.useFakeTimers();
    });

    afterEach(function() {
      clock = sinon.restore();
    });

    it('does not call loadMore if hasMore is false', function() {
      const relayLoadMoreStub = sinon.stub();
      const wrapper = shallow(buildApp({relayLoadMore: relayLoadMoreStub}));
      relayLoadMoreStub.reset();

      wrapper.instance()._attemptToLoadMoreReviews();
      assert.strictEqual(relayLoadMoreStub.callCount, 0);
    });

    it('calls loadMore immediately if hasMore is true and isLoading is false', function() {
      const relayLoadMoreStub = sinon.stub();
      const relayHasMore = () => { return true; };
      const wrapper = shallow(buildApp({relayHasMore, relayLoadMore: relayLoadMoreStub}));
      relayLoadMoreStub.reset();

      wrapper.instance()._attemptToLoadMoreReviews();
      assert.strictEqual(relayLoadMoreStub.callCount, 1);
      assert.deepEqual(relayLoadMoreStub.lastCall.args, [PAGE_SIZE, wrapper.instance().handleError]);
    });

    it('calls loadMore after a timeout if hasMore is true and isLoading is true', function() {
      const relayLoadMoreStub = sinon.stub();
      const relayHasMore = () => { return true; };
      const relayIsLoading = () => { return true; };
      const wrapper = shallow(buildApp({relayHasMore, relayIsLoading, relayLoadMore: relayLoadMoreStub}));
      // advancing the timer and resetting the stub to clear the initial calls of
      // _attemptToLoadMoreReviews when the component is initially mounted.
      clock.tick(PAGINATION_WAIT_TIME_MS);
      relayLoadMoreStub.reset();

      wrapper.instance()._attemptToLoadMoreReviews();
      assert.strictEqual(relayLoadMoreStub.callCount, 0);

      clock.tick(PAGINATION_WAIT_TIME_MS);
      assert.strictEqual(relayLoadMoreStub.callCount, 1);
      assert.deepEqual(relayLoadMoreStub.lastCall.args, [PAGE_SIZE, wrapper.instance().handleError]);
    });
  });

  describe('_loadMoreReviews', function() {
    it('calls this.props.relay.loadMore with correct args', function() {
      const relayLoadMoreStub = sinon.stub();
      const wrapper = shallow(buildApp({relayLoadMore: relayLoadMoreStub}));
      wrapper.instance()._loadMoreReviews();

      assert.deepEqual(relayLoadMoreStub.lastCall.args, [PAGE_SIZE, wrapper.instance().handleError]);
    });
  });

  describe('grouping and ordering comments', function() {
    it('groups the comments into threads based on replyId', function() {
      const originalCommentId = 1;
      const singleCommentId = 5;
      const review1 = reviewBuilder()
        .id(0)
        .submittedAt('2018-12-27T20:40:55Z')
        .addComment(c => c.id(originalCommentId).path('file0.txt').body('OG comment'))
        .build();

      const review2 = reviewBuilder()
        .id(1)
        .submittedAt('2018-12-28T20:40:55Z')
        .addComment(c => c.id(2).path('file0.txt').replyTo(originalCommentId).body('reply to OG comment'))
        .addComment(c => c.id(singleCommentId).path('file0.txt').body('I am single and free'))
        .build();

      const wrapper = shallow(buildApp({reviewSpecs: [review1, review2]}));

      // adding this manually to reviewsById because the last time you call collectComments it groups them, and we don't want to do that just yet.
      wrapper.instance().reviewsById.set(review1.id, {submittedAt: review1.submittedAt, comments: review1.comments, fetchingMoreComments: false});

      wrapper.instance().collectComments({reviewId: review2.id, submittedAt: review2.submittedAt, comments: review2.comments, fetchingMoreComments: false});
      const threadedComments = wrapper.instance().state[originalCommentId];
      assert.lengthOf(threadedComments, 2);
      assert.strictEqual(threadedComments[0].body, 'OG comment');
      assert.strictEqual(threadedComments[1].body, 'reply to OG comment');

      const singleComment = wrapper.instance().state[singleCommentId];
      assert.strictEqual(singleComment[0].body, 'I am single and free');
    });

    it('comments are ordered based on the order in which their reviews were submitted', function() {
      const originalCommentId = 1;
      const review1 = reviewBuilder()
        .id(0)
        .submittedAt('2018-12-20T20:40:55Z')
        .addComment(c => c.id(originalCommentId).path('file0.txt').body('OG comment'))
        .build();

      const review2 = reviewBuilder()
        .id(1)
        .submittedAt('2018-12-22T20:40:55Z')
        .addComment(c => c.id(2).path('file0.txt').replyTo(originalCommentId).body('first reply to OG comment'))
        .build();

      const review3 = reviewBuilder()
        .id(2)
        .submittedAt('2018-12-25T20:40:55Z')
        .addComment(c => c.id(3).path('file0.txt').replyTo(originalCommentId).body('second reply to OG comment'))
        .build();

      const wrapper = shallow(buildApp({reviewSpecs: [review1, review2, review3]}));

      // adding these manually to reviewsById because the last time you call collectComments it groups them, and we don't want to do that just yet.
      wrapper.instance().reviewsById.set(review2.id, {submittedAt: review2.submittedAt, comments: review2.comments, fetchingMoreComments: false});
      wrapper.instance().reviewsById.set(review1.id, {submittedAt: review1.submittedAt, comments: review1.comments, fetchingMoreComments: false});

      wrapper.instance().collectComments({reviewId: review3.id, submittedAt: review3.submittedAt, comments: review3.comments, fetchingMoreComments: false});
      const threadedComments = wrapper.instance().state[originalCommentId];
      assert.lengthOf(threadedComments, 3);

      assert.strictEqual(threadedComments[0].body, 'OG comment');
      assert.strictEqual(threadedComments[1].body, 'first reply to OG comment');
      assert.strictEqual(threadedComments[2].body, 'second reply to OG comment');
    });

    it('comments with a replyTo id that does not point to an existing comment are threaded separately', function() {
      const outdatedCommentId = 1;
      const replyToOutdatedCommentId = 2;
      const review = reviewBuilder()
        .id(2)
        .submittedAt('2018-12-28T20:40:55Z')
        .addComment(c => c.id(replyToOutdatedCommentId).path('file0.txt').replyTo(outdatedCommentId).body('reply to outdated comment'))
        .build();

      const wrapper = shallow(buildApp({reviewSpecs: [review]}));
      wrapper.instance().collectComments({reviewId: review.id, submittedAt: review.submittedAt, comments: review.comments, fetchingMoreComments: false});

      const comments = wrapper.instance().state[replyToOutdatedCommentId];
      assert.lengthOf(comments, 1);
      assert.strictEqual(comments[0].body, 'reply to outdated comment');
    });
  });

  describe('handleError', function() {
    it('attempts to load more reviews', function() {
      const wrapper = shallow(buildApp());

      const loadMoreStub = sinon.stub(wrapper.instance(), '_attemptToLoadMoreReviews');
      wrapper.instance().handleError();

      assert.strictEqual(loadMoreStub.callCount, 1);
    });
  });

  describe('compareReviewsByDate', function() {
    let wrapper;
    const reviewA = reviewBuilder().submittedAt('2018-12-28T20:40:55Z').build();
    const reviewB = reviewBuilder().submittedAt('2018-12-27T20:40:55Z').build();

    beforeEach(function() {
      wrapper = shallow(buildApp());
    });

    it('returns 1 if reviewA is older', function() {
      assert.strictEqual(wrapper.instance().compareReviewsByDate(reviewA, reviewB), 1);
    });
    it('return -1 if reviewB is older', function() {
      assert.strictEqual(wrapper.instance().compareReviewsByDate(reviewB, reviewA), -1);
    });
    it('returns 0 if reviews have the same date', function() {
      assert.strictEqual(wrapper.instance().compareReviewsByDate(reviewA, reviewA), 0);
    });
  });
});
<commit_msg>move clock inside the only test that needs it<commit_after>import React from 'react';
import {shallow} from 'enzyme';
import {reviewBuilder} from '../builder/pr';

import PullRequestReviewsController from '../../lib/controllers/pr-reviews-controller';

import {PAGE_SIZE, PAGINATION_WAIT_TIME_MS} from '../../lib/helpers';

describe('PullRequestReviewsController', function() {
  function buildApp(opts, overrideProps = {}) {
    const o = {
      relayHasMore: () => { return false; },
      relayLoadMore: () => {},
      relayIsLoading: () => { return false; },
      reviewSpecs: [],
      reviewStartCursor: 0,
      ...opts,
    };

    const reviews = {
      edges: o.reviewSpecs.map((spec, i) => ({
        cursor: `result${i}`,
        node: {
          id: spec.id,
          __typename: 'review',
        },
      })),
      pageInfo: {
        startCursor: `result${o.reviewStartCursor}`,
        endCursor: `result${o.reviewStartCursor + o.reviewSpecs.length}`,
        hasNextPage: o.reviewStartCursor + o.reviewSpecs.length < o.reviewItemTotal,
        hasPreviousPage: o.reviewStartCursor !== 0,
      },
      totalCount: o.reviewItemTotal,
    };

    const props = {
      relay: {
        hasMore: o.relayHasMore,
        loadMore: o.relayLoadMore,
        isLoading: o.relayIsLoading,
      },

      switchToIssueish: () => {},
      getBufferRowForDiffPosition: () => {},
      pullRequest: {reviews},
      ...overrideProps,
    };
    return <PullRequestReviewsController {...props} />;
  }
  it('returns null if props.pullRequest is falsy', function() {
    const wrapper = shallow(buildApp({}, {pullRequest: null}));
    assert.isNull(wrapper.getElement());
  });

  it('returns null if props.pullRequest.reviews is falsy', function() {
    const wrapper = shallow(buildApp({}, {pullRequest: {reviews: null}}));
    assert.isNull(wrapper.getElement());
  });

  it('renders a PullRequestReviewCommentsContainer for every review', function() {
    const review1 = reviewBuilder().build();
    const review2 = reviewBuilder().build();

    const reviewSpecs = [review1, review2];
    const wrapper = shallow(buildApp({reviewSpecs}));
    const containers = wrapper.find('ForwardRef(Relay(BarePullRequestReviewCommentsContainer))');
    assert.strictEqual(containers.length, 2);

    assert.strictEqual(containers.at(0).prop('review').id, review1.id);
    assert.strictEqual(containers.at(1).prop('review').id, review2.id);
  });

  it('renders a PullRequestReviewCommentsView and passes props through', function() {
    const review1 = reviewBuilder().build();
    const review2 = reviewBuilder().build();

    const reviewSpecs = [review1, review2];
    const passThroughProp = 'I only exist for the children';
    const wrapper = shallow(buildApp({reviewSpecs}, {passThroughProp}));
    const view = wrapper.find('PullRequestCommentsView');
    assert.strictEqual(view.length, 1);

    assert.strictEqual(wrapper.instance().props.passThroughProp, view.prop('passThroughProp'));
  });

  describe('collectComments', function() {
    it('sets this.reviewsById with correct data', function() {
      const wrapper = shallow(buildApp());
      const args = {reviewId: 123, submittedAt: '2018-12-27T20:40:55Z', comments: ['a comment',
      ], fetchingMoreComments: true};
      assert.strictEqual(wrapper.instance().reviewsById.size, 0);
      wrapper.instance().collectComments(args);
      const review = wrapper.instance().reviewsById.get(args.reviewId);
      delete args.reviewId;
      assert.deepEqual(review, args);
    });

    it('calls groupCommentsByThread if there are no more reviews or comments to be fetched', function() {
      const wrapper = shallow(buildApp());
      const groupCommentsStub = sinon.stub(wrapper.instance(), 'groupCommentsByThread');
      assert.isFalse(groupCommentsStub.called);
      const args = {reviewId: 123, submittedAt: '2018-12-27T20:40:55Z', comments: ['a comment',
      ], fetchingMoreComments: false};
      wrapper.instance().collectComments(args);
      assert.strictEqual(groupCommentsStub.callCount, 1);
    });
  });

  describe('attemptToLoadMoreReviews', function() {
    it('does not call loadMore if hasMore is false', function() {
      const relayLoadMoreStub = sinon.stub();
      const wrapper = shallow(buildApp({relayLoadMore: relayLoadMoreStub}));
      relayLoadMoreStub.reset();

      wrapper.instance()._attemptToLoadMoreReviews();
      assert.strictEqual(relayLoadMoreStub.callCount, 0);
    });

    it('calls loadMore immediately if hasMore is true and isLoading is false', function() {
      const relayLoadMoreStub = sinon.stub();
      const relayHasMore = () => { return true; };
      const wrapper = shallow(buildApp({relayHasMore, relayLoadMore: relayLoadMoreStub}));
      relayLoadMoreStub.reset();

      wrapper.instance()._attemptToLoadMoreReviews();
      assert.strictEqual(relayLoadMoreStub.callCount, 1);
      assert.deepEqual(relayLoadMoreStub.lastCall.args, [PAGE_SIZE, wrapper.instance().handleError]);
    });

    it('calls loadMore after a timeout if hasMore is true and isLoading is true', function() {
      const clock = sinon.useFakeTimers();
      const relayLoadMoreStub = sinon.stub();
      const relayHasMore = () => { return true; };
      const relayIsLoading = () => { return true; };
      const wrapper = shallow(buildApp({relayHasMore, relayIsLoading, relayLoadMore: relayLoadMoreStub}));
      // advancing the timer and resetting the stub to clear the initial calls of
      // _attemptToLoadMoreReviews when the component is initially mounted.
      clock.tick(PAGINATION_WAIT_TIME_MS);
      relayLoadMoreStub.reset();

      wrapper.instance()._attemptToLoadMoreReviews();
      assert.strictEqual(relayLoadMoreStub.callCount, 0);

      clock.tick(PAGINATION_WAIT_TIME_MS);
      assert.strictEqual(relayLoadMoreStub.callCount, 1);
      assert.deepEqual(relayLoadMoreStub.lastCall.args, [PAGE_SIZE, wrapper.instance().handleError]);
      sinon.restore();
    });
  });

  describe('_loadMoreReviews', function() {
    it('calls this.props.relay.loadMore with correct args', function() {
      const relayLoadMoreStub = sinon.stub();
      const wrapper = shallow(buildApp({relayLoadMore: relayLoadMoreStub}));
      wrapper.instance()._loadMoreReviews();

      assert.deepEqual(relayLoadMoreStub.lastCall.args, [PAGE_SIZE, wrapper.instance().handleError]);
    });
  });

  describe('grouping and ordering comments', function() {
    it('groups the comments into threads based on replyId', function() {
      const originalCommentId = 1;
      const singleCommentId = 5;
      const review1 = reviewBuilder()
        .id(0)
        .submittedAt('2018-12-27T20:40:55Z')
        .addComment(c => c.id(originalCommentId).path('file0.txt').body('OG comment'))
        .build();

      const review2 = reviewBuilder()
        .id(1)
        .submittedAt('2018-12-28T20:40:55Z')
        .addComment(c => c.id(2).path('file0.txt').replyTo(originalCommentId).body('reply to OG comment'))
        .addComment(c => c.id(singleCommentId).path('file0.txt').body('I am single and free'))
        .build();

      const wrapper = shallow(buildApp({reviewSpecs: [review1, review2]}));

      // adding this manually to reviewsById because the last time you call collectComments it groups them, and we don't want to do that just yet.
      wrapper.instance().reviewsById.set(review1.id, {submittedAt: review1.submittedAt, comments: review1.comments, fetchingMoreComments: false});

      wrapper.instance().collectComments({reviewId: review2.id, submittedAt: review2.submittedAt, comments: review2.comments, fetchingMoreComments: false});
      const threadedComments = wrapper.instance().state[originalCommentId];
      assert.lengthOf(threadedComments, 2);
      assert.strictEqual(threadedComments[0].body, 'OG comment');
      assert.strictEqual(threadedComments[1].body, 'reply to OG comment');

      const singleComment = wrapper.instance().state[singleCommentId];
      assert.strictEqual(singleComment[0].body, 'I am single and free');
    });

    it('comments are ordered based on the order in which their reviews were submitted', function() {
      const originalCommentId = 1;
      const review1 = reviewBuilder()
        .id(0)
        .submittedAt('2018-12-20T20:40:55Z')
        .addComment(c => c.id(originalCommentId).path('file0.txt').body('OG comment'))
        .build();

      const review2 = reviewBuilder()
        .id(1)
        .submittedAt('2018-12-22T20:40:55Z')
        .addComment(c => c.id(2).path('file0.txt').replyTo(originalCommentId).body('first reply to OG comment'))
        .build();

      const review3 = reviewBuilder()
        .id(2)
        .submittedAt('2018-12-25T20:40:55Z')
        .addComment(c => c.id(3).path('file0.txt').replyTo(originalCommentId).body('second reply to OG comment'))
        .build();

      const wrapper = shallow(buildApp({reviewSpecs: [review1, review2, review3]}));

      // adding these manually to reviewsById because the last time you call collectComments it groups them, and we don't want to do that just yet.
      wrapper.instance().reviewsById.set(review2.id, {submittedAt: review2.submittedAt, comments: review2.comments, fetchingMoreComments: false});
      wrapper.instance().reviewsById.set(review1.id, {submittedAt: review1.submittedAt, comments: review1.comments, fetchingMoreComments: false});

      wrapper.instance().collectComments({reviewId: review3.id, submittedAt: review3.submittedAt, comments: review3.comments, fetchingMoreComments: false});
      const threadedComments = wrapper.instance().state[originalCommentId];
      assert.lengthOf(threadedComments, 3);

      assert.strictEqual(threadedComments[0].body, 'OG comment');
      assert.strictEqual(threadedComments[1].body, 'first reply to OG comment');
      assert.strictEqual(threadedComments[2].body, 'second reply to OG comment');
    });

    it('comments with a replyTo id that does not point to an existing comment are threaded separately', function() {
      const outdatedCommentId = 1;
      const replyToOutdatedCommentId = 2;
      const review = reviewBuilder()
        .id(2)
        .submittedAt('2018-12-28T20:40:55Z')
        .addComment(c => c.id(replyToOutdatedCommentId).path('file0.txt').replyTo(outdatedCommentId).body('reply to outdated comment'))
        .build();

      const wrapper = shallow(buildApp({reviewSpecs: [review]}));
      wrapper.instance().collectComments({reviewId: review.id, submittedAt: review.submittedAt, comments: review.comments, fetchingMoreComments: false});

      const comments = wrapper.instance().state[replyToOutdatedCommentId];
      assert.lengthOf(comments, 1);
      assert.strictEqual(comments[0].body, 'reply to outdated comment');
    });
  });

  describe('handleError', function() {
    it('attempts to load more reviews', function() {
      const wrapper = shallow(buildApp());

      const loadMoreStub = sinon.stub(wrapper.instance(), '_attemptToLoadMoreReviews');
      wrapper.instance().handleError();

      assert.strictEqual(loadMoreStub.callCount, 1);
    });
  });

  describe('compareReviewsByDate', function() {
    let wrapper;
    const reviewA = reviewBuilder().submittedAt('2018-12-28T20:40:55Z').build();
    const reviewB = reviewBuilder().submittedAt('2018-12-27T20:40:55Z').build();

    beforeEach(function() {
      wrapper = shallow(buildApp());
    });

    it('returns 1 if reviewA is older', function() {
      assert.strictEqual(wrapper.instance().compareReviewsByDate(reviewA, reviewB), 1);
    });
    it('return -1 if reviewB is older', function() {
      assert.strictEqual(wrapper.instance().compareReviewsByDate(reviewB, reviewA), -1);
    });
    it('returns 0 if reviews have the same date', function() {
      assert.strictEqual(wrapper.instance().compareReviewsByDate(reviewA, reviewA), 0);
    });
  });
});
<|endoftext|>