<commit_before>/*
 * nv.js
 *
 * TODO NOTE to Mike: the parser can use setNBEData(dataset) to set nbedata and call redraw
 *
 * Here are the divs in nv.html:
 * - id="vis"
 * - id="filters"
 * - id="edit"
 * - id="nessusinfo"
 * - id="histograms"
 */

// colors
// http://colorbrewer2.org/index.php?type=sequential&scheme=Oranges&n=3
var nodeColor = d3.scale.linear()
    .domain([0.0, 10.0])
    .range([d3.hsl("#FEE6CE"), d3.hsl("#FDAE6B"), d3.hsl("#E6550D")]); // white-orange
    //.range(["hsl(62,100%,90%)", "hsl(228,30%,20%)"]); // yellow blue

// globals
var margin = {top: 20, right: 0, bottom: 0, left: 0},
    width = 960,
    height = 500 - margin.top - margin.bottom,
    formatNumber = d3.format(",d"),
    transitioning,
    nbedata; // All the data!

// treemap globals
var x,
    y,
    treemap,
    svg,
    grandparent;

// start the vis
init();

function init() {
  // initialize treemap
  initTreemap();

  // load treemap data (sets nbedata which calls drawTreemap() after it loads)
  // this should be commented out when we receive data from the parser
  loadJSONData('../../data/testdata/testdata6.json');

  // test changes of data using timeouts
  //window.setTimeout(function() { loadJSONData('../../data/testdata/testdata6.json'); }, 3000);
  //window.setTimeout(function() { loadJSONData('../../data/testdata/testdata7.json'); }, 10000);
}

// called after data load
function redraw() {
  drawTreemap();
}

// treemap functions
function initTreemap(){

  x = d3.scale.linear()
      .domain([0, width])
      .range([0, width]);

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

  treemap = d3.layout.treemap()
      .children(function(d, depth) { return depth ? null : d.values; })
      .sort(function(a, b) { return a.value - b.value; })
      .ratio(height / width * 0.5 * (1 + Math.sqrt(5)))
      .round(false);

  svg = d3.select("#vis").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.bottom + margin.top)
      .style("margin-left", -margin.left + "px")
      .style("margin.right", -margin.right + "px")
    .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
      .style("shape-rendering", "crispEdges");

  grandparent = svg.append("g")
      .attr("class", "grandparent");

  grandparent.append("rect")
      .attr("y", -margin.top)
      .attr("width", width)
      .attr("height", margin.top);

  grandparent.append("text")
      .attr("x", 6)
      .attr("y", 6 - margin.top)
      .attr("dy", ".75em");

}

function drawTreemap() {
  var root=d3.nest()
    .key(function(d) {return "group";})
    .key(function(d) {return d.ip;})
    .key(function(d) {return d.port;})
    .sortKeys(d3.ascending)
    .entries(nbedata);

  // free the root from its original array
  root = root[0];

  var nodes = [];

  initialize(root);
  accumulate(root);
  layout(root);
  display(root);

  function initialize(root) {
    root.x = root.y = 0;
    root.dx = width;
    root.dy = height;
    root.depth = 0;
  }

  // Aggregate the values for internal nodes. This is normally done by the
  // treemap layout, but not here because of our custom implementation.
  function accumulate(d) {
    nodes.push(d);

    d.cvss = accumulateCVSS(d);

    return d.values
      ? d.value = d.values.reduce(function(p, v) { return p + accumulate(v); }, 0)
      : d.value;
  }

  function accumulateCVSS(d){
    return d.values
      ? d.cvss = d.values.reduce(function(p, v) { return Math.max(p, accumulateCVSS(v)); }, 0)
      : d.cvss;
  }

  // Compute the treemap layout recursively such that each group of siblings
  // uses the same size (1×1) rather than the dimensions of the parent cell.
  // This optimizes the layout for the current zoom state. Note that a wrapper
  // object is created for the parent node for each group of siblings so that
  // the parent’s dimensions are not discarded as we recurse. Since each group
  // of sibling was laid out in 1×1, we must rescale to fit using absolute
  // coordinates. This lets us use a viewport to zoom.
  function layout(d) {
    if (d.values) {
      treemap.nodes({values: d.values});
      d.values.forEach(function(c) {
        c.x = d.x + c.x * d.dx;
        c.y = d.y + c.y * d.dy;
        c.dx *= d.dx;
        c.dy *= d.dy;
        c.parent = d;
        layout(c);
      });
    }
  }

  function display(d) {
    grandparent
      .datum(d.parent)
      .on("click", transition)
      .select("text")
      .text(name(d));

    var g1 = svg.insert("g", ".grandparent")
      .datum(d)
      .attr("class", "depth");

    var g = g1.selectAll("g")
      .data(d.values)
      .enter().append("g");

    g.filter(function(d) { return d.values; })
      .classed("children", true)
      .on("click", transition);

    // NOTE: can move the .style here to rect() to color by cell
    g.selectAll(".child")
      .data(function(d) { return d.values || [d]; })
      .enter().append("rect")
      .attr("class", "child")
      .style("fill", function(d) {
        return nodeColor(d.cvss);
      })
    .call(rect);

    g.append("rect")
      .attr("class", "parent")
      .call(rect)
      .append("title")
      .text(function(d) { return formatNumber(d.value); });

    g.append("text")
      .attr("dy", ".75em")
      .text(function(d) { return d.key; })
      .classed("rectlabel", true)
      .call(text);

    function transition(d) {
      if (transitioning || !d) return;
      transitioning = true;

      var g2 = display(d),
          t1 = g1.transition().duration(750),
          t2 = g2.transition().duration(750);

      // Update the domain only after entering new elements.
      x.domain([d.x, d.x + d.dx]);
      y.domain([d.y, d.y + d.dy]);

      // Enable anti-aliasing during the transition.
      svg.style("shape-rendering", null);

      // Draw child nodes on top of parent nodes.
      svg.selectAll(".depth").sort(function(a, b) { return a.depth - b.depth; });

      // Fade-in entering text.
      g2.selectAll("text").style("fill-opacity", 0);

      // Transition to the new view.
      t1.selectAll("text").call(text).style("fill-opacity", 0);
      t2.selectAll("text").call(text).style("fill-opacity", 1);
      t1.selectAll("rect").call(rect);
      t2.selectAll("rect").call(rect);

      // Remove the old node when the transition is finished.
      t1.remove().each("end", function() {
        svg.style("shape-rendering", "crispEdges");
        transitioning = false;
      });
    }

    return g;
  }

  function text(text) {
    text.attr("x", function(d) { return x(d.x) + 6; })
      .attr("y", function(d) { return y(d.y) + 6; });
  }

  function rect(rect) {
    rect.attr("x", function(d) { return x(d.x); })
      .attr("y", function(d) { return y(d.y); })
      .attr("width", function(d) { return x(d.x + d.dx) - x(d.x); })
      .attr("height", function(d) { return y(d.y + d.dy) - y(d.y); })
  }

  function name(d) {
    return d.parent
      ? name(d.parent) + "." + d.key
      : d.key;
  }
}

// replaces the current dataset and calls redraw
function setNBEData(dataset){
  nbedata = dataset;
  redraw();
}

function loadJSONData(file){
  // if file isn't .json file, load a default
  if(file.indexOf('json') === -1){
    console.log('invalid file named, reverting to a default');
    file = '../../data/testdata/testdata6.json';
  }

  // Load data and set to nbedata global
  d3.json(file, function(data) {
    setNBEData(data);
  });
}

<commit_msg>Added histogram option<commit_after>/*
 * nv.js
 *
 * TODO NOTE to Mike: the parser can use setNBEData(dataset) to set nbedata and call redraw
 *
 * Here are the divs in nv.html:
 * - id="vis"
 * - id="filters"
 * - id="edit"
 * - id="nessusinfo"
 * - id="histograms"
 */

// colors
// http://colorbrewer2.org/index.php?type=sequential&scheme=Oranges&n=3
var nodeColor = d3.scale.linear()
    .domain([0.0, 10.0])
    .range([d3.hsl("#FEE6CE"), d3.hsl("#FDAE6B"), d3.hsl("#E6550D")]); // white-orange
    //.range(["hsl(62,100%,90%)", "hsl(228,30%,20%)"]); // yellow blue

// globals
var margin = {top: 20, right: 0, bottom: 0, left: 0},
    width = 960,
    height = 500 - margin.top - margin.bottom,
    formatNumber = d3.format(",d"),
    transitioning,
    nbedata; // All the data!

// treemap globals
var x,
    y,
    treemap,
    svg,
    grandparent;

// start the vis
init();

function init() {
  // initialize treemap
  initTreemap();

  // initialize histograms
  initHistogram("#histograms", 20, "portHisto");

  // load treemap data (sets nbedata which calls drawTreemap() after it loads)
  // this should be commented out when we receive data from the parser
  loadJSONData('../../data/testdata/testdata6.json');

  // test changes of data using timeouts
  //window.setTimeout(function() { loadJSONData('../../data/testdata/testdata6.json'); }, 3000);
  //window.setTimeout(function() { loadJSONData('../../data/testdata/testdata7.json'); }, 10000);
}

// called after data load
function redraw() {
  drawTreemap();
  drawHistogram("#portHisto", 20, "port");
}

// treemap functions
function initTreemap(){

  x = d3.scale.linear()
      .domain([0, width])
      .range([0, width]);

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

  treemap = d3.layout.treemap()
      .children(function(d, depth) { return depth ? null : d.values; })
      .sort(function(a, b) { return a.value - b.value; })
      .ratio(height / width * 0.5 * (1 + Math.sqrt(5)))
      .round(false);

  svg = d3.select("#vis").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.bottom + margin.top)
      .style("margin-left", -margin.left + "px")
      .style("margin.right", -margin.right + "px")
    .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
      .style("shape-rendering", "crispEdges");

  grandparent = svg.append("g")
      .attr("class", "grandparent");

  grandparent.append("rect")
      .attr("y", -margin.top)
      .attr("width", width)
      .attr("height", margin.top);

  grandparent.append("text")
      .attr("x", 6)
      .attr("y", 6 - margin.top)
      .attr("dy", ".75em");

}

function drawTreemap() {
  var root=d3.nest()
    .key(function(d) {return "group";})
    .key(function(d) {return d.ip;})
    .key(function(d) {return d.port;})
    .sortKeys(d3.ascending)
    .entries(nbedata);

  // free the root from its original array
  root = root[0];

  var nodes = [];

  initialize(root);
  accumulate(root);
  layout(root);
  display(root);

  function initialize(root) {
    root.x = root.y = 0;
    root.dx = width;
    root.dy = height;
    root.depth = 0;
  }

  // Aggregate the values for internal nodes. This is normally done by the
  // treemap layout, but not here because of our custom implementation.
  function accumulate(d) {
    nodes.push(d);

    d.cvss = accumulateCVSS(d);

    return d.values
      ? d.value = d.values.reduce(function(p, v) { return p + accumulate(v); }, 0)
      : d.value;
  }

  function accumulateCVSS(d){
    return d.values
      ? d.cvss = d.values.reduce(function(p, v) { return Math.max(p, accumulateCVSS(v)); }, 0)
      : d.cvss;
  }

  // Compute the treemap layout recursively such that each group of siblings
  // uses the same size (1×1) rather than the dimensions of the parent cell.
  // This optimizes the layout for the current zoom state. Note that a wrapper
  // object is created for the parent node for each group of siblings so that
  // the parent’s dimensions are not discarded as we recurse. Since each group
  // of sibling was laid out in 1×1, we must rescale to fit using absolute
  // coordinates. This lets us use a viewport to zoom.
  function layout(d) {
    if (d.values) {
      treemap.nodes({values: d.values});
      d.values.forEach(function(c) {
        c.x = d.x + c.x * d.dx;
        c.y = d.y + c.y * d.dy;
        c.dx *= d.dx;
        c.dy *= d.dy;
        c.parent = d;
        layout(c);
      });
    }
  }

  function display(d) {
    grandparent
      .datum(d.parent)
      .on("click", transition)
      .select("text")
      .text(name(d));

    var g1 = svg.insert("g", ".grandparent")
      .datum(d)
      .attr("class", "depth");

    var g = g1.selectAll("g")
      .data(d.values)
      .enter().append("g");

    g.filter(function(d) { return d.values; })
      .classed("children", true)
      .on("click", transition);

    // NOTE: can move the .style here to rect() to color by cell
    g.selectAll(".child")
      .data(function(d) { return d.values || [d]; })
      .enter().append("rect")
      .attr("class", "child")
      .style("fill", function(d) {
        return nodeColor(d.cvss);
      })
    .call(rect);

    g.append("rect")
      .attr("class", "parent")
      .call(rect)
      .append("title")
      .text(function(d) { return formatNumber(d.value); });

    g.append("text")
      .attr("dy", ".75em")
      .text(function(d) { return d.key; })
      .classed("rectlabel", true)
      .call(text);

    function transition(d) {
      if (transitioning || !d) return;
      transitioning = true;

      var g2 = display(d),
          t1 = g1.transition().duration(750),
          t2 = g2.transition().duration(750);

      // Update the domain only after entering new elements.
      x.domain([d.x, d.x + d.dx]);
      y.domain([d.y, d.y + d.dy]);

      // Enable anti-aliasing during the transition.
      svg.style("shape-rendering", null);

      // Draw child nodes on top of parent nodes.
      svg.selectAll(".depth").sort(function(a, b) { return a.depth - b.depth; });

      // Fade-in entering text.
      g2.selectAll("text").style("fill-opacity", 0);

      // Transition to the new view.
      t1.selectAll("text").call(text).style("fill-opacity", 0);
      t2.selectAll("text").call(text).style("fill-opacity", 1);
      t1.selectAll("rect").call(rect);
      t2.selectAll("rect").call(rect);

      // Remove the old node when the transition is finished.
      t1.remove().each("end", function() {
        svg.style("shape-rendering", "crispEdges");
        transitioning = false;
      });
    }

    return g;
  }

  function text(text) {
    text.attr("x", function(d) { return x(d.x) + 6; })
      .attr("y", function(d) { return y(d.y) + 6; });
  }

  function rect(rect) {
    rect.attr("x", function(d) { return x(d.x); })
      .attr("y", function(d) { return y(d.y); })
      .attr("width", function(d) { return x(d.x + d.dx) - x(d.x); })
      .attr("height", function(d) { return y(d.y + d.dy) - y(d.y); })
  }

  function name(d) {
    return d.parent
      ? name(d.parent) + "." + d.key
      : d.key;
  }
}

//TODO - Evan
// function that initalizes one histogram
//sel   -> d3 selection
//n     -> number of bins
//name  -> name of histogram (id)
function initHistogram(sel, n, name) {

  var histoW = 400,
      histoH = 200;

  var nothing = [];

  for ( var i = 0; i < n; i++) nothing[i] = 0;

  var hist = d3.select(sel)
                .append("div")
                .attr("id", name)
                .attr("class", "histogram")
                .append("svg")
                .attr("width", histoW)
                .attr("height", histoH);

  hist.selectAll("rect")
      .data(nothing)
      .enter().append("rect")
      .attr("x", function(d, i) { return (histoW / n)*i - 0.5; })
      .attr("width", histoW / n)
      .attr("y", histoH - 0.05*histoH - 20)
      .attr("height", 0.05*histoH)
      .style("fill", "purple")
      .style("stroke", "white");

  // labels (x axis and title)
  var labels = d3.range(n);
  hist.selectAll("text#label")
      .data(labels)
      .enter().append("text")
      .attr("id", "label")
      .attr("x", function(d, i) { return (histoW / n)*i + 5; })
      .attr("y", histoH - 11)
      .style("font-size", "8px")
      .text( function(d) { return d+1 });

  hist.append("text")
      .attr("id", "title")
      .attr("x", histoW / 2 )
      .attr("y", histoH - 1 )
      .attr("text-anchor", "middle")
      .style("font-family", "Serif")
      .style("font-size", "10px")
      .text(name);
}

//TODO - Evan
// function that initalizes one histogram
//name  -> name of histogram (id)
//n     -> number of bins
//par   -> parameter in data being used
function drawHistogram(name, n, par) {

  var histoW = 400,
      histoH = 200;

  //TODO - Lane -> fix how histogram reads nbedata
  //create histogram
  var hist = d3.layout.histogram()
              .bins(n)
              .range([1, 20])
              .value(function(d,i) { /*if(i==0){console.log(d);}*/return d[par]; })
              (nbedata);

  //set domain for data
  var hScale = d3.scale.linear()
                  .domain([0, d3.max(hist, function(d, i) { return d[par]; }) ])
                  .range([0, histoH - 10]);
  d3.select(name)
    .selectAll("rect")
    .data(hist)
    .transition()
      .duration(1000)
      .attr("y", function(d) { return histoH - hScale(d[par]) - 20; })
      .attr("height", function(d) { return hScale(d[par]); });

}

// replaces the current dataset and calls redraw
function setNBEData(dataset){
  nbedata = dataset;
  redraw();
}

function loadJSONData(file){
  // if file isn't .json file, load a default
  if(file.indexOf('json') === -1){
    console.log('invalid file named, reverting to a default');
    file = '../../data/testdata/testdata6.json';
  }

  // Load data and set to nbedata global
  d3.json(file, function(data) {
    setNBEData(data);
  });
}

<|endoftext|>


<commit_before>var BIT_PLAYER_APP_ID = "mjkikpbeengfefopcnmhljmiobkghfpd";
//var BIT_PLAYER_APP_ID = "lhjejncdphamohhgcjkeineeajmhmnoh"; //dev

chrome.notifications.onButtonClicked.addListener(function(notificationId, buttonIndex)
{
	window.open('https://chrome.google.com/webstore/detail/bit-player/mjkikpbeengfefopcnmhljmiobkghfpd');
});

function error(error, buttons)
{
	chrome.notifications.create("app_error", {
			type: "basic",
			title: "Bit Player Launcher",
			iconUrl: "../images/icon64.png",
			message: error,
			buttons: buttons || []
		},
		function () // The callback is required before Chrome 42.
		{
		}
	);
}

chrome.contextMenus.onClicked.addListener(function (info)
{
	chrome.runtime.sendMessage(BIT_PLAYER_APP_ID, {
		command: 'open-torrent-url',
		url: info.linkUrl
	}, function (response)
	{
		if (undefined == response)
			return error('The Bit Player app is missing.', [{title: 'Click HERE to install it.'}]);

		if (response.result !== 1)
		{
			console.log(response);
			return error(result);
		}

		console.log('Torrent fetched successfully by Bit Player app.');
	})
});

chrome.runtime.onInstalled.addListener(function ()
{
	chrome.contextMenus.create({
		id: "contextMenu",
		title: "Play with Bit Player",
		contexts: ["link"],
		targetUrlPatterns: [
			"magnet:*"
			//,"*://*/*.torrent",
			//"*://*/*.torrent?*",
			//"*://*/*.torrent#*"
		]
	}, function ()
	{
	});
});

chrome.runtime.onMessageExternal.addListener(function (request, sender, sendResponse)
{
	sendResponse({
		installed: true,
		version: chrome.runtime.getManifest().version
	});
});

<commit_msg>launcher now supports torrents links<commit_after>var BIT_PLAYER_APP_ID = "mjkikpbeengfefopcnmhljmiobkghfpd";
//var BIT_PLAYER_APP_ID = "lhjejncdphamohhgcjkeineeajmhmnoh"; //dev

chrome.notifications.onButtonClicked.addListener(function(notificationId, buttonIndex)
{
	window.open('https://chrome.google.com/webstore/detail/bit-player/mjkikpbeengfefopcnmhljmiobkghfpd');
});

function error(error, buttons)
{
	chrome.notifications.create("app_error", {
			type: "basic",
			title: "Bit Player Launcher",
			iconUrl: "../images/icon64.png",
			message: error,
			buttons: buttons || []
		},
		function () // The callback is required before Chrome 42.
		{
		}
	);
}

chrome.contextMenus.onClicked.addListener(function (info)
{
	chrome.runtime.sendMessage(BIT_PLAYER_APP_ID, {
		command: 'open-torrent-url',
		url: info.linkUrl
	}, function (response)
	{
		if (undefined == response)
			return error('The Bit Player app is missing.', [{title: 'Click HERE to install it.'}]);

		if (response.result !== 1)
		{
			console.log(response);
			return error(result);
		}

		console.log('Torrent fetched successfully by Bit Player app.');
	})
});

chrome.runtime.onInstalled.addListener(function ()
{
	chrome.contextMenus.create({
		id: "contextMenu",
		title: "Play with Bit Player",
		contexts: ["link"],
		targetUrlPatterns: [
			"magnet:*",
			"*://*/*.torrent",
			"*://*/*.torrent?*",
			"*://*/*.torrent#*"
		]
	}, function ()
	{
	});
});

chrome.runtime.onMessageExternal.addListener(function (request, sender, sendResponse)
{
	sendResponse({
		installed: true,
		version: chrome.runtime.getManifest().version
	});
});

<|endoftext|>


<commit_before>// My localStorage
var LS = {
	prepend: 'anti-censorship-',
	get: function(k) {
		var self = this;
		return $.parseJSON(window.localStorage.getItem(this.prepend+k));
	},
	set: function(k, v) {
		return window.localStorage.setItem(this.prepend+k.toString(), JSON.stringify(v));
	}
};

// Anti-censorship, yo
var Anti = {

	init: function() {
		// Inject new sort options
		var extraHTML = '<option value="rating">Rating (+)</option>'+
	                    '<option value="workload">Workload (+)</option>';
		$('#sort-by').append(extraHTML);

		$('#submit-button').click(function() {
			// Kind of a hack; on pressing submit, switch to subject sort mode
			// so we don't have to deal with fetching data for ratings
			$('#sort-by option').removeAttr('selected');
			$('#sort-by option[value=subject]').attr('selected', true);
		});

		// Variables
		this.results = App.results;
		this.courses = App.results.models;

		// Bind to native app
		this.results.bind('fetchAllComplete', this.fetchEvalsAndRender, this);
		this.results.bind('changedSortOrder', this.fetchEvalsAndRender, this);
		this.results.bind('changedSortOrder', this.sortByRating, this);
	},

	render: function(course, ratings_rend, self) {
		// We sort by the current sort dropdown selection
		var sortBy = $('#sort-by').find(':selected').attr('value');

		// HACK use alternate method sortByRating to render
		// Had to do this to avoid weird async bug on time deadline
		if (sortBy == 'rating') {
			return;
		}

		// Get the search result currently rendered in the DOM that has the same ID
		var id = course.get('id');
		var $searchContainer = $('#search_results .content.scroller');
		var $searchResults = $searchContainer.find('.list-item');
		var $existingResult = $searchContainer.find('.list-item[data-id='+id+']');

		if (sortBy != 'rating' && sortBy != 'workload') {
			// We'll make it easy on ourselves for the old sort indexes.
			// Instead of writing a comparator function, let's accept that the
			// sort order of the original app is correct and simply insert rating HTML
			// at the right place
			var ratingHTML = self.getRatingHTMLForCourse(ratings_rend);
			$existingResult.find('.meeting').prepend(ratingHTML);
		} else {

			if (sortBy == 'workload') {

				// We render the course, moving the courses in the list with the same ID
				// to the top, then inserting with insertion sort (big O of N^2, but there
				// shouldn't be too many search results returned)
				var sortAttribute = 'data-'+sortBy;

				$searchResults.each(function(idx, result) {

					// The value of the sort attribute for the iteration of
					// the search list, e.g. value of `data-rating` for the item
					var comparatorValue = $(result).find('.ratings span['+sortAttribute+']').attr(sortAttribute);
					// Sort value of the course to be inserted
					var sortValue = (ratings_rend[sortBy] || 0);

					// All prepended courses get a data-new attribute, so if we don't
					// see data-new we're at the unsorted results.
				    if (!$(result).attr('data-new') || sortValue >= comparatorValue) {
				    	// Insert here
				    	var ratingHTML = self.getRatingHTMLForCourse(ratings_rend);
				    	$existingResult.attr('data-new', true);
						$existingResult.find('.meeting').prepend(ratingHTML);
						// If you reached yourself, there's no need to move
						if ($existingResult.attr('data-id') != $(result).attr('data-id')) {
				    		$existingResult.insertBefore(result);
				    	}
				    	return false;
				    }
				});
			}
		}

	},

	sortByRating: function() {
		var self = this;
		var $searchContainer = $('#search_results .content.scroller');
		var $searchResults = $searchContainer.find('.list-item');
		var $existingResult;
		var sortBy = $('#sort-by').find(':selected').attr('value');
		var htmlObj = [],
			html = '',
			ratingHTML,
		    node,
		    ratings,
		    quality,
		    els;
		if (sortBy == 'rating') {

			this.courses = App.results.models;
			_(this.courses).each(function(course) {
				ratings = LS.get(course.id);
				ratingHTML = self.getRatingHTMLForCourse(LS.get(course.id));
				$existingResult = $searchContainer.find('.list-item[data-id='+course.id+']');
				// Clone with deep nested events
				$cloneResult = $existingResult.clone(true, true);

				if (ratings) {
					quality = ratings.quality;
				} else {
					quality = 0;
				}

				htmlObj.push({ quality: quality, ratingHTML: ratingHTML, item: $cloneResult });
			});

			// Add the ratings html template to the elements that we cloned
			_(htmlObj).each(function(obj) {
				obj.item.find('.meeting').prepend(obj.ratingHTML);
			})

			// Sort it by rating
			htmlObj = _(htmlObj).sortBy(function(obj) {
			    return -(obj.quality - 5);
			});

			// reduce it into one big array of elements
			els = htmlObj.reduce(function(memo, obj) { return memo.add(obj.item); }, $());

			// inject into DOM
			$searchContainer.empty().append(els);
		}
		return;
	},

	// Fetch evals if they aren't cached, then call render
	fetchEvalsAndRender: function() {
		var self = this;
		// Update the courses variable since we may have fetched data
		this.courses = App.results.models;
		_(this.courses).each(function(course) {
			// Render each course with the course data and ratings
			self.getRatingsForCourse(course, self.render, self);
		});
	},

	// Given a course model, fetch its ratings
	getRatingsForCourse: function(course, cb, context) {
		var self = this;
		var id = course.get('id');
		var ratings = LS.get(id);
		if (ratings) {
			return cb(course, ratings, context);
		} else {
			$.ajax({
		         url: "https://ybb.yale.edu/courses/" + id,
		         type: "GET",
		         beforeSend: function(xhr){
		         	xhr.setRequestHeader('Accept', 'application/json, text/javascript, */*; q=0.01');
		         },
		         success: function(data) {
		         	ratings = self._calculateRatingsFromEvaluations(data.evaluations);
		         	var numFields = _(ratings).chain().values().filter(function(val) { return !_.isUndefined(val); }).value().length;
		         	if (!!numFields) {
		         		LS.set(id, ratings);
		        	}
		         	cb(course, ratings, context);
		         }
  		    });
		}
		return;
	},

	getTemplate: function(ratings__) {
		var html = this.getRatingHTMLForCourse(ratings__);
		// Add data-new attribute so we know which rows are new
		return _.template('<div class="list-item clearfix" data-new="true" data-id="<%= course.id %>" data-term="<%= course.term.oci %>">\n<span class="icon lock<%= course.lockClass %>">Lock\n	<span class="icon add-course<%= course.addClass %>" data-action="add">Add\n	Tab\n
\n'+html+ '
<input type="checkbox" class="compare-add-check" />
\n	<% if(course.canceled){ %>\nCanceled\n		<% } else { %>\n	<%= course.sessions.join(\'
\') %>\n		<% } %>\n
\n		<%= course.areas.join(\', \') %>\n		<%= course.term.nice_term %>\n
\n
\n		<%= course.subject %> <%= course.number %><%= course.section %>\n		<% if(course.number >= 500){ %>\n			[Grad]\n		<% } %>\n
\n
<%= course.title %>
\n
<%= course.professors.join(\', \') %>
\n
<%= course.description %>
\n
');
	},

	getRatingHTMLForCourse: function (ratings_) {
		if (!ratings_) {
			return '
'+
					  '\n'+
					      'Rating  N/A\n
'+
					      'Work  N/A\n'+
					  '\n'+
					'
\n';
		}
		var quality = (+ratings_.quality).toFixed(1);
		var workload = (+ratings_.workload).toFixed(1);
		var qualityClass = this.getCSSSelectorForAttribute(quality);
		var workloadClass = this.getCSSSelectorForAttribute(workload);

		if (quality == 'NaN') { quality = 0; }
		if (workload == 'NaN') { workload = 0; }

		return '
'+
				  '\n'+
				      'Rating '+ (quality ||' N/A')+'\n
'+
				      'Work '+ (workload ||' N/A')+'\n'+
				  '\n'+
				'
\n';
	},

	_calculateRatingsFromEvaluations: function(evaluations) {
		var qid = {
			workload: 5,
			quality: 6
		};

	    function averages(ratings_av) {
	    	var obj = _(ratings_av).chain()
					        .reduce(function(memo, rating) {
										return { total_votes: rating.votes + memo.total_votes,
										         total_value: rating.votes * rating.value + memo.total_value};
							                   }, { total_votes: 0, total_value: 0})
							.value()
							;
			return obj.total_value / obj.total_votes;
	    }

		var ratings = _(evaluations).chain()
						.pluck('ratings')
						.flatten()
						.filter(function(rating) {
							return rating.question_id == qid.workload ||
						           rating.question_id == qid.quality; })
						.groupBy(function(rating){ return rating.question_id; })
						.map(function(rating){ return _(rating).first(5); })
						.value()
						;

		return {
			// If you want to generate fake data:
			// Generates numbers between 2 and 5 since ratings below 2 are rare
			//quality: (Math.random() * 3) + 2,
			//workload: (Math.random() * 3) + 2
			quality: +(+(averages(ratings[1])).toFixed(1)) || undefined,
			workload: +(+(averages(ratings[0])).toFixed(1)) || undefined
		};
	},

	getCSSSelectorForAttribute: function(attr) {
		if (attr > 0 && attr <= 2) {
			return 'a';
		} else if (attr > 2 && attr <= 3) {
			return 'b';
		} else if (attr > 3 && attr <= 4) {
			return 'c';
		} else if (attr > 4) {
			return 'd';
		} else {
			return 'none';
		}
	}
};

var jsInitChecktimer = setInterval(checkForJS_Finish, 111);
function checkForJS_Finish() {
  if (typeof $ != "undefined" &&
      typeof App != "undefined") {
       clearInterval(jsInitChecktimer);
       Anti.init();
  }
}<commit_msg>tabs -> spaces, remove unnecessary code<commit_after>// My localStorage
var LS = {
  prepend: 'anti-censorship-',
  get: function(k) {
    var self = this;
    return $.parseJSON(window.localStorage.getItem(this.prepend+k));
  },
  set: function(k, v) {
    return window.localStorage.setItem(this.prepend+k.toString(), JSON.stringify(v));
  }
};

// Anti-censorship, yo
var Anti = {

  init: function() {
    // Inject new sort options
    var extraHTML = '<option value="rating">Rating (+)</option>'+
                    '<option value="workload">Workload (+)</option>';
    $('#sort-by').append(extraHTML);

    $('#submit-button').click(function() {
      // Kind of a hack; on pressing submit, switch to subject sort mode
      // so we don't have to deal with fetching data for ratings
      $('#sort-by option').removeAttr('selected');
      $('#sort-by option[value=subject]').attr('selected', true);
    });

    // Variables
    this.results = App.results;
    this.courses = App.results.models;

    // Bind to native app
    this.results.bind('fetchAllComplete', this.fetchEvalsAndRender, this);
    this.results.bind('changedSortOrder', this.fetchEvalsAndRender, this);
    this.results.bind('changedSortOrder', this.sortByRating, this);
  },

  render: function(course, ratingsrend, self) {
    // We sort by the current sort dropdown selection
    var sortBy = $('#sort-by').find(':selected').attr('value');

    // HACK use alternate method sortByRating to render
    // Had to do this to avoid weird async bug on time deadline
    if (sortBy == 'rating') { return; }

    // Get the search result currently rendered in the DOM that has the same ID
    var id = course.get('id');
    var $searchContainer = $('#search_results .content.scroller');
    var $searchResults = $searchContainer.find('.list-item');
    var $existingResult = $searchContainer.find('.list-item[data-id='+id+']');

    if (sortBy != 'rating' && sortBy != 'workload') {
      // We'll make it easy on ourselves for the old sort indexes.
      // Instead of writing a comparator function, let's accept that the
      // sort order of the original app is correct and simply insert rating HTML
      // at the right place
      var ratingHTML = self.getRatingHTMLForCourse(ratingsrend);
      $existingResult.find('.meeting').prepend(ratingHTML);
    } else {
      // We render the course, moving the courses in the list with the same ID
      // to the top, then inserting with insertion sort (big O of N^2, but there
      // shouldn't be too many search results returned)
      var sortAttribute = 'data-'+sortBy;

      $searchResults.each(function(idx, result) {

        // The value of the sort attribute for the iteration of
        // the search list, e.g. value of `data-rating` for the item
        var comparatorValue = $(result).find('.ratings span['+sortAttribute+']').attr(sortAttribute);
        // Sort value of the course to be inserted
        var sortValue = (ratingsrend[sortBy] || 0);

        // All prepended courses get a data-new attribute, so if we don't
        // see data-new we're at the unsorted results.
      if (!$(result).attr('data-new') || sortValue >= comparatorValue) {
        // Insert here
        var ratingHTML = self.getRatingHTMLForCourse(ratingsrend);
        $existingResult.attr('data-new', true);
        $existingResult.find('.meeting').prepend(ratingHTML);
        // If you reached yourself, there's no need to move
        if ($existingResult.attr('data-id') != $(result).attr('data-id')) {
          $existingResult.insertBefore(result);
        }
        return false;
      }
      });
    }
  },

  sortByRating: function() {
    var self = this;
    var $searchContainer = $('#search_results .content.scroller');
    var $searchResults = $searchContainer.find('.list-item');
    var $existingResult;
    var sortBy = $('#sort-by').find(':selected').attr('value');
    var htmlObj = [],
        html = '',
        ratingHTML,
        node,
        ratings,
        quality,
        els;
    if (sortBy == 'rating') {

      this.courses = App.results.models;
      _(this.courses).each(function(course) {
        ratings = LS.get(course.id);
        ratingHTML = self.getRatingHTMLForCourse(LS.get(course.id));
        $existingResult = $searchContainer.find('.list-item[data-id='+course.id+']');
        // Clone with deep nested events
        $cloneResult = $existingResult.clone(true, true);

        if (ratings) {
          quality = ratings.quality;
        } else {
          quality = 0;
        }

        htmlObj.push({ quality: quality, ratingHTML: ratingHTML, item: $cloneResult });
      });

      // Add the ratings html template to the elements that we cloned
      _(htmlObj).each(function(obj) {
        obj.item.find('.meeting').prepend(obj.ratingHTML);
      })

      // Sort it by rating
      htmlObj = _(htmlObj).sortBy(function(obj) {
      return -(obj.quality - 5);
      });

      // reduce it into one big array of elements
      els = htmlObj.reduce(function(memo, obj) { return memo.add(obj.item); }, $());

      // inject into DOM
      $searchContainer.empty().append(els);
    }
    return;
  },

  // Fetch evals if they aren't cached, then call render
  fetchEvalsAndRender: function() {
    var self = this;
    // Update the courses variable since we may have fetched data
    this.courses = App.results.models;
    _(this.courses).each(function(course) {
      // Render each course with the course data and ratings
      self.getRatingsForCourse(course, self.render, self);
    });
  },

  // Given a course model, fetch its ratings
  getRatingsForCourse: function(course, cb, context) {
    var self = this;
    var id = course.get('id');
    var ratings = LS.get(id);
    if (ratings) {
      return cb(course, ratings, context);
    } else {
      $.ajax({
         url: "https://ybb.yale.edu/courses/" + id,
         type: "GET",
         beforeSend: function(xhr){
           xhr.setRequestHeader('Accept', 'application/json, text/javascript, */*; q=0.01');
         },
         success: function(data) {
           ratings = self.calculateRatingsFromEvaluations(data.evaluations);
           var numFields = _(ratings).chain().values().filter(function(val) { return !_.isUndefined(val); }).value().length;
           if (!!numFields) {
             LS.set(id, ratings);
           }
           cb(course, ratings, context);
         }
      });
    }
    return;
  },

  getRatingHTMLForCourse: function (ratings) {
    if (!ratings) {
      return '
'+
        '\n'+
            'Rating  N/A\n
'+
            'Work  N/A\n'+
        '\n'+
          '
\n';
    }
    var quality = (+ratings.quality).toFixed(1);
    var workload = (+ratings.workload).toFixed(1);
    var qualityClass = this.getCSSSelectorForAttribute(quality);
    var workloadClass = this.getCSSSelectorForAttribute(workload);

    if (quality == 'NaN') { quality = 0; }
    if (workload == 'NaN') { workload = 0; }

    return '
'+
      '\n'+
          'Rating '+ (quality ||' N/A')+'\n
'+
          'Work '+ (workload ||' N/A')+'\n'+
      '\n'+
        '
\n';
  },

  calculateRatingsFromEvaluations: function(evaluations) {
    var qid = {
      workload: 5,
      quality: 6
    };

    function averages(ratingsav) {
      var obj = _(ratingsav).chain()
                .reduce(function(memo, rating) {
                      return { total_votes: rating.votes + memo.total_votes,
                               total_value: rating.votes * rating.value + memo.total_value};
                }, { total_votes: 0, total_value: 0})
                .value()
                ;
        return obj.total_value / obj.total_votes;
    }

    var ratings = _(evaluations).chain()
            .pluck('ratings')
            .flatten()
            .filter(function(rating) {
              return rating.question_id == qid.workload ||
                   rating.question_id == qid.quality; })
            .groupBy(function(rating){ return rating.question_id; })
            .map(function(rating){ return _(rating).first(5); })
            .value()
            ;

    return {
      // If you want to generate fake data:
      // Generates numbers between 2 and 5 since ratings below 2 are rare
      //quality: (Math.random() * 3) + 2,
      //workload: (Math.random() * 3) + 2
      quality: +(+(averages(ratings[1])).toFixed(1)) || undefined,
      workload: +(+(averages(ratings[0])).toFixed(1)) || undefined
    };
  },

  getCSSSelectorForAttribute: function(attr) {
    if (attr > 0 && attr <= 2) {
      return 'a';
    } else if (attr > 2 && attr <= 3) {
      return 'b';
    } else if (attr > 3 && attr <= 4) {
      return 'c';
    } else if (attr > 4) {
      return 'd';
    } else {
      return 'none';
    }
  }
};

var jsInitChecktimer = setInterval(checkForJS_Finish, 111);
function checkForJS_Finish() {
  if (typeof $ != "undefined" &&
      typeof App != "undefined") {
       clearInterval(jsInitChecktimer);
       Anti.init();
  }
}
<|endoftext|>


<commit_before>(function() {
  settings = {}
  chrome.storage.sync.get({
    showPositive: false,
    showNeutral: false,
    showNegative: false,
    showAll: true
  }, function(items) {
    settings.positive = items.showPositive;
    settings.neutral = items.showNeutral;
    settings.negative = items.showNegative;
    settings.showall = items.showAll;
  });
  console.log(settings)
  let $grabFromPage = $('div.commentarea div.md')
  let $url = window.location.pathname;
  let textToEval = {};
  $grabFromPage.addClass(function(index){
    return 'reddex' + index;
  });
  $grabFromPage.each(function(index){
    textToEval[$grabFromPage[index].className.split(' ')[1]] = $grabFromPage[index].innerText;
  });
  textToEval.url = $url.split('/')[2]
  console.log(textToEval)
  $.ajax({
    url: 'https://reddex.herokuapp.com/inbound',
    method: 'POST',
    data: textToEval
  })
  .then(function(response){
    console.log(response)
    for(key in response){
      $('.' + key).addClass(function(index){
        if((response[key] <= -0.65) && (settings.showall === true || settings.negative === true)){
           return 'neg2'
        }
        else if((response[key] <= -0.35) && (settings.showall === true || settings.negative === true)) {
          return 'neg1'
        }
        else if((response[key] > 0.65) && (settings.showall === true || settings.positive === true)) {
          return 'pos2'
        }
        else if((response[key] > 0.35) && (settings.showall === true || settings.positive === true)){
          return 'pos1'
        }
        else if((response[key] > -0.35 && response[key] <= 0.35) && (settings.showall === true || settings.neutral === true)){
          return 'neu'
        }
      })
    }
  });
})();
<commit_msg>adding in fix to remove old classes after changing options<commit_after>(function() {
  settings = {}
  chrome.storage.sync.get({
    showPositive: false,
    showNeutral: false,
    showNegative: false,
    showAll: true
  }, function(items) {
    settings.positive = items.showPositive;
    settings.neutral = items.showNeutral;
    settings.negative = items.showNegative;
    settings.showall = items.showAll;
  });
  let $grabFromPage = $('div.commentarea div.md')
  let $url = window.location.pathname;
  let textToEval = {};
  $grabFromPage.addClass(function(index){
    return 'reddex' + index;
  });
  $grabFromPage.each(function(index){
    textToEval[$grabFromPage[index].className.split(' ')[1]] = $grabFromPage[index].innerText;
  });
  textToEval.url = $url.split('/')[2]
  $.ajax({
    url: 'https://reddex.herokuapp.com/inbound',
    method: 'POST',
    data: textToEval
  })
  .then(function(response){
    $grabFromPage.removeClass('neu neg1 neg2 pos1 pos2')
    for(key in response){
      $('.' + key).addClass(function(index){
        if((response[key] <= -0.65) && (settings.showall === true || settings.negative === true)){
           return 'neg2'
        }
        else if((response[key] <= -0.35) && (settings.showall === true || settings.negative === true)) {
          return 'neg1'
        }
        else if((response[key] > 0.65) && (settings.showall === true || settings.positive === true)) {
          return 'pos2'
        }
        else if((response[key] > 0.35) && (settings.showall === true || settings.positive === true)){
          return 'pos1'
        }
        else if((response[key] > -0.35 && response[key] <= 0.35) && (settings.showall === true || settings.neutral === true)){
          return 'neu'
        }
      })
    }
  });
})();
<|endoftext|>


<commit_before>//basic.js
// ==UserScript==
// @name       Extension - Scratch
// @namespace  http://scratch.mit.edu
// @version    who cares?
// @description  An extension for scratch. By ipodlover3354.
// @match      *://scratch.mit.edu/projects/*
// @author ipodlover3354
// ==/UserScript==

console.log("Extension working. Made by ipodlover3354 using an example script");

new(function() {
	var ext = this;

	// Cleanup function when the extension is unloaded
	ext._shutdown = function() {};

	// Status reporting code
	// Use this to report missing hardware, plugin or unsupported browser
	ext._getStatus = function() {
		return {
			status: 2,
			msg: 'All set, 11 blocks loaded.'
		};
	};

	ext.color = function(color) {
		return color;
	}

	ext.hextodec = function(hex) {
		var decimal = parseInt(hexString, 16);
		return decimal;
	}

	ext.dectohex = function(dec) {
		return dec.toString(16);
	}

	ext.decodeURI = function(uri) {
		return decodeURI(uri);
	}
	ext.encodeURI = function(uri) {
		return encodeURI(uri);
	}

	// Block and block menu descriptions
	var descriptor = {
		blocks: [
			// Block type, block name, function name, param1 default value, param2 default value
			['r',"return color %c",'color'],
			['r', "hex to dec %s", 'hextodec',"000"],
			['r', "dec to hex %n", 'dectohex',15],
			['r','decode URI %s','decodeURI'],
			['r','encode URI %s','encodeURI']
		],
		menus: {

	}};;

	// Register the extension
	ScratchExtensions.register('Color - ipodlover3354', descriptor, ext);
})();
<commit_msg>Update color.js<commit_after>//basic.js
// ==UserScript==
// @name       Extension - Scratch
// @namespace  http://scratch.mit.edu
// @version    who cares?
// @description  An extension for scratch. By ipodlover3354.
// @match      *://scratch.mit.edu/projects/*
// @author ipodlover3354
// ==/UserScript==

console.log("Extension working. Made by ipodlover3354 using an example script");

new(function() {
	var ext = this;

	// Cleanup function when the extension is unloaded
	ext._shutdown = function() {};

	// Status reporting code
	// Use this to report missing hardware, plugin or unsupported browser
	ext._getStatus = function() {
		return {
			status: 2,
			msg: 'All set, 11 blocks loaded.'
		};
	};

	ext.color = function(color) {
		return color;
	}

	ext.hextodec = function(hex) {
		var decimal = parseInt(hexString, 16).ToString(10);
		return decimal;
	}

	ext.dectohex = function(dec) {
		return dec.toString(16);
	}

	ext.decodeURI = function(uri) {
		return decodeURI(uri);
	}
	ext.encodeURI = function(uri) {
		return encodeURI(uri);
	}

	// Block and block menu descriptions
	var descriptor = {
		blocks: [
			// Block type, block name, function name, param1 default value, param2 default value
			['r',"return color %c",'color'],
			['r', "hex to dec %s", 'hextodec',"000"],
			['r', "dec to hex %n", 'dectohex',15],
			['r','decode URI %s','decodeURI'],
			['r','encode URI %s','encodeURI']
		],
		menus: {

	}};;

	// Register the extension
	ScratchExtensions.register('Color - ipodlover3354', descriptor, ext);
})();
<|endoftext|>


<commit_before>function line(x1, y1, x2, y2, color){
  'use strict';

  var c = document.getElementById('c').getContext('2d');
  c.strokeStyle = color || 'black';
  c.beginPath();
  c.moveTo(x1, y1);
  c.lineTo(x2, y2);
  c.stroke();
}

function circle(x, y, r, fill){
  'use strict';

  var c = document.getElementById('c').getContext('2d');
  c.beginPath();
  c.arc(x, y, r, 0, 7, false);
  if (fill){
    c.fill();
  }
  c.stroke();
}

function triangle(x1, y1, x2, y2, x3, y3, fill){
  'use strict';

  var c = document.getElementById('c').getContext('2d');
  c.beginPath();
  c.moveTo(x1, y1);
  c.lineTo(x2, y2);
  c.lineTo(x3, y3);
  c.lineTo(x1, y1);
  if (fill){
    c.fill();
  }
  c.stroke();
}

function rectangle(x1, y1, x2, y2, fill){
  'use strict';

  var c = document.getElementById('c').getContext('2d');
  c.beginPath();
  c.moveTo(x1, y1);
  c.lineTo(x2, y1);
  c.lineTo(x2, y2);
  c.lineTo(x1, y2);
  c.lineTo(x1, y1);
  if (fill){
    c.fill();
  }
  c.stroke();
}

function coordinateAxis(){
  line(0, 250, 500, 250, 'dakgray');
  line(250, 0, 250, 500, 'dakgray');
  for (var i = 50; i < 250; i += 50){
    line(i, 245, i, 255, 'dakgray');
    line(245, i, 255, i, 'dakgray');
    line(500 - i, 245, 500 - i, 255, 'dakgray');
    line(245, 500 - i, 255, 500 - i, 'dakgray');
  }
}

function grid() {
  for (var i = 50; i < 500; i += 50){
    line(0, i, 500, i, '#f0f0f0');
    line(i, 0, i, 500, '#f0f0f0');
  }
}

(function(){
  'use strict';

  window.addEventListener('load', function(){
    coordinateAxis();
    grid();
    document.getElementById('lButton').addEventListener('click', function(){
      var x1 = document.getElementById('lX1').value;
      var y1 = document.getElementById('lY1').value;
      var x2 = document.getElementById('lX2').value;
      var y2 = document.getElementById('lY2').value;
      line(x1, y1, x2, y2);
    });
    document.getElementById('tButton').addEventListener('click', function(){
      var x1 = document.getElementById('tX1').value;
      var y1 = document.getElementById('tY1').value;
      var x2 = document.getElementById('tX2').value;
      var y2 = document.getElementById('tY2').value;
      var x3 = document.getElementById('tX3').value;
      var y3 = document.getElementById('tY3').value;
      var fill = document.getElementById('tFill').checked;
      triangle(x1, y1, x2, y2, x3, y3, fill);
    });
    document.getElementById('rButton').addEventListener('click', function(){
      var x1 = document.getElementById('rX1').value;
      var y1 = document.getElementById('rY1').value;
      var x2 = document.getElementById('rX2').value;
      var y2 = document.getElementById('rY2').value;
      var fill = document.getElementById('rFill').checked;
      rectangle(x1, y1, x2, y2, fill);
    });
  });
})();
<commit_msg>グリッドの色を変更<commit_after>function line(x1, y1, x2, y2, color){
  'use strict';

  var c = document.getElementById('c').getContext('2d');
  c.strokeStyle = color || 'black';
  c.beginPath();
  c.moveTo(x1, y1);
  c.lineTo(x2, y2);
  c.stroke();
}

function circle(x, y, r, fill){
  'use strict';

  var c = document.getElementById('c').getContext('2d');
  c.beginPath();
  c.arc(x, y, r, 0, 7, false);
  if (fill){
    c.fill();
  }
  c.stroke();
}

function triangle(x1, y1, x2, y2, x3, y3, fill){
  'use strict';

  var c = document.getElementById('c').getContext('2d');
  c.beginPath();
  c.moveTo(x1, y1);
  c.lineTo(x2, y2);
  c.lineTo(x3, y3);
  c.lineTo(x1, y1);
  if (fill){
    c.fill();
  }
  c.stroke();
}

function rectangle(x1, y1, x2, y2, fill){
  'use strict';

  var c = document.getElementById('c').getContext('2d');
  c.beginPath();
  c.moveTo(x1, y1);
  c.lineTo(x2, y1);
  c.lineTo(x2, y2);
  c.lineTo(x1, y2);
  c.lineTo(x1, y1);
  if (fill){
    c.fill();
  }
  c.stroke();
}

function coordinateAxis(){
  line(0, 250, 500, 250, 'dakgray');
  line(250, 0, 250, 500, 'dakgray');
  for (var i = 50; i < 250; i += 50){
    line(i, 245, i, 255, 'dakgray');
    line(245, i, 255, i, 'dakgray');
    line(500 - i, 245, 500 - i, 255, 'dakgray');
    line(245, 500 - i, 255, 500 - i, 'dakgray');
  }
}

function grid() {
  for (var i = 50; i < 500; i += 50){
    line(0, i, 500, i, 'gainsboro');
    line(i, 0, i, 500, 'gainsboro');
  }
}

(function(){
  'use strict';

  window.addEventListener('load', function(){
    coordinateAxis();
    grid();
    document.getElementById('lButton').addEventListener('click', function(){
      var x1 = document.getElementById('lX1').value;
      var y1 = document.getElementById('lY1').value;
      var x2 = document.getElementById('lX2').value;
      var y2 = document.getElementById('lY2').value;
      line(x1, y1, x2, y2);
    });
    document.getElementById('tButton').addEventListener('click', function(){
      var x1 = document.getElementById('tX1').value;
      var y1 = document.getElementById('tY1').value;
      var x2 = document.getElementById('tX2').value;
      var y2 = document.getElementById('tY2').value;
      var x3 = document.getElementById('tX3').value;
      var y3 = document.getElementById('tY3').value;
      var fill = document.getElementById('tFill').checked;
      triangle(x1, y1, x2, y2, x3, y3, fill);
    });
    document.getElementById('rButton').addEventListener('click', function(){
      var x1 = document.getElementById('rX1').value;
      var y1 = document.getElementById('rY1').value;
      var x2 = document.getElementById('rX2').value;
      var y2 = document.getElementById('rY2').value;
      var fill = document.getElementById('rFill').checked;
      rectangle(x1, y1, x2, y2, fill);
    });
  });
})();
<|endoftext|>


<commit_before>var timeoverride = null;
var timeperiod;
var unitname = "";

// init
$(function() {

  //run every X period of time the main loop.
  startTimer(180, $('#time'));

  // main
  RunForestRun()
});

// redraw when the slide radio buttons change
$('input[type=radio][name=slide]').change(function(e) {
  console.log(this.value);
  timeoverride = this.value;

  RunForestRun();
});

function getSearchParameters() {
  var prmstr = window.location.search.substr(1);
  return prmstr != null && prmstr != "" ? transformToAssocArray(prmstr) : {};
}

function transformToAssocArray( prmstr ) {
  var params = {};
  var prmarr = prmstr.split("&");
  for (var i = 0; i < prmarr.length; i++) {
    var tmparr = prmarr[i].split("=");
    params[tmparr[0]] = tmparr[1];
  }
  return params;
}

var params = getSearchParameters();

//update every X seconds
function startTimer(duration, display) {
  var timer = duration, minutes, seconds;
  setInterval(function () {
    minutes = parseInt(timer / 60, 10)
    seconds = parseInt(timer % 60, 10);

    minutes = minutes < 10 ? "0" + minutes : minutes;
    seconds = seconds < 10 ? "0" + seconds : seconds;

    $(display).text(minutes + ":" + seconds);

    if (--timer < 0) { //when the timer is 0 run the code
      timer = duration;
      RunForestRun();
    }
  }, 1000);
}

// fetch jobs from beacon
function fetchJobsFromBeacon(id, unit, cb) {
  var start = new Date(decodeURIComponent(params.start));
  var end = new Date(decodeURIComponent(params.end));

  GetJSONfromBeacon(id, start, end, function(data) {
    cb && cb(data);
  });
}

// render the page using the data provided
function renderPage(unit, jobs) {
  console.log(jobs);

  var start = new Date(decodeURIComponent(params.start));
  var end = new Date(decodeURIComponent(params.end));

  document.title = unit + " Job Statistics";

  $('#total').html("Total Job Count: " + (jobs.Results.length));

  prepareCharts(jobs, start, end);
  dc.renderAll();

  $('#loading').hide();
  $('#results').show();

  var options = {
    weekday: "short",
    year: "numeric",
    month: "2-digit",
    day: "numeric"
  };

  var html = "
Job statistics for " +
    unit + "

" + start.toLocaleTimeString("en-au", options) +
    " to " + end.toLocaleTimeString("en-au", options) + "
";
  $('#banner').html(html);
}

// make piece chart using our standard parameters
function makePie(elem, w, h, dimension, group) {
  var chart = dc.pieChart(elem);
  chart.width(w)
       .height(h)
       .radius(100)
       .innerRadius(0)
       .dimension(dimension)
       .legend(dc.legend())
       .title(function(d) { return d.value; })
       .group(group);
  return chart;
}

// gather and organise all of the data
// build charts and feed data
// render
function prepareCharts(jobs, start, end) {

  // convert timestamps to Date()s
  jobs.Results.forEach(function(d) {
    var rawdate = new Date(d.JobReceived);
    d.JobReceived = new Date(
      rawdate.getTime() + ( rawdate.getTimezoneOffset() * 60000 )
    );
  });

  var facts = crossfilter(jobs.Results);

  var all = facts.groupAll();

  // jobs per hour time chart
  var timeChart = dc.barChart("#dc-time-chart");
  var volumeByHour = facts.dimension(function(d) {
    return d3.time.hour(d.JobReceived);
  });

  var volumeByHourGroup = volumeByHour.group()
    .reduceCount(function(d) { return d.JobReceived; });

  timeChart.width(1000)
    .height(250)
    .transitionDuration(500)
    .brushOn(false)
    //.mouseZoomable(true)
    .margins({top: 10, right: 10, bottom: 20, left: 40})
    .dimension(volumeByHour)
    .group(volumeByHourGroup)
    //.brushOn(false)           // added for title
    .xUnits(d3.time.hours)
    .x(d3.time.scale().domain([new Date(start), new Date(end)]))
    .elasticY(true)
    //.x(d3.time.scale().domain(d3.extent(jobs.Results, function(d) {
    //return d.JobReceived; })))
    .xAxis();

  var tags = facts.dimension(function(d) {
    return d.Tags;
  });

  preparePieCharts(facts, tags);
}

// produces a 'group' for tag pie charts
function makeTagGroup(tags, predicate) {
  var group = tags.groupAll().reduce(
    function(p, v) {
      v.Tags.forEach (function(val, idx) {
        if (predicate(val)) {
          p[val.Name] = (p[val.Name] || 0) + 1; //increment counts
        }
      });
      return p;
    },
    function(p, v) {
      v.Tags.forEach (function(val, idx) {
        if (predicate(val)) {
          p[val.Name] = (p[val.Name] || 0) - 1; //decrement counts
        }
      });
      return p;
    },
    function() { return {}; }
  ).value();

  group.all = function() {
    var newObject = [];
    for (var key in this) {
      if (this.hasOwnProperty(key) && key != "all") {
        newObject.push({
          key: key,
          value: this[key]
        });
      }
    }
    return newObject;
  }

  return group;
}

// draw all of the pie charts
function preparePieCharts(facts, tags) {

  // produces a pie chart for displaying tags
  function makeTagPie(elem, tagGroupId) {
    var group = makeTagGroup(tags, function(val) {
      return val.TagGroupId == tagGroupId;
    });
    return makePie(elem, 450, 220, tags, group);
  }

  // produces a simple pie chart
  function makeSimplePie(elem, w, h, selector) {
    var dimension = facts.dimension(function (d) {
      return selector(d);
    });
    var group = dimension.group();

    var chart = makePie(elem, w, h, dimension, group);
  }

  makeSimplePie("#dc-jobtype-chart", 350, 220, function(d) {
    return d.Type;
  });

  makeSimplePie("#dc-local-chart", 450, 220, function(d) {
    switch(unitname)
    {
      case "NSW":
        return d.LGA;
        break;
      case "group selection":
        return d.LGA;
        break;
      default:
        return d.Address.Locality;
        break;
    }

  });

  makeSimplePie("#dc-priority-chart", 350, 220, function(d) {
    return d.JobPriorityType.Name;
  });

  makeTagPie('#dc-treetags-chart', 5);
  makeTagPie('#dc-hazardtags-chart', 7);
  makeTagPie('#dc-propertytags-chart', 13);
}

//Get times vars for the call
function RunForestRun() {

  if (timeoverride !== null) { //we are using a time override

    var end = new Date();

    var start = new Date();
    start.setDate(start.getDate() - (timeoverride/24));

    starttime = start.toISOString();
    endtime = end.toISOString();

    console.log(starttime);
    console.log(endtime);

    params.start = starttime;
    params.end = endtime;
  }

  function fetchComplete(data) {
    console.log("Done fetching from beacon, rendering graphs...");
    renderPage(unitname, data);
    console.log("Graphs rendered.");
  }

  if (unitname == "") {
    console.log("firstrun...will fetch vars");

    if (typeof params.hq !== 'undefined') {

      if (params.hq.split(",").length == 1) {

        GetUnitNamefromBeacon(params.hq, function(result) {
          unitname = result;

          fetchJobsFromBeacon(params.hq, result, fetchComplete);
        });

      } else {
        console.log("passed array of units");
        unitname = "group selection";
        fetchJobsFromBeacon(params.hq, unitname, fetchComplete);
      }
    } else { //no hq was sent, get them all
      unitname = "NSW";
      fetchJobsFromBeacon(null, unitname, fetchComplete);
    }
  } else {
    console.log("rerun...will NOT fetch vars");
    fetchJobsFromBeacon(params.hq, unitname, fetchComplete);
  }
}
<commit_msg>broken stats file<commit_after>var timeoverride = null;
var timeperiod;
var unitname = "";

// init
$(function() {

  //run every X period of time the main loop.
  startTimer(180, $('#time'));

  // main
  RunForestRun()
});

// redraw when the slide radio buttons change
$('input[type=radio][name=slide]').change(function(e) {
  console.log(this.value);
  timeoverride = this.value;

  RunForestRun();
});

function getSearchParameters() {
  var prmstr = window.location.search.substr(1);
  return prmstr != null && prmstr != "" ? transformToAssocArray(prmstr) : {};
}

function transformToAssocArray( prmstr ) {
  var params = {};
  var prmarr = prmstr.split("&");
  for (var i = 0; i < prmarr.length; i++) {
    var tmparr = prmarr[i].split("=");
    params[tmparr[0]] = tmparr[1];
  }
  return params;
}

var params = getSearchParameters();

//update every X seconds
function startTimer(duration, display) {
  var timer = duration, minutes, seconds;
  setInterval(function () {
    minutes = parseInt(timer / 60, 10)
    seconds = parseInt(timer % 60, 10);

    minutes = minutes < 10 ? "0" + minutes : minutes;
    seconds = seconds < 10 ? "0" + seconds : seconds;

    $(display).text(minutes + ":" + seconds);

    if (--timer < 0) { //when the timer is 0 run the code
      timer = duration;
      RunForestRun();
    }
  }, 1000);
}

// fetch jobs from beacon
function fetchJobsFromBeacon(id, unit, cb) {
  var start = new Date(decodeURIComponent(params.start));
  var end = new Date(decodeURIComponent(params.end));

  GetJSONfromBeacon(id, start, end, function(data) {
    cb && cb(data);
  });
}

// render the page using the data provided
function renderPage(unit, jobs) {
  console.log(jobs);

  var start = new Date(decodeURIComponent(params.start));
  var end = new Date(decodeURIComponent(params.end));

  document.title = unit + " Job Statistics";

  $('#total').html("Total Job Count: " + (jobs.Results.length));

  prepareCharts(jobs, start, end);
  dc.renderAll();

  $('#loading').hide();
  $('#results').show();

  var options = {
    weekday: "short",
    year: "numeric",
    month: "2-digit",
    day: "numeric"
  };

  var html = "
Job statistics for " +
    unit + "

" + start.toLocaleTimeString("en-au", options) +
    " to " + end.toLocaleTimeString("en-au", options) + "
";
  $('#banner').html(html);
}

// make pie chart using our standard parameters
function makePie(elem, w, h, dimension, group) {
  var chart = dc.pieChart(elem);
  chart.width(w)
       .height(h)
       .radius(100)
       .innerRadius(0)
       .dimension(dimension)
       .legend(dc.legend())
       .title(function(d) { return d.value; })
       .group(group);
  return chart;
}

// gather and organise all of the data
// build charts and feed data
// render
function prepareCharts(jobs, start, end) {

  // convert timestamps to Date()s
  jobs.Results.forEach(function(d) {
    var rawdate = new Date(d.JobReceived);
    d.JobReceivedFixed = new Date(
      rawdate.getTime() + ( rawdate.getTimezoneOffset() * 60000 )
    );
d.hazardTags = [];
d.treeTags = [];
d.propertyTags = [];
    d.Tags.forEach(function(d2){
      switch (d2.TagGroupId)
      {
        case 5:
          d.treeTags.push(d2.Name);
          break;
        case 7:
          d.hazardTags.push(d2.Name);
          break
        case 13:
          d.propertyTags.push(d2.Name);
          break;
      }
    });
  });

  var facts = crossfilter(jobs.Results);

  var all = facts.groupAll();

  // jobs per hour time chart
  var timeChart = dc.barChart("#dc-time-chart");
  var volumeByHour = facts.dimension(function(d) {
    return d3.time.hour(d.JobReceivedFixed);
  });

  var volumeByHourGroup = volumeByHour.group()
    .reduceCount(function(d) { return d.JobReceivedFixed; });

  timeChart.width(1000)
    .height(250)
    .transitionDuration(500)
    .brushOn(false)
    //.mouseZoomable(true)
    .margins({top: 10, right: 10, bottom: 20, left: 40})
    .dimension(volumeByHour)
    .group(volumeByHourGroup)
    //.brushOn(false)           // added for title
    .xUnits(d3.time.hours)
    .x(d3.time.scale().domain([new Date(start), new Date(end)]))
    .elasticY(true)
    //.x(d3.time.scale().domain(d3.extent(jobs.Results, function(d) {
    //return d.JobReceived; })))
    .xAxis();

  preparePieCharts(facts);
}

// draw all of the pie charts
function preparePieCharts(facts) {

  // produces a 'group' for tag pie charts
function makeTagGroup(fact) {
  var group = facts.groupAll().reduce(
    function(p, v) {
      v.fact.forEach (function(val, idx) {
        console.log(val);
          p[val] = (p[val] || 0) + 1; //increment counts
      });
      return p;
    },
    function(p, v) {
      fact.forEach (function(val, idx) {
          p[val] = (p[val] || 0) - 1; //decrement counts
      });
      return p;
    },
    function() { return {}; }
  ).value();

  group.all = function() {
    var newObject = [];
    for (var key in this) {
      if (this.hasOwnProperty(key) && key != "all") {
        newObject.push({
          key: key,
          value: this[key]
        });
      }
    }
    return newObject;
  }

  group.top = function(count) {
    var newObject = this.all();
     newObject.sort(function(a, b){return b.value - a.value});
    return newObject.slice(0, count);
  };

  return group;
}

  // produces a pie chart for displaying tags
  function makeTagPie(elem, fact) {
    var dimension = facts.dimension(function (d) {
      return fact(d);
    });

    var group = makeTagGroup(function(d) {
      return fact(d);
    });

    return makePie(elem, 450, 220, dimension, group);
  }

  // produces a simple pie chart
  function makeSimplePie(elem, w, h, selector) {
    var dimension = facts.dimension(function (d) {
      return selector(d);
    });
    var group = dimension.group();

    var chart = makePie(elem, w, h, dimension, group);

  }

  makeSimplePie("#dc-jobtype-chart", 350, 220, function(d) {
    return d.Type;
  });

  makeSimplePie("#dc-local-chart", 450, 220, function(d) {
    switch(unitname)
    {
      case "NSW":
        return d.LGA;
        break;
      case "group selection":
        return d.LGA;
        break;
      default:
        return d.Address.Locality;
        break;
    }

  });

  makeSimplePie("#dc-priority-chart", 350, 220, function(d) {
    return d.JobPriorityType.Name;
  });

  makeTagPie('#dc-treetags-chart', function(d) {
    return d.treeTags;
  });
  makeTagPie('#dc-hazardtags-chart', function(d) {
    return d.hazardTags;
  });
  makeTagPie('#dc-propertytags-chart', function(d) {
    return d.propertyTags;
  });

}

//Get times vars for the call
function RunForestRun() {

  if (timeoverride !== null) { //we are using a time override

    var end = new Date();

    var start = new Date();
    start.setDate(start.getDate() - (timeoverride/24));

    starttime = start.toISOString();
    endtime = end.toISOString();

    console.log(starttime);
    console.log(endtime);

    params.start = starttime;
    params.end = endtime;
  }

  function fetchComplete(data) {
    console.log("Done fetching from beacon, rendering graphs...");
    renderPage(unitname, data);
    console.log("Graphs rendered.");
  }

  if (unitname == "") {
    console.log("firstrun...will fetch vars");

    if (typeof params.hq !== 'undefined') {

      if (params.hq.split(",").length == 1) {

        GetUnitNamefromBeacon(params.hq, function(result) {
          unitname = result;

          fetchJobsFromBeacon(params.hq, result, fetchComplete);
        });

      } else {
        console.log("passed array of units");
        unitname = "group selection";
        fetchJobsFromBeacon(params.hq, unitname, fetchComplete);
      }
    } else { //no hq was sent, get them all
      unitname = "NSW";
      fetchJobsFromBeacon(null, unitname, fetchComplete);
    }
  } else {
    console.log("rerun...will NOT fetch vars");
    fetchJobsFromBeacon(params.hq, unitname, fetchComplete);
  }
}
<|endoftext|>


<commit_before>// Shape Monster!
// --------------
// File:   shape_monster.js
// Author: Chris Linstid <chris@linstid.com>
//
// This is a silly game that I'm building for my (as of July 2013) 17 month old
// daughter. She isn't quite ready to play it yet, but maybe by the time I get
// enough free minutes, she'll be ready.
//
// The basic premise of the game is to guide colorful shapes to the shape
// monsters that feed on them. There really is no end to the game, it's just
// for fun.

// document has loaded, let's get those shape monsters up and running
$(document).ready(function() {
    var stage = new Kinetic.Stage({
        container: 'content',
        width: 700,
        height: 700
    });

    var rectMonster = new Kinetic.Rect({
        name: 'rectMonster',
        x: 100,
        y: 300,
        width: 100,
        height: 100,
        fill: 'black',
        stroke: 'black',
        strokeWidth: 2,
    });

    var circleMonster = new Kinetic.Rect({
        name: 'circleMonster',
        x: 300,
        y: 300,
        width: 100,
        height: 100,
        fill: 'black',
        stroke: 'black',
        strokeWidth: 2,
    });

    var triangleMonster = new Kinetic.Rect({
        name: 'triangleMonster',
        x: 500,
        y: 300,
        width: 100,
        height: 100,
        fill: 'black',
        stroke: 'black',
        strokeWidth: 2,
    });

    var rect = new Kinetic.Rect({
        name: 'rect',
        x: 100,
        y: 100,
        width: 100,
        height: 100,
        fill: 'red',
        stroke: 'black',
        strokeWidth: 2,
        draggable: true
    });

    rect.on('dragmove', function(mouseEvent) {
        rect.moveToTop();
        if (rectMonster.intersects([mouseEvent.layerX,
                                   mouseEvent.layerY])) {
            var tween = new Kinetic.Tween({
                node: rect,
                duration: 0.5,
                width: 0,
                height: 0
            });
            tween.play();
            window.setTimeout(500, function() {
                rect.hide();
            });
        }
    });

    var circle = new Kinetic.Circle({
        name: 'circle',
        x: 200,
        y: 100,
        radius: 50,
        fill: 'blue',
        stroke: 'black',
        strokeWidth: 2,
        draggable: true
    });

    circle.on('dragmove', function(mouseEvent) {
        circle.moveToTop();
        if (circleMonster.intersects([mouseEvent.layerX,
                                     mouseEvent.layerY])) {
            var tween = new Kinetic.Tween({
                node: circle,
                duration: 0.5,
                radius: 0,
            });
            tween.play();
            window.setTimeout(500, function() {
                circle.hide();
            });
        }
    });

    var triangle = new Kinetic.RegularPolygon({
        name: 'triangle',
        x: 300,
        y: 100,
        radius: 52,
        sides: 3,
        fill: 'yellow',
        stroke: 'black',
        strokeWidth: 2,
        draggable: true
    });

    triangle.on('dragmove', function(mouseEvent) {
        triangle.moveToTop();
        if (triangleMonster.intersects([mouseEvent.layerX,
                                       mouseEvent.layerY])) {
            var tween = new Kinetic.Tween({
                node: triangle,
                duration: 0.5,
                radius: 0,
            });
            tween.play();
            window.setTimeout(500, function() {
                triangle.hide();
            });
        }
    });

    var monsterLayer = new Kinetic.Layer();
    monsterLayer.add(rectMonster);
    monsterLayer.add(circleMonster);
    monsterLayer.add(triangleMonster);
    stage.add(monsterLayer);

    var shapeLayer = new Kinetic.Layer();
    shapeLayer.add(rect);
    shapeLayer.add(circle);
    shapeLayer.add(triangle);
    stage.add(shapeLayer);
});

<commit_msg>Update collision detection to work with android touch.<commit_after>// Shape Monster!
// --------------
// File:   shape_monster.js
// Author: Chris Linstid <chris@linstid.com>
//
// This is a silly game that I'm building for my (as of July 2013) 17 month old
// daughter. She isn't quite ready to play it yet, but maybe by the time I get
// enough free minutes, she'll be ready.
//
// The basic premise of the game is to guide colorful shapes to the shape
// monsters that feed on them. There really is no end to the game, it's just
// for fun.

// get coordinates for the end result of a touch/click and drag
// returns an array: [x, y]
function getDragCoordinates(dragEvent) {
    var coordinates = [-1, -1];
    if (dragEvent instanceof TouchEvent) {
        coordinates[0] = dragEvent.targetNode.attrs.x;
        coordinates[1] = dragEvent.targetNode.attrs.y;
    }
    else if (dragEvent instanceof MouseEvent) {
        coordinates[0] = dragEvent.layerX;
        coordinates[1] = dragEvent.layerY;
    }
    else
    {
        return null;
    }

    return coordinates;
}

// document has loaded, let's get those shape monsters up and running
$(document).ready(function() {
    var stage = new Kinetic.Stage({
        container: 'content',
        width: 700,
        height: 700
    });

    var rectMonster = new Kinetic.Rect({
        name: 'rectMonster',
        x: 100,
        y: 300,
        width: 100,
        height: 100,
        fill: 'black',
        stroke: 'black',
        strokeWidth: 2,
    });

    var circleMonster = new Kinetic.Rect({
        name: 'circleMonster',
        x: 300,
        y: 300,
        width: 100,
        height: 100,
        fill: 'black',
        stroke: 'black',
        strokeWidth: 2,
    });

    var triangleMonster = new Kinetic.Rect({
        name: 'triangleMonster',
        x: 500,
        y: 300,
        width: 100,
        height: 100,
        fill: 'black',
        stroke: 'black',
        strokeWidth: 2,
    });

    var rect = new Kinetic.Rect({
        name: 'rect',
        x: 100,
        y: 100,
        width: 100,
        height: 100,
        fill: 'red',
        stroke: 'black',
        strokeWidth: 2,
        draggable: true
    });

    var circle = new Kinetic.Circle({
        name: 'circle',
        x: 200,
        y: 100,
        radius: 50,
        fill: 'blue',
        stroke: 'black',
        strokeWidth: 2,
        draggable: true
    });

    var triangle = new Kinetic.RegularPolygon({
        name: 'triangle',
        x: 300,
        y: 100,
        radius: 52,
        sides: 3,
        fill: 'yellow',
        stroke: 'black',
        strokeWidth: 2,
        draggable: true
    });

    var monsterLayer = new Kinetic.Layer();
    monsterLayer.add(rectMonster);
    monsterLayer.add(circleMonster);
    monsterLayer.add(triangleMonster);
    stage.add(monsterLayer);

    var shapeLayer = new Kinetic.Layer();
    shapeLayer.add(rect);
    shapeLayer.add(circle);
    shapeLayer.add(triangle);
    stage.add(shapeLayer);

    rect.on('dragmove', function(dragEvent) {
        rect.moveToTop();

        var coordinates = getDragCoordinates(dragEvent);
        if (!coordinates) {
            return;
        }
        var intersectionObject = monsterLayer.getIntersection(coordinates);
        if (intersectionObject && intersectionObject.shape === rectMonster) {
            var tween = new Kinetic.Tween({
                node: rect,
                duration: 0.5,
                width: 0,
                height: 0
            });
            rect.setDraggable(false);
            tween.play();
            window.setTimeout(500, function() {
                rect.remove();
            });
        }
    });

    circle.on('dragmove', function(dragEvent) {
        circle.moveToTop();

        var coordinates = getDragCoordinates(dragEvent);
        if (!coordinates) {
            return;
        }

        var intersectionObject = monsterLayer.getIntersection(coordinates);
        if (intersectionObject && intersectionObject.shape === circleMonster) {
            var tween = new Kinetic.Tween({
                node: circle,
                duration: 0.5,
                radius: 0,
            });
            circle.stopDrag();
            tween.play();
            window.setTimeout(500, function() {
                circle.remove();
            });
        }
    });

    triangle.on('dragmove', function(dragEvent) {
        triangle.moveToTop();

        var coordinates = getDragCoordinates(dragEvent);
        if (!coordinates) {
            return;
        }

        var intersectionObject = monsterLayer.getIntersection(coordinates);
        if (intersectionObject && intersectionObject.shape === triangleMonster) {
            var tween = new Kinetic.Tween({
                node: triangle,
                duration: 0.5,
                radius: 0,
            });
            triangle.stopDrag();
            tween.play();
            window.setTimeout(500, function() {
                triangle.remove();
            });
        }
    });

});

<|endoftext|>


<commit_before>/*
 * Copyright 2012 Igor Kalnitsky <igor@kalnitsky.org>
 *
 * This file is part of Icon Hider for Gnome Shell.
 *
 * Icon Hider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Icon Hider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Icon Hider Extension. If not, see <http://www.gnu.org/licenses/>.
 */

const Lang = imports.lang;
const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu;

const Me = imports.misc.extensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const _compat = Me.imports._compat;

const _ = imports.gettext.domain(Me.metadata['gettext-domain']).gettext;

// global consts
const EXTENSION_NAME = 'Icon Hider';
const GSETTINGS = {
    HIDDEN:             'hidden',
    KNOWN:              'known',
    IS_INDICATOR_SHOWN: 'is-indicator-shown',
    IS_USERNAME_SHOWN:  'is-username-shown'
};

/*
 * Indicator definition.
 *
 * Create item in StatusArea panel. Provide menu for manipulating
 * visiblity of other icons.
 */

function Indicator() {
    this._init.apply(this, arguments);
}

Indicator.prototype = {
    __proto__: PanelMenu.SystemStatusButton.prototype,

    /**
     * Constructor
     */
    _init: function(icon) {
        PanelMenu.SystemStatusButton.prototype._init.call(this, icon);
        Main.panel.addToStatusArea(EXTENSION_NAME, this);

        this._settings = Convenience.getSettings();
        this._createMenu();
    },

    /**
     * Create menu in top bar.
     */
    _createMenu: function() {
        let knownItems = this._settings.get_strv(GSETTINGS.KNOWN);
        let hiddenItems = this._settings.get_strv(GSETTINGS.HIDDEN);

        // create switchers list
        for each (let item in knownItems) {
            // create menu item
            let isHidden = (hiddenItems.indexOf(item) != -1);
            let menuItem = new PopupMenu.PopupSwitchMenuItem(item, !isHidden);
            this.menu.addMenuItem(menuItem);

            menuItem.statusAreaKey = item;

            // set handler
            menuItem.connect('toggled', Lang.bind(this, function (item) {
                item.state == false
                    ? this._hideItem(item)
                    : this._showItem(item);
            }));
        }

        // create service items
        this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());

        let settingsItem = new PopupMenu.PopupMenuItem(_("Settings"));
        settingsItem.connect('activate', Lang.bind(this, function() {
            var runPrefs = 'gnome-shell-extension-prefs ' + Me.metadata.uuid;
            Main.Util.trySpawnCommandLine(runPrefs);
        }));
        this.menu.addMenuItem(settingsItem);
    },

    /**
     * Hide element and mark it as hidden in settings.
     */
    _hideItem: function (item) {
        let hiddenItems = this._settings.get_strv(GSETTINGS.HIDDEN);

        if (hiddenItems.indexOf(item.statusAreaKey) == -1) {
            hiddenItems.push(item.statusAreaKey);
            this._settings.set_strv(GSETTINGS.HIDDEN, hiddenItems);
        }
    },

    /**
     * Show element and mark it as visible in settings.
     */
    _showItem: function (item) {
        let hiddenItems = this._settings.get_strv(GSETTINGS.HIDDEN);
        let index = hiddenItems.indexOf(item.statusAreaKey);

        while (index != -1) {
            hiddenItems.splice(index, 1);
            this._settings.set_strv(GSETTINGS.HIDDEN, hiddenItems);
            index = hiddenItems.indexOf(item.statusAreaKey);
        }
    }
}

/*
 * Extension definition.
 */

function Extension() {
    this._init();
}

Extension.prototype = {
    _init: function() {
        this._indicator = null;
        this._settings = Convenience.getSettings();
        this._traymanager = Main.statusIconDispatcher;

        this._statusArea = _compat.statusArea();
    },

    enable: function() {
        // load visibility
        this._hiddenIndicators = [];
        this._refreshIndicators();

        // create indicator
        this._indicator = new Indicator(_compat.indicatorIcon());

        // load utilities settings
        let isIndicatorShown = this._settings.get_boolean(GSETTINGS.IS_INDICATOR_SHOWN);
        let isUsernameShown = this._settings.get_boolean(GSETTINGS.IS_USERNAME_SHOWN);

        isIndicatorShown
            ? this._indicator.actor.show()
            : this._indicator.actor.hide();

        isUsernameShown
            ? this._statusArea.userMenu._name.show()
            : this._statusArea.userMenu._name.hide();

        // call `this._reloadSettings` if settings or tray icons was changed
        let reload = Lang.bind(this, this._reloadSettings);

        this._settingsId = this._settings.connect('changed::', reload);
        this._statusAddedId = this._traymanager.connect('status-icon-added', reload);
        this._statusRemovedId = this._traymanager.connect('status-icon-removed', reload);
    },

    /**
     * Clean-up:
     *   - restore icons' visibility
     *   - disconnect settings signal
     *   - destroy indicator
     */
    disable: function() {
        // restore visibility
        let hiddenItems = this._settings.get_strv(GSETTINGS.HIDDEN);
        for each (let item in hiddenItems)
            if (item in this._statusArea)
                this._statusArea[item].actor.show();

        this._indicator.destroy();
        this._indicator = null;

        this._settings.disconnect(this._settingsId);
        this._traymanager.disconnect(this._statusAddedId);
        this._traymanager.disconnect(this._statusRemovedId);

        // disconnect per-actor handlers
        for each (let value in this._hiddenIndicators)
        {
            let item = value['item'];
            let id = value['id'];

            this._statusArea[item].actor.disconnect(id);
        }
    },

    /**
     * This function is called when settings are changed.
     */
    _reloadSettings: function() {
        this.disable();
        this.enable();
    },

    _refreshIndicators: function() {
        // load visibility
        let hiddenItems = this._settings.get_strv(GSETTINGS.HIDDEN);
        let knownItems = this._settings.get_strv(GSETTINGS.KNOWN);

        let isKnownItemsChanged = false;
        for (let item in this._statusArea) {
            if (item === EXTENSION_NAME)
                continue;

            // add to known icons (used by prefs.js and indicator)
            if (knownItems.indexOf(item) == -1) {
                knownItems.push(item);
                isKnownItemsChanged = true;
            }

            // set icon visibility
            hiddenItems.indexOf(item) != -1
                ? this._statusArea[item].actor.hide()
                : this._statusArea[item].actor.show();

            if (hiddenItems.indexOf(item) != -1)
            {
                let id = this._statusArea[item].actor.connect('notify::visible',
                    Lang.bind(this, function(actor) {
                        actor.hide();
                    }
                ));

                this._hiddenIndicators.push({
                    'item': item,
                    'id': id
                });
            }
        }

        if (isKnownItemsChanged)
            this._settings.set_strv(GSETTINGS.KNOWN, knownItems);
    }
};

/**
 * Entry point.
 *
 * Should return an object with callable `enable` and `disable` properties.
 */
function init() {
    Convenience.initTranslations();
    return new Extension();
}
<commit_msg>Fixed bug with incorrect message in GnomeSHell 3.6<commit_after>/*
 * Copyright 2012 Igor Kalnitsky <igor@kalnitsky.org>
 *
 * This file is part of Icon Hider for Gnome Shell.
 *
 * Icon Hider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Icon Hider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Icon Hider Extension. If not, see <http://www.gnu.org/licenses/>.
 */

const Lang = imports.lang;
const Main = imports.ui.main;
const Shell = imports.gi.Shell;
const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu;

// extension-level modules
const Me = imports.misc.extensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const _compat = Me.imports._compat;

// gettext alias
const _ = imports.gettext.domain(Me.metadata['gettext-domain']).gettext;

// global consts
const EXTENSION_NAME = 'Icon Hider';
const GSETTINGS = {
    HIDDEN:             'hidden',
    KNOWN:              'known',
    IS_INDICATOR_SHOWN: 'is-indicator-shown',
    IS_USERNAME_SHOWN:  'is-username-shown'
};

/*
 * Indicator definition.
 *
 * Create item in StatusArea panel. Provide menu for manipulating
 * visiblity of other icons.
 */

function Indicator() {
    this._init.apply(this, arguments);
}

Indicator.prototype = {
    __proto__: PanelMenu.SystemStatusButton.prototype,

    /**
     * Constructor
     */
    _init: function(icon) {
        PanelMenu.SystemStatusButton.prototype._init.call(this, icon);
        Main.panel.addToStatusArea(EXTENSION_NAME, this);

        this._settings = Convenience.getSettings();
        this._createMenu();
    },

    /**
     * Create menu in top bar.
     */
    _createMenu: function() {
        let knownItems = this._settings.get_strv(GSETTINGS.KNOWN);
        let hiddenItems = this._settings.get_strv(GSETTINGS.HIDDEN);

        // create switchers list
        for each (let item in knownItems) {
            // create menu item
            let isHidden = (hiddenItems.indexOf(item) != -1);
            let menuItem = new PopupMenu.PopupSwitchMenuItem(item, !isHidden);
            this.menu.addMenuItem(menuItem);

            menuItem.statusAreaKey = item;

            // set handler
            menuItem.connect('toggled', Lang.bind(this, function (item) {
                item.state == false
                    ? this._hideItem(item)
                    : this._showItem(item);
            }));
        }

        // create service items
        this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());

        let settingsItem = new PopupMenu.PopupMenuItem(_("Settings"));
        settingsItem.connect('activate', Lang.bind(this, function() {
            var runPrefs = 'gnome-shell-extension-prefs ' + Me.metadata.uuid;
            Main.Util.trySpawnCommandLine(runPrefs);
        }));
        this.menu.addMenuItem(settingsItem);
    },

    /**
     * Hide element and mark it as hidden in settings.
     */
    _hideItem: function (item) {
        let hiddenItems = this._settings.get_strv(GSETTINGS.HIDDEN);

        if (hiddenItems.indexOf(item.statusAreaKey) == -1) {
            hiddenItems.push(item.statusAreaKey);
            this._settings.set_strv(GSETTINGS.HIDDEN, hiddenItems);
        }
    },

    /**
     * Show element and mark it as visible in settings.
     */
    _showItem: function (item) {
        let hiddenItems = this._settings.get_strv(GSETTINGS.HIDDEN);
        let index = hiddenItems.indexOf(item.statusAreaKey);

        while (index != -1) {
            hiddenItems.splice(index, 1);
            this._settings.set_strv(GSETTINGS.HIDDEN, hiddenItems);
            index = hiddenItems.indexOf(item.statusAreaKey);
        }
    }
}

/*
 * Extension definition.
 */

function Extension() {
    this._init();
}

Extension.prototype = {
    _init: function() {
        this._indicator = null;
        this._settings = Convenience.getSettings();

        this._traymanager = new Shell.TrayManager();
        this._traymanager.manage_stage(global.stage, Main.messageTray.actor);

        this._statusArea = _compat.statusArea();
    },

    enable: function() {
        // load visibility
        this._hiddenIndicators = [];
        this._refreshIndicators();

        // create indicator
        this._indicator = new Indicator(_compat.indicatorIcon());

        // load utilities settings
        let isIndicatorShown = this._settings.get_boolean(GSETTINGS.IS_INDICATOR_SHOWN);
        let isUsernameShown = this._settings.get_boolean(GSETTINGS.IS_USERNAME_SHOWN);

        isIndicatorShown
            ? this._indicator.actor.show()
            : this._indicator.actor.hide();

        isUsernameShown
            ? this._statusArea.userMenu._name.show()
            : this._statusArea.userMenu._name.hide();

        // call `this._reloadSettings` if settings or tray icons was changed
        let reload = Lang.bind(this, this._reloadSettings);

        this._settingsId = this._settings.connect('changed::', reload);
        this._trayAddedId = this._traymanager.connect('tray-icon-added', reload);
        this._trayRemovedId = this._traymanager.connect('tray-icon-removed', reload);
    },

    /**
     * Clean-up:
     *   - restore icons' visibility
     *   - disconnect settings signal
     *   - destroy indicator
     */
    disable: function() {
        // restore visibility
        let hiddenItems = this._settings.get_strv(GSETTINGS.HIDDEN);
        for each (let item in hiddenItems)
            if (item in this._statusArea)
                this._statusArea[item].actor.show();

        this._indicator.destroy();
        this._indicator = null;

        this._settings.disconnect(this._settingsId);
        this._traymanager.disconnect(this._trayAddedId);
        this._traymanager.disconnect(this._trayRemovedId);

        // disconnect per-actor handlers
        for each (let value in this._hiddenIndicators)
        {
            let item = value['item'];
            let id = value['id'];

            this._statusArea[item].actor.disconnect(id);
        }
    },

    /**
     * This function is called when settings are changed.
     */
    _reloadSettings: function() {
        this.disable();
        this.enable();
    },

    _refreshIndicators: function() {
        // load visibility
        let hiddenItems = this._settings.get_strv(GSETTINGS.HIDDEN);
        let knownItems = this._settings.get_strv(GSETTINGS.KNOWN);

        let isKnownItemsChanged = false;
        for (let item in this._statusArea) {
            if (item === EXTENSION_NAME)
                continue;

            // add to known icons (used by prefs.js and indicator)
            if (knownItems.indexOf(item) == -1) {
                knownItems.push(item);
                isKnownItemsChanged = true;
            }

            // set icon visibility
            hiddenItems.indexOf(item) != -1
                ? this._statusArea[item].actor.hide()
                : this._statusArea[item].actor.show();

            if (hiddenItems.indexOf(item) != -1)
            {
                let id = this._statusArea[item].actor.connect('notify::visible',
                    Lang.bind(this, function(actor) {
                        actor.hide();
                    }
                ));

                this._hiddenIndicators.push({
                    'item': item,
                    'id': id
                });
            }
        }

        if (isKnownItemsChanged)
            this._settings.set_strv(GSETTINGS.KNOWN, knownItems);
    }
};

/**
 * Entry point.
 *
 * Should return an object with callable `enable` and `disable` properties.
 */
function init() {
    Convenience.initTranslations();
    return new Extension();
}
<|endoftext|>


<commit_before>/**
 *
 * A very simple XMLHttpRequest-Interface
 *
 * @class xhr
 */
(function(){
	xhr = {
		/**
		 * Make a HTTP-Get-Request
		 *
		 * @method get
		 * @param {String} url
		 * @param {Function} success-callback
		 * @param {Function} error-callback
		 * @param additional_args
		 */
		get : function(url, success, error, additional_args){
			var xhr = new XMLHttpRequest();
			xhr.open('GET', url, true);
			xhr.onreadystatechange = function () {
				if (xhr.readyState === 4) {
					if(xhr.status === 200){
						success(xhr.responseText, additional_args);
					} else if (xhr.status === 0) {
						success(xhr.responseText, additional_args);
					} else if(typeof error === "function"){
						error(xhr.responseText, additional_args);
					}
				}
			};
			xhr.send(null);
		},
		/**
		 * Get JSON-Data from a server
		 *
		 * Just a wrapper for xhr.get, but tries to optain JSON
		 *
		 * @method getJSON
		 * @param {String} url
		 * @param {Function} success-callback
		 * @param {Function} error-callback
		 * @param additional_args
		 */
		getJSON : function(url, success, error, additional_args){
			this.get(url, function(resp, additional_args){
				success(JSON.parse(resp), additional_args);
			}, error);
		}
	};
})();
<commit_msg>xhr: add fixes for IE8<commit_after>/**
 *
 * A very simple XMLHttpRequest-Interface
 *
 * @class xhr
 */
(function(){
	// http://www.html5rocks.com/en/tutorials/cors/
	function createCORSRequest(method, url) {
		var xhr = new XMLHttpRequest();
		if ("withCredentials" in xhr) {
			// Check if the XMLHttpRequest object has a "withCredentials" property.
			// "withCredentials" only exists on XMLHTTPRequest2 objects.
			xhr.open(method, url, true);
		} else if (typeof XDomainRequest !== "undefined") {
			// Otherwise, check if XDomainRequest.
			// XDomainRequest only exists in IE, and is IE's way of making CORS requests.
			xhr = new XDomainRequest();
			xhr.open(method, url);
		} else {
			// Otherwise, CORS is not supported by the browser.
			xhr = null;
		}
		return xhr;
	}

	xhr = {
		/**
		 * Make a HTTP-Get-Request
		 *
		 * @method get
		 * @param {String} url
		 * @param {Function} success-callback
		 * @param {Function} error-callback
		 * @param additional_args
		 */
		get : function(url, success, error, additional_args){
			var xhr = createCORSRequest("GET", url);
			xhr.onload = function() {
				success(xhr.responseText, additional_args);
			};
			xhr.send(null);
		},
		/**
		 * Get JSON-Data from a server
		 *
		 * Just a wrapper for xhr.get, but tries to optain JSON
		 *
		 * @method getJSON
		 * @param {String} url
		 * @param {Function} success-callback
		 * @param {Function} error-callback
		 * @param additional_args
		 */
		getJSON : function(url, success, error, additional_args){
			this.get(url, function(resp, additional_args){
				success(JSON.parse(resp), additional_args);
			}, error);
		}
	};
})();
<|endoftext|>