<commit_before>function build_from_template(prefix, context) {
    var template_source = $(prefix + "-template").html();
    var template = Handlebars.compile(template_source);

    var html = template(context);
    $(prefix + "-content").html(html);
}

function build_attribute_button_handler(prefix) {
    function btn_handler() {
        var button = $(this);
        var attribute = $(prefix + "-" + button.data("type"));
        var value = attribute.data("value") | 0;
        var is_decrem = button.find(".glyphicon-minus").length

        value = is_decrem ? value - 1 : value + 1;

        attribute.data("value", value);
        attribute.text(value).trigger("change");
    }

    return btn_handler;
}

function connect_attribute_buttons(base_prefix, attr_prefix) {
    var buttons = $(base_prefix + " button");

    buttons.click(build_attribute_button_handler(attr_prefix));
}

function connect_attribute_display(prefix, lst) {
    for (var i = 0; i < lst.length; i++) {
        var attribute = $(prefix + "-" + lst[i].type);
        if (attribute) {
            attribute.text(attribute.data("value"));
        }

        attribute.on("change", on_attribute_change);
    }
}

function local_save_data() {
    var save_data = {};

    data_sets.forEach(function(data_set) {
        var data = window[data_set.name];
        save_data[data_set.name] = {};

        for (var i = 0; i < data.length; i++) {
            var attr = data[i].type;
            save_data[data_set.name][attr] = $(data_set.prefix + "-" + attr).data("value");
        }
    });

    window.localStorage.setItem("rpg-data", JSON.stringify(save_data));
}

function local_load_data() {
    var raw_data = window.localStorage.getItem("rpg-data");

    if (!raw_data) {
        return;
    }

    var parsed_data = JSON.parse(raw_data);

    data_sets.forEach(function(data_set) {
        var data = window[data_set.name];

        for (var i = 0; i < data.length; i++) {
            var attr = data[i].type;
            var span_attr = $(data_set.prefix + "-" + attr);
            var value = parsed_data[data_set.name][attr];

            span_attr.data("value", value).text(value).trigger("change");
        }
    });
}

function on_attribute_change(event) {
    var span = $(this);
    console.log(span);
}

var attributes_list = [
    // has 'attribute-' prefix
    { name: "Erő", type: "strength" },
    { name: "Ügyesség", type: "dexterity" },
    { name: "Gyorsaság", type: "speed" },
    { name: "Állóképesség", type: "stanima" },
    { name: "Egészség", type: "health" },
    { name: "Szépség", type: "beauty" },
    { name: "Intelligencia", type: "intelligence" },
    { name: "Akaraterő", type: "will-power" },
    { name: "Asztrál", type: "astral" }
];

var health_attributes_list = [
    // has 'health-' prefix
    { name: "Alap ÉP", type: "base-hp" },
    { name: "Max ÉP", type: "max-hp" },
    { name: "Akt. ÉP:", type: "current-hp" },
];

var data_sets = [
    { name: "attributes_list", prefix: "#attribute" },
    { name: "health_attributes_list", prefix: "#health" },
];

var data_connections = [
    { name: "on-health-change",
      on: "#attribute-health",
      update: "#health-max-hp",
      handler: function (on, update) {
        var health_value = $("#attribute-health").data("value") | 0;
        var value = $("#health-base-hp").data("value") + (health_value > 10 ? health_value - 10 : 0);
        $(update).data("value", value).text(value).trigger("chage");
      }
    },
    { name: "on-base-hp-change",
      on: "#health-base-hp",
      update: "#health-max-hp",
      handler: "on-health-change"    // defer the change operation to the other connection
    },
];

function connect_data_connections() {
    for (var i = 0; i < data_connections.length; i++) {
        var connection = data_connections[i];
        var attribute = $(connection.on);

        if (typeof(connection.handler) === "string") {
            // We found a handler which defers its call to another connection's handler
            // select that handler and modify the current connection.
            for (var j = 0; j < data_connections.length; i++) {
                if (data_connections[j].name == connection.handler) {
                    connection.handler = data_connections[j].handler;
                    break;
                }
            }
        }

        attribute.on("change", connection, on_connected_update);
    }
}

function on_connected_update(e) {
    e.data.handler(e.data.on, e.data.update);
}

$(document).ready(function() {
    build_from_template("#attributes-table", { attributes: attributes_list });
    connect_attribute_display("#attribute", attributes_list);
    connect_attribute_buttons("table.attributes", "#attribute");

    build_from_template("#health-table", { attributes: health_attributes_list });
    connect_attribute_display("#health", health_attributes_list);
    connect_attribute_buttons("table.health", "#health");

    connect_data_connections();
    $("#button-load-data").click(local_load_data);
    $("#button-save-data").click(local_save_data);
});
<commit_msg>Improve data connections<commit_after>function over_10(value) {
    return value > 10 ? value - 10 : 0;
}

function build_from_template(prefix, context) {
    var template_source = $(prefix + "-template").html();
    var template = Handlebars.compile(template_source);

    var html = template(context);
    $(prefix + "-content").html(html);
}

function build_attribute_button_handler(prefix) {
    function btn_handler() {
        var button = $(this);
        var attribute = $(prefix + "-" + button.data("type"));
        var value = attribute.data("value") | 0;
        var is_decrem = button.find(".glyphicon-minus").length

        value = is_decrem ? value - 1 : value + 1;

        attribute.data("value", value);
        attribute.text(value).trigger("change");
    }

    return btn_handler;
}

function connect_attribute_buttons(base_prefix, attr_prefix) {
    var buttons = $(base_prefix + " button");

    buttons.click(build_attribute_button_handler(attr_prefix));
}

function connect_attribute_display(prefix, lst) {
    for (var i = 0; i < lst.length; i++) {
        var attribute = $(prefix + "-" + lst[i].type);
        if (attribute) {
            attribute.text(attribute.data("value"));
        }

        attribute.on("change", on_attribute_change);
    }
}

function local_save_data() {
    var save_data = {};

    data_sets.forEach(function(data_set) {
        var data = window[data_set.name];
        save_data[data_set.name] = {};

        for (var i = 0; i < data.length; i++) {
            var attr = data[i].type;
            save_data[data_set.name][attr] = $(data_set.prefix + "-" + attr).data("value");
        }
    });

    window.localStorage.setItem("rpg-data", JSON.stringify(save_data));
}

function local_load_data() {
    var raw_data = window.localStorage.getItem("rpg-data");

    if (!raw_data) {
        return;
    }

    var parsed_data = JSON.parse(raw_data);

    data_sets.forEach(function(data_set) {
        var data = window[data_set.name];

        for (var i = 0; i < data.length; i++) {
            var attr = data[i].type;
            var span_attr = $(data_set.prefix + "-" + attr);
            var value = parsed_data[data_set.name][attr];

            span_attr.data("value", value).text(value).trigger("change");
        }
    });
}

function on_attribute_change(event) {
    var span = $(this);
    console.log(span);
}

var attributes_list = [
    // has 'attribute-' prefix
    { name: "Erő", type: "strength" },
    { name: "Ügyesség", type: "dexterity" },
    { name: "Gyorsaság", type: "speed" },
    { name: "Állóképesség", type: "stanima" },
    { name: "Egészség", type: "health" },
    { name: "Szépség", type: "beauty" },
    { name: "Intelligencia", type: "intelligence" },
    { name: "Akaraterő", type: "will-power" },
    { name: "Asztrál", type: "astral" }
];

var health_attributes_list = [
    // has 'health-' prefix
    { name: "Alap ÉP", type: "base-hp" },
    { name: "Max ÉP", type: "max-hp" },
    { name: "Akt. ÉP:", type: "current-hp" },

    { name: "Alap FP", type: "base-fp" },
    { name: "Max FP", type: "max-fp" },
    { name: "Akt. FP:", type: "current-fp" },
];

var data_sets = [
    { name: "attributes_list", prefix: "#attribute" },
    { name: "health_attributes_list", prefix: "#health" },
];

var data_connections = [
    { name: "on-hp-attr-change",
      on: ["#attribute-health", "#health-base-hp"],
      update: "#health-max-hp",
      handler: function (on, update) {
        var health_value = $("#attribute-health").data("value") | 0;
        var value = $("#health-base-hp").data("value") + (health_value > 10 ? health_value - 10 : 0);
        $(update).data("value", value).text(value).trigger("chage");
      }
    },

    { name: "on-fp-attr-change",
      on: ["#attribute-stanima", "#attribute-will-power"],
      update: "#health-max-fp",
      handler: function (on, update) {
        var stanima = over_10($("#attribute-stanima").data("value") | 0);
        var willpower = over_10($("#attribute-will-power").data("value") | 0);
        var value = $("#health-base-fp").data("value") + stanima + willpower;
        $(update).data("value", value).text(value).trigger("chage");
      }
    },
];

function connect_data_connections() {
    for (var i = 0; i < data_connections.length; i++) {
        var connection = data_connections[i];
        if (typeof(connection.handler) === "string") {
            // We found a handler which defers its call to another connection's handler
            // select that handler and modify the current connection.
            for (var j = 0; j < data_connections.length; i++) {
                if (data_connections[j].name == connection.handler) {
                    connection.handler = data_connections[j].handler;
                    break;
                }
            }
        }

        for (var j = 0; j < connection.on.length; j++) {
            var attribute = $(connection.on[j]);
            attribute.on("change", connection, on_connected_update);
        }
    }
}

function on_connected_update(e) {
    e.data.handler(e.data.on, e.data.update);
}

$(document).ready(function() {
    build_from_template("#attributes-table", { attributes: attributes_list });
    connect_attribute_display("#attribute", attributes_list);
    connect_attribute_buttons("table.attributes", "#attribute");

    build_from_template("#health-table", { attributes: health_attributes_list });
    connect_attribute_display("#health", health_attributes_list);
    connect_attribute_buttons("table.health", "#health");

    connect_data_connections();
    $("#button-load-data").click(local_load_data);
    $("#button-save-data").click(local_save_data);
});
<|endoftext|>


<commit_before><commit_msg>`sprockets.UI` also contains `RoleType`<commit_after><|endoftext|>


<commit_before>var JS_GAME = {};

JS_GAME.game = (function () {
  var isKeyDown = [];
  var context;
  var userData = [];
  var enemies = [];
  var frameLength = 1;// in milliseconds
  var socket;
  var connected = false;
  var user = "";
  var pass = "";
  var windowWidth = $(window).innerWidth();
  var windowHeight = $(window).innerHeight();

  function init() {
    user = document.getElementById("loginInfo").user.value;
    pass = document.getElementById("loginInfo").pass.value;
    if (user.indexOf(",") >= 0 || user.indexOf(":") >= 0){
      document.getElementById("loginInfo").user.value = "INVALID INPUT";
      return;
    }

    $("#user").blur();
    $("#pass").blur();
    $("#loginInfo").blur().remove();

    socket = new WebSocket("ws:167.88.120.57:38734");

    socket.onopen = function() {
      connected = true;
      socket.send("login:" + user + "," + pass);
    };

socket.onmessage = function(message) {
  if (message.data.indexOf("pos") == 0){
  userData = message.data.split(":")[1].split(",");

} else if (message.data.indexOf("dat") == 0){
  enemies = message.data.split(":")[1].split(",");
}
};

socket.onclose = function() {
  window.location.reload(false);
};

socket.onerror = function() {
};

document.body.innerHTML = "";
for (i = 0; i < 256; i++){
  isKeyDown[i] = false;
}
$('body').append('<canvas id="GameCanvas">');
var canvasElement = $('#GameCanvas');
canvasElement.attr('width', windowWidth).attr('height', windowHeight)t.attr('tabIndex', 0);
canvasElement.focus();

var canvas = canvasElement[0];

window.addEventListener( "keydown", keyPress, false);
window.addEventListener( "keyup", keyRelease, false);
context = canvas.getContext('2d');
gameLoop();
}

function gameLoop() {
  var keyData = "";
  for (i = 0; i < 256; i++){
    keyData += isKeyDown[i] ? 1 : 0;
  }
  try {
    socket.send("keys:" + keyData);
  } catch (err) {
  }
  context.clearRect(0, 0, windowWidth, windowHeight);
  //draw enemies
  for (i = 0; i < enemies.length; i += 4){
  context.fillStyle = enemies[i+2];
  context.fillRect(enemies[i], enemies[i+1], 30, 50);
  }
  //draw player
  context.fillStyle = userData[2];
  context.fillRect(userData[0], userData[1], 30, 50);
  //draw enemy names
  for (i = 0; i < enemies.length; i += 4){
  context.fillStyle = enemies[i+2];
  context.fillText(enemies[i+3],(enemies[i] - (context.measureText(enemies[i+3]).width / 2)) + 15,enemies[i+1] - 5);
  }
  //draw player name
  context.fillStyle = userData[2];
  context.font = "15px Arial";
  context.fillText(userData[3],(userData[0] - (context.measureText(userData[3]).width / 2)) + 15,userData[1] - 5);

  setTimeout(gameLoop, frameLength);
}

function keyPress(e){
  isKeyDown[e.keyCode] = true;
  return false;
}
function keyRelease(e){
  isKeyDown[e.keyCode] = false;
}
function isKeyPressed(c){
  return isKeyDown[c.charCodeAt(0)];
}

return {
  init: init
};
})();

$(document).ready(function() {
  $("#loginInfo").submit(function(event){
    event.preventDefault();
    JS_GAME.game.init();
    return false;
  });
});
<commit_msg>Cleaner code<commit_after>var JS_GAME = {};

JS_GAME.game = (function () {
  var isKeyDown = [];
  var context;
  var userData = [];
  var enemies = [];
  var frameLength = 1;// in milliseconds
  var socket;
  var connected = false;
  var user = "";
  var pass = "";
  var windowWidth = $(window).innerWidth();
  var windowHeight = $(window).innerHeight();

  function init() {
    user = document.getElementById("loginInfo").user.value;
    pass = document.getElementById("loginInfo").pass.value;
    if (user.indexOf(",") >= 0 || user.indexOf(":") >= 0){
      document.getElementById("loginInfo").user.value = "INVALID INPUT";
      return;
    }

    $("#user").blur();
    $("#pass").blur();
    $("#loginInfo").blur().remove();

    socket = new WebSocket("ws:167.88.120.57:38734");

    socket.onopen = function() {
      connected = true;
      socket.send("login:" + user + "," + pass);
    };

socket.onmessage = function(message) {
  if (message.data.indexOf("pos") == 0){
  userData = message.data.split(":")[1].split(",");

} else if (message.data.indexOf("dat") == 0){
  enemies = message.data.split(":")[1].split(",");
}
};

socket.onclose = function() {
  window.location.reload(false);
};

socket.onerror = function() {
};

document.body.innerHTML = "";
for (i = 0; i < 256; i++){
  isKeyDown[i] = false;
}
$('body').append('<canvas id="GameCanvas">');
var canvasElement = $('#GameCanvas');
canvasElement.attr({
  width: windowWidth,
  height: windowHeight,
  tabIndex: 0

});
canvasElement.focus();

var canvas = canvasElement[0];

window.addEventListener( "keydown", keyPress, false);
window.addEventListener( "keyup", keyRelease, false);
context = canvas.getContext('2d');
gameLoop();
}

function gameLoop() {
  var keyData = "";
  for (i = 0; i < 256; i++){
    keyData += isKeyDown[i] ? 1 : 0;
  }
  try {
    socket.send("keys:" + keyData);
  } catch (err) {
  }
  context.clearRect(0, 0, windowWidth, windowHeight);
  //draw enemies
  for (i = 0; i < enemies.length; i += 4){
  context.fillStyle = enemies[i+2];
  context.fillRect(enemies[i], enemies[i+1], 30, 50);
  }
  //draw player
  context.fillStyle = userData[2];
  context.fillRect(userData[0], userData[1], 30, 50);
  //draw enemy names
  for (i = 0; i < enemies.length; i += 4){
  context.fillStyle = enemies[i+2];
  context.fillText(enemies[i+3],(enemies[i] - (context.measureText(enemies[i+3]).width / 2)) + 15,enemies[i+1] - 5);
  }
  //draw player name
  context.fillStyle = userData[2];
  context.font = "15px Arial";
  context.fillText(userData[3],(userData[0] - (context.measureText(userData[3]).width / 2)) + 15,userData[1] - 5);

  setTimeout(gameLoop, frameLength);
}

function keyPress(e){
  isKeyDown[e.keyCode] = true;
  return false;
}
function keyRelease(e){
  isKeyDown[e.keyCode] = false;
}
function isKeyPressed(c){
  return isKeyDown[c.charCodeAt(0)];
}

return {
  init: init
};
})();

$(document).ready(function() {
  $("#loginInfo").submit(function(event){
    event.preventDefault();
    JS_GAME.game.init();
    return false;
  });
});
<|endoftext|>


<commit_before>function generateBarChart(id,data){

    var margin = {top: 0, right: 80, bottom: 30, left: 30},
        width = $(id).width() - margin.left - margin.right,
        height =  $(id).height() - margin.top - margin.bottom;

    var chart = d3.select(".chart")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var x = d3.scale.ordinal()
        .rangeRoundBands([0, width], .1);

    var y = d3.scale.linear()
        .range([height, 0]);

    var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom");

    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left")
        .ticks(5);

    var yGrid = d3.svg.axis()
        .scale(y)
        .orient("left")
        .tickSize(-width, 0, 0)
        .tickFormat("")
        .ticks(5);

    var svg = d3.select(id).append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var max = d3.max(data, function(d) { return d.newCases; });

    x.domain(data.map(function(d) { return formatDate(d.Date); }));
    y.domain([0, max]);

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

    svg.append("g")
        .attr("class", "y axis")
        .call(yAxis);

    svg.append("g")
        .attr("class", "grid")
        .call(yGrid);

    svg.selectAll(".totalbar")
        .data(data)
    .enter().append("rect")
        .attr("class", "totalbar")
        .attr("x", function(d) { return x(formatDate(d.Date)); })
        .attr("width", x.rangeBand()/2)
        .attr("y", function(d) { return y(d.newCases); })
        .attr("height", function(d) {
           return height - y(d.newCases);});

    svg.selectAll(".deathbar")
        .data(data)
    .enter().append("rect")
        .attr("class", "deathbar")
        .attr("x", function(d) { return x(formatDate(d.Date))+x.rangeBand()/2; })
        .attr("width", x.rangeBand()/2)
        .attr("y", function(d) { return y(d.newDeaths); })
        .attr("height", function(d) {
           return height - y(d.newDeaths);});

    svg.selectAll(".current")
        .data(data)
    .enter().append("rect")
        .attr("class", "current")
        .attr("x", function(d) { return x(formatDate(d.Date)); })
        .attr("width", x.rangeBand())
        .attr("y", function(d) { return y(max); })
        .attr("height", function(d) {
           return height - y(max);})
        .attr("opacity",0)
        .attr("id",function(d,i){return "barSelect"+i;})
        .on("click",function(d,i){
            d3.select("#barSelect"+currentWeek).attr("opacity",0);
            currentWeek=i;
            d3.select("#barSelect"+currentWeek).attr("opacity",0.15);
            transitionMap();
        });

    var g = svg.append("g");

    g.append("rect")
        .attr("x", width+10)
        .attr("y", 10)
        .attr("width", 10)
        .attr("height", 10)
        .attr("fill","steelblue");

    g.append("rect")
        .attr("x", width+10)
        .attr("y", 30)
        .attr("width", 10)
        .attr("height", 10)
        .attr("fill","red");

    g.append("text")
        .attr("x",width+25)
        .attr("y",18)
        .text("New Cases")
        .attr("font-size","10px");

    g.append("text")
        .attr("x",width+25)
        .attr("y",38)
        .text("Deaths")
        .attr("font-size","10px");

}

function generateMap(){
    var margin = {top: 10, right: 10, bottom: 10, left: 10},
    width = $('#map').width() - margin.left - margin.right,
    height = 425;

    var projection = d3.geo.mercator()
        .center([-5,7.7])
        .scale(1500);

    var svg = d3.select('#map').append("svg")
        .attr("width", width)
        .attr("height", height);

    var path = d3.geo.path()
        .projection(projection);

    var g = svg.append("g");

    g.selectAll("path")
        .data(westafrica.features)
        .enter()
        .append("path")
        .attr("d", path)
        .attr("stroke",'#aaaaaa')
        .attr("fill",'#ffffff')
        .attr("class","country");

    var g = svg.append("g");

    g.selectAll("path")
        .data(regions.features)
        .enter()
        .append("path")
        .attr("d", path)
        .attr("stroke",'#aaaaaa')
        .attr("fill",'#ff0000')
        .attr("opacity",0)
        .attr("id",function(d){return d.properties.NAME_REF.replace(/\s/g, '');})
        .attr("class","region");

    var g = svg.append("g");

    g.selectAll("path")
        .data(blockades_geo.features)
        .enter()
        .append("path")
        .attr("d", path)
        .attr("stroke",'brown')
        .attr("fill","none")
        .attr("stroke-width",2)
        .attr("opacity",1)
        .attr("class","blockade")
        .attr("id",function(d){
                    return d.properties.Border_ID;});

    var g = svg.append("g");

    g.selectAll("circles")
        .data(medical_centres_geo.features)
        .enter()
        .append("circle")
        .attr('cx',function(d){
                    var point = projection([ d.geometry.coordinates[0], d.geometry.coordinates[1] ]);
                    return point[0];
                })
        .attr('cy',function(d){
                    var point = projection([ d.geometry.coordinates[0], d.geometry.coordinates[1] ]);
                    return point[1];
                })
        .attr("r", 5)
        .attr("id",function(d){
                    return d.properties.ID;
        })
        .attr("class","medical_centres")
        .attr("fill",function(d){
            if(d.properties.Type=="Isolation"){
                return "green";
            }else{
                return "blue";
            }
                })
        .attr("opacity",0.7);

    var g = svg.append("g");

    g.append("rect")
        .attr("x", 0)
        .attr("y", 350)
        .attr("width", 10)
        .attr("height", 10)
        .attr("fill","#ff9999");

    g.append("text")
        .attr("x",15)
        .attr("y",358)
        .text("Confirmed Cases")
        .attr("font-size","10px");

    g.append("rect")
        .attr("x", 0)
        .attr("y", 374)
        .attr("width", 10)
        .attr("height", 2)
        .attr("fill","brown");

    g.append("text")
        .attr("x",15)
        .attr("y",378)
        .text("Blockade")
        .attr("font-size","10px");

    g.append("circle")
        .attr("cx",5)
        .attr("cy",335)
        .attr("r",5)
        .attr("fill","green");

    g.append("text")
        .attr("x",15)
        .attr("y",338)
        .text("Referral Centre")
        .attr("font-size","10px");

    g.append("circle")
        .attr("cx",5)
        .attr("cy",315)
        .attr("r",5)
        .attr("fill","blue");

    g.append("text")
        .attr("x",15)
        .attr("y",318)
        .text("Treatment")
        .attr("font-size","10px");

    var mapLabels = svg.append("g");

    mapLabels.selectAll('text')
      .data(westafrica.features)
         .enter()
         .append("text")
         .attr("x", function(d,i){
                     return path.centroid(d)[0]-20;})
         .attr("y", function(d,i){
                     return path.centroid(d)[1];})
         .attr("dy", ".55em")
         .attr("class","maplabel")
         .style("font-size","20px")
         .attr("opacity",0.4)
         .text(function(d,i){
                      return d.properties.NAME_REF;
                  });

}

function transitionMap(){

    $('#week').html("
Map for week ending " + mapSettings[currentWeek].Date + "
");

    var projection = d3.geo.mercator()
        .center([mapSettings[currentWeek].lng,mapSettings[currentWeek].lat])
        .scale(mapSettings[currentWeek].scale);

    var path = d3.geo.path()
        .projection(projection);

    d3.selectAll('.country').transition()
            .attr('d', path);

    d3.selectAll('.blockade').transition()
            .attr('d', path);

    d3.selectAll('.maplabel').transition()
        .attr("x", function(d,i){
                     return path.centroid(d)[0]-20;})
        .attr("y", function(d,i){
                     return path.centroid(d)[1];});

    //d3.selectAll(".medical_centres").transition();

    var data = regionDeaths[currentWeek].Deaths;
    data.forEach(function(element){
               d3.select("#"+element.Region.replace(/\s/g, ''))
                        .transition()
                        .attr("opacity",convertDeathsToOpacity(element.Deaths))
                        .attr('d', path);
            });

    var data = blockades[currentWeek].blockades;
    data.forEach(function(element){
               d3.select("#"+element.blockade_id.split(' ').join('_'))
                        .transition()
                        .attr("opacity",convertBlockadesToOpacity(element.enforced))
                        .attr('d', path);
            });

    var data = medical_centres[currentWeek].medical_centres;
    data.forEach(function(element){
               d3.select("#"+element.id.split(' ').join('_'))
                        .transition()
                        .attr("opacity",convertMedicalCentresToOpacity(element.open))
                        .attr('cx',function(d){
                                    var point = projection([ d.geometry.coordinates[0], d.geometry.coordinates[1] ]);
                                    return point[0];
                                })
                        .attr('cy',function(d){
                                    var point = projection([ d.geometry.coordinates[0], d.geometry.coordinates[1] ]);
                                    return point[1];
                                });
            });

}

function convertDeathsToOpacity(deaths){
    var opacity = deaths/90*0.7;
    if(opacity>0){opacity=opacity+0.2;}
    return opacity;
}

function convertBlockadesToOpacity(enforce){
    if(enforce=="F"){
        return 0;
    } else {
        return 0.75;
    }
}

function convertMedicalCentresToOpacity(open){
    if(open==1){
        return 0.75;
    } else {
        return 0;
    }
}

function formatDate(date){
    var month=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
    return date.substring(0,2) + " " + month[parseInt((date.substring(4,5))-1)];
}

var currentWeek=0;
generateBarChart('#bar_chart',totalCasesAndDeaths);
d3.select("#barSelect"+currentWeek).attr("opacity",0.15);
generateMap();
transitionMap();

$(document).keydown(function(e) {
    switch(e.which) {
        case 37:
            d3.select("#barSelect"+currentWeek).attr("opacity",0);
            currentWeek=currentWeek-1;
            if(currentWeek<0){currentWeek=0;}
            d3.select("#barSelect"+currentWeek).attr("opacity",0.15);
            transitionMap();
            break;

        case 39:
            d3.select("#barSelect"+currentWeek).attr("opacity",0);
            currentWeek=currentWeek+1;
            if(currentWeek>totalCasesAndDeaths.length-1){
                currentWeek=totalCasesAndDeaths.length-1;
            }
            d3.select("#barSelect"+currentWeek).attr("opacity",0.15);
            transitionMap();
            break;

        default: return; // exit this handler for other keys
    }
    e.preventDefault(); // prevent the default action (scroll / move caret)
});
<commit_msg>Updated cases to opacity function for new max value<commit_after>function generateBarChart(id,data){

    var margin = {top: 0, right: 80, bottom: 30, left: 30},
        width = $(id).width() - margin.left - margin.right,
        height =  $(id).height() - margin.top - margin.bottom;

    var chart = d3.select(".chart")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var x = d3.scale.ordinal()
        .rangeRoundBands([0, width], .1);

    var y = d3.scale.linear()
        .range([height, 0]);

    var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom");

    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left")
        .ticks(5);

    var yGrid = d3.svg.axis()
        .scale(y)
        .orient("left")
        .tickSize(-width, 0, 0)
        .tickFormat("")
        .ticks(5);

    var svg = d3.select(id).append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var max = d3.max(data, function(d) { return d.newCases; });

    x.domain(data.map(function(d) { return formatDate(d.Date); }));
    y.domain([0, max]);

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

    svg.append("g")
        .attr("class", "y axis")
        .call(yAxis);

    svg.append("g")
        .attr("class", "grid")
        .call(yGrid);

    svg.selectAll(".totalbar")
        .data(data)
    .enter().append("rect")
        .attr("class", "totalbar")
        .attr("x", function(d) { return x(formatDate(d.Date)); })
        .attr("width", x.rangeBand()/2)
        .attr("y", function(d) { return y(d.newCases); })
        .attr("height", function(d) {
           return height - y(d.newCases);});

    svg.selectAll(".deathbar")
        .data(data)
    .enter().append("rect")
        .attr("class", "deathbar")
        .attr("x", function(d) { return x(formatDate(d.Date))+x.rangeBand()/2; })
        .attr("width", x.rangeBand()/2)
        .attr("y", function(d) { return y(d.newDeaths); })
        .attr("height", function(d) {
           return height - y(d.newDeaths);});

    svg.selectAll(".current")
        .data(data)
    .enter().append("rect")
        .attr("class", "current")
        .attr("x", function(d) { return x(formatDate(d.Date)); })
        .attr("width", x.rangeBand())
        .attr("y", function(d) { return y(max); })
        .attr("height", function(d) {
           return height - y(max);})
        .attr("opacity",0)
        .attr("id",function(d,i){return "barSelect"+i;})
        .on("click",function(d,i){
            d3.select("#barSelect"+currentWeek).attr("opacity",0);
            currentWeek=i;
            d3.select("#barSelect"+currentWeek).attr("opacity",0.15);
            transitionMap();
        });

    var g = svg.append("g");

    g.append("rect")
        .attr("x", width+10)
        .attr("y", 10)
        .attr("width", 10)
        .attr("height", 10)
        .attr("fill","steelblue");

    g.append("rect")
        .attr("x", width+10)
        .attr("y", 30)
        .attr("width", 10)
        .attr("height", 10)
        .attr("fill","red");

    g.append("text")
        .attr("x",width+25)
        .attr("y",18)
        .text("New Cases")
        .attr("font-size","10px");

    g.append("text")
        .attr("x",width+25)
        .attr("y",38)
        .text("Deaths")
        .attr("font-size","10px");

}

function generateMap(){
    var margin = {top: 10, right: 10, bottom: 10, left: 10},
    width = $('#map').width() - margin.left - margin.right,
    height = 425;

    var projection = d3.geo.mercator()
        .center([-5,7.7])
        .scale(1500);

    var svg = d3.select('#map').append("svg")
        .attr("width", width)
        .attr("height", height);

    var path = d3.geo.path()
        .projection(projection);

    var g = svg.append("g");

    g.selectAll("path")
        .data(westafrica.features)
        .enter()
        .append("path")
        .attr("d", path)
        .attr("stroke",'#aaaaaa')
        .attr("fill",'#ffffff')
        .attr("class","country");

    var g = svg.append("g");

    g.selectAll("path")
        .data(regions.features)
        .enter()
        .append("path")
        .attr("d", path)
        .attr("stroke",'#aaaaaa')
        .attr("fill",'#ff0000')
        .attr("opacity",0)
        .attr("id",function(d){return d.properties.NAME_REF.replace(/\s/g, '');})
        .attr("class","region");

    var g = svg.append("g");

    g.selectAll("path")
        .data(blockades_geo.features)
        .enter()
        .append("path")
        .attr("d", path)
        .attr("stroke",'brown')
        .attr("fill","none")
        .attr("stroke-width",2)
        .attr("opacity",1)
        .attr("class","blockade")
        .attr("id",function(d){
                    return d.properties.Border_ID;});

    var g = svg.append("g");

    g.selectAll("circles")
        .data(medical_centres_geo.features)
        .enter()
        .append("circle")
        .attr('cx',function(d){
                    var point = projection([ d.geometry.coordinates[0], d.geometry.coordinates[1] ]);
                    return point[0];
                })
        .attr('cy',function(d){
                    var point = projection([ d.geometry.coordinates[0], d.geometry.coordinates[1] ]);
                    return point[1];
                })
        .attr("r", 5)
        .attr("id",function(d){
                    return d.properties.ID;
        })
        .attr("class","medical_centres")
        .attr("fill",function(d){
            if(d.properties.Type=="Isolation"){
                return "green";
            }else{
                return "blue";
            }
                })
        .attr("opacity",0.7);

    var g = svg.append("g");

    g.append("rect")
        .attr("x", 0)
        .attr("y", 350)
        .attr("width", 10)
        .attr("height", 10)
        .attr("fill","#ff9999");

    g.append("text")
        .attr("x",15)
        .attr("y",358)
        .text("Confirmed Cases")
        .attr("font-size","10px");

    g.append("rect")
        .attr("x", 0)
        .attr("y", 374)
        .attr("width", 10)
        .attr("height", 2)
        .attr("fill","brown");

    g.append("text")
        .attr("x",15)
        .attr("y",378)
        .text("Blockade")
        .attr("font-size","10px");

    g.append("circle")
        .attr("cx",5)
        .attr("cy",335)
        .attr("r",5)
        .attr("fill","green");

    g.append("text")
        .attr("x",15)
        .attr("y",338)
        .text("Referral Centre")
        .attr("font-size","10px");

    g.append("circle")
        .attr("cx",5)
        .attr("cy",315)
        .attr("r",5)
        .attr("fill","blue");

    g.append("text")
        .attr("x",15)
        .attr("y",318)
        .text("Treatment")
        .attr("font-size","10px");

    var mapLabels = svg.append("g");

    mapLabels.selectAll('text')
      .data(westafrica.features)
         .enter()
         .append("text")
         .attr("x", function(d,i){
                     return path.centroid(d)[0]-20;})
         .attr("y", function(d,i){
                     return path.centroid(d)[1];})
         .attr("dy", ".55em")
         .attr("class","maplabel")
         .style("font-size","20px")
         .attr("opacity",0.4)
         .text(function(d,i){
                      return d.properties.NAME_REF;
                  });

}

function transitionMap(){

    $('#week').html("
Map for week ending " + mapSettings[currentWeek].Date + "
");

    var projection = d3.geo.mercator()
        .center([mapSettings[currentWeek].lng,mapSettings[currentWeek].lat])
        .scale(mapSettings[currentWeek].scale);

    var path = d3.geo.path()
        .projection(projection);

    d3.selectAll('.country').transition()
            .attr('d', path);

    d3.selectAll('.blockade').transition()
            .attr('d', path);

    d3.selectAll('.maplabel').transition()
        .attr("x", function(d,i){
                     return path.centroid(d)[0]-20;})
        .attr("y", function(d,i){
                     return path.centroid(d)[1];});

    //d3.selectAll(".medical_centres").transition();

    var data = regionDeaths[currentWeek].Deaths;
    data.forEach(function(element){
               d3.select("#"+element.Region.replace(/\s/g, ''))
                        .transition()
                        .attr("opacity",convertDeathsToOpacity(element.Deaths))
                        .attr('d', path);
            });

    var data = blockades[currentWeek].blockades;
    data.forEach(function(element){
               d3.select("#"+element.blockade_id.split(' ').join('_'))
                        .transition()
                        .attr("opacity",convertBlockadesToOpacity(element.enforced))
                        .attr('d', path);
            });

    var data = medical_centres[currentWeek].medical_centres;
    data.forEach(function(element){
               d3.select("#"+element.id.split(' ').join('_'))
                        .transition()
                        .attr("opacity",convertMedicalCentresToOpacity(element.open))
                        .attr('cx',function(d){
                                    var point = projection([ d.geometry.coordinates[0], d.geometry.coordinates[1] ]);
                                    return point[0];
                                })
                        .attr('cy',function(d){
                                    var point = projection([ d.geometry.coordinates[0], d.geometry.coordinates[1] ]);
                                    return point[1];
                                });
            });

}

function convertDeathsToOpacity(deaths){
    var opacity = deaths/200*0.7;
    if(opacity>0){opacity=opacity+0.2;}
    return opacity;
}

function convertBlockadesToOpacity(enforce){
    if(enforce=="F"){
        return 0;
    } else {
        return 0.75;
    }
}

function convertMedicalCentresToOpacity(open){
    if(open==1){
        return 0.75;
    } else {
        return 0;
    }
}

function formatDate(date){
    var month=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
    return date.substring(0,2) + " " + month[parseInt((date.substring(4,5))-1)];
}

var currentWeek=0;
generateBarChart('#bar_chart',totalCasesAndDeaths);
d3.select("#barSelect"+currentWeek).attr("opacity",0.15);
generateMap();
transitionMap();

$(document).keydown(function(e) {
    switch(e.which) {
        case 37:
            d3.select("#barSelect"+currentWeek).attr("opacity",0);
            currentWeek=currentWeek-1;
            if(currentWeek<0){currentWeek=0;}
            d3.select("#barSelect"+currentWeek).attr("opacity",0.15);
            transitionMap();
            break;

        case 39:
            d3.select("#barSelect"+currentWeek).attr("opacity",0);
            currentWeek=currentWeek+1;
            if(currentWeek>totalCasesAndDeaths.length-1){
                currentWeek=totalCasesAndDeaths.length-1;
            }
            d3.select("#barSelect"+currentWeek).attr("opacity",0.15);
            transitionMap();
            break;

        default: return; // exit this handler for other keys
    }
    e.preventDefault(); // prevent the default action (scroll / move caret)
});
<|endoftext|>


<commit_before>/*
    While I'm not trying to enforce how creators present their themes in self posts,
    I will require consistency for my own sanity.

    For self-posts to pass the checks, they will require the following syntax:
    [Download](direct link to download file or page)
        Example: [Preview](http://download.site/theme.zip)
        If this is not available, no quick download link will be provided.
    [Preview](direct link to desired preview image)
        Example: [Preview](http://imgur.com/myimage.jpg)
        If this is not provided, Reddit's fallback will be used if available otherwise the post will be skipped.
        URLs are not verified for being available, thus non-existant images will be displayed accordingly.

        For security, the only allowed image domain is Imgur.
        Imgur album support for the first image may eventually be implemented, but it is not currently.
    None of these are case-sensitive.

*/

var VitaThemes = {
    cache: [],
    config: {
        'page': {
            running: false, //Probably bad way to do this. Tracking if we're currently processing the page load.
            buffer: 150,    //Amount of pixels within range of the bottom of the screen to load the next page.
            size: 20,       //Amount of results to cap at per page. Doesn't guarantee amount that will pass processing checks.
            after: "",      //Current page.
        }
    },
    init: function() {
        console.log("init called, it's a miracle");
        this.bind();
        this.fetch.reddit();
    },
    bind: function() {
        var that = this;

        //Searching
        $("#run_search").click(function(e) {
            e.preventDefault();
            that.search();
        });

        $("#search").keyup(function(e){
            if(e.keyCode == 13) { that.search(); }
        });

        $(document).on('click', '.author', function() {
            $("#search").val("author:"+$(this).text());
            that.search();
        });

        //Scrolling
        $(window).scroll(function() {
           //Eventually add thumbnail lazy loading.
           if(that.config.page.running == false && $(window).scrollTop() + $(window).height() >= $(document).height() - that.config.page.buffer) {
               console.log('bottom');
               that.config.page.running = true; //Prevent spamming.
               that.fetch.reddit(); //Do thing.
           }
        });
    },
    search: function() {
        //Empty cache, clear page, reset pagination.
        this.config.page.running = true;
        this.cache = [];
        $('#items').html("");
        this.config.page.after = "";

        this.fetch.reddit();
    },
    run: function(empty) {
        var that = this,
            start = ($(".item") && $(".item").last().index() + 1 || 0);

        $.each(this.cache.slice(start), function(index, value) {
            $('#items').append(that.generate.item(value));
        });
    },
    fetch: {
        parse: function(info) {
            //Determine if we can get the info we need

            //info.self, info.is_self
            /*  Attempt to detect the link to the preview image in the selftext, otherwise attempt to use Reddit's fallback.
                Currently doesn't care about what's at the other end of the URL. The policing should be done via the subreddit.
            */

            var preview;

            //Check if the provided preview link is imgur.
            if (info.selftext && /\[preview\]\((.+?)\)/im.test(info.selftext)) {
                var imgur = /^(?:https?:\/\/)?(?:(?:i|www)\.)?imgur\.com\/(?!gallery)([a-z0-9]{3,})/i, //Overkill.
                    temp = info.selftext.match(/\[preview\]\((.+?)\)/im).pop();

                //If imgur, sanitize the URL and proceed. Otherwise set to false.
                preview = (imgur.test(temp)) ? temp.replace(/https?:/, "") : false;
            };
            if (!preview) { preview = (info.preview && info.preview.images[0].source.url || false); }

            if (!preview) {
                console.log('No preview.', info); //Log problematic items.
                return false;
            }

            var download = (info.selftext && /\[download\]\((.+?)\)/im.test(info.selftext)) ? info.selftext.match(/\[download\]\((.+?)\)/im).pop() : false;

            var info = {
                'name': info.title.replace(/\[(Theme|Release)\]/ig, ""),
                'author': info.author,
                'url': info.url,
                'downloadUrl': download,
                'previewUrl': preview,
                'nsfw': info.over_18,
                'stats': {
                    'comments': info.num_comments,
                    'votes': {
                        'up': info.ups,
                        'down': info.downs
                    }
                }
            };

            return info;
        },
        process: function (info) {
            var temp = this.parse(info);

            if (temp !== false)
                VitaThemes.cache.push(temp);
        },
        reddit: function(callback) {
            var that = this;

            if (VitaThemes.config.page.after == null) { //If this is null, we've hit the end of the results.
                VitaThemes.config.page.running = false;
                (callback || VitaThemes.run());
                return false;
            }

            //Obtain search box for options
            var search = encodeURIComponent($("#search").val()),
                sort = $("select#sort").val(),
                t = $("select#t").val(),
                scope = "sort="+sort+"&t="+t,
                pagination = "after=" + (VitaThemes.config.page.after || "") + "&limit=" + VitaThemes.config.page.size,
                out = (search.length > 0) ? "search.json?restrict_sr=on&"+scope+"&"+pagination+"&q="+search : ".json?"+scope+"&"+pagination;

            $.getJSON("https://www.reddit.com/r/vitathemes/"+out, function(data) {
                var after = data.data.after,
                    before = data.data.before;
                //console.log(after, before, data);

                $.each(data.data.children, function(index, content) {
                    that.process(content.data);
                });

                VitaThemes.config.page.after = data.data.after; //Store for pagination.

                VitaThemes.config.page.running = false;
                (callback || VitaThemes.run());
            });
        }
    },
    generate: {
        item: function(info) {
            //info.name, info.url, info.votes?, img.preview, etc.
            var item = $("
", {class: 'item'});

            //Populate
            $("", {class: 'preview ' + ((info.nsfw)?'nsfw':''), src: info.previewUrl}).appendTo(item); //Append the preview image.
            $("
", {class: 'name', text: info.name}).appendTo(item); //Append the name.
            this.quicklinks(info).appendTo(item); //Append quicklinks.

            //item = $("
", {class: 'col-sm-3'}).append(item); //Wrap up for Bootstrap

            return item;
        },
        quicklinks: function(info) {
            //Overly complicated yet future-proof HTML generation. Don't judge me.
            var quicklinks = $("
", {class: 'quicklinks'}),
                fa_global = 'fa fa-fw ';

            if (info.downloadUrl !== false) {
                $("", {href: info.downloadUrl, target: '_blank'}).append($("", {class:fa_global+'fa-download'})).appendTo(quicklinks);
            }

            var discuss = $("", {class: 'discuss', href: info.url, target: '_blank', title: 'Discussion'})
            $("
", {class: 'comments', text: (info.stats.comments > 99) ? '99+' : info.stats.comments}).appendTo(discuss);
            $("", {class: fa_global+'fa-comments'}).appendTo(discuss);
            discuss.appendTo(quicklinks);

            //Stats
            var icon = $("", {class:fa_global+'fa-bar-chart'})[0].outerHTML,
                icon_comment = $("", {class: fa_global+'fa-comment'})[0].outerHTML,
                icon_author = $("", {class: fa_global+'fa-pencil'})[0].outerHTML,
                up = $("", {class: 'up boats', title: 'Upvotes', text: +info.stats.votes.up})[0].outerHTML,
                down = $("", {class: 'down boats', title: 'Downvotes', text: info.stats.votes.down})[0].outerHTML,

                author = $("", {class: 'author', title: 'Search by author', html: icon_author + info.author})[0].outerHTML;

            $("
", {class: 'stats', html: icon + " " + up + " / " + down + "
" + author}).appendTo(quicklinks);

            return quicklinks;
        }
    }
}

$(document).ready(function() { VitaThemes.init() });<commit_msg>Add configurable target subreddit.<commit_after>/*
    While I'm not trying to enforce how creators present their themes in self posts,
    I will require consistency for my own sanity.

    For self-posts to pass the checks, they will require the following syntax:
    [Download](direct link to download file or page)
        Example: [Preview](http://download.site/theme.zip)
        If this is not available, no quick download link will be provided.
    [Preview](direct link to desired preview image)
        Example: [Preview](http://imgur.com/myimage.jpg)
        If this is not provided, Reddit's fallback will be used if available otherwise the post will be skipped.
        URLs are not verified for being available, thus non-existant images will be displayed accordingly.

        For security, the only allowed image domain is Imgur.
        Imgur album support for the first image may eventually be implemented, but it is not currently.
    None of these are case-sensitive.

*/

var VitaThemes = {
    cache: [],
    config: {
        'target': 'r/vitathemes', //Read target to fetch info. Should also support multireddits (r/sub1+sub2)
        'page': {
            running: false, //Probably bad way to do this. Tracking if we're currently processing the page load.
            buffer: 150,    //Amount of pixels within range of the bottom of the screen to load the next page.
            size: 20,       //Amount of results to cap at per page. Doesn't guarantee amount that will pass processing checks.
            after: "",      //Current page.
        }
    },
    init: function() {
        console.log("init called, it's a miracle");
        this.bind();
        this.fetch.reddit();
    },
    bind: function() {
        var that = this;

        //Searching
        $("#run_search").click(function(e) {
            e.preventDefault();
            that.search();
        });

        $("#search").keyup(function(e){
            if(e.keyCode == 13) { that.search(); }
        });

        $(document).on('click', '.author', function() {
            $("#search").val("author:"+$(this).text());
            that.search();
        });

        //Scrolling
        $(window).scroll(function() {
           //Eventually add thumbnail lazy loading.
           if(that.config.page.running == false && $(window).scrollTop() + $(window).height() >= $(document).height() - that.config.page.buffer) {
               console.log('bottom');
               that.config.page.running = true; //Prevent spamming.
               that.fetch.reddit(); //Do thing.
           }
        });
    },
    search: function() {
        //Empty cache, clear page, reset pagination.
        this.config.page.running = true;
        this.cache = [];
        $('#items').html("");
        this.config.page.after = "";

        this.fetch.reddit();
    },
    run: function(empty) {
        var that = this,
            start = ($(".item") && $(".item").last().index() + 1 || 0);

        $.each(this.cache.slice(start), function(index, value) {
            $('#items').append(that.generate.item(value));
        });
    },
    fetch: {
        parse: function(info) {
            //Determine if we can get the info we need

            //info.self, info.is_self
            /*  Attempt to detect the link to the preview image in the selftext, otherwise attempt to use Reddit's fallback.
                Currently doesn't care about what's at the other end of the URL. The policing should be done via the subreddit.
            */

            var preview;

            //Check if the provided preview link is imgur.
            if (info.selftext && /\[preview\]\((.+?)\)/im.test(info.selftext)) {
                var imgur = /^(?:https?:\/\/)?(?:(?:i|www)\.)?imgur\.com\/(?!gallery)([a-z0-9]{3,})/i, //Overkill.
                    temp = info.selftext.match(/\[preview\]\((.+?)\)/im).pop();

                //If imgur, sanitize the URL and proceed. Otherwise set to false.
                preview = (imgur.test(temp)) ? temp : false;
            };
            if (!preview) { preview = (info.preview && info.preview.images[0].source.url || false); }

            if (!preview) {
                console.log('No preview.', info); //Log problematic items.
                return false;
            }

            if (location.protocol !== 'file:')
                preview = preview.replace(/https?:/, ""); //Remove instances of http: and https: to inherit protocol.
            var download = (info.selftext && /\[download\]\((.+?)\)/im.test(info.selftext)) ? info.selftext.match(/\[download\]\((.+?)\)/im).pop() : false;

            var info = {
                'name': info.title.replace(/\[(Theme|Release)\]/ig, ""),
                'author': info.author,
                'url': info.url,
                'downloadUrl': download,
                'previewUrl': preview,
                'nsfw': info.over_18,
                'stats': {
                    'comments': info.num_comments,
                    'votes': {
                        'up': info.ups,
                        'down': info.downs
                    }
                }
            };

            return info;
        },
        process: function (info) {
            var temp = this.parse(info);

            if (temp !== false)
                VitaThemes.cache.push(temp);
        },
        reddit: function(callback) {
            var that = this;

            if (VitaThemes.config.page.after == null) { //If this is null, we've hit the end of the results.
                VitaThemes.config.page.running = false;
                (callback || VitaThemes.run());
                return false;
            }

            //Obtain search box for options
            var search = encodeURIComponent($("#search").val()),
                sort = $("select#sort").val(),
                t = $("select#t").val(),
                scope = "sort="+sort+"&t="+t,
                pagination = "after=" + (VitaThemes.config.page.after || "") + "&limit=" + VitaThemes.config.page.size,
                out = (search.length > 0) ? "search.json?restrict_sr=on&"+scope+"&"+pagination+"&q="+search : ".json?"+scope+"&"+pagination;

            $.getJSON("https://www.reddit.com/"+VitaThemes.config.target+"/"+out, function(data) {
                var after = data.data.after,
                    before = data.data.before;
                //console.log(after, before, data);

                $.each(data.data.children, function(index, content) {
                    that.process(content.data);
                });

                VitaThemes.config.page.after = data.data.after; //Store for pagination.

                VitaThemes.config.page.running = false;
                (callback || VitaThemes.run());
            });
        }
    },
    generate: {
        item: function(info) {
            //info.name, info.url, info.votes?, img.preview, etc.
            var item = $("
", {class: 'item'});

            //Populate
            $("", {class: 'preview ' + ((info.nsfw)?'nsfw':''), src: info.previewUrl}).appendTo(item); //Append the preview image.
            $("
", {class: 'name', text: info.name}).appendTo(item); //Append the name.
            this.quicklinks(info).appendTo(item); //Append quicklinks.

            //item = $("
", {class: 'col-sm-3'}).append(item); //Wrap up for Bootstrap

            return item;
        },
        quicklinks: function(info) {
            //Overly complicated yet future-proof HTML generation. Don't judge me.
            var quicklinks = $("
", {class: 'quicklinks'}),
                fa_global = 'fa fa-fw ';

            if (info.downloadUrl !== false) {
                $("", {href: info.downloadUrl, target: '_blank'}).append($("", {class:fa_global+'fa-download'})).appendTo(quicklinks);
            }

            var discuss = $("", {class: 'discuss', href: info.url, target: '_blank', title: 'Discussion'})
            $("
", {class: 'comments', text: (info.stats.comments > 99) ? '99+' : info.stats.comments}).appendTo(discuss);
            $("", {class: fa_global+'fa-comments'}).appendTo(discuss);
            discuss.appendTo(quicklinks);

            //Stats
            var icon = $("", {class:fa_global+'fa-bar-chart'})[0].outerHTML,
                icon_comment = $("", {class: fa_global+'fa-comment'})[0].outerHTML,
                icon_author = $("", {class: fa_global+'fa-pencil'})[0].outerHTML,
                up = $("", {class: 'up boats', title: 'Upvotes', text: +info.stats.votes.up})[0].outerHTML,
                down = $("", {class: 'down boats', title: 'Downvotes', text: info.stats.votes.down})[0].outerHTML,

                author = $("", {class: 'author', title: 'Search by author', html: icon_author + info.author})[0].outerHTML;

            $("
", {class: 'stats', html: icon + " " + up + " / " + down + "
" + author}).appendTo(quicklinks);

            return quicklinks;
        }
    }
}

$(document).ready(function() { VitaThemes.init() });<|endoftext|>


<commit_before>function stringify(x) {
    if (typeof x == 'function') {
        return '[function]';
    } else {
        try {
            return JSON.stringify(x);
        } catch(e) { return ''; }
    }
}

function require(x) {
    var scripts = document.head.getElementsByTagName('script');
    // do not re-add scripts
    for (var i = 0; i < scripts.length; i++) {
        if (scripts[i].src == x) return 'loaded';
    }
    var scr = document.head.appendChild(document.createElement('script'));
    scr.onload = runCodes;
    scr.src = x;
}

function xhr(url, callback) {
    var x = new XMLHttpRequest();
    x.open("GET", url, true);
    x.onload = callback;
    x.send();
}

var hasstyle = false,
    ssurl = 'http://macwright.org/sealion/sealion.css';

for (var ss = 0; ss < document.styleSheets.length; ss++) {
    if (document.styleSheets[ss].href == ssurl) {
        hasstyle = true;
    }
}

if (!hasstyle) {
    var link = document.head.appendChild(document.createElement('link'));
    link.rel = 'stylesheet';
    link.type = 'text/css';
    link.href = ssurl;
}

function sealion(div) {
    var s = {};

    div.className = div.className + ' sl-wrap';

    var left = div.appendChild(document.createElement('div')),
        right = div.appendChild(document.createElement('right')),
        code = left.appendChild(document.createElement('textarea')),
        results = right.appendChild(document.createElement('pre'));

    left.className = 'sl-left';
    right.className = 'sl-right';
    code.className = 'code';
    results.className = 'results';

    var editor = CodeMirror.fromTextArea(code, {
        mode: 'javascript',
        matchBrackets: true,
        onChange: runCodes,
        tabSize: 2,
        smartIndent: false
    });

    var result = CodeMirror.fromTextArea(results, {
        mode: 'javascript',
        tabSize: 2,
        readOnly: true
    });

    function runCodes() {
        var v = editor.getValue().split('\n');
        var res = '';
        for (var i = 0; i < v.length; i++) {
            if (v[i]) {
                try {
                    if (v[i].match(/^\s*?\/\//)) {
                        res += '\n';
                    } else {
                        res += stringify((function() {
                            return eval(v.slice(0,i+1).join('\n'));
                        })()) + '\n';
                    }
                } catch(e) {
                    if (!(e instanceof SyntaxError)) res += e;
                    else res += '\n';
                }
            } else res += '\n';
        }
        result.setValue(res);
    }

    function gist(id) {
        xhr("https://api.github.com/gists/" + id, function() {
            var r = JSON.parse(this.response);
            for (var k in r.files) {
                return editor.setValue(r.files[k].content);
            }
        });
    }

    s.gist = gist;
    return s;
}
<commit_msg>Inner<commit_after>function stringify(x) {
    if (typeof x == 'function') {
        return '[function]';
    } else {
        try {
            return JSON.stringify(x);
        } catch(e) { return ''; }
    }
}

function require(x) {
    var scripts = document.head.getElementsByTagName('script');
    // do not re-add scripts
    for (var i = 0; i < scripts.length; i++) {
        if (scripts[i].src == x) return 'loaded';
    }
    var scr = document.head.appendChild(document.createElement('script'));
    scr.onload = runCodes;
    scr.src = x;
}

function xhr(url, callback) {
    var x = new XMLHttpRequest();
    x.open("GET", url, true);
    x.onload = callback;
    x.send();
}

var hasstyle = false,
    ssurl = 'http://macwright.org/sealion/sealion.css';

for (var ss = 0; ss < document.styleSheets.length; ss++) {
    if (document.styleSheets[ss].href == ssurl) {
        hasstyle = true;
    }
}

if (!hasstyle) {
    var link = document.head.appendChild(document.createElement('link'));
    link.rel = 'stylesheet';
    link.type = 'text/css';
    link.href = ssurl;
}

function sealion(div) {
    var s = {};

    var inner = div.innerHTML;
    div.innerHTML = '';
    div.className = div.className + ' sl-wrap';

    var left = div.appendChild(document.createElement('div')),
        right = div.appendChild(document.createElement('right')),
        code = left.appendChild(document.createElement('textarea')),
        results = right.appendChild(document.createElement('pre'));

    results.value = inner;

    left.className = 'sl-left';
    right.className = 'sl-right';
    code.className = 'code';
    results.className = 'results';

    var editor = CodeMirror.fromTextArea(code, {
        mode: 'javascript',
        matchBrackets: true,
        onChange: runCodes,
        tabSize: 2,
        smartIndent: false
    });

    var result = CodeMirror.fromTextArea(results, {
        mode: 'javascript',
        tabSize: 2,
        readOnly: true
    });

    function runCodes() {
        var v = editor.getValue().split('\n');
        var res = '';
        for (var i = 0; i < v.length; i++) {
            if (v[i]) {
                try {
                    if (v[i].match(/^\s*?\/\//)) {
                        res += '\n';
                    } else {
                        res += stringify((function() {
                            return eval(v.slice(0,i+1).join('\n'));
                        })()) + '\n';
                    }
                } catch(e) {
                    if (!(e instanceof SyntaxError)) res += e;
                    else res += '\n';
                }
            } else res += '\n';
        }
        result.setValue(res);
    }

    function gist(id) {
        xhr("https://api.github.com/gists/" + id, function() {
            var r = JSON.parse(this.response);
            for (var k in r.files) {
                return editor.setValue(r.files[k].content);
            }
        });
    }

    s.gist = gist;
    return s;
}
<|endoftext|>


<commit_before>/*
    While I'm not trying to enforce how creators present their themes in self posts,
    I will require consistency for my own sanity.

    For self-posts to pass the checks, they will require the following syntax:
    [Download](direct link to download file or page)
        Example: [Preview](http://download.site/theme.zip)
        If this is not available, no quick download link will be provided.
    [Preview](direct link to desired preview image)
        Example: [Preview](http://imgur.com/myimage.jpg)
        If this is not provided, Reddit's fallback will be used if available otherwise the post will be skipped.
        URLs are not verified for being available, thus non-existant images will be displayed accordingly.

        For security, the only allowed image domain is Imgur.
        Imgur album support for the first image may eventually be implemented, but it is not currently.
    None of these are case-sensitive.

*/

var VitaThemes = {
    cache: [],
    config: {
        'ignoreInvalid': true,
        'target': 'r/vitathemes+vitahacks', //Read target to fetch info. Should also support multireddits (r/sub1+sub2)
        'page': {
            running: false, //Probably bad way to do this. Tracking if we're currently processing the page load.
            buffer: 150,    //Amount of pixels within range of the bottom of the screen to load the next page.
            size: 25,       //Amount of results to cap at per page. Doesn't guarantee amount that will pass processing checks.
            after: "",      //Current page.
        }
    },
    saveConfig: function(time, sort, search) {
        //Store search options in URL hash. Array and join?
        window.location.hash = (time && sort && search) ? [VitaThemes.config.target, time, sort, search].join("/") : (this.config.target !== 'r/vitathemes+vitahacks') ? this.config.target : '';
    },
    loadConfig: function() {
        //Load initial search options based on URL hash. Currently unoptimized and prone to huge failure!
        var temp = window.location.hash.split('/'); // ["#r", subreddit(s), time, sort, search]

        if (temp.length < 2) return false;

        this.config.target = "r/"+temp[1]; //Life is simply unfair.
        $("#subreddit_link").attr({title: this.config.target, href: '//reddit.com/'+this.config.target});
        if (temp[2]) $("select#t").find("[value^="+temp[2]+"]").attr("selected", "selected");
        if (temp[3]) $("select#sort").find("[value^="+temp[3]+"]").attr("selected", "selected");
        if (temp[4]) $("#search").val(decodeURIComponent(temp[4]));
    },
    init: function() {
        console.log("init called, it's a miracle");

        this.loadConfig();
        this.bind();

        this.doScroll();
    },
    bind: function() {
        var that = this;

        //Searching
        $("#run_search").click(function(e) {
            e.preventDefault();
            that.search();
        });

        $("#search").keyup(function(e){
            if(e.keyCode == 13) { that.search(); }
        });

        $(document).on('click', '.author', function() {
            $("#search").val("author:"+$(this).text());
            that.search();
        });

        //Scrolling
        $(window).scroll(function() { that.doScroll(); });
        $("#infinite_scroll").click(function() { that.doScroll(); });
    },
    doScroll: function(skip) {
        if (VitaThemes.config.page.after !== null && this.canScroll()) {
            console.log("bottom / scrollin' scrollin' scrollin'");
            this.config.page.running = true; //Prevent spamming.
            this.fetch.reddit(false, true); //Do thing. No callback (false), noSave (true).
        }
    },
    canScroll: function() {
        var buffer = $(document).height() - this.config.page.buffer
            bar = $("#infinite_scroll").offset().top,
            max = $(window).scrollTop() + $(window).height();

        return (!this.config.page.running && (bar <= max) /*|| (max >= buffer)*/);
    },
    search: function() {
        //Empty cache, clear page, reset pagination.
        this.config.page.running = true;
        this.cache = [];
        $('#items').html("");
        this.config.page.after = "";

        this.fetch.reddit();
    },
    run: function() {
        var that = this,
            start = ($(".item") && $(".item").last().index() + 1 || 0);

        $.each(this.cache.slice(start), function(index, value) {
            $('#items').append(that.generate.item(value));
        });

        this.doScroll();
    },
    fetch: {
        parse: function(info) {
            //Determine if we can get the info we need

            //info.self, info.is_self
            /*  Attempt to detect the link to the preview image in the selftext, otherwise attempt to use Reddit's fallback.
                Currently doesn't care about what's at the other end of the URL. The policing should be done via the subreddit.
            */

            var preview = this.detectUrl.preview(info);
            if (!preview) return false;

            //Check title
            if (/(^\[?request|tutorial)/i.test(info.title) ||
                (info.subreddit == "vitahacks" && !/theme/i.test(info.title))
            ) {
                console.warn('Potentially irrelevant post detected. (based on title)', info);
                return false;
            }

            var info = {
                'name': info.title.replace(/\[(Theme|Release)\]/ig, ""),
                'author': info.author,
                'url': info.url, //Whatever the post may link to (otherwise, to the thread)
                'permalink': "//reddit.com"+info.permalink, //Permalink to the thread
                'downloadUrl': this.detectUrl.download(info),
                'previewUrl': preview,
                'time': info.created_utc,
                'nsfw': info.over_18,
                'stats': {
                    'archived': info.archived,
                    'comments': info.num_comments,
                    'votes': {
                        'up': info.ups,
                        'down': info.downs
                    }
                }
            };

            return info;
        },
        detectUrl: {
            preview: function(info) {
                //Check if the provided preview link is imgur.
                var preview = false;

                if (info.selftext && /\[preview\]\((.+?)\)/im.test(info.selftext)) {
                    var imgur = /^(?:https?:\/\/)?(?:(?:i|www)\.)?imgur\.com\/(?!gallery)([a-z0-9]{3,})/i, //Overkill.
                        temp = info.selftext.match(/\[preview\]\((.+?)\)/im).pop();

                    //If imgur, sanitize the URL and proceed. Otherwise set to false.
                    preview = (imgur.test(temp)) ? temp : false;
                };
                if (!preview) { preview = (info.preview && info.preview.images[0].source.url || false); }
                if (!preview && VitaThemes.config.ignoreInvalid == true) {
                    console.warn('No preview.', info); //Log problematic items.
                    return false;
                }
                if (location.protocol !== 'file:')
                    preview = preview.replace(/https?:/, ""); //Remove instances of http: and https: to inherit protocol.

                return preview;
            },
            download: function(info) {
                //Check for download link
                var download = false,
                    search = [
                    {t: 'selftext_html', regex: /(DL|Download):? *<a href="(.+?)"/im},
                    {t: 'selftext', regex: /\[download\]\((.+?)\)/im}
                ];

                $.each(search, function (i, search) {
                    var target = info[search.t];

                    if (target && search.regex.test(target)) {
                        download = target.match(search.regex).pop();
                        return true;
                    }
                });

                return download;
            }
        },
        process: function(info) {
            var temp = this.parse(info);

            if (temp !== false)
                VitaThemes.cache.push(temp);
        },
        reddit: function(callback, noSave) {
            var that = this;

            if (VitaThemes.config.page.after == null) { //If this is null, we've hit the end of the results.
                VitaThemes.config.page.running = false;
                (callback || VitaThemes.run());
                return false;
            }

            $("#infinite_scroll #pending").show();
            $("#infinite_scroll #chickens").hide();

            //Obtain search box for options
            var search = encodeURIComponent($("#search").val()),
                sort = $("select#sort").val(),
                t = $("select#t").val(),
                scope = "sort="+sort+"&t="+t,
                pagination = "after=" + (VitaThemes.config.page.after || "") + "&limit=" + VitaThemes.config.page.size,
                out = (search.length > 0) ? "search.json?restrict_sr=on&"+scope+"&"+pagination+"&q="+search : ".json?"+scope+"&"+pagination;

            if (!noSave) VitaThemes.saveConfig(t, sort, search); //Store search options in URL hash.

            $.getJSON("https://www.reddit.com/"+VitaThemes.config.target+"/"+out, function(data) {
                var after = data.data.after,
                    before = data.data.before;
                //console.log(after, before, data);

                $.each(data.data.children, function(index, content) {
                    that.process(content.data);
                });

                VitaThemes.config.page.after = data.data.after; //Store for pagination.

                VitaThemes.config.page.running = false;
                $("#infinite_scroll #pending").hide();
                $("#infinite_scroll #chickens").show();
                (callback || VitaThemes.run());
            });
        }
    },
    generate: {
        item: function(info) {
            //info.name, info.url, info.votes?, img.preview, etc.
            var item = $("
", {class: 'item'});

            //Populate
            $("", {href: info.url, target: '_blank'}).append(
                $("", {class: 'preview ' + ((info.nsfw)?'nsfw':''), src: info.previewUrl}) //Append the preview image.
            ).appendTo(item);
            $("
", {class: 'name', text: info.name}).appendTo(item); //Append the name.
            this.quicklinks(info).appendTo(item); //Append quicklinks.

            //item = $("
", {class: 'col-sm-3'}).append(item); //Wrap up for Bootstrap

            return item;
        },
        quicklinks: function(info) {
            //Overly complicated yet future-proof HTML generation. Don't judge me.
            var quicklinks = $("
", {class: 'quicklinks'}),
                fa_global = 'fa fa-fw ';

            if (info.downloadUrl !== false) {
                $("", {href: info.downloadUrl, target: '_blank'}).append($("", {class:fa_global+'fa-download'})).appendTo(quicklinks);
            }

            var discuss = $("", {class: 'discuss', href: info.permalink, target: '_blank', title: 'Discussion'})
            $("
", {class: 'comments', text: (info.stats.comments > 99) ? '99+' : info.stats.comments}).appendTo(discuss);
            $("", {class: fa_global+'fa-comments'}).appendTo(discuss);
            discuss.appendTo(quicklinks);

            //Stats
            var icon = $("", {class:fa_global+'fa-bar-chart'})[0].outerHTML,
                icon_comment = $("", {class: fa_global+'fa-comment'})[0].outerHTML,
                icon_author = $("", {class: fa_global+'fa-pencil'})[0].outerHTML,
                up = $("", {class: 'up boats', title: 'Upvotes', text: +info.stats.votes.up})[0].outerHTML,
                down = $("", {class: 'down boats', title: 'Downvotes', text: info.stats.votes.down})[0].outerHTML,

                author = $("", {class: 'author', title: 'Search by author', html: icon_author + info.author})[0].outerHTML;

            $("
", {class: 'stats', html: icon + " " + up + " / " + down + "
" + author}).appendTo(quicklinks);

            return quicklinks;
        }
    }
}

$(document).ready(function() { VitaThemes.init() });<commit_msg>Relocate attribute update to be consistent.<commit_after>/*
    While I'm not trying to enforce how creators present their themes in self posts,
    I will require consistency for my own sanity.

    For self-posts to pass the checks, they will require the following syntax:
    [Download](direct link to download file or page)
        Example: [Preview](http://download.site/theme.zip)
        If this is not available, no quick download link will be provided.
    [Preview](direct link to desired preview image)
        Example: [Preview](http://imgur.com/myimage.jpg)
        If this is not provided, Reddit's fallback will be used if available otherwise the post will be skipped.
        URLs are not verified for being available, thus non-existant images will be displayed accordingly.

        For security, the only allowed image domain is Imgur.
        Imgur album support for the first image may eventually be implemented, but it is not currently.
    None of these are case-sensitive.

*/

var VitaThemes = {
    cache: [],
    config: {
        'ignoreInvalid': true,
        'target': 'r/vitathemes+vitahacks', //Read target to fetch info. Should also support multireddits (r/sub1+sub2)
        'page': {
            running: false, //Probably bad way to do this. Tracking if we're currently processing the page load.
            buffer: 150,    //Amount of pixels within range of the bottom of the screen to load the next page.
            size: 25,       //Amount of results to cap at per page. Doesn't guarantee amount that will pass processing checks.
            after: "",      //Current page.
        }
    },
    saveConfig: function(time, sort, search) {
        //Store search options in URL hash. Array and join?
        window.location.hash = (time && sort && search) ? [VitaThemes.config.target, time, sort, search].join("/") : (this.config.target !== 'r/vitathemes+vitahacks') ? this.config.target : '';
    },
    loadConfig: function() {
        //Load initial search options based on URL hash. Currently unoptimized and prone to huge failure!
        var temp = window.location.hash.split('/'); // ["#r", subreddit(s), time, sort, search]

        if (temp.length < 2) return false;

        this.config.target = "r/"+temp[1]; //Life is simply unfair.
        if (temp[2]) $("select#t").find("[value^="+temp[2]+"]").attr("selected", "selected");
        if (temp[3]) $("select#sort").find("[value^="+temp[3]+"]").attr("selected", "selected");
        if (temp[4]) $("#search").val(decodeURIComponent(temp[4]));
    },
    init: function() {
        console.log("init called, it's a miracle");

        this.loadConfig();
        $("#subreddit_link").attr({title: this.config.target, href: '//reddit.com/'+this.config.target});
        this.bind();

        this.doScroll();
    },
    bind: function() {
        var that = this;

        //Searching
        $("#run_search").click(function(e) {
            e.preventDefault();
            that.search();
        });

        $("#search").keyup(function(e){
            if(e.keyCode == 13) { that.search(); }
        });

        $(document).on('click', '.author', function() {
            $("#search").val("author:"+$(this).text());
            that.search();
        });

        //Scrolling
        $(window).scroll(function() { that.doScroll(); });
        $("#infinite_scroll").click(function() { that.doScroll(); });
    },
    doScroll: function(skip) {
        if (VitaThemes.config.page.after !== null && this.canScroll()) {
            console.log("bottom / scrollin' scrollin' scrollin'");
            this.config.page.running = true; //Prevent spamming.
            this.fetch.reddit(false, true); //Do thing. No callback (false), noSave (true).
        }
    },
    canScroll: function() {
        var buffer = $(document).height() - this.config.page.buffer
            bar = $("#infinite_scroll").offset().top,
            max = $(window).scrollTop() + $(window).height();

        return (!this.config.page.running && (bar <= max) /*|| (max >= buffer)*/);
    },
    search: function() {
        //Empty cache, clear page, reset pagination.
        this.config.page.running = true;
        this.cache = [];
        $('#items').html("");
        this.config.page.after = "";

        this.fetch.reddit();
    },
    run: function() {
        var that = this,
            start = ($(".item") && $(".item").last().index() + 1 || 0);

        $.each(this.cache.slice(start), function(index, value) {
            $('#items').append(that.generate.item(value));
        });

        this.doScroll();
    },
    fetch: {
        parse: function(info) {
            //Determine if we can get the info we need

            //info.self, info.is_self
            /*  Attempt to detect the link to the preview image in the selftext, otherwise attempt to use Reddit's fallback.
                Currently doesn't care about what's at the other end of the URL. The policing should be done via the subreddit.
            */

            var preview = this.detectUrl.preview(info);
            if (!preview) return false;

            //Check title
            if (/(^\[?request|tutorial)/i.test(info.title) ||
                (info.subreddit == "vitahacks" && !/theme/i.test(info.title))
            ) {
                console.warn('Potentially irrelevant post detected. (based on title)', info);
                return false;
            }

            var info = {
                'name': info.title.replace(/\[(Theme|Release)\]/ig, ""),
                'author': info.author,
                'url': info.url, //Whatever the post may link to (otherwise, to the thread)
                'permalink': "//reddit.com"+info.permalink, //Permalink to the thread
                'downloadUrl': this.detectUrl.download(info),
                'previewUrl': preview,
                'time': info.created_utc,
                'nsfw': info.over_18,
                'stats': {
                    'archived': info.archived,
                    'comments': info.num_comments,
                    'votes': {
                        'up': info.ups,
                        'down': info.downs
                    }
                }
            };

            return info;
        },
        detectUrl: {
            preview: function(info) {
                //Check if the provided preview link is imgur.
                var preview = false;

                if (info.selftext && /\[preview\]\((.+?)\)/im.test(info.selftext)) {
                    var imgur = /^(?:https?:\/\/)?(?:(?:i|www)\.)?imgur\.com\/(?!gallery)([a-z0-9]{3,})/i, //Overkill.
                        temp = info.selftext.match(/\[preview\]\((.+?)\)/im).pop();

                    //If imgur, sanitize the URL and proceed. Otherwise set to false.
                    preview = (imgur.test(temp)) ? temp : false;
                };
                if (!preview) { preview = (info.preview && info.preview.images[0].source.url || false); }
                if (!preview && VitaThemes.config.ignoreInvalid == true) {
                    console.warn('No preview.', info); //Log problematic items.
                    return false;
                }
                if (location.protocol !== 'file:')
                    preview = preview.replace(/https?:/, ""); //Remove instances of http: and https: to inherit protocol.

                return preview;
            },
            download: function(info) {
                //Check for download link
                var download = false,
                    search = [
                    {t: 'selftext_html', regex: /(DL|Download):? *<a href="(.+?)"/im},
                    {t: 'selftext', regex: /\[download\]\((.+?)\)/im}
                ];

                $.each(search, function (i, search) {
                    var target = info[search.t];

                    if (target && search.regex.test(target)) {
                        download = target.match(search.regex).pop();
                        return true;
                    }
                });

                return download;
            }
        },
        process: function(info) {
            var temp = this.parse(info);

            if (temp !== false)
                VitaThemes.cache.push(temp);
        },
        reddit: function(callback, noSave) {
            var that = this;

            if (VitaThemes.config.page.after == null) { //If this is null, we've hit the end of the results.
                VitaThemes.config.page.running = false;
                (callback || VitaThemes.run());
                return false;
            }

            $("#infinite_scroll #pending").show();
            $("#infinite_scroll #chickens").hide();

            //Obtain search box for options
            var search = encodeURIComponent($("#search").val()),
                sort = $("select#sort").val(),
                t = $("select#t").val(),
                scope = "sort="+sort+"&t="+t,
                pagination = "after=" + (VitaThemes.config.page.after || "") + "&limit=" + VitaThemes.config.page.size,
                out = (search.length > 0) ? "search.json?restrict_sr=on&"+scope+"&"+pagination+"&q="+search : ".json?"+scope+"&"+pagination;

            if (!noSave) VitaThemes.saveConfig(t, sort, search); //Store search options in URL hash.

            $.getJSON("https://www.reddit.com/"+VitaThemes.config.target+"/"+out, function(data) {
                var after = data.data.after,
                    before = data.data.before;
                //console.log(after, before, data);

                $.each(data.data.children, function(index, content) {
                    that.process(content.data);
                });

                VitaThemes.config.page.after = data.data.after; //Store for pagination.

                VitaThemes.config.page.running = false;
                $("#infinite_scroll #pending").hide();
                $("#infinite_scroll #chickens").show();
                (callback || VitaThemes.run());
            });
        }
    },
    generate: {
        item: function(info) {
            //info.name, info.url, info.votes?, img.preview, etc.
            var item = $("
", {class: 'item'});

            //Populate
            $("", {href: info.url, target: '_blank'}).append(
                $("", {class: 'preview ' + ((info.nsfw)?'nsfw':''), src: info.previewUrl}) //Append the preview image.
            ).appendTo(item);
            $("
", {class: 'name', text: info.name}).appendTo(item); //Append the name.
            this.quicklinks(info).appendTo(item); //Append quicklinks.

            //item = $("
", {class: 'col-sm-3'}).append(item); //Wrap up for Bootstrap

            return item;
        },
        quicklinks: function(info) {
            //Overly complicated yet future-proof HTML generation. Don't judge me.
            var quicklinks = $("
", {class: 'quicklinks'}),
                fa_global = 'fa fa-fw ';

            if (info.downloadUrl !== false) {
                $("", {href: info.downloadUrl, target: '_blank'}).append($("", {class:fa_global+'fa-download'})).appendTo(quicklinks);
            }

            var discuss = $("", {class: 'discuss', href: info.permalink, target: '_blank', title: 'Discussion'})
            $("
", {class: 'comments', text: (info.stats.comments > 99) ? '99+' : info.stats.comments}).appendTo(discuss);
            $("", {class: fa_global+'fa-comments'}).appendTo(discuss);
            discuss.appendTo(quicklinks);

            //Stats
            var icon = $("", {class:fa_global+'fa-bar-chart'})[0].outerHTML,
                icon_comment = $("", {class: fa_global+'fa-comment'})[0].outerHTML,
                icon_author = $("", {class: fa_global+'fa-pencil'})[0].outerHTML,
                up = $("", {class: 'up boats', title: 'Upvotes', text: +info.stats.votes.up})[0].outerHTML,
                down = $("", {class: 'down boats', title: 'Downvotes', text: info.stats.votes.down})[0].outerHTML,

                author = $("", {class: 'author', title: 'Search by author', html: icon_author + info.author})[0].outerHTML;

            $("
", {class: 'stats', html: icon + " " + up + " / " + down + "
" + author}).appendTo(quicklinks);

            return quicklinks;
        }
    }
}

$(document).ready(function() { VitaThemes.init() });<|endoftext|>


<commit_before>Hm_Ajax = {

    callback: false,

    request: function(args, callback) {
        console.log(args);
        Hm_Ajax.callback = callback;
        $.post('', args )
        .done(Hm_Ajax.done)
        .fail(Hm_Ajax.fail)
        .always(Hm_Ajax.always);
        return false;
    },

    done: function(res) {
        res = jQuery.parseJSON(res);
        if (Hm_Ajax.callback) {
            Hm_Ajax.callback(res);
        }
    },

    fail: function(res) {
        Hm_Notices.show({0: 'An error occured communicating with the server'});
    },

    always: function(res) {
    }
}
Hm_Notices = {

    show: function(msgs) {
        var msg_list = $.map(msgs, function(v) { return v; });
        $('.sys_messages').html(msg_list.join('
'));
    }
}
<commit_msg>remove debug<commit_after>Hm_Ajax = {

    callback: false,

    request: function(args, callback) {
        Hm_Ajax.callback = callback;
        $.post('', args )
        .done(Hm_Ajax.done)
        .fail(Hm_Ajax.fail)
        .always(Hm_Ajax.always);
        return false;
    },

    done: function(res) {
        res = jQuery.parseJSON(res);
        if (Hm_Ajax.callback) {
            Hm_Ajax.callback(res);
        }
    },

    fail: function(res) {
        Hm_Notices.show({0: 'An error occured communicating with the server'});
    },

    always: function(res) {
    }
}
Hm_Notices = {

    show: function(msgs) {
        var msg_list = $.map(msgs, function(v) { return v; });
        $('.sys_messages').html(msg_list.join('
'));
    }
}
<|endoftext|>


<commit_before>var findme_map = L.map('findme-map')
    .setView([37.7, -97.3], 3),
    osmUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
    osmAttrib = 'Map data © OpenStreetMap contributors',
    osm = L.tileLayer(osmUrl, {minZoom: 2, maxZoom: 18, attribution: osmAttrib}).addTo(findme_map),
    category_data = [];

var findme_marker = L.marker([0,0], {draggable:true}).addTo(findme_map);
findme_marker.setOpacity(0);

if (location.hash) location.hash = '';

var successString,loadingText;

i18n.init({ fallbackLng: 'en-US', postAsync: 'false' }, function() {
    $("body").i18n();

    successString=i18n.t('messages.success', { escapeInterpolation: false });
    loadingText=i18n.t('messages.loadingText');

    var detectedLang = i18n.lng();
    var buildSelectControl = function(data) {
        $("#category").select2({data: data});
    };

    $.getJSON('./locales/' + detectedLang + '/categories.json', buildSelectControl).fail(function () {
        // 404? Fall back to en-US
         $.getJSON('./locales/en-US/categories.json', buildSelectControl);
    });
});

function zoom_to_point(chosen_place, map, marker) {
    console.log(chosen_place);

    marker.setOpacity(1);
    marker.setLatLng([chosen_place.lat, chosen_place.lon]);

    map.setView(chosen_place, 18, {animate: true});
}
$("#use_my_location").click(function (e) {
    $("#couldnt-find").hide();
    $("#success").hide();
    if ("geolocation" in navigator) {
        navigator.geolocation.getCurrentPosition(function(position) {
            var point = {
                lat: position.coords.latitude,
                lon: position.coords.longitude
            }

            zoom_to_point(point, findme_map, findme_marker);

            $('#success').html(successString);
            $('#success').show();
            window.scrollTo(0, $('#address').position().top - 30);
            $('.step-2 a').attr('href', '#details');
        }, function (error) {
            $("#couldnt-find").show();
        });
    } else {
      $("#couldnt-find").show();
    }
});
$("#find").submit(function(e) {
    e.preventDefault();
    $("#couldnt-find").hide();
    $("#success").hide();
    var address_to_find = $("#address").val();
    if (address_to_find.length === 0) return;
    var qwarg = {
        format: 'json',
        q: address_to_find
    };
    var url = "https://nominatim.openstreetmap.org/search?" + $.param(qwarg);
    $("#findme h4").text(loadingText);
    $("#findme").addClass("loading");
    $.getJSON(url, function(data) {
        if (data.length > 0) {
            zoom_to_point(data[0], findme_map, findme_marker);

            $('#success').html(successString);
            $('#success').show();
            window.scrollTo(0, $('#address').position().top - 30);
            $('.step-2 a').attr('href', '#details');
        } else {
            $("#couldnt-find").show();
        }
        $("#findme").removeClass("loading");
    });
});

$(window).on('hashchange', function() {
    if (location.hash == '#details') {
        $('#collect-data-step').removeClass('hide');
        $('#address-step').addClass('hide');
        $('#confirm-step').addClass('hide');
        $('.steps').addClass('on-2');
        $('.steps').removeClass('on-3');
    } else if (location.hash == '#done') {
        $('#confirm-step').removeClass('hide');
        $('#collect-data-step').addClass('hide');
        $('#address-step').addClass('hide');
        $('.steps').addClass('on-3');
    } else {
        $('#address-step').removeClass('hide');
        $('#collect-data-step').addClass('hide');
        $('#confirm-step').addClass('hide');
        $('.steps').removeClass('on-2');
        $('.steps').removeClass('on-3');
    }
    findme_map.invalidateSize();
});

$("#collect-data-done").click(function() {
    location.hash = '#done';

    var note_body = "onosm.org submitted note from a business:\n" +
        "Name: " + $("#name").val() + "\n" +
        "Phone: " + $("#phone").val() + "\n" +
        "Website: " + $("#website").val() + "\n" +
        "Twitter: " + $("#twitter").val() + "\n" +
        "Hours: " + $("#opening_hours").val() + "\n" +
        "Category: " + $("#category").val() + "\n" +
        "Address: " + $("#address").val(),
        latlon = findme_marker.getLatLng(),
        qwarg = {
            lat: latlon.lat,
            lon: latlon.lng,
            text: note_body
        };

    $.post('https://api.openstreetmap.org/api/0.6/notes.json', qwarg);
});

function clearFields() {
    $("#name").val('');
    $("#phone").val('');
    $("#website").val('');
    $("#social").val('');
    $("#opening_hours").val('');
    $("#category").val('');
    $("#address").val('');
}
<commit_msg>Twitter, not Social<commit_after>var findme_map = L.map('findme-map')
    .setView([37.7, -97.3], 3),
    osmUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
    osmAttrib = 'Map data © OpenStreetMap contributors',
    osm = L.tileLayer(osmUrl, {minZoom: 2, maxZoom: 18, attribution: osmAttrib}).addTo(findme_map),
    category_data = [];

var findme_marker = L.marker([0,0], {draggable:true}).addTo(findme_map);
findme_marker.setOpacity(0);

if (location.hash) location.hash = '';

var successString,loadingText;

i18n.init({ fallbackLng: 'en-US', postAsync: 'false' }, function() {
    $("body").i18n();

    successString=i18n.t('messages.success', { escapeInterpolation: false });
    loadingText=i18n.t('messages.loadingText');

    var detectedLang = i18n.lng();
    var buildSelectControl = function(data) {
        $("#category").select2({data: data});
    };

    $.getJSON('./locales/' + detectedLang + '/categories.json', buildSelectControl).fail(function () {
        // 404? Fall back to en-US
         $.getJSON('./locales/en-US/categories.json', buildSelectControl);
    });
});

function zoom_to_point(chosen_place, map, marker) {
    console.log(chosen_place);

    marker.setOpacity(1);
    marker.setLatLng([chosen_place.lat, chosen_place.lon]);

    map.setView(chosen_place, 18, {animate: true});
}
$("#use_my_location").click(function (e) {
    $("#couldnt-find").hide();
    $("#success").hide();
    if ("geolocation" in navigator) {
        navigator.geolocation.getCurrentPosition(function(position) {
            var point = {
                lat: position.coords.latitude,
                lon: position.coords.longitude
            }

            zoom_to_point(point, findme_map, findme_marker);

            $('#success').html(successString);
            $('#success').show();
            window.scrollTo(0, $('#address').position().top - 30);
            $('.step-2 a').attr('href', '#details');
        }, function (error) {
            $("#couldnt-find").show();
        });
    } else {
      $("#couldnt-find").show();
    }
});
$("#find").submit(function(e) {
    e.preventDefault();
    $("#couldnt-find").hide();
    $("#success").hide();
    var address_to_find = $("#address").val();
    if (address_to_find.length === 0) return;
    var qwarg = {
        format: 'json',
        q: address_to_find
    };
    var url = "https://nominatim.openstreetmap.org/search?" + $.param(qwarg);
    $("#findme h4").text(loadingText);
    $("#findme").addClass("loading");
    $.getJSON(url, function(data) {
        if (data.length > 0) {
            zoom_to_point(data[0], findme_map, findme_marker);

            $('#success').html(successString);
            $('#success').show();
            window.scrollTo(0, $('#address').position().top - 30);
            $('.step-2 a').attr('href', '#details');
        } else {
            $("#couldnt-find").show();
        }
        $("#findme").removeClass("loading");
    });
});

$(window).on('hashchange', function() {
    if (location.hash == '#details') {
        $('#collect-data-step').removeClass('hide');
        $('#address-step').addClass('hide');
        $('#confirm-step').addClass('hide');
        $('.steps').addClass('on-2');
        $('.steps').removeClass('on-3');
    } else if (location.hash == '#done') {
        $('#confirm-step').removeClass('hide');
        $('#collect-data-step').addClass('hide');
        $('#address-step').addClass('hide');
        $('.steps').addClass('on-3');
    } else {
        $('#address-step').removeClass('hide');
        $('#collect-data-step').addClass('hide');
        $('#confirm-step').addClass('hide');
        $('.steps').removeClass('on-2');
        $('.steps').removeClass('on-3');
    }
    findme_map.invalidateSize();
});

$("#collect-data-done").click(function() {
    location.hash = '#done';

    var note_body = "onosm.org submitted note from a business:\n" +
        "Name: " + $("#name").val() + "\n" +
        "Phone: " + $("#phone").val() + "\n" +
        "Website: " + $("#website").val() + "\n" +
        "Twitter: " + $("#twitter").val() + "\n" +
        "Hours: " + $("#opening_hours").val() + "\n" +
        "Category: " + $("#category").val() + "\n" +
        "Address: " + $("#address").val(),
        latlon = findme_marker.getLatLng(),
        qwarg = {
            lat: latlon.lat,
            lon: latlon.lng,
            text: note_body
        };

    $.post('https://api.openstreetmap.org/api/0.6/notes.json', qwarg);
});

function clearFields() {
    $("#name").val('');
    $("#phone").val('');
    $("#website").val('');
    $("#twitter").val('');
    $("#opening_hours").val('');
    $("#category").val('');
    $("#address").val('');
}
<|endoftext|>