<commit_before>/*
	This file is part of cdauth’s map.

	OSM Route Manager is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cdauth’s map 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 Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with cdauth’s map.  If not, see <http://www.gnu.org/licenses/>.

	Obtain the source code from http://svn.cdauth.de/viewvc.cgi/Tools/osm/map/
	or svn://svn.cdauth.de/tools/osm/map/.
*/

var map;
var layerMarkers;
var layerResults;
var lastHash;
var newLocationHash;
var icon;
var iconHighlight;
var lastSearch;
var lastSearchLayer;

function initMap()
{
	if(location.search.length > 1)
	{ // Move query string to location hash part
		var search_obj = decodeQueryString(location.search.substr(1));
		var hash_obj = decodeQueryString(getLocationHash().substr(1));
		for(var i in search_obj)
			hash_obj[i] = search_obj[i];
		location.replace(location.pathname+"#"+encodeQueryString(hash_obj));
		return;
	}

	var form_el = document.createElement("form");
	form_el.method = "get";
	form_el.action = "";
	form_el.id = "search";
	form_el.onsubmit = function(){ geoSearch(); return false; };
	var el1,el2,el3;
	el1 = document.createElement("dl");
	el2 = document.createElement("dt");
	el3 = document.createElement("label");
	el3.htmlFor = "search-input";
	el3.appendChild(document.createTextNode(OpenLayers.i18n("Search")));
	el2.appendChild(el3);
	el1.appendChild(el2);
	el2 = document.createElement("dd");
	el3 = document.createElement("input");
	el3.type = "text";
	el3.id = "search-input";
	el3.name = "search";
	el3.title = OpenLayers.i18n("Enter a search string, a URL of a GPX, KML, OSM or GML file or an OSM object like “node 123” or “trace 123”.");
	el2.appendChild(el3);
	el1.appendChild(el2);
	form_el.appendChild(el1);

	el1 = document.createElement("ul");
	el2 = document.createElement("li");
	el3 = document.createElement("input");
	el3.type = "submit";
	el3.id = "search-button";
	el3.value = OpenLayers.i18n("Search");
	el2.appendChild(el3);
	el1.appendChild(el2);
	el2 = document.createElement("li");
	el3 = document.createElement("input");
	el3.type = "button";
	el3.id = "search-button-reset";
	el3.onclick = function(){ document.getElementById("search-input").value = ""; this.form.onsubmit(); return false; };
	el3.value = OpenLayers.i18n("Clear");
	el2.appendChild(el3);
	el1.appendChild(el2);
	form_el.appendChild(el1);

	el1 = document.createElement("p");
	el1.id = "search-osm-cc";
	el1.innerHTML = OpenLayers.i18n("Search results from OpenStreetMap, cc-by-sa-2.0");
	form_el.appendChild(el1);

	domInsertAfter(form_el, document.getElementById("map"));

	OpenLayers.Layer.cdauth.XML.proxy = "gpx.php";
	map = new OpenLayers.Map.cdauth("map", { cdauthTheme : null });

	icon = new OpenLayers.Icon('marker.png', new OpenLayers.Size(21,25), new OpenLayers.Pixel(-9, -25));
	iconHighlight = new OpenLayers.Icon('marker-green.png', new OpenLayers.Size(21,25), new OpenLayers.Pixel(-9, -25));

	map.addAllAvailableLayers();

	var activeTool = null;
	var cookies = document.cookie.split(/;\s*/);
	for(var i=0; i<cookies.length; i++)
	{
		var cookie = cookies[i].split("=");
		if(cookie[0] == "cdauthTool")
		{
			activeTool = decodeURIComponent(cookie[1]);
			break;
		}
	}

	var toolbar = new OpenLayers.Control.Panel();
	var moveControl = new OpenLayers.Control({ title : OpenLayers.i18n("Move map") });
	map.addControl(moveControl);
	toolbar.addControls(moveControl);
	toolbar.defaultControl = moveControl;

	var osb = new OpenLayers.Layer.OpenStreetBugs(OpenLayers.i18n("OpenStreetBugs"), { visibility: false, theme: null, shortName: "OSBu" });
	map.addLayer(osb);

	var osbControl = new OpenLayers.Control.OpenStreetBugs(osb);
	map.addControl(osbControl);
	toolbar.addControls(osbControl);

	layerMarkers = new OpenLayers.Layer.cdauth.Markers.LonLat(OpenLayers.i18n("Markers"), { shortName : "m" });
	map.addLayer(layerMarkers);
	var markerControl = new OpenLayers.Control.cdauth.CreateMarker(layerMarkers);
	map.addControl(markerControl);
	toolbar.addControls(markerControl);

	map.addControl(toolbar);
	if(activeTool)
	{
		for(var i=0; i<toolbar.controls.length; i++)
		{
			if(toolbar.controls[i].title == activeTool)
			{
				toolbar.activateControl(toolbar.controls[i]);
				break;
			}
		}
	}

	toolbar.activateControl = function(control) {
		var ret = OpenLayers.Control.Panel.prototype.activateControl.apply(this, arguments);

		document.cookie = "cdauthTool="+encodeURIComponent(control.title)+";expires="+(new Date((new Date()).getTime() + 86400000000)).toGMTString();
		return ret;
	};

	layerResults = new OpenLayers.Layer.cdauth.Markers.GeoSearch(OpenLayers.i18n("Search results"), { nameFinderURL : "namefinder.php", nameFinder2URL : "namefinder2.php", shortName : "s" });
	map.addLayer(layerResults);

	var hashHandler = new OpenLayers.Control.cdauth.URLHashHandler({
		updateMapView : function() {
			var query_object = decodeQueryString(this.getLocationHash());
			if(query_object.search == "%s")
				delete query_object.search;
			if(typeof query_object.search == "object" && query_object.search.s == "%s")
				delete query_object.search.s;
			if(typeof query_object.search != "undefined" && (typeof query_object.search != "object" || typeof query_object.search.s != "undefined"))
			{
				document.getElementById("search-input").value = (typeof query_object.search == "object" ? query_object.search.s : query_object.search);
				var gpx_layer = geoSearch(true, (typeof query_object.lon != "undefined" && typeof query_object.lat != "undefined"));
				if(gpx_layer)
				{
					delete query_object.search;
					var i=0;
					if(query_object.xml)
					{
						while(typeof query_object.xml[i] != "undefined")
							i++;
					}
					else
						query_object.xml = { };
					query_object.xml[i] = gpx_layer.cdauthURL;
				}
			}
			this.map.zoomToQuery(query_object);
			this.updateLocationHash();
		}
	});
	map.addControl(hashHandler);
	hashHandler.activate();

	map.addControl(new OpenLayers.Control.cdauth.GeoLocation());

	layerResults.events.register("searchBegin", map, function(){
		document.getElementById("search-input").disabled = document.getElementById("search-button").disabled = document.getElementById("search-button-reset").disabled = true;
	});
	layerResults.events.register("searchSuccess", map, function(){
		document.getElementById("search-input").disabled = document.getElementById("search-button").disabled = document.getElementById("search-button-reset").disabled = false;
	});
	layerResults.events.register("searchFailure", map, function(){
		document.getElementById("search-input").disabled = document.getElementById("search-button").disabled = document.getElementById("search-button-reset").disabled = false;
	});
}

function geoSearch(onlygpx, dontzoomgpx)
{
	var search = document.getElementById("search-input").value;

	var gpx = false;
	if(search.match(/^http:\/\//) && !search.match(/^http:\/\/(www\.)?osm\.org\/go\//))
	{
		var m;
		if(m = search.match(/[#?](.*)$/))
		{
			var query_string = decodeQueryString(m[1]);
			if(typeof query_string.lon == "undefined" || typeof query_string.lat == "undefined")
				gpx = true;
		}
		else
			gpx = true;
	}
	else
	{
		var m = search.match(/^(node|way|relation|trace)\s*#?\s*(\d+)$/i);
		if(m)
		{
			gpx = true;
			switch(m[1].toLowerCase())
			{
				case "node": search = "http://www.openstreetmap.org/api/0.6/node/"+m[2]; break;
				case "way": search = "http://www.openstreetmap.org/api/0.6/way/"+m[2]+"/full"; break;
				case "relation": search = "http://www.openstreetmap.org/api/0.6/relation/"+m[2]+"/full"; break;
				case "trace": search = "http://www.openstreetmap.org/trace/"+m[2]+"/data"; break;
			}
		}
	}

	if(gpx)
	{
		layerResults.geoSearch("");

		document.getElementById("search-input").disabled = document.getElementById("search-button").disabled = document.getElementById("search-button-reset").disabled = true;
		var layer = new OpenLayers.Layer.cdauth.XML(null, search, { removableInLayerSwitcher: true });
		map.addLayer(layer);
		layer.events.register("loadend", layer, function() {
			if(!dontzoomgpx)
			{
				var extent = this.getDataExtent();
				if(extent)
					map.zoomToExtent(extent);
			}
			document.getElementById("search-input").disabled = document.getElementById("search-button").disabled = document.getElementById("search-button-reset").disabled = false;
		});
		return layer;
	}
	else if(!onlygpx)
		layerResults.geoSearch(search);

	return false;
}

OpenLayers.Lang.en = OpenLayers.Util.extend(OpenLayers.Lang.en, {
	"Move map" : "Move map",
	"Search" : "Search",
	"Enter a search string, a URL of a GPX, KML, OSM or GML file or an OSM object like “node 123” or “trace 123”." : "Enter a search string, a URL of a GPX, KML, OSM or GML file or an OSM object like “node 123” or “trace 123”.",
	"Clear" : "Clear",
	"Search results from OpenStreetMap, cc-by-sa-2.0" : "Search results from OpenStreetMap, cc-by-sa-2.0",
	"OpenStreetBugs" : "OpenStreetBugs",
	"Markers" : "Markers",
	"Search results" : "Search results"
});

OpenLayers.Lang.de = OpenLayers.Util.extend(OpenLayers.Lang.de, {
	"Move map" : "Karte verschieben",
	"Search" : "Suchen",
	"Enter a search string, a URL of a GPX, KML, OSM or GML file or an OSM object like “node 123” or “trace 123”." : "Ein Suchbegriff, eine URL einer GPX-, KML- OSM- oder GML-Datei oder ein OSM-Objekt wie „node 123“, „way 123“, „relation 123“ oder „trace 123“",
	"Clear" : "Löschen",
	"Search results from OpenStreetMap, cc-by-sa-2.0" : "Suchergebnisse aus OpenStreetMap, cc-by-sa-2.0",
	"OpenStreetBugs" : "OpenStreetBugs",
	"Markers" : "Marker",
	"Search results" : "Suchergebnisse"
});<commit_msg>Run updateMapView() on activate() only if a Permalink is set.<commit_after>/*
	This file is part of cdauth’s map.

	OSM Route Manager is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cdauth’s map 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 Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with cdauth’s map.  If not, see <http://www.gnu.org/licenses/>.

	Obtain the source code from http://svn.cdauth.de/viewvc.cgi/Tools/osm/map/
	or svn://svn.cdauth.de/tools/osm/map/.
*/

var map;
var layerMarkers;
var layerResults;
var lastHash;
var newLocationHash;
var icon;
var iconHighlight;
var lastSearch;
var lastSearchLayer;

function initMap()
{
	if(location.search.length > 1)
	{ // Move query string to location hash part
		var search_obj = decodeQueryString(location.search.substr(1));
		var hash_obj = decodeQueryString(getLocationHash().substr(1));
		for(var i in search_obj)
			hash_obj[i] = search_obj[i];
		location.replace(location.pathname+"#"+encodeQueryString(hash_obj));
		return;
	}

	var form_el = document.createElement("form");
	form_el.method = "get";
	form_el.action = "";
	form_el.id = "search";
	form_el.onsubmit = function(){ geoSearch(); return false; };
	var el1,el2,el3;
	el1 = document.createElement("dl");
	el2 = document.createElement("dt");
	el3 = document.createElement("label");
	el3.htmlFor = "search-input";
	el3.appendChild(document.createTextNode(OpenLayers.i18n("Search")));
	el2.appendChild(el3);
	el1.appendChild(el2);
	el2 = document.createElement("dd");
	el3 = document.createElement("input");
	el3.type = "text";
	el3.id = "search-input";
	el3.name = "search";
	el3.title = OpenLayers.i18n("Enter a search string, a URL of a GPX, KML, OSM or GML file or an OSM object like “node 123” or “trace 123”.");
	el2.appendChild(el3);
	el1.appendChild(el2);
	form_el.appendChild(el1);

	el1 = document.createElement("ul");
	el2 = document.createElement("li");
	el3 = document.createElement("input");
	el3.type = "submit";
	el3.id = "search-button";
	el3.value = OpenLayers.i18n("Search");
	el2.appendChild(el3);
	el1.appendChild(el2);
	el2 = document.createElement("li");
	el3 = document.createElement("input");
	el3.type = "button";
	el3.id = "search-button-reset";
	el3.onclick = function(){ document.getElementById("search-input").value = ""; this.form.onsubmit(); return false; };
	el3.value = OpenLayers.i18n("Clear");
	el2.appendChild(el3);
	el1.appendChild(el2);
	form_el.appendChild(el1);

	el1 = document.createElement("p");
	el1.id = "search-osm-cc";
	el1.innerHTML = OpenLayers.i18n("Search results from OpenStreetMap, cc-by-sa-2.0");
	form_el.appendChild(el1);

	domInsertAfter(form_el, document.getElementById("map"));

	OpenLayers.Layer.cdauth.XML.proxy = "gpx.php";
	map = new OpenLayers.Map.cdauth("map", { cdauthTheme : null });

	icon = new OpenLayers.Icon('marker.png', new OpenLayers.Size(21,25), new OpenLayers.Pixel(-9, -25));
	iconHighlight = new OpenLayers.Icon('marker-green.png', new OpenLayers.Size(21,25), new OpenLayers.Pixel(-9, -25));

	map.addAllAvailableLayers();

	var activeTool = null;
	var cookies = document.cookie.split(/;\s*/);
	for(var i=0; i<cookies.length; i++)
	{
		var cookie = cookies[i].split("=");
		if(cookie[0] == "cdauthTool")
		{
			activeTool = decodeURIComponent(cookie[1]);
			break;
		}
	}

	var toolbar = new OpenLayers.Control.Panel();
	var moveControl = new OpenLayers.Control({ title : OpenLayers.i18n("Move map") });
	map.addControl(moveControl);
	toolbar.addControls(moveControl);
	toolbar.defaultControl = moveControl;

	var osb = new OpenLayers.Layer.OpenStreetBugs(OpenLayers.i18n("OpenStreetBugs"), { visibility: false, theme: null, shortName: "OSBu" });
	map.addLayer(osb);

	var osbControl = new OpenLayers.Control.OpenStreetBugs(osb);
	map.addControl(osbControl);
	toolbar.addControls(osbControl);

	layerMarkers = new OpenLayers.Layer.cdauth.Markers.LonLat(OpenLayers.i18n("Markers"), { shortName : "m" });
	map.addLayer(layerMarkers);
	var markerControl = new OpenLayers.Control.cdauth.CreateMarker(layerMarkers);
	map.addControl(markerControl);
	toolbar.addControls(markerControl);

	map.addControl(toolbar);
	if(activeTool)
	{
		for(var i=0; i<toolbar.controls.length; i++)
		{
			if(toolbar.controls[i].title == activeTool)
			{
				toolbar.activateControl(toolbar.controls[i]);
				break;
			}
		}
	}

	toolbar.activateControl = function(control) {
		var ret = OpenLayers.Control.Panel.prototype.activateControl.apply(this, arguments);

		document.cookie = "cdauthTool="+encodeURIComponent(control.title)+";expires="+(new Date((new Date()).getTime() + 86400000000)).toGMTString();
		return ret;
	};

	layerResults = new OpenLayers.Layer.cdauth.Markers.GeoSearch(OpenLayers.i18n("Search results"), { nameFinderURL : "namefinder.php", nameFinder2URL : "namefinder2.php", shortName : "s" });
	map.addLayer(layerResults);

	var hashHandler = new OpenLayers.Control.cdauth.URLHashHandler({
		updateMapView : function() {
			var query_object = decodeQueryString(this.getLocationHash());
			if(query_object.search == "%s")
				delete query_object.search;
			if(typeof query_object.search == "object" && query_object.search.s == "%s")
				delete query_object.search.s;
			if(typeof query_object.search != "undefined" && (typeof query_object.search != "object" || typeof query_object.search.s != "undefined"))
			{
				document.getElementById("search-input").value = (typeof query_object.search == "object" ? query_object.search.s : query_object.search);
				var gpx_layer = geoSearch(true, (typeof query_object.lon != "undefined" && typeof query_object.lat != "undefined"));
				if(gpx_layer)
				{
					delete query_object.search;
					var i=0;
					if(query_object.xml)
					{
						while(typeof query_object.xml[i] != "undefined")
							i++;
					}
					else
						query_object.xml = { };
					query_object.xml[i] = gpx_layer.cdauthURL;
				}
			}
			this.map.zoomToQuery(query_object);
			this.updateLocationHash();
		}
	});
	map.addControl(hashHandler);
	hashHandler.activate();
	hashHandler.updateMapView();

	map.addControl(new OpenLayers.Control.cdauth.GeoLocation());

	layerResults.events.register("searchBegin", map, function(){
		document.getElementById("search-input").disabled = document.getElementById("search-button").disabled = document.getElementById("search-button-reset").disabled = true;
	});
	layerResults.events.register("searchSuccess", map, function(){
		document.getElementById("search-input").disabled = document.getElementById("search-button").disabled = document.getElementById("search-button-reset").disabled = false;
	});
	layerResults.events.register("searchFailure", map, function(){
		document.getElementById("search-input").disabled = document.getElementById("search-button").disabled = document.getElementById("search-button-reset").disabled = false;
	});
}

function geoSearch(onlygpx, dontzoomgpx)
{
	var search = document.getElementById("search-input").value;

	var gpx = false;
	if(search.match(/^http:\/\//) && !search.match(/^http:\/\/(www\.)?osm\.org\/go\//))
	{
		var m;
		if(m = search.match(/[#?](.*)$/))
		{
			var query_string = decodeQueryString(m[1]);
			if(typeof query_string.lon == "undefined" || typeof query_string.lat == "undefined")
				gpx = true;
		}
		else
			gpx = true;
	}
	else
	{
		var m = search.match(/^(node|way|relation|trace)\s*#?\s*(\d+)$/i);
		if(m)
		{
			gpx = true;
			switch(m[1].toLowerCase())
			{
				case "node": search = "http://www.openstreetmap.org/api/0.6/node/"+m[2]; break;
				case "way": search = "http://www.openstreetmap.org/api/0.6/way/"+m[2]+"/full"; break;
				case "relation": search = "http://www.openstreetmap.org/api/0.6/relation/"+m[2]+"/full"; break;
				case "trace": search = "http://www.openstreetmap.org/trace/"+m[2]+"/data"; break;
			}
		}
	}

	if(gpx)
	{
		layerResults.geoSearch("");

		document.getElementById("search-input").disabled = document.getElementById("search-button").disabled = document.getElementById("search-button-reset").disabled = true;
		var layer = new OpenLayers.Layer.cdauth.XML(null, search, { removableInLayerSwitcher: true });
		map.addLayer(layer);
		layer.events.register("loadend", layer, function() {
			if(!dontzoomgpx)
			{
				var extent = this.getDataExtent();
				if(extent)
					map.zoomToExtent(extent);
			}
			document.getElementById("search-input").disabled = document.getElementById("search-button").disabled = document.getElementById("search-button-reset").disabled = false;
		});
		return layer;
	}
	else if(!onlygpx)
		layerResults.geoSearch(search);

	return false;
}

OpenLayers.Lang.en = OpenLayers.Util.extend(OpenLayers.Lang.en, {
	"Move map" : "Move map",
	"Search" : "Search",
	"Enter a search string, a URL of a GPX, KML, OSM or GML file or an OSM object like “node 123” or “trace 123”." : "Enter a search string, a URL of a GPX, KML, OSM or GML file or an OSM object like “node 123” or “trace 123”.",
	"Clear" : "Clear",
	"Search results from OpenStreetMap, cc-by-sa-2.0" : "Search results from OpenStreetMap, cc-by-sa-2.0",
	"OpenStreetBugs" : "OpenStreetBugs",
	"Markers" : "Markers",
	"Search results" : "Search results"
});

OpenLayers.Lang.de = OpenLayers.Util.extend(OpenLayers.Lang.de, {
	"Move map" : "Karte verschieben",
	"Search" : "Suchen",
	"Enter a search string, a URL of a GPX, KML, OSM or GML file or an OSM object like “node 123” or “trace 123”." : "Ein Suchbegriff, eine URL einer GPX-, KML- OSM- oder GML-Datei oder ein OSM-Objekt wie „node 123“, „way 123“, „relation 123“ oder „trace 123“",
	"Clear" : "Löschen",
	"Search results from OpenStreetMap, cc-by-sa-2.0" : "Suchergebnisse aus OpenStreetMap, cc-by-sa-2.0",
	"OpenStreetBugs" : "OpenStreetBugs",
	"Markers" : "Marker",
	"Search results" : "Suchergebnisse"
});<|endoftext|>


<commit_before>// ;; #path=Mappable #kind=interface
// There are various things that positions can be mapped through.
// We'll denote those as 'mappable'. This is not an actual class in
// the codebase, only an agreed-on interface.

// :: (pos: number, bias: ?number) → number #path=Mappable.map
// Map a position through this object. When given, `bias` (should be
// -1 or 1) determines in which direction to move when a chunk of
// content is inserted at or around the mapped position.

// :: (pos: number, bias: ?number) → MapResult #path=Mappable.mapResult
// Map a position, and return an object containing additional
// information about the mapping. The result's `deleted` field tells
// you whether the position was deleted (completely enclosed in a
// replaced range) during the mapping.

// Recovery values encode a range index and an offset. They are
// represented as numbers, because tons of them will be created when
// mapping, for example, a large number of marked ranges. The number's
// lower 16 bits provide the index, the remaining bits the offset.
//
// Note: We intentionally don't use bit shift operators to en- and
// decode these, since those clip to 32 bits, which we might in rare
// cases want to overflow. A 64-bit float can represent 48-bit
// integers precisely.

const lower16 = 0xffff
const factor16 = Math.pow(2, 16)

function makeRecover(index, offset) { return index + offset * factor16 }
function recoverIndex(value) { return value & lower16 }
function recoverOffset(value) { return (value - (value & lower16)) / factor16 }

// ;; An object representing a mapped position with some extra
// information.
class MapResult {
  constructor(pos, deleted = false, recover = null) {
    // :: number The mapped version of the position.
    this.pos = pos
    // :: bool Tells you whether the position was deleted, that is,
    // whether the step removed its surroundings from the document.
    this.deleted = deleted
    this.recover = recover
  }
}
exports.MapResult = MapResult

// ;; A position map, holding information about the way positions in
// the pre-step version of a document correspond to positions in the
// post-step version. This class implements `Mappable`.
class PosMap {
  // :: ([number])
  // Create a position map. The modifications to the document are
  // represented as an array of numbers, in which each group of three
  // represents a modified chunk as `[start, oldSize, newSize]`.
  constructor(ranges, inverted = false) {
    this.ranges = ranges
    this.inverted = inverted
  }

  recover(value) {
    let diff = 0, index = recoverIndex(value)
    if (!this.inverted) for (let i = 0; i < index; i++)
      diff += this.ranges[i * 3 + 2] - this.ranges[i * 3 + 1]
    return this.ranges[index * 3] + diff + recoverOffset(value)
  }

  // :: (number, ?number) → MapResult
  // Map the given position through this map. The `bias` parameter can
  // be used to control what happens when the transform inserted
  // content at (or around) this position—if `bias` is negative, the a
  // position before the inserted content will be returned, if it is
  // positive, a position after the insertion is returned.
  mapResult(pos, bias) { return this._map(pos, bias, false) }

  // :: (number, ?number) → number
  // Map the given position through this map, returning only the
  // mapped position.
  map(pos, bias) { return this._map(pos, bias, true) }

  _map(pos, bias, simple) {
    let diff = 0, oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2
    for (let i = 0; i < this.ranges.length; i += 3) {
      let start = this.ranges[i] - (this.inverted ? diff : 0)
      if (start > pos) break
      let oldSize = this.ranges[i + oldIndex], newSize = this.ranges[i + newIndex], end = start + oldSize
      if (pos <= end) {
        let side = !oldSize ? bias : pos == start ? -1 : pos == end ? 1 : bias
        let result = start + diff + (side < 0 ? 0 : newSize)
        if (simple) return result
        let recover = makeRecover(i / 3, pos - start)
        return new MapResult(result, pos != start && pos != end, recover)
      }
      diff += newSize - oldSize
    }
    return simple ? pos + diff : new MapResult(pos + diff)
  }

  touches(pos, recover) {
    let diff = 0, index = recoverIndex(recover)
    let oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2
    for (let i = 0; i < this.ranges.length; i += 3) {
      let start = this.ranges[i] - (this.inverted ? diff : 0)
      if (start > pos) break
      let oldSize = this.ranges[i + oldIndex], end = start + oldSize
      if (pos <= end && i == index * 3) return true
      diff += this.ranges[i + newIndex] - oldSize
    }
    return false
  }

  // :: () → PosMap
  // Create an inverted version of this map. The result can be used to
  // map positions in the post-step document to the pre-step document.
  invert() {
    return new PosMap(this.ranges, !this.inverted)
  }

  toString() {
    return (this.inverted ? "-" : "") + JSON.stringify(this.ranges)
  }
}
exports.PosMap = PosMap

PosMap.empty = new PosMap([])

// ;; A remapping represents a pipeline of zero or more mappings. It
// is a specialized data structured used to manage mapping through a
// series of steps, typically including inverted and non-inverted
// versions of the same step. (This comes up when ‘rebasing’ steps for
// collaboration or history management.) This class implements
// `Mappable`.
class Remapping {
  // :: (?[PosMap], ?number)
  // Create a new remapping with the given position maps, with its
  // current start index pointing at `mapFrom`.
  constructor(maps, mapFrom = 0, mirror) {
    // :: [PosMap]
    this.maps = maps || []
    // :: number
    // The current starting position in the `maps` array, used when
    // `map` or `mapResult` is called.
    this.mapFrom = mapFrom
    this.mirror = mirror
  }

  getMirror(n) {
    if (this.mirror) for (let i = 0; i < this.mirror.length; i++)
      if (this.mirror[i] == n) return this.mirror[i + (i % 2 ? -1 : 1)]
  }

  setMirror(n, m) {
    if (!this.mirror) this.mirror = []
    this.mirror.push(n, m)
  }

  // :: (PosMap, ?number)
  // Add a map to the end of this remapping. If `mirrors` is given, it
  // should be the index of the map that is the mirror image of this
  // one.
  appendMap(map, mirrors) {
    this.maps.push(map)
    if (mirrors != null) this.setMirror(this.maps.length - 1, mirrors)
  }

  // :: (number, ?number) → MapResult
  // Map a position through this remapping, returning a mapping
  // result.
  mapResult(pos, bias) { return this._map(pos, bias, false) }

  // :: (number, ?number) → number
  // Map a position through this remapping.
  map(pos, bias) {
    if (this.mirror) return this._map(pos, bias, true)
    for (let i = this.mapFrom; i < this.maps.length; i++)
      pos = this.maps[i].map(pos, bias)
    return pos
  }

  _map(pos, bias, simple) {
    let deleted = false, recoverables = null

    for (let i = this.mapFrom; i < this.maps.length; i++) {
      let map = this.maps[i], rec = recoverables && recoverables[i]
      if (rec != null && map.touches(pos, rec)) {
        pos = map.recover(rec)
        continue
      }

      let result = map.mapResult(pos, bias)
      if (result.recover != null) {
        let corr = this.getMirror(i)
        if (corr != null && corr > i) {
          if (result.deleted) {
            i = corr
            pos = this.maps[corr].recover(result.recover)
            continue
          } else {
            ;(recoverables || (recoverables = Object.create(null)))[corr] = result.recover
          }
        }
      }

      if (result.deleted) deleted = true
      pos = result.pos
    }

    return simple ? pos : new MapResult(pos, deleted)
  }
}
exports.Remapping = Remapping
<commit_msg>Make collab history go through a transform<commit_after>// ;; #path=Mappable #kind=interface
// There are various things that positions can be mapped through.
// We'll denote those as 'mappable'. This is not an actual class in
// the codebase, only an agreed-on interface.

// :: (pos: number, bias: ?number) → number #path=Mappable.map
// Map a position through this object. When given, `bias` (should be
// -1 or 1) determines in which direction to move when a chunk of
// content is inserted at or around the mapped position.

// :: (pos: number, bias: ?number) → MapResult #path=Mappable.mapResult
// Map a position, and return an object containing additional
// information about the mapping. The result's `deleted` field tells
// you whether the position was deleted (completely enclosed in a
// replaced range) during the mapping.

// Recovery values encode a range index and an offset. They are
// represented as numbers, because tons of them will be created when
// mapping, for example, a large number of marked ranges. The number's
// lower 16 bits provide the index, the remaining bits the offset.
//
// Note: We intentionally don't use bit shift operators to en- and
// decode these, since those clip to 32 bits, which we might in rare
// cases want to overflow. A 64-bit float can represent 48-bit
// integers precisely.

const lower16 = 0xffff
const factor16 = Math.pow(2, 16)

function makeRecover(index, offset) { return index + offset * factor16 }
function recoverIndex(value) { return value & lower16 }
function recoverOffset(value) { return (value - (value & lower16)) / factor16 }

// ;; An object representing a mapped position with some extra
// information.
class MapResult {
  constructor(pos, deleted = false, recover = null) {
    // :: number The mapped version of the position.
    this.pos = pos
    // :: bool Tells you whether the position was deleted, that is,
    // whether the step removed its surroundings from the document.
    this.deleted = deleted
    this.recover = recover
  }
}
exports.MapResult = MapResult

// ;; A position map, holding information about the way positions in
// the pre-step version of a document correspond to positions in the
// post-step version. This class implements `Mappable`.
class PosMap {
  // :: ([number])
  // Create a position map. The modifications to the document are
  // represented as an array of numbers, in which each group of three
  // represents a modified chunk as `[start, oldSize, newSize]`.
  constructor(ranges, inverted = false) {
    this.ranges = ranges
    this.inverted = inverted
  }

  recover(value) {
    let diff = 0, index = recoverIndex(value)
    if (!this.inverted) for (let i = 0; i < index; i++)
      diff += this.ranges[i * 3 + 2] - this.ranges[i * 3 + 1]
    return this.ranges[index * 3] + diff + recoverOffset(value)
  }

  // :: (number, ?number) → MapResult
  // Map the given position through this map. The `bias` parameter can
  // be used to control what happens when the transform inserted
  // content at (or around) this position—if `bias` is negative, the a
  // position before the inserted content will be returned, if it is
  // positive, a position after the insertion is returned.
  mapResult(pos, bias) { return this._map(pos, bias, false) }

  // :: (number, ?number) → number
  // Map the given position through this map, returning only the
  // mapped position.
  map(pos, bias) { return this._map(pos, bias, true) }

  _map(pos, bias, simple) {
    let diff = 0, oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2
    for (let i = 0; i < this.ranges.length; i += 3) {
      let start = this.ranges[i] - (this.inverted ? diff : 0)
      if (start > pos) break
      let oldSize = this.ranges[i + oldIndex], newSize = this.ranges[i + newIndex], end = start + oldSize
      if (pos <= end) {
        let side = !oldSize ? bias : pos == start ? -1 : pos == end ? 1 : bias
        let result = start + diff + (side < 0 ? 0 : newSize)
        if (simple) return result
        let recover = makeRecover(i / 3, pos - start)
        return new MapResult(result, pos != start && pos != end, recover)
      }
      diff += newSize - oldSize
    }
    return simple ? pos + diff : new MapResult(pos + diff)
  }

  touches(pos, recover) {
    let diff = 0, index = recoverIndex(recover)
    let oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2
    for (let i = 0; i < this.ranges.length; i += 3) {
      let start = this.ranges[i] - (this.inverted ? diff : 0)
      if (start > pos) break
      let oldSize = this.ranges[i + oldIndex], end = start + oldSize
      if (pos <= end && i == index * 3) return true
      diff += this.ranges[i + newIndex] - oldSize
    }
    return false
  }

  // :: () → PosMap
  // Create an inverted version of this map. The result can be used to
  // map positions in the post-step document to the pre-step document.
  invert() {
    return new PosMap(this.ranges, !this.inverted)
  }

  toString() {
    return (this.inverted ? "-" : "") + JSON.stringify(this.ranges)
  }
}
exports.PosMap = PosMap

PosMap.empty = new PosMap([])

// ;; A remapping represents a pipeline of zero or more mappings. It
// is a specialized data structured used to manage mapping through a
// series of steps, typically including inverted and non-inverted
// versions of the same step. (This comes up when ‘rebasing’ steps for
// collaboration or history management.) This class implements
// `Mappable`.
class Remapping {
  // :: (?[PosMap], ?number)
  // Create a new remapping with the given position maps, with its
  // current start index pointing at `mapFrom`.
  constructor(maps, mapFrom = 0, mirror) {
    // :: [PosMap]
    this.maps = maps || []
    // :: number
    // The current starting position in the `maps` array, used when
    // `map` or `mapResult` is called.
    this.mapFrom = mapFrom
    this.mapTo = this.maps.length
    this.mirror = mirror
  }

  getMirror(n) {
    if (this.mirror) for (let i = 0; i < this.mirror.length; i++)
      if (this.mirror[i] == n) return this.mirror[i + (i % 2 ? -1 : 1)]
  }

  setMirror(n, m) {
    if (!this.mirror) this.mirror = []
    this.mirror.push(n, m)
  }

  // :: (PosMap, ?number)
  // Add a map to the end of this remapping. If `mirrors` is given, it
  // should be the index of the map that is the mirror image of this
  // one.
  appendMap(map, mirrors) {
    this.maps.push(map)
    this.mapTo++
    if (mirrors != null) this.setMirror(this.maps.length - 1, mirrors)
  }

  appendMapping(mapping) {
    for (let i = 0, startSize = this.maps.length; i < mapping.maps.length; i++) {
      let mirr = mapping.getMirror(i)
      this.appendMap(mapping.maps[i], mirr != null && mirr < i ? startSize + mirr : null)
    }
  }

  // :: (number, ?number) → MapResult
  // Map a position through this remapping, returning a mapping
  // result.
  mapResult(pos, bias) { return this._map(pos, bias, false) }

  // :: (number, ?number) → number
  // Map a position through this remapping.
  map(pos, bias) {
    if (this.mirror) return this._map(pos, bias, true)
    for (let i = this.mapFrom; i < this.mapTo; i++)
      pos = this.maps[i].map(pos, bias)
    return pos
  }

  _map(pos, bias, simple) {
    let deleted = false, recoverables = null

    for (let i = this.mapFrom; i < this.mapTo; i++) {
      let map = this.maps[i], rec = recoverables && recoverables[i]
      if (rec != null && map.touches(pos, rec)) {
        pos = map.recover(rec)
        continue
      }

      let result = map.mapResult(pos, bias)
      if (result.recover != null) {
        let corr = this.getMirror(i)
        if (corr != null && corr > i && corr < this.mapTo) {
          if (result.deleted) {
            i = corr
            pos = this.maps[corr].recover(result.recover)
            continue
          } else {
            ;(recoverables || (recoverables = Object.create(null)))[corr] = result.recover
          }
        }
      }

      if (result.deleted) deleted = true
      pos = result.pos
    }

    return simple ? pos : new MapResult(pos, deleted)
  }
}
exports.Remapping = Remapping
<|endoftext|>


<commit_before>(function(){
    var LOCATION = "location";
    var WOUNDED = "wounded";
    var KILLED = "killed";
    var quantize;
    var text;
    var id = "#statesvg";

    var currentYear = 2013;
    var currentSelection = KILLED;
    var stateData;

    function tooltipHtml(stateName, id, dataObject, selection) {
        return "
" + stateName + "
" +
        "

 Affected(per million): " + dataObject[id][selection] + "
</table";
    }

    function mouseOver(d){
        d3.select("#tooltip")
        .transition()
        .duration(100)
        .style("opacity", 0.9);

        d3.select("#tooltip").html(tooltipHtml(d.n, d.id, mouseOver.dataObject, mouseOver.selection))
        .style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY) + "px");
    }

    function mouseOut(){
        d3.select("#tooltip").transition().duration(500).style("opacity", 0);
    }

    function setUpScale() {
        var states = Object.keys(stateData[currentYear]);
        var max = Math.max.apply(null, states.map(function(element) { return stateData[currentYear][element][currentSelection]}));

        quantize = d3.scale.quantize()
                   .domain([0, max])
                   .range(d3.range(9).map(function(i) { return "q" + i + "-9"; }));
    }

    function drawMap(stateData, year, selection){
        setUpScale();

        mouseOver.dataObject = stateData[year];
        mouseOver.selection = selection;

        d3.select(id).selectAll(".state")
            .data(uStatePaths).enter()
            .append("path")

        d3.selectAll("path")
            .attr("class", function(d){console.log(d.id + " " + stateData[year][d.id][selection]);return "state " + quantize(stateData[year][d.id][selection]);})
            .attr("d", function(d){ return d.d;})
            .on("mouseover", mouseOver)
            .on("mouseout", mouseOut);

        drawLegend();
    }

    function drawLegend() {
        var legend = d3.select("#legend").selectAll('g.legendEntry')
        .data(quantize.range())
        .enter()
        .append('g')
        .attr("transform", "translate(700, 15)");

        legend.append("text")
        .text("Affected per million")

        legend
        .append('rect')
        .attr("x", "10px")
        .attr("y", function(d, i) {
        return i * 15;
        })
        .attr("width", 10)
        .attr("height", 10)
        .style("stroke", "black")
        .style("stroke-width", 1)
        .attr("class", function(d){return d;});
        //the data objects are the fill colors

        if(!text){
            text = legend
            .append('text');
        }

        text
        .attr("x", "25px")
        .attr("y", function(d, i) {
        return i * 15;
        })
        .attr("dy", "0.8em")
        .text(function(d,i) {
            var extent = quantize.invertExtent(d);

            var format = d3.format("0.0f");
            return format(+extent[0]) + " - " + format(+extent[1]);
        });
    }

    function init() {

        d3.select("#type").on('change', function(){
            currentSelection = this.value;
            drawMap(stateData, currentYear, this.value);
        });
        d3.select("#year").on('change', function(){
            currentYear = this.value;
            drawMap(stateData, this.value, currentSelection);
        });

        d3.json("out.json", function(error, data){
            stateData = data;
            drawMap(stateData, currentYear, currentSelection)
        });
    }

    init();
})();
<commit_msg>Stop changing the scale from year to year<commit_after>(function(){
    var LOCATION = "location";
    var WOUNDED = "wounded";
    var KILLED = "killed";
    var quantize;
    var text;
    var id = "#statesvg";

    var currentYear = 2013;
    var currentSelection = KILLED;
    var stateData;

    function tooltipHtml(stateName, id, dataObject, selection) {
        return "
" + stateName + "
" +
        "

 Affected(per million): " + dataObject[id][selection] + "
</table";
    }

    function mouseOver(d){
        d3.select("#tooltip")
        .transition()
        .duration(100)
        .style("opacity", 0.9);

        d3.select("#tooltip").html(tooltipHtml(d.n, d.id, mouseOver.dataObject, mouseOver.selection))
        .style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY) + "px");
    }

    function mouseOut(){
        d3.select("#tooltip").transition().duration(500).style("opacity", 0);
    }

    function setUpScale(data) {
        var max = 0;
        for(year in data){
            for(state in data[year]) {
                if(data[year] && data[year][state]) {
                    wounded = data[year][state][KILLED];
                    killed = data[year][state][WOUNDED];
                    thisMax = Math.max.apply(null, [killed, wounded]);

                    if(thisMax > max) {
                        max = thisMax;
                    }
                }
            }
        }

        quantize = d3.scale.quantize()
                   .domain([0, max])
                   .range(d3.range(9).map(function(i) { return "q" + i + "-9"; }));
    }

    function drawMap(stateData, year, selection){

        mouseOver.dataObject = stateData[year];
        mouseOver.selection = selection;

        d3.select(id).selectAll(".state")
            .data(uStatePaths).enter()
            .append("path")

        d3.selectAll("path")
            .attr("class", function(d){console.log(d.id + " " + stateData[year][d.id][selection]);return "state " + quantize(stateData[year][d.id][selection]);})
            .attr("d", function(d){ return d.d;})
            .on("mouseover", mouseOver)
            .on("mouseout", mouseOut);

        drawLegend();
    }

    function drawLegend() {
        var legend = d3.select("#legend").selectAll('g.legendEntry')
        .data(quantize.range())
        .enter()
        .append('g')
        .attr("transform", "translate(700, 15)");

        legend.append("text")
        .text("Affected per million")

        legend
        .append('rect')
        .attr("x", "10px")
        .attr("y", function(d, i) {
        return i * 15;
        })
        .attr("width", 10)
        .attr("height", 10)
        .style("stroke", "black")
        .style("stroke-width", 1)
        .attr("class", function(d){return d;});
        //the data objects are the fill colors

        if(!text){
            text = legend
            .append('text');
        }

        text
        .attr("x", "25px")
        .attr("y", function(d, i) {
        return i * 15;
        })
        .attr("dy", "0.8em")
        .text(function(d,i) {
            var extent = quantize.invertExtent(d);

            var format = d3.format("0.0f");
            return format(+extent[0]) + " - " + format(+extent[1]);
        });
    }

    function init() {

        d3.select("#type").on('change', function(){
            currentSelection = this.value;
            drawMap(stateData, currentYear, this.value);
        });
        d3.select("#year").on('change', function(){
            currentYear = this.value;
            drawMap(stateData, this.value, currentSelection);
        });

        d3.json("out.json", function(error, data){
            stateData = data;
            setUpScale(data);
            drawMap(stateData, currentYear, currentSelection)
        });
    }

    init();
})();
<|endoftext|>


<commit_before>/*
* @Author: Sushil Jain
* @Date:   2017-02-24 11:52:20
* @Last Modified by:   sushiljainam
* @Last Modified time: 2017-02-24 19:17:54
*/

'use strict';

const
	TYPEOF_NUM = 'number',
	TYPEOF_OBJ = 'object';

var ObjPC = function (string, opts) {
	if(arguments.length<1){
		var string = '';
	}
	var string = string || '';

	//check if string is an array, store it elsewhere, make it string

	var sLen = string.length;
	var opts = opts || {};
	if(typeof opts === TYPEOF_NUM){
		sLen = opts;
		opts = undefined;
	} else if (typeof opts === TYPEOF_OBJ){
		sLen = opts.length || sLen;
	} else {
		opts = undefined;
	}

	// return this;
	return new ResultPC(sLen, string, opts);
}

var ResultPC = function (len, string, opts) {
	var res = this;

	return res;
}

ObjPC.permute = function(string, opts) {
	//return ResultPC
};

ObjPC.names = function(string, opts) {
	//return ResultPC
};

ResultPC.prototype.count = function(opts) {
	//return number
};

ResultPC.prototype.rank = function(opts) {
	//return number
};

ResultPC.prototype.list = function(opts) {
	//return array
};

exports = module.exports = ObjPC;<commit_msg>working result obj<commit_after>/*
* @Author: Sushil Jain
* @Date:   2017-02-24 11:52:20
* @Last Modified by:   sushiljainam
* @Last Modified time: 2017-02-24 19:34:05
*/

'use strict';

const
	TYPEOF_NUM = 'number',
	TYPEOF_OBJ = 'object';

var ObjPC = function (string, opts) {
	if(arguments.length<1){
		var string = '';
	}
	var string = string || '';

	//check if string is an array, store it elsewhere, make it string

	var sLen = string.length;
	var opts = opts || {};
	if(typeof opts === TYPEOF_NUM){
		sLen = opts;
		opts = undefined;
	} else if (typeof opts === TYPEOF_OBJ){
		sLen = opts.length || sLen;
	} else {
		opts = undefined;
	}

	// return this;
	return new ResultPC(sLen, string, opts);
}

var ResultPC = function (len, string, opts) {
	var res = this;
	res.len = len;
	res.string = string;
	res.opts = opts;
	res.arrIndex = res.arrIndex || 0;
	return res;
}

ObjPC.permute = function(string, opts) {
	//return this(filtered args)
};

ObjPC.names = function(string, opts) {
	//return this(filtered args)
};

ResultPC.prototype.count = function(opts) {
	//return number
};

ResultPC.prototype.rank = function(opts) {
	//return number
};

ResultPC.prototype.list = function(opts) {
	//return array
};

exports = module.exports = ObjPC;<|endoftext|>


<commit_before>
var request = require('request');
const pad = require('pad');

const nhlStandingsURL = "https://statsapi.web.nhl.com/api/v1/standings?season=20172018";

function updateNHLStandings(completion) {
    request(nhlStandingsURL, function (error, response, body) {
        if (!error) {

            console.log("");

			const jsonData = JSON.parse(body);

			const standings = makeNHLStandings(jsonData.records);

            console.log("");

			completion(standings);
        } else {
            console.log("Error: " + error);
			completion("Det sket sig. :-( " + error);
        }
    });
}

function makeNHLStandings(records) {

    var output = "```\nNHL Standings\n\n";

	var conferences = {
		"Eastern": [],
		"Western": []
	};

	for (var r = 0; r < records.length; r++) {
		const record = records[r];
		const conferenceName = record.conference.name;
		for (var t = 0; t < record.teamRecords.length; t++) {
			const teamRecord = record.teamRecords[t];
			const teamName = teamRecord.team.name;
			const conferenceRank = teamRecord.conferenceRank;
			conferences[conferenceName].push({
				name: teamName,
				rank: conferenceRank
			});
		}
	}

	output += pad("    WESTERN", 25) + "        EASTERN\n\n";

	for (var i = 0; i < 16; i++) {
		const position = pad(2, String(i + 1));
		if (i < 15) {
			const westernTeam = conferences["Western"][i];
			output += "    " + pad(position + ". " + westernTeam.name, 25);
		}
		const easternTeam = conferences["Eastern"][i];
		output += pad(position + ". " + easternTeam.name, 25);

		output += "\n";
	}

    output += "```\n";

    return output;
}

exports.updateNHLStandings = updateNHLStandings;
<commit_msg>NHL formatting<commit_after>
var request = require('request');
const pad = require('pad');

const nhlStandingsURL = "https://statsapi.web.nhl.com/api/v1/standings?season=20172018";

function updateNHLStandings(completion) {
    request(nhlStandingsURL, function (error, response, body) {
        if (!error) {

            console.log("");

			const jsonData = JSON.parse(body);

			const standings = makeNHLStandings(jsonData.records);

            console.log("");

			completion(standings);
        } else {
            console.log("Error: " + error);
			completion("Det sket sig. :-( " + error);
        }
    });
}

function makeNHLStandings(records) {

    var output = "```\nNHL Standings\n\n";

	var conferences = {
		"Eastern": [],
		"Western": []
	};

	for (var r = 0; r < records.length; r++) {
		const record = records[r];
		const conferenceName = record.conference.name;
		for (var t = 0; t < record.teamRecords.length; t++) {
			const teamRecord = record.teamRecords[t];
			const teamName = teamRecord.team.name;
			const conferenceRank = teamRecord.conferenceRank;
			conferences[conferenceName].push({
				name: teamName,
				rank: conferenceRank
			});
		}
	}

	output += pad("    WESTERN", 25) + "        EASTERN\n\n";

	for (var i = 0; i < 16; i++) {
		const position = pad(2, String(i + 1));
		if (i < 15) {
			const westernTeam = conferences["Western"][i];
			output += pad(position + ". " + westernTeam.name, 25);
		} else {
			output += pad(" ", 25);
		}
		const easternTeam = conferences["Eastern"][i];
		output += "    " + pad(position + ". " + easternTeam.name, 25);

		output += "\n";
	}

    output += "```\n";

    return output;
}

exports.updateNHLStandings = updateNHLStandings;
<|endoftext|>


<commit_before>var NUMROWS = 7;
var NUMCOLS = 6;
var GEMR = 50;
var COLORS = ["red", "blue", "green", "yellow", "purple", "pink"];
var ACTIVEGEM = 0;
var ACTIVE = false;
var LIST = [];

$(function() {
    for (col=0; col < NUMCOLS; col++) {
        for (row=0; row < NUMROWS; row++) {
            var random = Math.floor(Math.random() * 6);
            var gem = $("

");
            var number_id = row.toString() + col.toString();
            gem.attr("id", number_id);
            gem.addClass(COLORS[random]);
            // gem.css("background-color", COLORS[random]);
            gem.css("top", row*GEMR+"px");
            gem.css("left", col*GEMR+"px");
            gem.appendTo("#board");
            console.log($('#00').attr('class').split(" ")[1]);
        }
    }
    $(".gem").mouseover(move);
    $(".gem").mousedown(function() {
        ACTIVEGEM = $(this);
        ACTIVE = true;
        LIST = [];
    });
    $(".gem").mouseup(function() {
        removeCol();
        removeRow();
        console.log(LIST)
        // removeGems("00", NaN, NaN);
        ACTIVE = false;
    });
});

function move() {
    if (ACTIVE) {
        var top = $(this).css("top");
        var left = $(this).css("left");
        var id_swap = $(this).attr("id");
        $(this).css("top", ACTIVEGEM.css("top"));
        $(this).css("left", ACTIVEGEM.css("left"));
        $(this).attr("id", ACTIVEGEM.attr('id'));
        ACTIVEGEM.css("top", top);
        ACTIVEGEM.css("left", left);
        ACTIVEGEM.attr('id', id_swap);
    }
}

function removeCol() {
    for (col=0; col < NUMCOLS; col++) {
        for (row=0; row < NUMROWS; row++) {
            var count = 1;
            try {
                while ($("#" + row.toString() + col.toString()).attr('class').split(" ")[1] == $("#" + (row + 1).toString() + col.toString()).attr('class').split(" ")[1]) {
                count += 1;
                row += 1;
                }
                if (count >= 3) {
                    for (y=0; y < count; y++) {
                        var number = (row-y).toString() + col.toString();
                        console.log(number);
                        LIST.push(number);
                        console.log(LIST);
                    }
                }
            } catch(error) {}
        }
    }
}

function removeRow() {
    for (col=0; col < NUMCOLS; col++) {
        for (row=0; row < NUMROWS; row++) {
            var count = 1;
            try {
                while ($("#" + row.toString() + col.toString()).attr('class').split(" ")[1] == $("#" + row.toString() + (col+1).toString()).attr('class').split(" ")[1]) {
                    count += 1;
                    col += 1;
                }
                if (count >= 3) {
                    for (y=0; y < count; y++) {
                        var number = row.toString() + (col-y).toString();
                        console.log(number);
                        LIST.push(number);
                        console.log(LIST);
                    }
                }
            } catch(error) {}
        }
    }
}

// function removeGems(id, color, list) {
//     var row = parseInt(id[0]);
//     var col = parseInt(id[1]);
//     if (row < NUMROWS && col < NUMCOLS) {
//         var gem = $("#"+id);
//         if (gem.css("background-color") === color) {
//             var newlist = list.slice();
//             newlist.push(id);
//             // console.log(newlist);
//             removeGems((row+1).toString() + col.toString(), color, newlist);
//             removeGems(row.toString() + (col + 1).toString(), color, newlist);
//         } else {
//             if (list.length >= 3) {
//                 // console.log("HOLY SHIT IT'S WORKING")
//                 // console.log(list.length)
//                 for (i=0; i < list.length; i++) {
//                     console.log("currently at " + id)
//                     console.log("id is " + list[i]);
//                     $("#" + list[i]).css("background-color", "black");
//                 }
//             }
//             removeGems((row+1).toString() + col.toString(), gem.css("background-color"), [id]);
//             removeGems(row.toString() + (col + 1).toString(), gem.css("background-color"), [id]);
//         }
//     } else {
//         for (i=0; i < list.length; i++) {
//                     console.log("currently at " + id)
//                     console.log("id is " + list[i]);
//                     $("#" + list[i]).css("background-color", "black");
//                 }
//     }
// }
<commit_msg>start gemfall thinking about setting a the gems a class them iterate over them again and move them from the gem on top<commit_after>var NUMROWS = 7;
var NUMCOLS = 6;
var GEMR = 50;
var COLORS = ["red", "blue", "green", "yellow", "purple", "pink"];
var ACTIVEGEM = 0;
var ACTIVE = false;
var LIST = [];

$(function() {
    for (col=0; col < NUMCOLS; col++) {
        for (row=0; row < NUMROWS; row++) {
            var random = Math.floor(Math.random() * 6);
            var gem = $("

");
            var number_id = row.toString() + col.toString();
            gem.attr("id", number_id);
            gem.addClass(COLORS[random]);
            // gem.css("background-color", COLORS[random]);
            gem.css("top", row*GEMR+"px");
            gem.css("left", col*GEMR+"px");
            gem.appendTo("#board");
        }
    }
    $(".gem").mouseover(move);
    $(".gem").mousedown(function() {
        ACTIVEGEM = $(this);
        ACTIVE = true;
        LIST = [];
    });
    $(".gem").mouseup(function() {
        removeCol();
        removeRow();
        console.log(LIST);
        gemFall();
        ACTIVE = false;
    });
});

function move() {
    if (ACTIVE) {
        moveGem(this, ACTIVEGEM);
    }
}

function moveGem(to, from) {
    var top = $(to).css("top");
    var left = $(to).css("left");
    var id_swap = $(to).attr("id");
    $(to).css("top", from.css("top"));
    $(to).css("left", from.css("left"));
    $(to).attr("id", from.attr('id'));
    from.css("top", top);
    from.css("left", left);
    from.attr('id', id_swap);
}

function removeCol() {
    for (col=0; col < NUMCOLS; col++) {
        var count = 0;
        var collection = [];
        while (count <= NUMROWS) {
            var gem = $("#" + count.toString() + col.toString());
            try {
                if (gem.attr('class').split(" ")[1] !== collection[0].attr('class').split(" ")[1]) {
                    if (collection.length >= 3) {
                        LIST.push(collection);
                    }
                    collection = [];
                }
            } catch(err) {
                if (collection.length >= 3) {
                    LIST.push(collection);
                }
                collection = [];
            }
            collection.push(gem);
            count++;
        }
    }
}

function removeRow() {
    for (row=0; row < NUMROWS; row++) {
        var count = 0;
        var collection = [];
        while (count <= NUMCOLS) {
            var gem = $("#" + row.toString() + count.toString());
            try {
                if (gem.attr('class').split(" ")[1] !== collection[0].attr('class').split(" ")[1]) {
                    if (collection.length >= 3) {
                        LIST.push(collection);
                    }
                    collection = [];
                }
            } catch(err) {
                if (collection.length >= 3) {
                    LIST.push(collection);
                }
                collection = [];
            }
            collection.push(gem);
            count++;
        }
    }
}

function gemFall(){

}
<|endoftext|>


<commit_before>var CACHE_NAME = 'music-blocks-site-precache';
var urlsToCache = [
    'index.html',
    'loading-animatoon.gif',
    'manifest.json',
    'favicon.ico',

    'header-icons/down.svg',
    'header-icons/restore-trash-button.svg',
    'header-icons/edit.svg',
    'header-icons/rotate-left.svg',
    'header-icons/empty-trash-button.svg',
    'header-icons/rotate-right.svg',
    'header-icons/erase-button.svg',
    'header-icons/run-button.svg',
    'header-icons/export-button.svg',
    'header-icons/samples-button.svg',
    'header-icons/export-chunk.svg',
    'header-icons/save-blocks-button.svg',
    'header-icons/export-drums.svg',
    'header-icons/save-button.svg',
    'header-icons/fast-button.svg',
    'header-icons/save-to-file-button.svg',
    'header-icons/fast-mouse-button.svg',
    'header-icons/scroll-lock-button.svg',
    'header-icons/folder-open.svg',
    'header-icons/scroll-unlock-button.svg',
    'header-icons/go-home-button.svg',
    'header-icons/share.svg',
    'header-icons/go-home-faded-button.svg',
    'header-icons/show.svg',
    'header-icons/grab.svg',
    'header-icons/slow-button.svg',
    'header-icons/help-button.svg',
    'header-icons/slow-music-button.svg',
    'header-icons/hide-blocks-button.svg',
    'header-icons/smaller-button.svg',
    'header-icons/hide.svg',
    'header-icons/sort.svg',
    'header-icons/invert.svg',
    'header-icons/stats-button.svg',
    'header-icons/lilypond-button.svg',
    'header-icons/step-button.svg',
    'header-icons/menu-button.svg',
    'header-icons/step-music-button.svg',
    'header-icons/myblocks-button.svg',
    'header-icons/stop-turtle-button.svg',
    'header-icons/next-button.svg',
    'header-icons/turtle-button.svg',
    'header-icons/open-button.svg',
    'header-icons/up.svg',
    'header-icons/open-toolbar-button.svg',
    'header-icons/utility-button.svg',

    'images/bubbles.svg',
    'images/dupstack.svg',
    'images/mouse2.svg',
    'images/ridebell.svg',
    'images/camera.svg',
    'images/emptybox.svg',
    'images/mouse.svg',
    'images/slap.svg',
    'images/Cartesian.svg',
    'images/emptyheap.svg',
    'images/negroot.svg',
    'images/snaredrum.svg',
    'images/cat.svg',
    'images/emptystart.svg',
    'images/nocode.svg',
    'images/splash.svg',
    'images/chine.svg',
    'images/expand.svg',
    'images/noconnection.svg',
    'images/syntaxerror.svg',
    'images/clang.svg',
    'images/fingercymbals.svg',
    'images/nofile.svg',
    'images/synth2.svg',
    'images/clap.svg',
    'images/floortom.svg',
    'images/noinput.svg',
    'images/synth.svg',
    'images/close.svg',
    'images/go-down.svg',
    'images/nojournal.svg',
    'images/tom.svg',
    'images/collapse.svg',
    'images/go-up.svg',
    'images/nomedia.svg',
    'images/trash.svg',
    'images/cowbell.svg',
    'images/help-container.svg',
    'images/nomicrophone.svg',
    'images/trianglebell.svg',
    'images/crash.svg',
    'images/nostack.svg',
    'images/turtle2.svg',
    'images/cricket.svg',
    'images/hihat.svg',
    'images/notanumber.svg',
    'images/turtle.svg',
    'images/cup.svg',
    'images/icons.svg',
    'images/notastring.svg',
    'images/video.svg',
    'images/darbuka.svg',
    'images/incompatible.svg',
    'images/overflowerror.svg',
    'images/voices.svg',
    'images/dog.svg',
    'images/kick.svg',
    'images/planetgraphic.png',
    'images/zerodivide.svg',

    'lib/domReady.js',
    'lib/require.js',

    'lib/reqwest.js',
    'lib/jquery-2.1.4.js',
    'lib/jquery-ui.js',
    'lib/webL10n.js',
    'lib/tone.min.js',
    'lib/jquery.ruler.js',
    'lib/modernizr-2.6.2.min.js',
    'lib/easeljs-0.7.1.min.js',
    'lib/tweenjs-0.5.1.min.js',
    'lib/movieclip-0.7.1.min.js',

    'lib/easeljs.js',
    'lib/tweenjs.js',
    'lib/preloadjs.js',
    'lib/tone.js',
    'lib/howler.js',
    'lib/p5.min.js',
    'lib/p5.sound.min.js',
    'lib/p5.dom.min.js',
    'lib/mespeak.js',
    'lib/mespeak_config.json',
    'lib/voices/en/en.json',
    'lib/prefixfree.min.js',
    'lib/Chart.js',

    'css/activity.css',

    'js/detectIE.js',
    'js/pitchdrummatrix.js',
    'js/soundsamples.js',
    'js/activity.js',
    'js/launch.js',
    'js/pitchslider.js',
    'js/status.js',
    'js/analytics.js',
    'js/lilypond.js',
    'js/pitchstaircase.js',
    'js/sugarizer-compatibility.js',
    'js/artwork.js',
    'js/loader.js',
    'js/pitchtimematrix.js',
    'js/tempo.js',
    'js/basicblocks.js',
    'js/logo.js',
    'js/platformstyle.js',
    'js/trash.js',
    'js/blockfactory.js',
    'js/macros.js',
    'js/pluginsviewer.js',
    'js/turtledefs.js',
    'js/block.js',
    'js/modewidget.js',
    'js/protoblocks.js',
    'js/turtle.js',
    'js/blocks.js',
    'js/munsell.js',
    'js/rhythmruler.js',
    'js/utilitybox.js',
    'js/boundary.js',
    'js/musicutils.js',
    'js/samplesviewer.js',
    'js/utils.js',
    'js/clearbox.js',
    'js/palette.js',
    'js/savebox.js',

    'lib/sugar-web/env.js',
    'lib/sugar-web/activity/activity.js',
];

self.addEventListener('install', function(event) {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});
<commit_msg>fix typos<commit_after>var CACHE_NAME = 'music-blocks-site-precache';
var urlsToCache = [
    'index.html',
    'loading-animation.gif',
    'manifest.json',
    'favicon.ico',

    'header-icons/down.svg',
    'header-icons/restore-trash-button.svg',
    'header-icons/edit.svg',
    'header-icons/rotate-left.svg',
    'header-icons/empty-trash-button.svg',
    'header-icons/rotate-right.svg',
    'header-icons/erase-button.svg',
    'header-icons/run-button.svg',
    'header-icons/export-button.svg',
    'header-icons/samples-button.svg',
    'header-icons/export-chunk.svg',
    'header-icons/save-blocks-button.svg',
    'header-icons/export-drums.svg',
    'header-icons/save-button.svg',
    'header-icons/fast-button.svg',
    'header-icons/save-to-file-button.svg',
    'header-icons/fast-mouse-button.svg',
    'header-icons/scroll-lock-button.svg',
    'header-icons/folder-open.svg',
    'header-icons/scroll-unlock-button.svg',
    'header-icons/go-home-button.svg',
    'header-icons/share.svg',
    'header-icons/go-home-faded-button.svg',
    'header-icons/show.svg',
    'header-icons/grab.svg',
    'header-icons/slow-button.svg',
    'header-icons/help-button.svg',
    'header-icons/slow-music-button.svg',
    'header-icons/hide-blocks-button.svg',
    'header-icons/smaller-button.svg',
    'header-icons/hide.svg',
    'header-icons/sort.svg',
    'header-icons/invert.svg',
    'header-icons/stats-button.svg',
    'header-icons/lilypond-button.svg',
    'header-icons/step-button.svg',
    'header-icons/menu-button.svg',
    'header-icons/step-music-button.svg',
    'header-icons/myblocks-button.svg',
    'header-icons/stop-turtle-button.svg',
    'header-icons/next-button.svg',
    'header-icons/turtle-button.svg',
    'header-icons/open-button.svg',
    'header-icons/up.svg',
    'header-icons/open-toolbar-button.svg',
    'header-icons/utility-button.svg',

    'images/bubbles.svg',
    'images/dupstack.svg',
    'images/mouse2.svg',
    'images/ridebell.svg',
    'images/camera.svg',
    'images/emptybox.svg',
    'images/mouse.svg',
    'images/slap.svg',
    'images/Cartesian.svg',
    'images/emptyheap.svg',
    'images/negroot.svg',
    'images/snaredrum.svg',
    'images/cat.svg',
    'images/emptystart.svg',
    'images/nocode.svg',
    'images/splash.svg',
    'images/chine.svg',
    'images/expand.svg',
    'images/noconnection.svg',
    'images/syntaxerror.svg',
    'images/clang.svg',
    'images/fingercymbals.svg',
    'images/nofile.svg',
    'images/synth2.svg',
    'images/clap.svg',
    'images/floortom.svg',
    'images/noinput.svg',
    'images/synth.svg',
    'images/close.svg',
    'images/go-down.svg',
    'images/nojournal.svg',
    'images/tom.svg',
    'images/collapse.svg',
    'images/go-up.svg',
    'images/nomedia.svg',
    'images/trash.svg',
    'images/cowbell.svg',
    'images/help-container.svg',
    'images/nomicrophone.svg',
    'images/trianglebell.svg',
    'images/crash.svg',
    'images/nostack.svg',
    'images/turtle2.svg',
    'images/cricket.svg',
    'images/hihat.svg',
    'images/notanumber.svg',
    'images/turtle.svg',
    'images/cup.svg',
    'images/icons.svg',
    'images/notastring.svg',
    'images/video.svg',
    'images/darbuka.svg',
    'images/incompatible.svg',
    'images/overflowerror.svg',
    'images/voices.svg',
    'images/dog.svg',
    'images/kick.svg',
    'images/planetgraphic.png',
    'images/zerodivide.svg',

    'lib/domReady.js',
    'lib/require.js',

    'lib/reqwest.js',
    'lib/jquery-2.1.4.js',
    'lib/jquery-ui.js',
    'lib/webL10n.js',
    'lib/tone.min.js',
    'lib/jquery.ruler.js',
    'lib/modernizr-2.6.2.min.js',
    'lib/easeljs-0.7.1.min.js',
    'lib/tweenjs-0.5.1.min.js',
    'lib/movieclip-0.7.1.min.js',

    'lib/easeljs.js',
    'lib/tweenjs.js',
    'lib/preloadjs.js',
    'lib/tone.js',
    'lib/howler.js',
    'lib/p5.min.js',
    'lib/p5.sound.min.js',
    'lib/p5.dom.min.js',
    'lib/mespeak.js',
    'lib/mespeak_config.json',
    'lib/voices/en/en.json',
    'lib/prefixfree.min.js',
    'lib/Chart.js',

    'css/activity.css',

    'js/detectIE.js',
    'js/pitchdrummatrix.js',
    'js/soundsamples.js',
    'js/activity.js',
    'js/launch.js',
    'js/pitchslider.js',
    'js/status.js',
    'js/analytics.js',
    'js/lilypond.js',
    'js/pitchstaircase.js',
    'js/sugarizer-compatibility.js',
    'js/artwork.js',
    'js/loader.js',
    'js/pitchtimematrix.js',
    'js/tempo.js',
    'js/basicblocks.js',
    'js/logo.js',
    'js/platformstyle.js',
    'js/trash.js',
    'js/blockfactory.js',
    'js/macros.js',
    'js/pluginsviewer.js',
    'js/turtledefs.js',
    'js/block.js',
    'js/modewidget.js',
    'js/protoblocks.js',
    'js/turtle.js',
    'js/blocks.js',
    'js/munsell.js',
    'js/rhythmruler.js',
    'js/utilitybox.js',
    'js/boundary.js',
    'js/musicutils.js',
    'js/samplesviewer.js',
    'js/utils.js',
    'js/clearbox.js',
    'js/palette.js',
    // 'js/savebox.js',

    'lib/sugar-web/env.js',
    'lib/sugar-web/activity/activity.js',
];

self.addEventListener('install', function(event) {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});
<|endoftext|>


<commit_before>var CACHE_NAME = 'music-blocks-site-precache';
var urlsToCache = [
    'index.html',
    'loading-animation.gif',
    'manifest.json',
    'favicon.ico',

    'header-icons/a-button.svg',
    'header-icons/add.svg',
    'header-icons/advanced.svg',
    'header-icons/apply.svg',
    'header-icons/b-button.svg',
    'header-icons/beginner.svg',
    'header-icons/bigger-button.svg',
    'header-icons/bigger-disable-button.svg',
    'header-icons/cancel-button.svg',
    'header-icons/Cartesian-button.svg',
    'header-icons/Cartesian-polar-button.svg',
    'header-icons/clear-button.svg',
    'header-icons/close-button.svg',
    'header-icons/close-toolbar-button.svg',
    'header-icons/collapse-blocks-button.svg',
    'header-icons/copy-button.svg',
    'header-icons/compile-button.svg',
    'header-icons/delete.svg',
    'header-icons/download-button.svg',
    'header-icons/download-merge.svg',
    'header-icons/download.svg',
    'header-icons/down.svg',
    'header-icons/edit.svg',
    'header-icons/effects.svg',
    'header-icons/new-button.svg',
    'header-icons/new-project-button.svg',
    'header-icons/envelope.svg',
    'header-icons/erase-button.svg',
    'header-icons/export-button.svg',
    'header-icons/export-chunk.svg',
    'header-icons/export-drums.svg',
    'header-icons/fast-button.svg',
    'header-icons/fast-mouse-button.svg',
    'header-icons/fb-inactive.svg',
    'header-icons/filter.svg',
    'header-icons/filter+.svg',
    'header-icons/folder-open.svg',
    'header-icons/go-home-button.svg',
    'header-icons/go-home-faded-button.svg',
    'header-icons/grab-handle.svg',
    'header-icons/grab.svg',
    'header-icons/hard-stop-turtle-button.svg',
    'header-icons/help-button.svg',
    'header-icons/hide-blocks-button.svg',
    'header-icons/hide.svg',
    'header-icons/invert.svg',
    'header-icons/language-button.svg',
    'header-icons/lilypond-button.svg',
    'header-icons/media-playback-pause-insensitive.svg',
    'header-icons/media-playback-pause.svg',
    'header-icons/media-playback-start-insensitive.svg',
    'header-icons/media-playback-start.svg',
    'header-icons/media-playlist-repeat-insensitive.svg',
    'header-icons/media-playlist-repeat.svg',
    'header-icons/menu-button.svg',
    'header-icons/myblocks-button.svg',
    'header-icons/new-project-button.svg',
    'header-icons/next-button.svg',
    'header-icons/no-grid-button.svg',
    'header-icons/open-button.svg',
    'header-icons/open-merge-button.svg',
    'header-icons/optimize-off-button.svg',
    'header-icons/optimize-on-button.svg',
    'header-icons/open-toolbar-button.svg',
    'header-icons/oscillator.svg',
    'header-icons/palette-button.svg',
    'header-icons/paste-button.svg',
    'header-icons/paste-disabled-button.svg',
    'header-icons/pause-button.svg',
    'header-icons/planet-button.svg',
    'header-icons/play-button.svg',
    'header-icons/play-chord.svg',
    'header-icons/play-scale.svg',
    'header-icons/plugins-button.svg',
    'header-icons/plugins-delete-button.svg',
    'header-icons/plugins-delete-disabled-button.svg',
    'header-icons/polar-button.svg',
    'header-icons/popdown-palette-button.svg',
    'header-icons/popout.svg',
    'header-icons/publish.svg',
    'header-icons/restore-button.svg',
    'header-icons/restore-trash-button.svg',
    'header-icons/rotate-left.svg',
    'header-icons/rotate-right.svg',
    'header-icons/run-button.svg',
    'header-icons/samples-button.svg',
    'header-icons/save-block-artwork_backup.svg',
    'header-icons/save-block-artwork.svg',
    'header-icons/save-blocks-button.svg',
    'header-icons/save-button-dark.svg',
    'header-icons/save-button.svg',
    'header-icons/save-lilypond.svg',
    'header-icons/save-png.svg',
    'header-icons/save-svg.svg',
    'header-icons/save-tb.svg',
    'header-icons/save-to-file-button.svg',
    'header-icons/save-wav.svg',
    'header-icons/scroll-lock-button.svg',
    'header-icons/scroll-unlock-button.svg',
    'header-icons/search-button.svg',
    'header-icons/share.svg',
    'header-icons/show.svg',
    'header-icons/slow-button.svg',
    'header-icons/slow-music-button.svg',
    'header-icons/smaller-button.svg',
    'header-icons/smaller-disabled-button.svg',
    'header-icons/sort.svg',
    'header-icons/stats-button.svg',
    'header-icons/step-button.svg',
    'header-icons/step-music-button.svg',
    'header-icons/stop-button.svg',
    'header-icons/stop-turtle-button.svg',
    'header-icons/synth.svg',
    'header-icons/tap-active-button.svg',
    'header-icons/tap-button.svg',
    'header-icons/turtle-button.svg',
    'header-icons/upload-planet.svg',
    'header-icons/up.svg',
    'header-icons/utility-button.svg',

    'images/8_bellset_key_1.svg',
    'images/8_bellset_key_2.svg',
    'images/8_bellset_key_3.svg',
    'images/8_bellset_key_4.svg',
    'images/8_bellset_key_5.svg',
    'images/8_bellset_key_6.svg',
    'images/8_bellset_key_7.svg',
    'images/8_bellset_key_8.svg',
    'images/bottle.svg',
    'images/bubbles.svg',
    'images/camera.svg',
    'images/Cartesian.svg',
    'images/cat.svg',
    'images/chime.svg',
    'images/clang.svg',
    'images/clap.svg',
    'images/close.svg',
    'images/collapse.svg',
    'images/cowbell.svg',
    'images/crash.svg',
    'images/cricket.svg',
    'images/cup.svg',
    'images/darbuka.svg',
    'images/dog.svg',
    'images/dupstack.svg',
    'images/emptybox.svg',
    'images/emptyheap.svg',
    'images/emptystart.svg',
    'images/expand.svg',
    'images/fingercymbals.svg',
    'images/floortom.svg',
    'images/go-down.svg',
    'images/go-up.svg',
    'images/help-container.svg',
    'images/hihat.svg',
    'images/icons.svg',
    'images/incompatible.svg',
    'images/kick.svg',
    'images/mouse2.svg',
    'images/mouse.svg',
    'images/negroot.svg',
    'images/nocode.svg',
    'images/noconnection.svg',
    'images/nofile.svg',
    'images/noinput.svg',
    'images/nojournal.svg',
    'images/nomedia.svg',
    'images/nomicrophone.svg',
    'images/nostack.svg',
    'images/notanumber.svg',
    'images/notastring.svg',
    'images/overflowerror.svg',
    'images/planetgraphic.png',
    'images/polar.svg',
    'images/ridebell.svg',
    'images/slap.svg',
    'images/snaredrum.svg',
    'images/splash.svg',
    'images/syntaxerror.svg',
    'images/synth2.svg',
    'images/synth.svg',
    'images/tom.svg',
    'images/trash.svg',
    'images/trianglebell.svg',
    'images/turtle2.svg',
    'images/turtle.svg',
    'images/video.svg',
    'images/voices.svg',
    'images/zerodivide.svg',

    'lib/Chart.js',
    'lib/domReady.js',
    'lib/easeljs.min.js',
    'lib/howler.js',
    'lib/jquery-2.1.4.js',
    'lib/jquery-ui.js',
    'lib/jquery-cookie.js',
    'lib/jquery.ruler.js',
    'lib/mespeak.js',
    'lib/mespeak_config.json',
    'lib/modernizr-2.6.2.min.js',
    'lib/p5.dom.min.js',
    'lib/p5.min.js',
    'lib/p5.sound.min.js',
    'lib/prefixfree.min.js',
    'lib/preloadjs.min.js',
    'lib/require.js',
    'lib/reqwest.js',
    'lib/text.js',
    'lib/Tone.min.js',
    'lib/tweenjs.min.js',
    'lib/voices/en/en.json',
    'lib/webL10n.js',

    'css/activity.css',

    'js/abc.js',
    'js/activity.js',
    'js/rubrics.js',
    'js/artwork.js',
    'js/background.js',
    'js/basicblocks.js',
    'js/blockfactory.js',
    'js/block.js',
    'js/blocks.js',
    'js/boundary.js',
    'js/clearbox.js',
    'js/languagebox.js',
    'js/lilypond.js',
    'js/loader.js',
    'js/logo.js',
    'js/macros.js',
    'js/palette.js',
    'js/pastebox.js',
    'js/playbackbox.js',
    'js/pluginsviewer.js',
    'js/protoblocks.js',
    'js/savebox.js',
    'js/SaveInterface.js',
    'js/sugarizer-compatibility.js',
    'js/trash.js',
    'js/turtledefs.js',
    'js/turtle.js',
    'js/utilitybox.js',

    'js/widgets/modewidget.js',
    'js/widgets/pitchdrummatrix.js',
    'js/widgets/pitchslider.js',
    'js/widgets/pitchstaircase.js',
    'js/widgets/pitchtimematrix.js',
    'js/widgets/rhythmruler.js',
    'js/widgets/status.js',
    'js/widgets/tempo.js',
    'js/widgets/timbre.js',

    'js/utils/detectIE.js',
    'js/utils/munsell.js',
    'js/utils/musicutils.js',
    'js/utils/platformstyle.js',
    'js/utils/synthutils.js',
    'js/utils/utils.js',

    'lib/sugar-web/env.js',
    'lib/sugar-web/activity/activity.js',

    'planet/index.html',
    'planet/css/style.css',
    'planet/fonts/material-icons.css',
    'planet/fonts/material-icons.woff2',
    'planet/fonts/roboto/Roboto-Bold.woff',
    'planet/fonts/roboto/Roboto-Light.woff2',
    'planet/fonts/roboto/Roboto-Regular.woff',
    'planet/fonts/roboto/Roboto-Thin.woff2',
    'planet/fonts/roboto/Roboto-Bold.woff2',
    'planet/fonts/roboto/Roboto-Medium.woff',
    'planet/fonts/roboto/Roboto-Regular.woff2',
    'planet/fonts/roboto/Roboto-Light.woff',
    'planet/fonts/roboto/Roboto-Medium.woff2',
    'planet/fonts/roboto/Roboto-Thin.woff',
    'planet/images/mbgraphic.png',
    'planet/images/tbgraphic.png',
    'planet/js/Converter.js',
    'planet/js/helper.js',
    'planet/js/Planet.js',
    'planet/js/SaveInterface.js',
    'planet/js/GlobalCard.js',
    'planet/js/LocalCard.js',
    'planet/js/ProjectStorage.js',
    'planet/js/ServerInterface.js',
    'planet/js/GlobalPlanet.js',
    'planet/js/LocalPlanet.js',
    'planet/js/ProjectViewer.js',
    'planet/js/GlobalTag.js',
    'planet/js/main.js',
    'planet/js/Publisher.js',
    'planet/lib/jquery-3.2.1.min.js',
    'planet/lib/materialize.min.css',
    'planet/lib/materialize.min.js',

    'sounds/samples/manifest.js'
];

self.addEventListener('install', function(event) {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});
<commit_msg>add missing file<commit_after>var CACHE_NAME = 'music-blocks-site-precache';
var urlsToCache = [
    'index.html',
    'loading-animation.gif',
    'manifest.json',
    'favicon.ico',

    'header-icons/a-button.svg',
    'header-icons/add.svg',
    'header-icons/advanced.svg',
    'header-icons/apply.svg',
    'header-icons/b-button.svg',
    'header-icons/beginner.svg',
    'header-icons/bigger-button.svg',
    'header-icons/bigger-disable-button.svg',
    'header-icons/cancel-button.svg',
    'header-icons/Cartesian-button.svg',
    'header-icons/Cartesian-polar-button.svg',
    'header-icons/clear-button.svg',
    'header-icons/close-button.svg',
    'header-icons/close-toolbar-button.svg',
    'header-icons/collapse-blocks-button.svg',
    'header-icons/copy-button.svg',
    'header-icons/compile-button.svg',
    'header-icons/delete.svg',
    'header-icons/download-button.svg',
    'header-icons/download-merge.svg',
    'header-icons/download.svg',
    'header-icons/down.svg',
    'header-icons/edit.svg',
    'header-icons/effects.svg',
    'header-icons/empty-trash-confirm-button.svg',
    'header-icons/new-button.svg',
    'header-icons/new-project-button.svg',
    'header-icons/envelope.svg',
    'header-icons/erase-button.svg',
    'header-icons/export-button.svg',
    'header-icons/export-chunk.svg',
    'header-icons/export-drums.svg',
    'header-icons/fast-button.svg',
    'header-icons/fast-mouse-button.svg',
    'header-icons/fb-inactive.svg',
    'header-icons/filter.svg',
    'header-icons/filter+.svg',
    'header-icons/folder-open.svg',
    'header-icons/go-home-button.svg',
    'header-icons/go-home-faded-button.svg',
    'header-icons/grab-handle.svg',
    'header-icons/grab.svg',
    'header-icons/hard-stop-turtle-button.svg',
    'header-icons/help-button.svg',
    'header-icons/hide-blocks-button.svg',
    'header-icons/hide.svg',
    'header-icons/invert.svg',
    'header-icons/language-button.svg',
    'header-icons/lilypond-button.svg',
    'header-icons/media-playback-pause-insensitive.svg',
    'header-icons/media-playback-pause.svg',
    'header-icons/media-playback-start-insensitive.svg',
    'header-icons/media-playback-start.svg',
    'header-icons/media-playlist-repeat-insensitive.svg',
    'header-icons/media-playlist-repeat.svg',
    'header-icons/menu-button.svg',
    'header-icons/myblocks-button.svg',
    'header-icons/new-project-button.svg',
    'header-icons/next-button.svg',
    'header-icons/no-grid-button.svg',
    'header-icons/open-button.svg',
    'header-icons/open-merge-button.svg',
    'header-icons/optimize-off-button.svg',
    'header-icons/optimize-on-button.svg',
    'header-icons/open-toolbar-button.svg',
    'header-icons/oscillator.svg',
    'header-icons/palette-button.svg',
    'header-icons/paste-button.svg',
    'header-icons/paste-disabled-button.svg',
    'header-icons/pause-button.svg',
    'header-icons/planet-button.svg',
    'header-icons/play-button.svg',
    'header-icons/play-chord.svg',
    'header-icons/play-scale.svg',
    'header-icons/plugins-button.svg',
    'header-icons/plugins-delete-button.svg',
    'header-icons/plugins-delete-disabled-button.svg',
    'header-icons/polar-button.svg',
    'header-icons/popdown-palette-button.svg',
    'header-icons/popout.svg',
    'header-icons/publish.svg',
    'header-icons/restore-button.svg',
    'header-icons/restore-trash-button.svg',
    'header-icons/rotate-left.svg',
    'header-icons/rotate-right.svg',
    'header-icons/run-button.svg',
    'header-icons/samples-button.svg',
    'header-icons/save-block-artwork_backup.svg',
    'header-icons/save-block-artwork.svg',
    'header-icons/save-blocks-button.svg',
    'header-icons/save-button-dark.svg',
    'header-icons/save-button.svg',
    'header-icons/save-lilypond.svg',
    'header-icons/save-png.svg',
    'header-icons/save-svg.svg',
    'header-icons/save-tb.svg',
    'header-icons/save-to-file-button.svg',
    'header-icons/save-wav.svg',
    'header-icons/scroll-lock-button.svg',
    'header-icons/scroll-unlock-button.svg',
    'header-icons/search-button.svg',
    'header-icons/share.svg',
    'header-icons/show.svg',
    'header-icons/slow-button.svg',
    'header-icons/slow-music-button.svg',
    'header-icons/smaller-button.svg',
    'header-icons/smaller-disabled-button.svg',
    'header-icons/sort.svg',
    'header-icons/stats-button.svg',
    'header-icons/step-button.svg',
    'header-icons/step-music-button.svg',
    'header-icons/stop-button.svg',
    'header-icons/stop-turtle-button.svg',
    'header-icons/synth.svg',
    'header-icons/tap-active-button.svg',
    'header-icons/tap-button.svg',
    'header-icons/turtle-button.svg',
    'header-icons/upload-planet.svg',
    'header-icons/up.svg',
    'header-icons/utility-button.svg',

    'images/8_bellset_key_1.svg',
    'images/8_bellset_key_2.svg',
    'images/8_bellset_key_3.svg',
    'images/8_bellset_key_4.svg',
    'images/8_bellset_key_5.svg',
    'images/8_bellset_key_6.svg',
    'images/8_bellset_key_7.svg',
    'images/8_bellset_key_8.svg',
    'images/bottle.svg',
    'images/bubbles.svg',
    'images/camera.svg',
    'images/Cartesian.svg',
    'images/cat.svg',
    'images/chime.svg',
    'images/clang.svg',
    'images/clap.svg',
    'images/close.svg',
    'images/collapse.svg',
    'images/cowbell.svg',
    'images/crash.svg',
    'images/cricket.svg',
    'images/cup.svg',
    'images/darbuka.svg',
    'images/dog.svg',
    'images/dupstack.svg',
    'images/emptybox.svg',
    'images/emptyheap.svg',
    'images/emptystart.svg',
    'images/expand.svg',
    'images/fingercymbals.svg',
    'images/floortom.svg',
    'images/go-down.svg',
    'images/go-up.svg',
    'images/help-container.svg',
    'images/hihat.svg',
    'images/icons.svg',
    'images/incompatible.svg',
    'images/kick.svg',
    'images/mouse2.svg',
    'images/mouse.svg',
    'images/negroot.svg',
    'images/nocode.svg',
    'images/noconnection.svg',
    'images/nofile.svg',
    'images/noinput.svg',
    'images/nojournal.svg',
    'images/nomedia.svg',
    'images/nomicrophone.svg',
    'images/nostack.svg',
    'images/notanumber.svg',
    'images/notastring.svg',
    'images/overflowerror.svg',
    'images/planetgraphic.png',
    'images/polar.svg',
    'images/ridebell.svg',
    'images/slap.svg',
    'images/snaredrum.svg',
    'images/splash.svg',
    'images/syntaxerror.svg',
    'images/synth2.svg',
    'images/synth.svg',
    'images/tom.svg',
    'images/trash.svg',
    'images/trianglebell.svg',
    'images/turtle2.svg',
    'images/turtle.svg',
    'images/video.svg',
    'images/voices.svg',
    'images/zerodivide.svg',

    'lib/Chart.js',
    'lib/domReady.js',
    'lib/easeljs.min.js',
    'lib/howler.js',
    'lib/jquery-2.1.4.js',
    'lib/jquery-ui.js',
    'lib/jquery-cookie.js',
    'lib/jquery.ruler.js',
    'lib/mespeak.js',
    'lib/mespeak_config.json',
    'lib/modernizr-2.6.2.min.js',
    'lib/p5.dom.min.js',
    'lib/p5.min.js',
    'lib/p5.sound.min.js',
    'lib/prefixfree.min.js',
    'lib/preloadjs.min.js',
    'lib/require.js',
    'lib/reqwest.js',
    'lib/text.js',
    'lib/Tone.min.js',
    'lib/tweenjs.min.js',
    'lib/voices/en/en.json',
    'lib/webL10n.js',

    'css/activity.css',

    'js/abc.js',
    'js/activity.js',
    'js/rubrics.js',
    'js/artwork.js',
    'js/background.js',
    'js/basicblocks.js',
    'js/blockfactory.js',
    'js/block.js',
    'js/blocks.js',
    'js/boundary.js',
    'js/clearbox.js',
    'js/languagebox.js',
    'js/lilypond.js',
    'js/loader.js',
    'js/logo.js',
    'js/macros.js',
    'js/palette.js',
    'js/pastebox.js',
    'js/playbackbox.js',
    'js/pluginsviewer.js',
    'js/protoblocks.js',
    'js/savebox.js',
    'js/SaveInterface.js',
    'js/sugarizer-compatibility.js',
    'js/trash.js',
    'js/turtledefs.js',
    'js/turtle.js',
    'js/utilitybox.js',

    'js/widgets/modewidget.js',
    'js/widgets/pitchdrummatrix.js',
    'js/widgets/pitchslider.js',
    'js/widgets/pitchstaircase.js',
    'js/widgets/pitchtimematrix.js',
    'js/widgets/rhythmruler.js',
    'js/widgets/status.js',
    'js/widgets/tempo.js',
    'js/widgets/timbre.js',

    'js/utils/detectIE.js',
    'js/utils/munsell.js',
    'js/utils/musicutils.js',
    'js/utils/platformstyle.js',
    'js/utils/synthutils.js',
    'js/utils/utils.js',

    'lib/sugar-web/env.js',
    'lib/sugar-web/activity/activity.js',

    'planet/index.html',
    'planet/css/style.css',
    'planet/fonts/material-icons.css',
    'planet/fonts/material-icons.woff2',
    'planet/fonts/roboto/Roboto-Bold.woff',
    'planet/fonts/roboto/Roboto-Light.woff2',
    'planet/fonts/roboto/Roboto-Regular.woff',
    'planet/fonts/roboto/Roboto-Thin.woff2',
    'planet/fonts/roboto/Roboto-Bold.woff2',
    'planet/fonts/roboto/Roboto-Medium.woff',
    'planet/fonts/roboto/Roboto-Regular.woff2',
    'planet/fonts/roboto/Roboto-Light.woff',
    'planet/fonts/roboto/Roboto-Medium.woff2',
    'planet/fonts/roboto/Roboto-Thin.woff',
    'planet/images/mbgraphic.png',
    'planet/images/tbgraphic.png',
    'planet/js/Converter.js',
    'planet/js/helper.js',
    'planet/js/Planet.js',
    'planet/js/SaveInterface.js',
    'planet/js/GlobalCard.js',
    'planet/js/LocalCard.js',
    'planet/js/ProjectStorage.js',
    'planet/js/ServerInterface.js',
    'planet/js/GlobalPlanet.js',
    'planet/js/LocalPlanet.js',
    'planet/js/ProjectViewer.js',
    'planet/js/GlobalTag.js',
    'planet/js/main.js',
    'planet/js/Publisher.js',
    'planet/lib/jquery-3.2.1.min.js',
    'planet/lib/materialize.min.css',
    'planet/lib/materialize.min.js',

    'sounds/samples/manifest.js'
];

self.addEventListener('install', function(event) {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});
<|endoftext|>