<commit_before>var FcAlexkTPM = {

	// The string id of the card. This must be set by the loader
	id : null,

	// The card uuid. This is used to uniquely identify this particular piece of javascript
	uuid : null,

	// The target DOM node we want to manipulate
	target : null,

	// Forecast.io => climacons icon conversion
	icons : {
		"clear-day" : "sun", 
		"clear-night" : "moon", 
		"rain" : "rain", 
		"snow" : "snow",
		"sleet" : "sleet", 
		"wind" : "wind", 
		"fog" : "fog", 
		"cloudy" : "cloud", 
		"partly-cloudy-day" : "cloud sun", 
		"partly-cloudy-night" : "cloud moon",
		"hail" : "hail", 
		"lightning" : "lightning", 
		"tornado" : "tornado"
	},

	// Forecast.io APIKey
	apiKey : null,

	// Whether or not to use farenheit or centigrade
	metric : false,

	// Cache data loaded from GeoIP
	geoIp : null,

	position : null,

	/**
	 * Load function is the bootstrap method all cards inherit.
	 * 
	 * @param  string id  The unique ID of the card we want this card to manipulate
	 */
	load : function(id) {
		// Set some variables
		this.id = id;
		this.uuid = "FcAlexkTPM-" + this.id;
		this.target = "#FcAlexkTPM[data-attr-id='" + this.id + "']";
		this.apiKey = $("." + this.id + "-modal").find("input#Weather_apikey").val();
		this.metric = $("." + this.id + "-modal").find("input#Weather_metric").is(":checked");

		var canUseCard = true;

		if (!this.getGeoIp())
			canUseCard = false;

		this.setLocationString(this);

		if (this.apiKey == null || this.apiKey == undefined || this.apiKey == '' )
			canUseCard = false;

		if (canUseCard)
			this.getLocation();
		else
			this.showWarnings();
	},

	/**
	 * Attempts to retrieve the geoIP information from the user
	 * 
	 * @return boolean   If we can use GeoIP. This is used by canUseCard outlined above.
	 */
	getGeoIp : function(callback) {
		var key = this.uuid + "-geoip",
			response = JSON.parse(localStorage.getItem(key)),
			self = this;

		if (response == undefined || response == null || response == '')
		{
			// This request MUST be syncronous, otherwise if we hit an error the card breaks.
			$.ajax({
				url :'https://j.maxmind.com/js/apis/geoip2/v2.0/geoip2.js', 
				dataType : 'script',
				success : function(script, textStatus) {

					if (textStatus != "success")
						return false;

					geoip2.city(function(data) {
						self.geoIp = response = data;
						localStorage.setItem(key, JSON.stringify(data));
						
						if (callback != undefined)
							callback(self.geoIp);
					});					
				}
			});			

			return true;
		}
		
		self.geoIp = response;

		if (callback != undefined)
			callback(self.geoIp);

		return true;
	},

	/**
	 * Retrieves the location using navigator.geoLocation, which should be more accurate than lat/long
	 */
	getLocation : function() {
		var self = this;
		if (navigator.geolocation)
	    	navigator.geolocation.getCurrentPosition(function(position) { self.position = position; self.showPosition(position, self); });
	    else
	    	this.showWarnings();

	},

	/**
	 * Set the location for the current objhect
	 * @param this  self   The current object
	 */
	setLocationString : function(self) {
		var response = null;

		self.getGeoIp(function(data) {
			if (data.country.iso_code == "US")
				response = data.city.names.en + ", " + data.subdivisions[0].iso_code;
			else
				response = data.citynames.en + "," + data.subdivisions[0].names.en;

			$(self.target).find(".location").text(response);
		});
	},

	/**
	 * Uses the current position to update the DOM
	 * @param  geoLocation position      geoLocation.position 
	 * @param  FcAlexkTPM  self          The containing class so that we can do callbacks correctly
	 */
	showPosition : function(position, self) {

		if (localStorage)
		{
			var key = self.uuid + "-last",
				response = localStorage.getItem(key),
				now = new Date().getTime().toString();

			// If we don't have any previous data from Forecast.io, or the previous data is older than 15 minutes, make another request
			if (response == undefined || response == null || response == '' || (response.timestamp + 900000) <= now)
			{
				// Syncronous request to laod data from Forecast.io
				$.ajax({
					type: 'POST',
					// See Weather.php (Weather::getCurrentConditions()) for how this callback works. Forecast.io has Allow-Access-Origin disabled
					url : CiiDashboard.endPoint + "/card/callmethod/id/" + self.id + "/method/getCurrentConditions", 
					data : { "latitude" : position.coords.latitude, "longitude" : position.coords.longitude },
					success : function(data) {

						if (data.replace(/\s/g, "") == "Forbidden")
						{
							response = false;
							self.showWarnings();
							return false;
						}

						// Cache the data in localstorage for 15 minutes
						var object = JSON.stringify( { "value" : data, "timestamp": new Date().getTime() } );
						localStorage.setItem(key, object);
						response = JSON.parse(data);
						response.value = JSON.parse(response.value);
						self.displayWeather(self, response);
					}
				});				
			}
			else
			{
				response = JSON.parse(response);
				response.value = JSON.parse(response.value);
				self.displayWeather(self, response);
			}
		}
		else
			console.log("Local Storage is not supported on this device. This card requies localStorage to function");
	},

	/**
	 * Displays the weather for this card
	 * @param  this     self      The current object
	 * @param  JSON     response  The response data
	 */
	displayWeather : function(self, response) {
		self.setLocationString(self);

		if (response == false)
			return false;

		// Update the card<commit_msg>And now we're error free<commit_after>var FcAlexkTPM = {

	// The string id of the card. This must be set by the loader
	id : null,

	// The card uuid. This is used to uniquely identify this particular piece of javascript
	uuid : null,

	// The target DOM node we want to manipulate
	target : null,

	// Forecast.io => climacons icon conversion
	icons : {
		"clear-day" : "sun", 
		"clear-night" : "moon", 
		"rain" : "rain", 
		"snow" : "snow",
		"sleet" : "sleet", 
		"wind" : "wind", 
		"fog" : "fog", 
		"cloudy" : "cloud", 
		"partly-cloudy-day" : "cloud sun", 
		"partly-cloudy-night" : "cloud moon",
		"hail" : "hail", 
		"lightning" : "lightning", 
		"tornado" : "tornado"
	},

	// Forecast.io APIKey
	apiKey : null,

	// Whether or not to use farenheit or centigrade
	metric : false,

	// Cache data loaded from GeoIP
	geoIp : null,

	position : null,

	/**
	 * Load function is the bootstrap method all cards inherit.
	 * 
	 * @param  string id  The unique ID of the card we want this card to manipulate
	 */
	load : function(id) {
		// Set some variables
		this.id = id;
		this.uuid = "FcAlexkTPM-" + this.id;
		this.target = "#FcAlexkTPM[data-attr-id='" + this.id + "']";
		this.apiKey = $("." + this.id + "-modal").find("input#Weather_apikey").val();
		this.metric = $("." + this.id + "-modal").find("input#Weather_metric").is(":checked");

		var canUseCard = true;

		if (!this.getGeoIp())
			canUseCard = false;

		this.setLocationString(this);

		if (this.apiKey == null || this.apiKey == undefined || this.apiKey == '' )
			canUseCard = false;

		if (canUseCard)
			this.getLocation();
		else
			this.showWarnings();
	},

	/**
	 * Attempts to retrieve the geoIP information from the user
	 * 
	 * @return boolean   If we can use GeoIP. This is used by canUseCard outlined above.
	 */
	getGeoIp : function(callback) {
		var key = this.uuid + "-geoip",
			response = JSON.parse(localStorage.getItem(key)),
			self = this;

		if (response == undefined || response == null || response == '')
		{
			// This request MUST be syncronous, otherwise if we hit an error the card breaks.
			$.ajax({
				url :'https://j.maxmind.com/js/apis/geoip2/v2.0/geoip2.js', 
				dataType : 'script',
				success : function(script, textStatus) {

					if (textStatus != "success")
						return false;

					geoip2.city(function(data) {
						self.geoIp = response = data;
						localStorage.setItem(key, JSON.stringify(data));
						
						if (callback != undefined)
							callback(self.geoIp);
					});					
				}
			});			

			return true;
		}
		
		self.geoIp = response;

		if (callback != undefined)
			callback(self.geoIp);

		return true;
	},

	/**
	 * Retrieves the location using navigator.geoLocation, which should be more accurate than lat/long
	 */
	getLocation : function() {
		var self = this;
		if (navigator.geolocation)
	    	navigator.geolocation.getCurrentPosition(function(position) { self.position = position; self.showPosition(position, self); });
	    else
	    	this.showWarnings();

	},

	/**
	 * Set the location for the current objhect
	 * @param this  self   The current object
	 */
	setLocationString : function(self) {
		var response = null;

		self.getGeoIp(function(data) {
			if (data.country.iso_code == "US")
				response = data.city.names.en + ", " + data.subdivisions[0].iso_code;
			else
				response = data.citynames.en + "," + data.subdivisions[0].names.en;

			$(self.target).find(".location").text(response);
		});
	},

	/**
	 * Uses the current position to update the DOM
	 * @param  geoLocation position      geoLocation.position 
	 * @param  FcAlexkTPM  self          The containing class so that we can do callbacks correctly
	 */
	showPosition : function(position, self) {

		if (localStorage)
		{
			var key = self.uuid + "-last",
				response = localStorage.getItem(key),
				now = new Date().getTime().toString();

			// If we don't have any previous data from Forecast.io, or the previous data is older than 15 minutes, make another request
			if (response == undefined || response == null || response == '' || (response.timestamp + 900000) <= now)
			{
				// Syncronous request to laod data from Forecast.io
				$.ajax({
					type: 'POST',
					// See Weather.php (Weather::getCurrentConditions()) for how this callback works. Forecast.io has Allow-Access-Origin disabled
					url : CiiDashboard.endPoint + "/card/callmethod/id/" + self.id + "/method/getCurrentConditions", 
					data : { "latitude" : position.coords.latitude, "longitude" : position.coords.longitude },
					success : function(data) {

						if (data.replace(/\s/g, "") == "Forbidden")
						{
							response = false;
							self.showWarnings();
							return false;
						}

						// Cache the data in localstorage for 15 minutes
						var object = JSON.stringify( { "value" : data, "timestamp": new Date().getTime() } );
						localStorage.setItem(key, object);
						response = JSON.parse(object),
						response.value = JSON.parse(response.value);
						self.displayWeather(self, response);
					}
				});				
			}
			else
			{
				response = JSON.parse(response);
				response.value = JSON.parse(response.value);
				self.displayWeather(self, response);
			}
		}
		else
			console.log("Local Storage is not supported on this device. This card requies localStorage to function");
	},

	/**
	 * Displays the weather for this card
	 * @param  this     self      The current object
	 * @param  JSON     response  The response data
	 */
	displayWeather : function(self, response) {
		self.setLocationString(self);

		if (response == false)
			return false;

		// Update the card
{'fraction_non_alphanumeric': 0.13858817213921445, 'fraction_numerical': 0.0030419611702603563, 'mean_word_length': 2.8852971845672575, 'pattern_counts': {'":': 4, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '135490', 'n_tokens_mistral': 4263, 'n_tokens_neox': 3527, 'n_words': 987}