<commit_before>/*
	Guy Moore 3/2015 - Ifixit ninja test.

	TODO: Figure out how to store id's for tiles.
	TODO: Add pagination.
	TODO: Show placeholder before an image has loaded.
*/

//Categories that will be pulled from the ifixit api.
var categories;

/*
	Request 20 items, this will just be to test adding tiles to the page..
	TODO: Add category hierarchy, so the user doesn't have to go through a list of things.
*/
var getAllCategories = new Request.JSON({
	url: 'https://www.ifixit.com/api/2.0/categories/all',
	onSuccess: function( responseJSON, responseText ) {
		categories = responseJSON;
		//Iterate through the categories and
		for( var x = 0; x < categories.length; x++ )
		{
			//Create a new category and store the div.
			var categoryDiv = createCategory(categories[x]);

			//Get the image for the category and insert it into the previously created category.
			getCategoryImage( categories[x], categoryDiv )
		}
		/*
			TODO: Figure out how ids should be stored before uncommenting this.
			for( var x = 0; x < categories.length; x++ )
			{
				getCategoryImage(categories[x]);
			}
		*/
	},
	onError: function( text, error ) {
		alert('There was a problem getting the categories.');
	}
});

//TODO: Correct how the id is selected once you figure out what it should be.
/*
	Get an image for the specific category argument.

	@param category String the name of the category
*/
var getCategoryImage = function( category, div ) {
	var imageRequest = new Request.JSON({
		url: 'https://www.ifixit.com/api/2.0/categories/' + category,
		onSuccess: function( responseJSON, responseText ) {

			//Check to make sure that there is an image, if not set placeholder.
			var imageSource;
			if( responseJSON['image'] !== null && responseJSON['image']['medium'] !== null ) {
				imageSource = responseJSON['image']['medium'];
			}
			else {
				//TODO: Add placeholder image for items that don't have an image.
				imageSource = "img/cross.svg";
			}

			var image = new Element( 'img', {
				src: imageSource,
				alt: category,
				class: 'categoryImage',
				draggable: 'false' //Don't allow just the image to be dragged.
			});

			//Insert the new image element at the top of the div for the current category.
			image.inject( div, 'top');
		},
		onError: function( error ) {
			console.log('Failed to get the image for ' + category );
		}
	}).get();
}

/*
	Create a new category and insesrt it into the mainBody.

	@return div object for the category.
*/
var createCategory = function( category ) {

	//
	var onDragStart = 'event.dataTransfer.setData(\'text/plain\', \'' + category + '\')';

	//Create a new div for the category
	var categoryDiv = new Element('div', {
		class: 'category tile',
		id: category, //TODO: Fix what the id should be set to, since it can't contain spaces.
		draggable: 'true'
		//ondragstart: onDragStart
	});

	//This doesn't work? I don't know why this doesn't work. TODO: Ask iFixit why this doesn't work.
	//If I had to guess, it is because it doesn't see any valid drop targets.
	//NOPE the other method will work without valid drop targets, so this should too.
	/*
	//The events that happen when dragging starts.
	categoryDiv.addEvent('dragstart', function( event ) {
		console.log('started drag event.');
		event.dataTransfer.setData('text/plain', category);
		event.dataTransfer.effectAllowed = "copy";
		//Set the drag image for the cursor.
		//event.dataTransfer.setDragImage( image, xOffset, yOffset);
	})
	*/

	//Do everything vanilla because mootools doesn't work for this. Why do you make me sad Mootools :(
	categoryDiv.addEventListener('dragstart', handleDragStart, false);
	categoryDiv.addEventListener('dragend', handleDragEnd, false);

	//Nest the drag start event handler so we can set the category as the transfer data for the drag,
	//otherwise we would not be able to pass data when dragging.
	function handleDragStart( event ) {
		//Set the data type so this will work in firefox.
		event.dataTransfer.setData('text/plain', category)
	}

	//This is the text describing what the tile is, it is the lower title of the tile.
	var categoryTitle = new Element('p', {
		class: 'categoryTitle',
		html: category
	});

	//Insert the newly created category into the main body.
	categoryDiv.inject(mainBody);
	//nest the title in its div.
	categoryTitle.inject( categoryDiv );

	return categoryDiv;
}

function handleDragEnd( event ) {
	//Prevent the default action.
	event.preventDefault();
}

function addItemsToGearBag( items ) {

	//MDN says not to do this, prefixed names are buggy. Possible that these don't use standards.
	//var indexedDB = window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;

	var db;
	var DBOpenRequest = window.indexedDB.open("gearBag", 1);
	DBOpenRequest.onsuccess = function( event ) {
		db = DBOpenRequest.result;
		var transaction = db.transaction(["items"], "readwrite");
		transaction.onerror = function( event ) {
			console.log( 'error on transaction', event );
		}
		transaction.oncomplete = function( event ) {
			console.log( 'completed transaction', event );
		}

		var objectStore = transaction.objectStore("items");
		for( var i in items ) {
			var request = objectStore.add(items[i]);
			request.onsuccess = function( event ) {
				console.log( 'Added an item.', items[i] );
			}
			request.onerror = function( event ) {
				console.log( 'There was an error adding an item.', items[i] );
			}
		}
	}
	DBOpenRequest.onerror = function( event ) {
		console.log('There was an error opening the gear bag', event.target.errorCode);
	}

	//Handle what needs to happen if the database isn't created or is an older version.
	DBOpenRequest.onupgradeneeded = upgradeDatabase;
}

/*
	Handle upgrading, or instantiating the datbase.

	@paramater the event from the onupgradeneeded event.
*/
function upgradeDatabase( event ) {

	console.log('upgrading the database');

	//Handle upgrading the db or creating it..
	var db = event.target.result;

	//Adding the object store named Items with a key called name.
	var objectStore = db.createObjectStore("items", { keyPath: "name" });

	//Adding an index for the quantity of items.
	//objectStore.createIndex("number", "number", { unique: false });
}

/*
	Retrieve all of the gear bag items.

	@parameter callback function first paramter error, second parameter
*/
function getAllGearBagItems( callback ) {

	//The database is set after a successful open request is ran.
	var db;

	//Create the request to open the gear bag.
	var DBOpenRequest = window.indexedDB.open("gearBag", 1);
	DBOpenRequest.onsuccess = function( event ) {
		db = DBOpenRequest.result;
		var transaction = db.transaction(["items"], "readwrite");
		transaction.onerror = function( event ) {
			console.log( 'error on transaction', event.target.errorCode );
			callback( event.result );
		}
		transaction.oncomplete = function( event ) {
			console.log( 'completed transaction', event );
		}

		var objectStore = transaction.objectStore("items");

		//Array of all the items.
		var items = [];
		objectStore.openCursor().onsuccess = function( event ) {
			var cursor = event.target.result;
			if( cursor ) {
				items.push(cursor.value);
				cursor.continue();
			}
			else
			{
				callback( Null, items );
				console.log(items, 'here is everything in the database.');
			}
		}
	}
	//Set how the database should be upgraded or instantiated.
	DBOpenRequest.onupgradeneeded = upgradeDatabase;
}

/*
	Delete all items listen in the items array argument.
*/
var deleteGearBagItems = function( items ) {
	//The database is set after a successful open request is ran.
	var db;

	var DBOpenRequest = window.indexedDB.open("gearBag", 1);
	DBOpenRequest.onsuccess = function( event ) {
		db = DBOpenRequest.result;
		var transaction = db.transaction(["items"], "readwrite");
		transaction.onerror = function( event ) {
			console.log( 'error on transaction', event.target.errorCode );
		}
		transaction.oncomplete = function( event ) {
			console.log( 'completed transaction', event );
			var objectStore = transaction.objectStore("items");

			for( var i in items )
			{
				var request = objectStore.delete(items[i]);
				request.onsuccess = function() {
					console.log('Removed an item from the gear bag.', items[i] );
				}
				request.onerror = function() {
					console.log( 'Failed to remove an item from the gear bag.', event.target.errorCode );
				}
			}
		}

	}
	DBOpenRequest.onerror = function( event ) {
		console.log( 'error opening the gear bag', event.target.errorCode );
	}
	DBOpenRequest.oncomplete = function( event ) {
		console.log( 'completed ', event );
	}
}

/*

	@param an array of items that should be checked whether or not they are in the database.

	@param callback has one parameter either true or false. True if the item was found, and false if it wasn't.
	The callback function should count how many times it is given the result true, if it returns for every single
	item passed, then everything thing is there, but if it returns false, then something is not there.

*/
function checkGearBagItems( items, callback ) {
	//The database is set after a successful open request is ran.
	var db;

	var DBOpenRequest = window.indexedDB.open("gearBag", 1);
	DBOpenRequest.onsuccess = function( event ) {
		console.log('maybe in here.');
		db = DBOpenRequest.result;

		var transaction = db.transaction(["items"], "readwrite");
		var objectStore = transaction.objectStore("items");

		for( var i = 0; i < items.length; i++ ) {
			console.log( 'checking', items[i] );

			var request = objectStore.get( items[i] );

			request.onsuccess = function( event ) {
				if( typeof request.result !== "undefined" && typeof request.result.name !== "undefined" )
				{
					callback(true);
				}
				else
				{
					//not sure if this stops the function this function is nested in.
					return callback(false);
				}
			}
			request.onerror = function( event ) {
				console.log( 'couldn\'t check for an item', event.target.errorCode );
			}
		}
		transaction.oncomplete = function( event ) {
			console.log('completed transaction', event );
		}
		transaction.onerror = function( event ) {
			console.log('Failed to start transaction with items.', event );
		}

	}

	DBOpenRequest.onerror = function( event ) {
		console.log( 'error opening the gear bag', event.target.errorCode );
	}

	DBOpenRequest.onupgradeneeded = upgradeDatabase;
}

/*
	Clear the default of doing absolutely nothing on drops for the droppables to declare
	the dropArea class element as an allowed drop area. Add special hilighting classes
	to the drop area when a drop enters the drop area.
*/
var setDropArea = function() {
	var dropArea = $$('div.dropArea')[0];

	/*
		You must prevent the default behavior on both dragenter and dragover
		according to the MDN guide on drag and drop.

		Do not use Mootools to add events because they are not working for some reason..
	*/
	dropArea.addEventListener('drop', handleGearBagDrop, false);
	dropArea.addEventListener('dragenter', handleDragEnter, false);
	dropArea.addEventListener('dragover', handleDragOver, false);
	dropArea.addEventListener('dragleave', handleDragLeave, false);

}

function handleGearBagDrop( event ) {

	//Get the data from the drop event.
	var data = event.dataTransfer.getData("text/plain");

	var handleDropCallback = function( inGearBag ) {
		console.log( 'Is it in the gearbag?', inGearBag );
		if( inGearBag ) {
			console.log( 'The item is already in the gear bag.');
			//TODO: Add message to tell the user that the item they dropped is already in the gearbag.
		}
		else {
			var itemObject = { name: data };
			addItemsToGearBag( [itemObject] );
		}
	}
	checkGearBagItems( [data], handleDropCallback );

	console.log( 'Checking for :', data );

	//TODO: Check if the dropped item is already in the database.
	//TODO: If the item is not in the database then add it.
	//Prevent the browser from handling the drop in case it decides to do something browsery.
	event.preventDefault();
}

function handleDragEnter( event ) {
	console.log('handleDragEnter');
	event.preventDefault();
	//TODO: Highlight the droppable or something schnazzy.
}

/*
	Iterate through the list provided to see if it contains at least one type that is equal to the value.
*/
function contains( list, value ) {

	for( var i = 0; i < list.length; i++ )
	{
		if( list[i] === value )
		{
			return true;
		}
	}

	return false
}

function handleDragOver( event ) {

	//The default is to not do anything, but if the drag contains plain text, then allow the drop.
	var isPlainText = contains( event.dataTransfer.types, "text/plain" )

	if( isPlainText )
	{
		console.log('DOING THE THING YOU SAID');
		event.preventDefault();
	}
}

/*
	Drag leave will be called even on the drag being cancelled so you can be
	sure that it can do cleanup.
*/
function handleDragLeave( event ) {
	//TODO: Remove hilighting and schnazz.
	console.log('handleDragLeave');
}

setDropArea();
getAllCategories.get({});
//addItemToGearBag( [{name: "1965-1969 Chevrolet Corvair"}] );
//deleteGearBagItems( ["1965-1969 Chevrolet Corvair"] );
<commit_msg>Added splitting up the uri with a regular expression.<commit_after>/*
	Guy Moore 3/2015 - Ifixit ninja test.

	TODO: Figure out how to store id's for tiles.
	TODO: Add pagination.
	TODO: Show placeholder before an image has loaded.
*/

//Categories that will be pulled from the ifixit api.
var categories;

/*
	Request 20 items, this will just be to test adding tiles to the page..
	TODO: Add category hierarchy, so the user doesn't have to go through a list of things.
*/
var getAllCategories = new Request.JSON({
	url: 'https://www.ifixit.com/api/2.0/categories/all',
	onSuccess: function( responseJSON, responseText ) {
		categories = responseJSON;
		//Iterate through the categories and
		for( var x = 0; x < categories.length; x++ )
		{
			//Create a new category and store the div.
			var categoryDiv = createCategory(categories[x]);

			//Get the image for the category and insert it into the previously created category.
			getCategoryImage( categories[x], categoryDiv )
		}
		/*
			TODO: Figure out how ids should be stored before uncommenting this.
			for( var x = 0; x < categories.length; x++ )
			{
				getCategoryImage(categories[x]);
			}
		*/
	},
	onError: function( text, error ) {
		alert('There was a problem getting the categories.');
	}
});

//TODO: Correct how the id is selected once you figure out what it should be.
/*
	Get an image for the specific category argument.

	@param category String the name of the category
*/
var getCategoryImage = function( category, div ) {
	var imageRequest = new Request.JSON({
		url: 'https://www.ifixit.com/api/2.0/categories/' + category,
		onSuccess: function( responseJSON, responseText ) {

			//Check to make sure that there is an image, if not set placeholder.
			var imageSource;
			if( responseJSON['image'] !== null && responseJSON['image']['medium'] !== null ) {
				imageSource = responseJSON['image']['medium'];
			}
			else {
				//TODO: Add placeholder image for items that don't have an image.
				imageSource = "img/cross.svg";
			}

			var image = new Element( 'img', {
				src: imageSource,
				alt: category,
				class: 'categoryImage',
				draggable: 'false' //Don't allow just the image to be dragged.
			});

			//Insert the new image element at the top of the div for the current category.
			image.inject( div, 'top');
		},
		onError: function( error ) {
			console.log('Failed to get the image for ' + category );
		}
	}).get();
}

/*
	Create a new category and insesrt it into the mainBody.

	@return div object for the category.
*/
var createCategory = function( category ) {

	//
	var onDragStart = 'event.dataTransfer.setData(\'text/plain\', \'' + category + '\')';

	//Create a new div for the category
	var categoryDiv = new Element('div', {
		class: 'category tile',
		id: category, //TODO: Fix what the id should be set to, since it can't contain spaces.
		draggable: 'true'
		//ondragstart: onDragStart
	});

	//This doesn't work? I don't know why this doesn't work. TODO: Ask iFixit why this doesn't work.
	//If I had to guess, it is because it doesn't see any valid drop targets.
	//NOPE the other method will work without valid drop targets, so this should too.
	/*
	//The events that happen when dragging starts.
	categoryDiv.addEvent('dragstart', function( event ) {
		console.log('started drag event.');
		event.dataTransfer.setData('text/plain', category);
		event.dataTransfer.effectAllowed = "copy";
		//Set the drag image for the cursor.
		//event.dataTransfer.setDragImage( image, xOffset, yOffset);
	})
	*/

	//Do everything vanilla because mootools doesn't work for this. Why do you make me sad Mootools :(
	categoryDiv.addEventListener('dragstart', handleDragStart, false);
	categoryDiv.addEventListener('dragend', handleDragEnd, false);

	//Nest the drag start event handler so we can set the category as the transfer data for the drag,
	//otherwise we would not be able to pass data when dragging.
	function handleDragStart( event ) {
		//Set the data type so this will work in firefox.
		event.dataTransfer.setData('text/plain', category)
	}

	//This is the text describing what the tile is, it is the lower title of the tile.
	var categoryTitle = new Element('p', {
		class: 'categoryTitle',
		html: category
	});

	//Insert the newly created category into the main body.
	categoryDiv.inject(mainBody);
	//nest the title in its div.
	categoryTitle.inject( categoryDiv );

	return categoryDiv;
}

function handleDragEnd( event ) {
	//Prevent the default action.
	event.preventDefault();
}

function addItemsToGearBag( items ) {

	//MDN says not to do this, prefixed names are buggy. Possible that these don't use standards.
	//var indexedDB = window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;

	var db;
	var DBOpenRequest = window.indexedDB.open("gearBag", 1);
	DBOpenRequest.onsuccess = function( event ) {
		db = DBOpenRequest.result;
		var transaction = db.transaction(["items"], "readwrite");
		transaction.onerror = function( event ) {
			console.log( 'error on transaction', event );
		}
		transaction.oncomplete = function( event ) {
			console.log( 'completed transaction', event );
		}

		var objectStore = transaction.objectStore("items");
		for( var i in items ) {
			console.log(items[i]);
			var request = objectStore.add(items[i]);
			request.onsuccess = function( event ) {
				console.log( 'Added an item.', items[i] );
			}
			request.onerror = function( event ) {
				console.log( 'There was an error adding an item.', items[i] );
			}
		}
	}
	DBOpenRequest.onerror = function( event ) {
		console.log('There was an error opening the gear bag', event.target.errorCode);
	}

	//Handle what needs to happen if the database isn't created or is an older version.
	DBOpenRequest.onupgradeneeded = upgradeDatabase;
}

/*
	Handle upgrading, or instantiating the datbase.

	@paramater the event from the onupgradeneeded event.
*/
function upgradeDatabase( event ) {

	console.log('upgrading the database');

	//Handle upgrading the db or creating it..
	var db = event.target.result;

	//Adding the object store named Items with a key called name.
	var objectStore = db.createObjectStore("items", { keyPath: "name" });

	//Adding an index for the quantity of items.
	//objectStore.createIndex("number", "number", { unique: false });
}

/*
	Retrieve all of the gear bag items.

	@parameter callback function first paramter error, second parameter
*/
function getAllGearBagItems( callback ) {

	//The database is set after a successful open request is ran.
	var db;

	//Create the request to open the gear bag.
	var DBOpenRequest = window.indexedDB.open("gearBag", 1);
	DBOpenRequest.onsuccess = function( event ) {
		db = DBOpenRequest.result;
		var transaction = db.transaction(["items"], "readwrite");
		transaction.onerror = function( event ) {
			console.log( 'error on transaction', event.target.errorCode );
			callback( event.result );
		}
		transaction.oncomplete = function( event ) {
			console.log( 'completed transaction', event );
		}

		var objectStore = transaction.objectStore("items");

		//Array of all the items.
		var items = [];
		objectStore.openCursor().onsuccess = function( event ) {
			var cursor = event.target.result;
			if( cursor ) {
				items.push(cursor.value);
				cursor.continue();
			}
			else
			{
				callback( Null, items );
				console.log(items, 'here is everything in the database.');
			}
		}
	}
	//Set how the database should be upgraded or instantiated.
	DBOpenRequest.onupgradeneeded = upgradeDatabase;
}

/*
	Delete all items listen in the items array argument.
*/
var deleteGearBagItems = function( items ) {
	//The database is set after a successful open request is ran.
	var db;

	var DBOpenRequest = window.indexedDB.open("gearBag", 1);
	DBOpenRequest.onsuccess = function( event ) {
		db = DBOpenRequest.result;
		var transaction = db.transaction(["items"], "readwrite");
		transaction.onerror = function( event ) {
			console.log( 'error on transaction', event.target.errorCode );
		}
		transaction.oncomplete = function( event ) {
			console.log( 'completed transaction', event );
			var objectStore = transaction.objectStore("items");

			for( var i in items )
			{
				var request = objectStore.delete(items[i]);
				request.onsuccess = function() {
					console.log('Removed an item from the gear bag.', items[i] );
				}
				request.onerror = function() {
					console.log( 'Failed to remove an item from the gear bag.', event.target.errorCode );
				}
			}
		}

	}
	DBOpenRequest.onerror = function( event ) {
		console.log( 'error opening the gear bag', event.target.errorCode );
	}
	DBOpenRequest.oncomplete = function( event ) {
		console.log( 'completed ', event );
	}
}

/*

	@param an array of items that should be checked whether or not they are in the database.

	@param callback has one parameter either true or false. True if the item was found, and false if it wasn't.
	The callback function should count how many times it is given the result true, if it returns for every single
	item passed, then everything thing is there, but if it returns false, then something is not there.

*/
function checkGearBagItems( items, callback ) {
	//The database is set after a successful open request is ran.
	var db;

	var DBOpenRequest = window.indexedDB.open("gearBag", 1);
	DBOpenRequest.onsuccess = function( event ) {
		console.log('maybe in here.');
		db = DBOpenRequest.result;

		var transaction = db.transaction(["items"], "readwrite");
		var objectStore = transaction.objectStore("items");

		for( var i = 0; i < items.length; i++ ) {
			console.log( 'checking', items[i] );

			var request = objectStore.get( items[i] );

			request.onsuccess = function( event ) {
				if( typeof request.result !== "undefined" && typeof request.result.name !== "undefined" )
				{
					callback(true);
				}
				else
				{
					//not sure if this stops the function this function is nested in.
					return callback(false);
				}
			}
			request.onerror = function( event ) {
				console.log( 'couldn\'t check for an item', event.target.errorCode );
			}
		}
		transaction.oncomplete = function( event ) {
			console.log('completed transaction', event );
		}
		transaction.onerror = function( event ) {
			console.log('Failed to start transaction with items.', event );
		}

	}

	DBOpenRequest.onerror = function( event ) {
		console.log( 'error opening the gear bag', event.target.errorCode );
	}

	DBOpenRequest.onupgradeneeded = upgradeDatabase;
}

/*
	Clear the default of doing absolutely nothing on drops for the droppables to declare
	the dropArea class element as an allowed drop area. Add special hilighting classes
	to the drop area when a drop enters the drop area.
*/
var setDropArea = function() {
	var dropArea = $$('div.dropArea')[0];

	/*
		You must prevent the default behavior on both dragenter and dragover
		according to the MDN guide on drag and drop.

		Do not use Mootools to add events because they are not working for some reason..
	*/
	dropArea.addEventListener('drop', handleGearBagDrop, false);
	dropArea.addEventListener('dragenter', handleDragEnter, false);
	dropArea.addEventListener('dragover', handleDragOver, false);
	dropArea.addEventListener('dragleave', handleDragLeave, false);

}

function handleGearBagDrop( event ) {

	//Get the data from the drop event.
	var data = event.dataTransfer.getData("text/plain");

	var handleDropCallback = function( inGearBag ) {
		console.log( 'Is it in the gearbag?', inGearBag );
		if( inGearBag ) {
			console.log( 'The item is already in the gear bag.');
			//TODO: Add message to tell the user that the item they dropped is already in the gearbag.
		}
		else {
			var itemObject = { name: data };
			addItemsToGearBag( [itemObject] );
		}
	}
	checkGearBagItems( [data], handleDropCallback );

	console.log( 'Checking for :', data );

	//TODO: Check if the dropped item is already in the database.
	//TODO: If the item is not in the database then add it.
	//Prevent the browser from handling the drop in case it decides to do something browsery.
	event.preventDefault();
}

function handleDragEnter( event ) {
	console.log('handleDragEnter');
	event.preventDefault();
	//TODO: Highlight the droppable or something schnazzy.
}

/*
	Iterate through the list provided to see if it contains at least one type that is equal to the value.
*/
function contains( list, value ) {

	for( var i = 0; i < list.length; i++ )
	{
		if( list[i] === value )
		{
			return true;
		}
	}

	return false
}

function handleDragOver( event ) {

	//The default is to not do anything, but if the drag contains plain text, then allow the drop.
	var isPlainText = contains( event.dataTransfer.types, "text/plain" )

	if( isPlainText )
	{
		console.log('DOING THE THING YOU SAID');
		event.preventDefault();
	}
}

/*
	Drag leave will be called even on the drag being cancelled so you can be
	sure that it can do cleanup.
*/
function handleDragLeave( event ) {
	//TODO: Remove hilighting and schnazz.
	console.log('handleDragLeave');
}

/*
	Handle routing of pages.
*/
function handleHashChange() {

	uri = location.hash;
	var regex = /[^\/[^#]/g;
	var matched = null;
	while (matched = regex.exec(uri)) {
	  console.log(matched[0]);
	}
}

window.onhashchange = handleHashChange;

setDropArea();
getAllCategories.get({});
addItemToGearBag( [{name: "1965-1969 Chevrolet Corvair"}] );
//deleteGearBagItems( ["1965-1969 Chevrolet Corvair"] );
<|endoftext|>


<commit_before>'use strict';

function repo_init(){
    core_repo_init({
      'beforeunload': {
        'todo': function(){
            if(start_time > -1){
                return 'Timer and splits not yet saveable. Leave?';
            }
        },
      },
      'events': {
        'add-split': {
          'onclick': add_split,
        },
        'reset-key-display': {
          'onclick': reset_timer,
        },
        'start-key-display': {
          'onclick': start,
        },
        'stop': {
          'onclick': stop,
        },
      },
      'globals': {
        'current_time': {
          'hours': 0,
          'minutes': 0,
          'seconds': 0,
          'milliseconds': 0,
        },
        'start_time': -1,
        'time_ms': 0,
      },
      'keybinds': {
        32: {
          'todo': add_split,
        },
        72: {
          'todo': start,
        },
        84: {
          'todo': reset_timer,
        },
      },
      'title': 'Timer.htm',
    });

    core_interval_modify({
      'id': 'timer',
      'paused': true,
      'todo': draw,
    });
}
<commit_msg>added stop() to repo_escape()<commit_after>'use strict';

function repo_escape(){
    stop();
}

function repo_init(){
    core_repo_init({
      'beforeunload': {
        'todo': function(){
            if(start_time > -1){
                return 'Timer and splits not yet saveable. Leave?';
            }
        },
      },
      'events': {
        'add-split': {
          'onclick': add_split,
        },
        'reset-key-display': {
          'onclick': reset_timer,
        },
        'start-key-display': {
          'onclick': start,
        },
        'stop': {
          'onclick': stop,
        },
      },
      'globals': {
        'current_time': {
          'hours': 0,
          'minutes': 0,
          'seconds': 0,
          'milliseconds': 0,
        },
        'start_time': -1,
        'time_ms': 0,
      },
      'keybinds': {
        32: {
          'todo': add_split,
        },
        72: {
          'todo': start,
        },
        84: {
          'todo': reset_timer,
        },
      },
      'title': 'Timer.htm',
    });

    core_interval_modify({
      'id': 'timer',
      'paused': true,
      'todo': draw,
    });
}
<|endoftext|>


<commit_before>
function randAngle() {
  var rand = Math.random()
  return rand * 2 * Math.PI
}

function generateStep(lastStep) {
  var l = 1
  var angle = randAngle()
  var x = l * Math.cos(angle) + lastStep.position.x
  var y = l * Math.sin(angle) + lastStep.position.y
  var d = Math.sqrt(Math.pow(x,2) + Math.pow(y,2))
  var i = lastStep.step + 1
  return {position: {x: x, y: y}, distance: d, step: i}
}

function drawCanvas(stepList) {
  var path_ctx = document.getElementById("path-chart")
  var distance_ctx = document.getElementById("distance-chart")
  var pathData = stepList.map((step) => { return step.position })
  var distanceData = stepList.map((step) => { return {x: step.step, y: step.distance} })
  console.log(distanceData);

  var pathChart = new Chart(path_ctx, {
      type: 'line',
      data: {
        datasets: [{
          lineTension: 0,
          borderWidth: 2,
          borderColor: "rgba(75,192,192,1)",
          fill: false,
          label: 'Caminho',
          data: pathData
        }]
      },
      options: {
        scales: {
          xAxes: [{
            type: 'linear',
            position: 'bottom'
          }]
        }
      }
  });
  var distanceChart = new Chart(distance_ctx, {
      type: 'line',
      data: {

        datasets: [{
          lineTension: 0,
          borderWidth: 2,
          borderColor: "rgba(75,192,192,1)",
          fill: false,
          label: 'Distancia',
          data: distanceData
        }]
      },
      options: {
        scales: {
          yAxes: [{
            display: true
          }]
        }
      }
  });
}

function simulate(steps) {
  var stepList = []
  stepList.push({position: {x: 0, y: 0}, distance: 0, step: 0})

  for (var i = 0; i < steps; i++) {
    var lastStep = stepList.slice(-1)[0]
    stepList.push(generateStep(lastStep))
  }

  drawCanvas(stepList)

}
<commit_msg>Fix distance chart<commit_after>
function randAngle() {
  var rand = Math.random()
  return rand * 2 * Math.PI
}

function generateStep(lastStep) {
  var l = 1
  var angle = randAngle()
  var x = l * Math.cos(angle) + lastStep.position.x
  var y = l * Math.sin(angle) + lastStep.position.y
  var d = Math.sqrt(Math.pow(x,2) + Math.pow(y,2))
  var i = lastStep.step + 1
  var e = Math.sqrt(i)
  return {position: {x: x, y: y}, distance: d, step: i, estimated: e}
}

function drawCanvas(stepList) {
  var path_ctx = document.getElementById("path-chart")
  var distance_ctx = document.getElementById("distance-chart")
  var pathData = stepList.map((step) => { return step.position })
  var distanceData = stepList.map((step) => { return {x: step.step, y: step.distance} })
  var estimatedDistanceData = stepList.map((step) => { return {x: step.step, y: step.estimated} })
  console.log(distanceData);

  var pathChart = new Chart(path_ctx, {
      type: 'line',
      data: {
        datasets: [{
          lineTension: 0,
          borderWidth: 2,
          borderColor: "#FFC000",
          backgroundColor: "#FFC000",
          pointBorderColor: "#64c2d6",
          pointBackgroundColor: "#4F81BC",
          pointBorderWidth: 1,
          fill: false,
          label: 'Caminho',
          data: pathData
        }]
      },
      options: {
        tooltips: {
          position: 'nearest',
          bodyFontStyle: 'bold',
          displayColors: false,
          callbacks: {
            label: (tooltipItems) => {
              return 'y: ' + tooltipItems.yLabel.toFixed(3);
            },
            title: (tooltipItems) => {
              return 'x: ' + tooltipItems[0].xLabel.toFixed(3);
            }
          }
        },
        legend: {
          onClick: null
        },
        scales: {
          xAxes: [{
            type: 'linear',
            position: 'bottom'
          }]
        }
      }
  });
  var distanceChart = new Chart(distance_ctx, {
      type: 'line',
      data: {

        datasets: [{
          lineTension: 0,
          borderWidth: 2,
          borderColor: "#4F81BC",
          backgroundColor: "#4F81BC",
          fill: false,
          label: 'Distancia',
          data: distanceData,
          pointRadius: 0,
          hitRadius: 5
        }, {
          lineTension: 0.4,
          borderWidth: 2,
          borderColor: "#BD4A47",
          backgroundColor: "#BD4A47",
          fill: false,
          label: 'Estimado (\u221An)',
          data: estimatedDistanceData,
          pointRadius: 0,
          hitRadius: 5
        }]
      },
      options: {
        tooltips: {
          mode: 'index',
          position: 'nearest',
          callbacks: {
            label: (tooltipItems) => {
              return ' ' + tooltipItems.yLabel.toFixed(3);
            },
            title: (tooltipItems) => {
              return 'Passo ' + tooltipItems[0].xLabel;
            }
          }
        },
        legend: {
          onClick: null
        },
        scales: {
          xAxes: [{
            type: 'linear',
            position: 'bottom'
          }]
        }
      }
  });
}

function simulate(steps) {
  var stepList = []
  stepList.push({position: {x: 0, y: 0}, distance: 0, step: 0, estimated: 0})

  for (var i = 0; i < steps; i++) {
    var lastStep = stepList.slice(-1)[0]
    stepList.push(generateStep(lastStep))
  }

  drawCanvas(stepList)

}
<|endoftext|>


<commit_before>var chalmersId = "9021014001960000";
var kapellplatsenId = "9021014003760000";
var chalmersTvargataId = "9021014001970000";
var chalmersplatsenId = "9021014001961000";

var monthObj = ["januari", "februari", "mars", "april", "maj", "juni", "juli", "augusti", "september", "oktober", "november", "december"];
var dayObj = ["Söndag", "Måndag", "Tisdag", "Untzdag", "Torsdag", "Fredag", "Lördag"];

var newDate = new Date();

function getStops() {
	var baseUrl = "https://api.fam-ericsson.se/vasttrafik/?id=";

	$.getJSON(baseUrl + chalmersId, function(data) {
		var api = data;

		if (api.trafik != null) {
			var serverTime = api.serverDateTime.unixTimestamp;

			$("#chalmersTable").html("");

			$.each(api.trafik, function(currentFirst, linjeinfo) {
				$.each(linjeinfo.avgang, function(currentSecond, avgang) {

					var nasta = timeDiff(avgang.unixTimestamp[0], serverTime) / 60;
					var darefter = timeDiff(avgang.unixTimestamp[1], serverTime) / 60;

					if (isNaN(darefter)) {
						darefter = "-";
					}
					if (nasta <= 0) {
						nasta = "nu";
					}
					if (darefter <= 0) {
						darefter = "nu";
					}
					if (linjeinfo.linje == 55 && linjeinfo.trafiktyp == "buss") {
						linjeinfo.bgFarg = "#EAF5CC";
						linjeinfo.fgFarg = "#3AB73D";
					}

					$("#chalmersTable").append("
" + linjeinfo.linje + "	 " + avgang.resmal + " 	" + avgang.lage[0] + "	" + nasta + "	" + darefter + "	");
				});
			});
		} else {
			$("#chalmersTable").html("
	 Inga avgångar	-	60+	-	");
		}
	});

	$.getJSON(baseUrl + kapellplatsenId, function(data) {
		var api = data;

		if (api.trafik != null) {
			var serverTime = api.serverDateTime.unixTimestamp;

			$("#kapellplatsenTable").html("");

			$.each(api.trafik, function(currentFirst, linjeinfo) {
				$.each(linjeinfo.avgang, function(currentSecond, avgang) {

					var nasta = timeDiff(avgang.unixTimestamp[0], serverTime) / 60;
					var darefter = timeDiff(avgang.unixTimestamp[1], serverTime) / 60;

					if (isNaN(darefter)) {
						darefter = "-";
					}
					if (nasta <= 0) {
						nasta = "nu";
					}
					if (darefter <= 0) {
						darefter = "nu";
					}
					if (linjeinfo.linje == 55 && linjeinfo.trafiktyp == "buss") {
						linjeinfo.bgFarg = "#EAF5CC";
						linjeinfo.fgFarg = "#3AB73D";
					}

					$("#kapellplatsenTable").append("
" + linjeinfo.linje + "	 " + avgang.resmal + " 	" + avgang.lage[0] + "	" + nasta + "	" + darefter + "	");
				});
			});
		} else {
			$("#kapellplatsenTable").html("
	 Inga avgångar	-	60+	-	");
		}
	});

	$.getJSON(baseUrl + chalmersTvargataId, function(data) {
		var api = data;

		if (api.trafik != null) {
			var serverTime = api.serverDateTime.unixTimestamp;

			$("#chalmersTvargataTable").html("");

			$.each(api.trafik, function(currentFirst, linjeinfo) {
				$.each(linjeinfo.avgang, function(currentSecond, avgang) {

					var nasta = timeDiff(avgang.unixTimestamp[0], serverTime) / 60;
					var darefter = timeDiff(avgang.unixTimestamp[1], serverTime) / 60;

					if (isNaN(darefter)) {
						darefter = "-";
					}
					if (nasta <= 0) {
						nasta = "nu";
					}
					if (darefter <= 0) {
						darefter = "nu";
					}
					if (linjeinfo.linje == 55 && linjeinfo.trafiktyp == "buss") {
						linjeinfo.bgFarg = "#EAF5CC";
						linjeinfo.fgFarg = "#3AB73D";
					}

					$("#chalmersTvargataTable").append("
" + linjeinfo.linje + "	 " + avgang.resmal + " 	" + avgang.lage[0] + "	" + nasta + "	" + darefter + "	");
				});
			});
		} else {
			$("#chalmersTvargataTable").html("
	 Inga avgångar	-	60+	-	");
		}
	});

	$.getJSON(baseUrl + chalmersplatsenId, function(data) {
		var api = data;

		if (api.trafik != null) {
			var serverTime = api.serverDateTime.unixTimestamp;

			$("#chalmersplatsenTable").html("");

			$.each(api.trafik, function(currentFirst, linjeinfo) {
				$.each(linjeinfo.avgang, function(currentSecond, avgang) {

					var nasta = timeDiff(avgang.unixTimestamp[0], serverTime) / 60;
					var darefter = timeDiff(avgang.unixTimestamp[1], serverTime) / 60;

					if (isNaN(darefter)) {
						darefter = "-";
					}
					if (nasta <= 0) {
						nasta = "nu";
					}
					if (darefter <= 0) {
						darefter = "nu";
					}
					if (linjeinfo.linje == 55 && linjeinfo.trafiktyp == "buss") {
						linjeinfo.bgFarg = "#EAF5CC";
						linjeinfo.fgFarg = "#3AB73D";
					}

					$("#chalmersplatsenTable").append("
" + linjeinfo.linje + "	 " + avgang.resmal + " 	" + avgang.lage[0] + "	" + nasta + "	" + darefter + "	");
				});
			});
		} else {
			$("#chalmersplatsenTable").html("
	 Inga avgångar	-	60+	-	");
		}
	});
}

function getFood() {
	var matsedel_dagar = ["Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag"];
	$.getJSON("https://api.fam-ericsson.se/matsedel/beta/", function(data) {
		$("#matsedel_dagar").html("");
		var date = new Date();
		var day = date.getDay();
		if (matsedel_dagar[day] == "Lördag" || matsedel_dagar[day] == "Söndag") {
			$("#matsedel_dagar").html("
" + matsedel_dagar[day] + "

Ingen mat idag
");
		} else {
			$.each(data.food, function(curr, food) {
				if (food.day == matsedel_dagar[day]) {
					if (food.day == "Onsdag") {
						food.day = "Untzdag";
					}
					$("#matsedel_dagar").append("
" + food.day + "

" + food.reg + "
Vegetariskt
" + food.veg + "
");
					if (matsedel_dagar[day] != "Fredag") {
						$("#matsedel_dagar").append("
");
					}
				} else if (food.day == matsedel_dagar[day + 1] && matsedel_dagar[day + 1] != "Lördag") {
					if (food.day == "Onsdag") {
						food.day = "Untzdag";
					}
					$("#matsedel_dagar").append("
" + food.day + "

" + food.reg + "
Vegetariskt
" + food.veg + "
");
				}
			});
		}
	});
}

function getGitHub() {
	$.getJSON("https://api.github.com/repos/itggot-joel-eriksson/ITG-Infoskarm/releases", function (data) {
	    var title = "Version";
	    var body = data[0].tag_name;
	    body = body.replace("-", "--");
	    var color = "green";
	    if (data[0].prerelease) {
	        color = "red";
	    }

	    var img_url = "https://img.shields.io/badge/" + title + "-" + body + "-" + color + ".svg?style=flat-square&v=" + Date.now();

		if ($("#github_version").length == 0 && color == "red") {
			$("body").prepend("");
		} else if (color == "red") {
			$("#github_version").attr("src", img_url);
		} else {
			$("#github_version").remove();
		}
	});
}

function timeDiff(fromUnix, toUnix) {
	return Math.abs(Math.floor(fromUnix - toUnix));
}

function dateDiff(fromDate, toDate, interval) {
	var second=1000, minute=second*60, hour=minute*60, day=hour*24, week=day*7;
	fromDate = new Date(fromDate);
	toDate = new Date(toDate);
	var timediff = toDate - fromDate;
	if (isNaN(timediff)) {
		return NaN
	};
	switch (interval) {
		case "years": return toDate.getFullYear() - fromDate.getFullYear();
		case "months": return (
			( toDate.getFullYear() * 12 + toDate.getMonth() )
			-
			( fromDate.getFullYear() * 12 + fromDate.getMonth() )
		);
		case "weeks"  : return Math.floor(timediff / week);
		case "days"   : return Math.floor(timediff / day);
		case "hours"  : return Math.floor(timediff / hour);
		case "minutes": return Math.abs(Math.floor(timediff / minute));
		case "seconds": return Math.floor(timediff / second);
		default: return undefined;
	}
}

function clock() {
	var now = new Date();
	var year = now.getFullYear();
	var month = now.getMonth() + 1;
	var date = now.getDate();

	var hours = now.getHours();
	var minutes = now.getMinutes();
	var seconds = now.getSeconds();

	if(seconds < 10) {
		seconds = "0" + seconds;
	} else {
		seconds = seconds.toString();
	}
	if(minutes < 10) {
		minutes = "0" + minutes;
	} else {
		minutes = minutes.toString();
	}
	if(hours < 10) {
		hours = "0" + hours;
	} else {
		hours = hours.toString();
	}
	if(date < 10) {
		date = "0" + date;
	} else {
		date = date.toString();
	}
	if(month < 10) {
		month = "0" + month;
	} else {
		month = month.toString();
	}

	$("#datetime #clock").html("
" + hours + ":" + minutes + ":" + seconds + "
");

	var today = "
" + dayObj[now.getDay()] + " " + date + " " + monthObj[month - 1] + "
Vecka " + getWeek() + "
";
	$("#datetime #date").html(today);

	if(seconds == "00" || seconds == "30") {
        getStops();
		chalmersCam();
	}

	if (minutes == "00" && seconds == "00") {
		getFood();
		getGitHub();
	}
}

function chalmersCam() {
	$("#chalmers_cam").attr("src", "https://api.fam-ericsson.se/gbgcamera/?camera=17&v=" + Date.now()).on("error", function() {
		$(this).attr("src", "img/error.png");
		chalmersCam();
	});
}

function getWeek() {
	date = new Date();
	weekdays = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
	weekday = weekdays[date.getDay()];
	date.setHours(0,0,0);
	date.setDate(date.getDate() + 4 - (date.getDay()||7));
	yearStart = new Date(date.getFullYear(),0,1);
	weekNo = Math.ceil(( ( (date - yearStart) / 86400000) + 1)/7);
	return weekNo;
}

clock();
getStops();
chalmersCam();
getFood();
getGitHub();

var clockInterval = setInterval(clock,1000);
<commit_msg>Datumformatering och hämta om i js/main.js<commit_after>var chalmersId = "9021014001960000";
var kapellplatsenId = "9021014003760000";
var chalmersTvargataId = "9021014001970000";
var chalmersplatsenId = "9021014001961000";

var monthObj = ["januari", "februari", "mars", "april", "maj", "juni", "juli", "augusti", "september", "oktober", "november", "december"];
var dayObj = ["Söndag", "Måndag", "Tisdag", "Untzdag", "Torsdag", "Fredag", "Lördag"];

var newDate = new Date();

function getStops() {
	var baseUrl = "https://api.fam-ericsson.se/vasttrafik/?id=";

	$.getJSON(baseUrl + chalmersId, function(data) {
		var api = data;

		if (api.trafik != null) {
			var serverTime = api.serverDateTime.unixTimestamp;

			$("#chalmersTable").html("");

			$.each(api.trafik, function(currentFirst, linjeinfo) {
				$.each(linjeinfo.avgang, function(currentSecond, avgang) {

					var nasta = timeDiff(avgang.unixTimestamp[0], serverTime) / 60;
					var darefter = timeDiff(avgang.unixTimestamp[1], serverTime) / 60;

					if (isNaN(darefter)) {
						darefter = "-";
					}
					if (nasta <= 0) {
						nasta = "nu";
					}
					if (darefter <= 0) {
						darefter = "nu";
					}
					if (linjeinfo.linje == 55 && linjeinfo.trafiktyp == "buss") {
						linjeinfo.bgFarg = "#EAF5CC";
						linjeinfo.fgFarg = "#3AB73D";
					}

					$("#chalmersTable").append("
" + linjeinfo.linje + "	 " + avgang.resmal + " 	" + avgang.lage[0] + "	" + nasta + "	" + darefter + "	");
				});
			});
		} else {
			$("#chalmersTable").html("
	 Inga avgångar	-	60+	-	");
		}
	});

	$.getJSON(baseUrl + kapellplatsenId, function(data) {
		var api = data;

		if (api.trafik != null) {
			var serverTime = api.serverDateTime.unixTimestamp;

			$("#kapellplatsenTable").html("");

			$.each(api.trafik, function(currentFirst, linjeinfo) {
				$.each(linjeinfo.avgang, function(currentSecond, avgang) {

					var nasta = timeDiff(avgang.unixTimestamp[0], serverTime) / 60;
					var darefter = timeDiff(avgang.unixTimestamp[1], serverTime) / 60;

					if (isNaN(darefter)) {
						darefter = "-";
					}
					if (nasta <= 0) {
						nasta = "nu";
					}
					if (darefter <= 0) {
						darefter = "nu";
					}
					if (linjeinfo.linje == 55 && linjeinfo.trafiktyp == "buss") {
						linjeinfo.bgFarg = "#EAF5CC";
						linjeinfo.fgFarg = "#3AB73D";
					}

					$("#kapellplatsenTable").append("
" + linjeinfo.linje + "	 " + avgang.resmal + " 	" + avgang.lage[0] + "	" + nasta + "	" + darefter + "	");
				});
			});
		} else {
			$("#kapellplatsenTable").html("
	 Inga avgångar	-	60+	-	");
		}
	});

	$.getJSON(baseUrl + chalmersTvargataId, function(data) {
		var api = data;

		if (api.trafik != null) {
			var serverTime = api.serverDateTime.unixTimestamp;

			$("#chalmersTvargataTable").html("");

			$.each(api.trafik, function(currentFirst, linjeinfo) {
				$.each(linjeinfo.avgang, function(currentSecond, avgang) {

					var nasta = timeDiff(avgang.unixTimestamp[0], serverTime) / 60;
					var darefter = timeDiff(avgang.unixTimestamp[1], serverTime) / 60;

					if (isNaN(darefter)) {
						darefter = "-";
					}
					if (nasta <= 0) {
						nasta = "nu";
					}
					if (darefter <= 0) {
						darefter = "nu";
					}
					if (linjeinfo.linje == 55 && linjeinfo.trafiktyp == "buss") {
						linjeinfo.bgFarg = "#EAF5CC";
						linjeinfo.fgFarg = "#3AB73D";
					}

					$("#chalmersTvargataTable").append("
" + linjeinfo.linje + "	 " + avgang.resmal + " 	" + avgang.lage[0] + "	" + nasta + "	" + darefter + "	");
				});
			});
		} else {
			$("#chalmersTvargataTable").html("
	 Inga avgångar	-	60+	-	");
		}
	});

	$.getJSON(baseUrl + chalmersplatsenId, function(data) {
		var api = data;

		if (api.trafik != null) {
			var serverTime = api.serverDateTime.unixTimestamp;

			$("#chalmersplatsenTable").html("");

			$.each(api.trafik, function(currentFirst, linjeinfo) {
				$.each(linjeinfo.avgang, function(currentSecond, avgang) {

					var nasta = timeDiff(avgang.unixTimestamp[0], serverTime) / 60;
					var darefter = timeDiff(avgang.unixTimestamp[1], serverTime) / 60;

					if (isNaN(darefter)) {
						darefter = "-";
					}
					if (nasta <= 0) {
						nasta = "nu";
					}
					if (darefter <= 0) {
						darefter = "nu";
					}
					if (linjeinfo.linje == 55 && linjeinfo.trafiktyp == "buss") {
						linjeinfo.bgFarg = "#EAF5CC";
						linjeinfo.fgFarg = "#3AB73D";
					}

					$("#chalmersplatsenTable").append("
" + linjeinfo.linje + "	 " + avgang.resmal + " 	" + avgang.lage[0] + "	" + nasta + "	" + darefter + "	");
				});
			});
		} else {
			$("#chalmersplatsenTable").html("
	 Inga avgångar	-	60+	-	");
		}
	});
}

function getFood() {
	var matsedel_dagar = ["Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag"];
	$.getJSON("https://api.fam-ericsson.se/matsedel/beta/", function(data) {
		$("#matsedel_dagar").html("");
		var date = new Date();
		var day = date.getDay();
		if (matsedel_dagar[day] == "Lördag" || matsedel_dagar[day] == "Söndag") {
			$("#matsedel_dagar").html("
" + matsedel_dagar[day] + "

Ingen mat idag
");
		} else {
			$.each(data.food, function(curr, food) {
				if (food.day == matsedel_dagar[day]) {
					if (food.day == "Onsdag") {
						food.day = "Untzdag";
					}
					$("#matsedel_dagar").append("
" + food.day + "

" + food.reg + "
Vegetariskt
" + food.veg + "
");
					if (matsedel_dagar[day] != "Fredag") {
						$("#matsedel_dagar").append("
");
					}
				} else if (food.day == matsedel_dagar[day + 1] && matsedel_dagar[day + 1] != "Lördag") {
					if (food.day == "Onsdag") {
						food.day = "Untzdag";
					}
					$("#matsedel_dagar").append("
" + food.day + "

" + food.reg + "
Vegetariskt
" + food.veg + "
");
				}
			});
		}
	});
}

function getGitHub() {
	$.getJSON("https://api.github.com/repos/itggot-joel-eriksson/ITG-Infoskarm/releases", function (data) {
	    var title = "Version";
	    var body = data[0].tag_name;
	    body = body.replace("-", "--");
	    var color = "green";
	    if (data[0].prerelease) {
	        color = "red";
	    }

	    var img_url = "https://img.shields.io/badge/" + title + "-" + body + "-" + color + ".svg?style=flat-square&v=" + Date.now();

		if ($("#github_version").length == 0 && color == "red") {
			$("body").prepend("");
		} else if (color == "red") {
			$("#github_version").attr("src", img_url);
		} else {
			$("#github_version").remove();
		}
	});
}

function timeDiff(fromUnix, toUnix) {
	return Math.abs(Math.floor(fromUnix - toUnix));
}

function dateDiff(fromDate, toDate, interval) {
	var second=1000, minute=second*60, hour=minute*60, day=hour*24, week=day*7;
	fromDate = new Date(fromDate);
	toDate = new Date(toDate);
	var timediff = toDate - fromDate;
	if (isNaN(timediff)) {
		return NaN
	};
	switch (interval) {
		case "years": return toDate.getFullYear() - fromDate.getFullYear();
		case "months": return (
			( toDate.getFullYear() * 12 + toDate.getMonth() )
			-
			( fromDate.getFullYear() * 12 + fromDate.getMonth() )
		);
		case "weeks"  : return Math.floor(timediff / week);
		case "days"   : return Math.floor(timediff / day);
		case "hours"  : return Math.floor(timediff / hour);
		case "minutes": return Math.abs(Math.floor(timediff / minute));
		case "seconds": return Math.floor(timediff / second);
		default: return undefined;
	}
}

function clock() {
	var now = new Date();
	var year = now.getFullYear();
	var month = now.getMonth() + 1;
	var date = now.getDate();

	var hours = now.getHours();
	var minutes = now.getMinutes();
	var seconds = now.getSeconds();

	if(seconds < 10) {
		seconds = "0" + seconds;
	} else {
		seconds = seconds.toString();
	}
	if(minutes < 10) {
		minutes = "0" + minutes;
	} else {
		minutes = minutes.toString();
	}
	if(hours < 10) {
		hours = "0" + hours;
	} else {
		hours = hours.toString();
	}

	$("#datetime #clock").html("
" + hours + ":" + minutes + ":" + seconds + "
");

	var today = "
" + dayObj[now.getDay()] + " " + date + " " + monthObj[month - 1] + "
Vecka " + getWeek() + "
";
	$("#datetime #date").html(today);

	if(seconds == "00" || seconds == "30") {
        getStops();
		chalmersCam();
	}

	if (minutes == "00" && seconds == "00") {
		getFood();
		getGitHub();
	}

	if (hours == "00" && minutes == "00" && seconds == "00") {
		location.reload();
	}
}

function chalmersCam() {
	$("#chalmers_cam").attr("src", "https://api.fam-ericsson.se/gbgcamera/?camera=17&v=" + Date.now()).on("error", function() {
		$(this).attr("src", "img/error.png");
		chalmersCam();
	});
}

function getWeek() {
	date = new Date();
	weekdays = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
	weekday = weekdays[date.getDay()];
	date.setHours(0,0,0);
	date.setDate(date.getDate() + 4 - (date.getDay()||7));
	yearStart = new Date(date.getFullYear(),0,1);
	weekNo = Math.ceil(( ( (date - yearStart) / 86400000) + 1)/7);
	return weekNo;
}

clock();
getStops();
chalmersCam();
getFood();
getGitHub();

var clockInterval = setInterval(clock,1000);
<|endoftext|>


<commit_before>(function ($) {
  'use strict';

  var navbarHeight = $('.navbar').height();

  $('body').scrollspy({
    target: '#navbar',
    offset: navbarHeight + 10
  });

  $('a[href^="#"]').click(function (event) {
    event.preventDefault();

    $('#navbar').collapse('hide');

    var target = this.hash || 'body';

    $(window).stop(true).scrollTo(target, {
      duration: 1000,
      interrupt: true,
      offset: -navbarHeight
    });
  });

  var source = $('#reviews-template').html();
  var template = Handlebars.compile(source);
  var context = {
    reviews: [
      {
        reviewer: 'Andrei Popescu',
        avatar: 'assets/app/img/avatar.png',
        text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi, officia!',
        rating: 4
      },
      {
        reviewer: 'Ion Popescu',
        avatar: 'assets/app/img/avatar.png',
        text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ullam, nisi.',
        rating: 3
      }
    ]
  };
  var html = template(context);

  $('#reviews-template').after(html);

  $('.reviews').slick({
    autoplay: true,
    nextArrow: '<button type="button" class="slick-next"></button>',
    prevArrow: '<button type="button" class="slick-prev"></button>'
  });
})(jQuery);
<commit_msg>Updated main javascript<commit_after>(function ($) {
  'use strict';

  var navbarHeight = $('.navbar').height();

  $('body').scrollspy({
    target: '#navbar',
    offset: navbarHeight + 10
  });

  $('a[href^="#"]').click(function (event) {
    event.preventDefault();

    $('#navbar').collapse('hide');

    var target = this.hash || 'body';

    $(window).stop(true).scrollTo(target, {
      duration: 1000,
      interrupt: true,
      offset: -navbarHeight
    });
  });

  var source = $('#reviews-template').html();
  var template = Handlebars.compile(source);
  var context = {
    reviews: [
      {
        reviewer: 'Claudia Ifrim',
        avatar: 'https://scontent.xx.fbcdn.net/hprofile-xfp1/v/l/t1.0-1/c167.31.386.386/s100x100/44202_1411148200733_735995_n.jpg?oh=ad19b2f805afbf63840d243868f5f190&oe=5744B2AE',
        text: 'In vara anului trecut am achizitionat o noua masina. Am zis bugetul disponibil si ce as vrea de la masina pe care o caut si Gabi mi-a prezentat 3 oferte, a negociat pretul pentru oferta aleasa, a tinut legatura cu firma de leasing si s-a ocupat de toate formalitatile necesare. Pentru mine a ramas doar un test drive si preluarea masinii livrate.',
        rating: 5
      },
      {
        reviewer: 'Cătălin Dogaru',
        avatar: 'https://scontent.xx.fbcdn.net/hprofile-xal1/v/t1.0-1/p100x100/11666058_931880383535643_3616477844817336457_n.jpg?oh=e35cb36f719557e423add05bb3275329&oe=56FFF39F',
        text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Et dignissimos sapiente iste asperiores pariatur accusamus a voluptatum placeat, cupiditate voluptate.',
        rating: 4
      }
    ]
  };
  var html = template(context);

  $('#reviews-template').after(html);

  $('.reviews').slick({
    autoplay: true,
    nextArrow: '<button type="button" class="slick-next"></button>',
    prevArrow: '<button type="button" class="slick-prev"></button>'
  });
})(jQuery);
<|endoftext|>


<commit_before>/*
 * © Code for Karlsruhe and contributors.
 * See the file LICENSE for details.
 */

var TILES_URL = '//cartodb-basemaps-a.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png';
var ATTRIBUTION = 'Map data © OpenStreetMap ' +
                  'contributors, ' +
                  'CC-BY-SA. Tiles © ' +
                  'CartoDB';
var DEFAULT_CITY = "karlsruhe";

var map;
var nowGroup = L.layerGroup();
var todayGroup = L.layerGroup();
var otherGroup = L.layerGroup();
var unclassifiedGroup = L.layerGroup();

var now = new Date();
var TIME_NOW = [now.getHours(), now.getMinutes()];
var DAY_INDEX = (now.getDay() + 6) % 7;  // In our data, first day is Monday
var DAY_NAMES = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'];
var DEFAULT_MARKET_TITLE = 'Markt';

L.AwesomeMarkers.Icon.prototype.options.prefix = 'fa';
var nowIcon = L.AwesomeMarkers.icon({markerColor: 'green', icon: 'shopping-cart'});
var todayIcon = L.AwesomeMarkers.icon({markerColor: 'darkgreen', icon: 'shopping-cart'});
var otherIcon = L.AwesomeMarkers.icon({markerColor: 'cadetblue', icon: 'shopping-cart'});
var unclassifiedIcon = L.AwesomeMarkers.icon({markerColor: 'darkpurple', icon: 'shopping-cart'});

/*
 * Return 0-padded string of a number.
 */
function pad(num, totalDigits) {
    var s = num.toString();
    while (s.length < totalDigits) {
        s = '0' + s;
    }
    return s;
}

/*
 * Creates time-table HTML code.
 *
 * `openingRanges` is a list of ranges compiled via opening_hours.js.
 * The first and second element of each range item are the starting and closing dates.
 */
function getTimeTable(openingRanges) {
    var html = '
';
    if (openingRanges !== undefined) {
        for (var index = 0, openingRangesLength = openingRanges.length; index < openingRangesLength; ++index) {
            var openingRange = openingRanges[index];

            var dayIsToday = openingRangeMatchesDay(openingRange, now);
            var tableRow = getTableRowForDay(openingRange, dayIsToday);
            html += tableRow;
        }
    }
    html += '
';
    return html;
}

/*
 * Returns table row for a day with opening hours.
 * If the day matches today the row is styled.
 */
function getTableRowForDay(openingRange, dayIsToday) {
    var openFromDate = openingRange[0];
    var openTillDate = openingRange[1];
    var dayNameIndex = openFromDate.getDay();
    var dayName = DAY_NAMES[dayNameIndex];
    var cls = dayIsToday ? ' class="today"' : '';
    var formattedOpenFrom = moment(openFromDate).format('HH:mm');
    var formattedOpenTill = moment(openTillDate).format('HH:mm');
    return '
' + dayName + '	' +
           '' + formattedOpenFrom + ' - ' + formattedOpenTill + ' Uhr
';
}

/*
 * Initialize map.
 */
function initMap() {
    var tiles = new L.TileLayer(TILES_URL, {attribution: ATTRIBUTION});
    map = new L.Map('map').addLayer(tiles);
}

/*
 * Moves the map to its initial position.
 */
function positionMap(mapInitialization) {
    var coordinates = mapInitialization.coordinates;
    var zoomLevel = mapInitialization.zoom_level;
    map.setView(L.latLng(coordinates[1], coordinates[0]), zoomLevel);
}

/*
 * Initialize layer controls.
 *
 * Controls which serve no purpose are disabled. For example, if
 * currently no markets are open then the corresponding radio
 * button is disabled.
 */
function initControls() {
    var todayCount = todayGroup.getLayers().length;
    if (todayCount === 0) {
        // No markets today or all of today's markets currently open
        $('#today').attr('disabled', true);
    }
    if (nowGroup.getLayers().length > 0) {
        $('#now').attr('checked', true);
    } else {
        $('#now').attr('disabled', true);
        if (todayCount > 0) {
            $('#today').attr('checked', true);
        } else {
            $('#other').attr('checked', true);
        }
    }
    $("input[name=display]").change(updateLayers);
}

/*
 * Update layer visibility according to layer control settings.
 */
function updateLayers() {
    var value = document.querySelector('[name="display"]:checked').value;
    switch (value) {
        case "now":
            map.removeLayer(todayGroup);
            map.removeLayer(otherGroup);
            break;
        case "today":
            map.addLayer(todayGroup);
            map.removeLayer(otherGroup);
            break;
        case "other":
            map.addLayer(todayGroup);
            map.addLayer(otherGroup);
            break;
    }
}

/*
 * Returns true if opening range matches the day of the given date; otherwise false.
 */
function openingRangeMatchesDay(openingRange, date) {
    var openFromDate = openingRange[0];
    var openTillDate = openingRange[1];
    var dayIndex = date.getDay();
    return openFromDate.getDay() === dayIndex && openTillDate.getDay() === dayIndex;
}

/*
 * Returns true if opening range contains the time of the given date; otherwise false.
 */
function openingRangeContainsTime(openingRange, date) {
    var range = moment.range(openingRange[0], openingRange[1]);
    return range.contains(date);
}

/*
 * Returns opening ranges compiled via opening_hours.js.
 */
function getOpeningRanges(openingHoursStrings) {
    var monday = moment().startOf("week").add(1, 'days').toDate();
    var sunday = moment().endOf("week").add(1, 'days').toDate();
    var oh = new opening_hours(openingHoursStrings);
    return oh.getOpenIntervals(monday, sunday);
}

/*
 * Returns opening range for date or undefined.
 */
function getOpeningRangeForDate(openingRanges, date) {
    if (openingRanges !== undefined) {
        for (var index = 0, openingRangesLength = openingRanges.length; index < openingRangesLength; ++index) {
            var openingRange = openingRanges[index];

            var dayIsToday = openingRangeMatchesDay(openingRange, date);
            if (dayIsToday) {
                return openingRange;
            }
        }
    }
    return undefined;
}

/*
 * Create map markers from JSON market data.
 */
function initMarkers(featureCollection) {
    L.geoJson(featureCollection, {
        onEachFeature: initMarker
    });
}

function initMarker(feature) {
    var properties = feature.properties;
    var openingHoursStrings = properties.opening_hours;
    if (openingHoursStrings === undefined) {
        throw "Missing property 'opening_hours' for " + properties.title + " (" + properties.location + ").";
    }
    var todayOpeningRange;
    var timeTableHtml;
    var openingHoursUnclassified;
    if (openingHoursStrings === null || openingHoursStrings.length === 0) {
        openingHoursUnclassified = properties.openingHoursUnclassified;
    } else {
        var openingRanges = getOpeningRanges(openingHoursStrings);
        todayOpeningRange = getOpeningRangeForDate(openingRanges, now);
        timeTableHtml = getTimeTable(openingRanges);
    }

    var coordinates = feature.geometry.coordinates;
    var marker = L.marker(L.latLng(coordinates[1], coordinates[0]));
    var where = properties.location;
    if (where === undefined) {
        throw "Missing property 'location' for " + properties.title + ".";
    }
    if (where !== null) {
        where = '
' + where + '
';
    } else {
        where = '';
    }
    var title = properties.title;
    if (title === undefined) {
        throw "Missing property 'title'.";
    }
    if (title === null || title.length === 0) {
        title = DEFAULT_MARKET_TITLE;
    }
    var popupHtml = '
' + title + '
' + where;
    if (openingHoursUnclassified !== undefined) {
        popupHtml += '
' + openingHoursUnclassified + '
';
    } else {
        popupHtml += timeTableHtml;
    }
    marker.bindPopup(popupHtml);
    if (todayOpeningRange !== undefined) {
        if (openingRangeContainsTime(todayOpeningRange, now)) {
            marker.setIcon(nowIcon);
            nowGroup.addLayer(marker);
        } else {
            marker.setIcon(todayIcon);
            todayGroup.addLayer(marker);
        }
    } else {
        if (openingHoursUnclassified !== undefined) {
            marker.setIcon(unclassifiedIcon);
            unclassifiedGroup.addLayer(marker);
        } else {
            marker.setIcon(otherIcon);
            otherGroup.addLayer(marker);
        }
    }
}

/*
 * Initialize legend.
 */
function initLegend() {
    var legend = L.control({position: 'bottomright'}),
        currentCity = getCityName(),
        apiUrl = "https://api.github.com/repos/wo-ist-markt/wo-ist-markt.github.io/contents/cities",
        dropDownCitySelection = $('#dropDownCitySelection');

    legend.onAdd = function () {
        return L.DomUtil.get('legend');
    };

    // populate select box
    $.get(apiUrl, function(result) {
        $.each(result, function(idx, value) {
            var cityKey = value.name.replace(".json", "");
            var cityLabel = cityKey.replace(/(^|\s|\-)([a-zA-ZäöüÄÖÜß])/g, function(l) {
                return l.toUpperCase();
            });
            dropDownCitySelection.append(
                $('<option></option>').val(cityKey).html(cityLabel)
            );
            dropDownCitySelection.val(currentCity);
        });
        dropDownCitySelection.select2({
            minimumResultsForSearch: 10
        }).change(function() {
            updateUrlHash(dropDownCitySelection.select2().val());
            window.location.reload(true);
        });
        // Force select2 update to fix dropdown position
        dropDownCitySelection.select2('open');
        dropDownCitySelection.select2('close');
    });

    // Stop map movement by mouse events in legend.
    // See https://gis.stackexchange.com/a/106777/48264.
    L.DomEvent.disableClickPropagation(L.DomUtil.get('legend'));

    legend.addTo(map);
}

/*
 * Returns the city name when present in the hash of the current URI;
 * otherwise the default city name;
 */
function getCityName() {
    var hash = decodeURIComponent(window.location.hash);
    if (hash === undefined || hash === "") {
        return DEFAULT_CITY;
    } else {
        hash = hash.toLowerCase();
        return hash.substring(1, hash.length);
    }
}

/*
 * Updates the URL hash in the browser.
 */
function updateUrlHash(cityName) {
    if (cityName === undefined) {
        throw "City name is undefined.";
    }
    if (history.pushState) {
        history.pushState(null, null, "#" + cityName);
    } else {
        window.location.hash = cityName;
    }
}

/*
 * Constructs a file path for the market data from the given city name.
 */
function getMarketDataFilePath(cityName) {
    if (cityName === undefined) {
        throw "City name is undefined.";
    }
    return "cities/" + cityName + ".json";
}

/*
 * Returns the given string in camel case.
 */
function toCamelCase(str) {
    return str.replace(/(?:^|\s)\w/g, function(match) {
        return match.toUpperCase();
    });
}

/*
 * Updates the document title.
 */
function updateDocumentTitle(cityName) {
    if (cityName === undefined) {
        throw "City name is undefined.";
    }
    var formattedCityName = toCamelCase(cityName);
    document.title = "Wo ist Markt in " + formattedCityName +"?";
}

/*
 * Updates the legend data source.
 */
function updateLegendDataSource(dataSource) {
    var title = dataSource.title;
    var url = dataSource.url;
    $("#legend #dataSource").html('' + title + '');
}

/*
 * Initialize application when market data is loaded.
 */
function init(json, cityName) {
    positionMap(json.metadata.map_initialization);
    updateLegendDataSource(json.metadata.data_source);
    initMarkers(json);
    initControls();
    map.addLayer(unclassifiedGroup);
    map.addLayer(nowGroup);
    updateLayers();
    updateDocumentTitle(cityName);
    updateUrlHash(cityName);
}

/*
 * Forces reloading when URI hash changed.
 */
$(window).on('hashchange',function() {
    window.location.reload(true);
});

$(document).ready(function() {
    initMap();
    initLegend();
    var cityName = getCityName();
    var marketDataFileName = getMarketDataFilePath(cityName);
    $.getJSON(marketDataFileName, function(json) {
        init(json, cityName);
    }).fail(function() {
        console.log("Failure loading '" + marketDataFileName + "'. Loading market file for default city (" + DEFAULT_CITY + ") instead.");
        cityName = DEFAULT_CITY;
        marketDataFileName = getMarketDataFilePath(cityName);
        $.getJSON(marketDataFileName, function(json) {
            init(json, cityName);
        }).fail(function() {
           console.log("Failure loading default market file.");
        });
    });
});
<commit_msg>Fix #26: Avoid page reload on city change.<commit_after>/*
 * © Code for Karlsruhe and contributors.
 * See the file LICENSE for details.
 */

var TILES_URL = '//cartodb-basemaps-a.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png';
var ATTRIBUTION = 'Map data © OpenStreetMap ' +
                  'contributors, ' +
                  'CC-BY-SA. Tiles © ' +
                  'CartoDB';
var DEFAULT_CITY = "karlsruhe";
var CITY_LIST_API_URL = 'https://api.github.com/repos/wo-ist-markt/' +
                        'wo-ist-markt.github.io/contents/cities';

var map;
var nowGroup = L.layerGroup();
var todayGroup = L.layerGroup();
var otherGroup = L.layerGroup();
var unclassifiedGroup = L.layerGroup();

var now = new Date();
var TIME_NOW = [now.getHours(), now.getMinutes()];
var DAY_INDEX = (now.getDay() + 6) % 7;  // In our data, first day is Monday
var DAY_NAMES = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'];
var DEFAULT_MARKET_TITLE = 'Markt';

L.AwesomeMarkers.Icon.prototype.options.prefix = 'fa';
var nowIcon = L.AwesomeMarkers.icon({markerColor: 'green', icon: 'shopping-cart'});
var todayIcon = L.AwesomeMarkers.icon({markerColor: 'darkgreen', icon: 'shopping-cart'});
var otherIcon = L.AwesomeMarkers.icon({markerColor: 'cadetblue', icon: 'shopping-cart'});
var unclassifiedIcon = L.AwesomeMarkers.icon({markerColor: 'darkpurple', icon: 'shopping-cart'});

/*
 * Return 0-padded string of a number.
 */
function pad(num, totalDigits) {
    var s = num.toString();
    while (s.length < totalDigits) {
        s = '0' + s;
    }
    return s;
}

/*
 * Creates time-table HTML code.
 *
 * `openingRanges` is a list of ranges compiled via opening_hours.js.
 * The first and second element of each range item are the starting and closing dates.
 */
function getTimeTable(openingRanges) {
    var html = '
';
    if (openingRanges !== undefined) {
        for (var index = 0, openingRangesLength = openingRanges.length; index < openingRangesLength; ++index) {
            var openingRange = openingRanges[index];

            var dayIsToday = openingRangeMatchesDay(openingRange, now);
            var tableRow = getTableRowForDay(openingRange, dayIsToday);
            html += tableRow;
        }
    }
    html += '
';
    return html;
}

/*
 * Returns table row for a day with opening hours.
 * If the day matches today the row is styled.
 */
function getTableRowForDay(openingRange, dayIsToday) {
    var openFromDate = openingRange[0];
    var openTillDate = openingRange[1];
    var dayNameIndex = openFromDate.getDay();
    var dayName = DAY_NAMES[dayNameIndex];
    var cls = dayIsToday ? ' class="today"' : '';
    var formattedOpenFrom = moment(openFromDate).format('HH:mm');
    var formattedOpenTill = moment(openTillDate).format('HH:mm');
    return '
' + dayName + '	' +
           '' + formattedOpenFrom + ' - ' + formattedOpenTill + ' Uhr
';
}

/*
 * Moves the map to its initial position.
 */
function positionMap(mapInitialization) {
    var coordinates = mapInitialization.coordinates;
    var zoomLevel = mapInitialization.zoom_level;
    map.setView(L.latLng(coordinates[1], coordinates[0]), zoomLevel);
}

/*
 * Initialize layer controls.
 *
 * Controls which serve no purpose are disabled. For example, if
 * currently no markets are open then the corresponding radio
 * button is disabled.
 */
function initControls() {
    var todayCount = todayGroup.getLayers().length;
    if (todayCount === 0) {
        // No markets today or all of today's markets currently open
        $('#today').attr('disabled', true);
    }
    if (nowGroup.getLayers().length > 0) {
        $('#now').attr('checked', true);
    } else {
        $('#now').attr('disabled', true);
        if (todayCount > 0) {
            $('#today').attr('checked', true);
        } else {
            $('#other').attr('checked', true);
        }
    }
    $("input[name=display]").change(updateLayers);
}

/*
 * Update layer visibility according to layer control settings.
 */
function updateLayers() {
    var value = document.querySelector('[name="display"]:checked').value;
    switch (value) {
        case "now":
            map.removeLayer(todayGroup);
            map.removeLayer(otherGroup);
            break;
        case "today":
            map.addLayer(todayGroup);
            map.removeLayer(otherGroup);
            break;
        case "other":
            map.addLayer(todayGroup);
            map.addLayer(otherGroup);
            break;
    }
}

/*
 * Returns true if opening range matches the day of the given date; otherwise false.
 */
function openingRangeMatchesDay(openingRange, date) {
    var openFromDate = openingRange[0];
    var openTillDate = openingRange[1];
    var dayIndex = date.getDay();
    return openFromDate.getDay() === dayIndex && openTillDate.getDay() === dayIndex;
}

/*
 * Returns true if opening range contains the time of the given date; otherwise false.
 */
function openingRangeContainsTime(openingRange, date) {
    var range = moment.range(openingRange[0], openingRange[1]);
    return range.contains(date);
}

/*
 * Returns opening ranges compiled via opening_hours.js.
 */
function getOpeningRanges(openingHoursStrings) {
    var monday = moment().startOf("week").add(1, 'days').toDate();
    var sunday = moment().endOf("week").add(1, 'days').toDate();
    var oh = new opening_hours(openingHoursStrings);
    return oh.getOpenIntervals(monday, sunday);
}

/*
 * Returns opening range for date or undefined.
 */
function getOpeningRangeForDate(openingRanges, date) {
    if (openingRanges !== undefined) {
        for (var index = 0, openingRangesLength = openingRanges.length; index < openingRangesLength; ++index) {
            var openingRange = openingRanges[index];

            var dayIsToday = openingRangeMatchesDay(openingRange, date);
            if (dayIsToday) {
                return openingRange;
            }
        }
    }
    return undefined;
}

/*
 * Create map markers from JSON market data.
 */
function initMarkers(featureCollection) {
    nowGroup.clearLayers();
    todayGroup.clearLayers();
    otherGroup.clearLayers();
    unclassifiedGroup.clearLayers();
    L.geoJson(featureCollection, {
        onEachFeature: initMarker
    });
}

function initMarker(feature) {
    var properties = feature.properties;
    var openingHoursStrings = properties.opening_hours;
    if (openingHoursStrings === undefined) {
        throw "Missing property 'opening_hours' for " + properties.title + " (" + properties.location + ").";
    }
    var todayOpeningRange;
    var timeTableHtml;
    var openingHoursUnclassified;
    if (openingHoursStrings === null || openingHoursStrings.length === 0) {
        openingHoursUnclassified = properties.openingHoursUnclassified;
    } else {
        var openingRanges = getOpeningRanges(openingHoursStrings);
        todayOpeningRange = getOpeningRangeForDate(openingRanges, now);
        timeTableHtml = getTimeTable(openingRanges);
    }

    var coordinates = feature.geometry.coordinates;
    var marker = L.marker(L.latLng(coordinates[1], coordinates[0]));
    var where = properties.location;
    if (where === undefined) {
        throw "Missing property 'location' for " + properties.title + ".";
    }
    if (where !== null) {
        where = '
' + where + '
';
    } else {
        where = '';
    }
    var title = properties.title;
    if (title === undefined) {
        throw "Missing property 'title'.";
    }
    if (title === null || title.length === 0) {
        title = DEFAULT_MARKET_TITLE;
    }
    var popupHtml = '
' + title + '
' + where;
    if (openingHoursUnclassified !== undefined) {
        popupHtml += '
' + openingHoursUnclassified + '
';
    } else {
        popupHtml += timeTableHtml;
    }
    marker.bindPopup(popupHtml);
    if (todayOpeningRange !== undefined) {
        if (openingRangeContainsTime(todayOpeningRange, now)) {
            marker.setIcon(nowIcon);
            nowGroup.addLayer(marker);
        } else {
            marker.setIcon(todayIcon);
            todayGroup.addLayer(marker);
        }
    } else {
        if (openingHoursUnclassified !== undefined) {
            marker.setIcon(unclassifiedIcon);
            unclassifiedGroup.addLayer(marker);
        } else {
            marker.setIcon(otherIcon);
            otherGroup.addLayer(marker);
        }
    }
}

/*
 * Returns the city name when present in the hash of the current URI;
 * otherwise the default city name;
 */
function getCityName() {
    var hash = decodeURIComponent(window.location.hash);
    if (hash === undefined || hash === "") {
        return DEFAULT_CITY;
    } else {
        hash = hash.toLowerCase();
        return hash.substring(1, hash.length);
    }
}

/*
 * Updates the URL hash in the browser.
 */
function updateUrlHash(cityName) {
    if (cityName === undefined) {
        throw "City name is undefined.";
    }
    if (history.pushState) {
        history.pushState(null, null, "#" + cityName);
    } else {
        window.location.hash = cityName;
    }
}

/*
 * Returns the given string in camel case.
 */
function toCamelCase(str) {
    return str.replace(/(?:^|\s)\w/g, function(match) {
        return match.toUpperCase();
    });
}

/*
 * Updates the legend data source.
 */
function updateLegendDataSource(dataSource) {
    var title = dataSource.title;
    var url = dataSource.url;
    $("#legend #dataSource").html('' + title + '');
}

/*
 * Convert a city ID to a UI label.
 */
function cityIdToLabel(s) {
    return s.replace(/(^|\s|\-)([a-zA-ZäöüÄÖÜß])/g, function (x) {
        return x.toUpperCase();
    });
}

/*
 * Set the current city.
 *
 * `city` is the city ID.
 */
function setCity(city) {
    var filename = 'cities/' + city + '.json';
    $.getJSON(filename, function(json) {
        positionMap(json.metadata.map_initialization);
        updateLegendDataSource(json.metadata.data_source);
        initMarkers(json);
        initControls();
        map.addLayer(unclassifiedGroup);
        map.addLayer(nowGroup);
        updateLayers();
        updateUrlHash(city);
        document.title = 'Wo ist Markt in ' + cityIdToLabel(city) + '?';
        // Update drop down but avoid recursion
        $('#dropDownCitySelection').val(city).trigger('change', true);
    }).fail(function() {
        console.log('Failure loading "' + filename + '".');
        if (city !== DEFAULT_CITY) {
            console.log('Loading default city "' + DEFAULT_CITY +
                        '" instead.');
            setCity(DEFAULT_CITY);
        }
    });
}

/*
 * Load the IDs of the available cities.
 *
 * Returns a jQuery `Deferred` object that resolves to an array of city IDs.
 */
function loadCityIDs() {
    var d = $.Deferred();
    $.get(CITY_LIST_API_URL, function(result) {
        var ids = [];
        $.each(result, function(_, file) {
            if (file.name.indexOf('.json', file.name.length - 5) !== -1) {
                ids.push(file.name.slice(0, -5));
            }
        });
        d.resolve(ids);
    }).fail(function() {
        d.fail();
    });
    return d;
}

$(window).on('hashchange',function() {
    setCity(getCityName());
});

$(document).ready(function() {
    var tiles = new L.TileLayer(TILES_URL, {attribution: ATTRIBUTION});
    map = new L.Map('map').addLayer(tiles);
    var legend = L.control({position: 'bottomright'});
    var dropDownCitySelection = $('#dropDownCitySelection');
    legend.onAdd = function () { return L.DomUtil.get('legend'); };

    // Populate dropdown
    loadCityIDs().done(function(cityIDs) {
        for (var i = 0; i < cityIDs.length; i++) {
            var id = cityIDs[i];
            dropDownCitySelection.append(
                $('<option></option>').val(id)
                                      .html(cityIdToLabel(id))
            );
        }
        dropDownCitySelection.select2({
            minimumResultsForSearch: 10
        }).change(function(e, keepCity) {
            // If we programmatically change the select2 value then we also
            // need to trigger 'change'. However that would cause an infinite
            // recursion in our case since we're doing that from inside
            // setCity. Therefore we add a custom "keepCity" parameter that is
            // set when the change event is triggered from within setCity so
            // that we can avoid a recursion in that case.
            if (!keepCity) {
                setCity(dropDownCitySelection.val());
            }
        }).on('select2:close', function() {
            $(':focus').blur();
        });
        // Force select2 update to fix dropdown position
        dropDownCitySelection.select2('open');
        dropDownCitySelection.select2('close');

        setCity(getCityName());
    });

    // Stop map movement by mouse events in legend.
    // See https://gis.stackexchange.com/a/106777/48264.
    L.DomEvent.disableClickPropagation(L.DomUtil.get('legend'));

    legend.addTo(map);
});

<|endoftext|>


<commit_before>function memoryTestInit()
{
    var delay = 33,
        step = 648,
        curMemory = 0,
        memory = 26732;

    $("#output").append("
Memory Test : 0K
");

    function updateMemory()
    {
        curMemory += step;
        $("#memoryTestNumber").html(curMemory+"K");
        if (curMemory < memory)
        {
            window.setTimeout(updateMemory, delay);
        }
        else
        {
            $("#memoryTest").append(" OK");
            $("#output").append("
");
            deviceScanInit();
        };
    }

    updateMemory();
}

function deviceScanInit()
{
    var delay = 300,
        devices = ["USB", "Keyboard", "Mouse"],
        current = 0,
        dots = 0;

    $("#output").append("
Scanning For Devices
");

    function scanDevices()
    {
        var temp = "";
        if (!$("#deviceScan"+devices[current]).length)
        {
            $("#output").append("
Scanning for "+devices[current]+"
");
        }
        for (var i = 0; i < dots; i++)
        {
            //$("#dots"+devices[current]).append(".");
            temp+=".";
        }
        $("#dots"+devices[current]).html(temp);
        if (dots < 4)
        {
            dots++;
            window.setTimeout(scanDevices, delay);
        }
        else
        {
            dots = 0;
            $("#deviceScan"+devices[current]).append("  FOUND");
            if (current < devices.length-1)
            {
                current++
                window.setTimeout(scanDevices, delay);
            }
            else
            {
                $("#output").append("
");
                $("#output").append("

Welcome To SpookyOS

");
                showCommands();
            }
        }
    }
    scanDevices();
}

function showCommands()
{
    $("#output").append("
help    - Show this help
");
    $("#output").append("
project - Show projects I've worked on
");
    $("#output").append("
github  - Open My Github Page
");
    $("#output").append("
twitter - Open My Twitter Page
");
    $("#output").append("
reddit  - Open My Reddit Page
");
    $("#output").append("
Steam   - Open My Steam Page

");
    $("#inputContainer").css("visibility","visible")
}

memoryTestInit();
<commit_msg>spelling<commit_after>function memoryTestInit()
{
    var delay = 33,
        step = 648,
        curMemory = 0,
        memory = 26732;

    $("#output").append("
Memory Test : 0K
");

    function updateMemory()
    {
        curMemory += step;
        $("#memoryTestNumber").html(curMemory+"K");
        if (curMemory < memory)
        {
            window.setTimeout(updateMemory, delay);
        }
        else
        {
            $("#memoryTest").append(" OK");
            $("#output").append("
");
            deviceScanInit();
        };
    }

    updateMemory();
}

function deviceScanInit()
{
    var delay = 300,
        devices = ["USB", "Keyboard", "Mouse"],
        current = 0,
        dots = 0;

    $("#output").append("
Scanning For Devices
");

    function scanDevices()
    {
        var temp = "";
        if (!$("#deviceScan"+devices[current]).length)
        {
            $("#output").append("
Scanning for "+devices[current]+"
");
        }
        for (var i = 0; i < dots; i++)
        {
            //$("#dots"+devices[current]).append(".");
            temp+=".";
        }
        $("#dots"+devices[current]).html(temp);
        if (dots < 4)
        {
            dots++;
            window.setTimeout(scanDevices, delay);
        }
        else
        {
            dots = 0;
            $("#deviceScan"+devices[current]).append("  FOUND");
            if (current < devices.length-1)
            {
                current++
                window.setTimeout(scanDevices, delay);
            }
            else
            {
                $("#output").append("
");
                $("#output").append("

Welcome To SpookyOS

");
                showCommands();
            }
        }
    }
    scanDevices();
}

function showCommands()
{
    $("#output").append("
help    - Show this help
");
    $("#output").append("
project - Show projects I've worked on
");
    $("#output").append("
github  - Open My Github Page
");
    $("#output").append("
twitter - Open My Twitter Page
");
    $("#output").append("
reddit  - Open My Reddit Page
");
    $("#output").append("
steam   - Open My Steam Page

");
    $("#inputContainer").css("visibility","visible")
}

memoryTestInit();
<|endoftext|>