D3/Javascript code conundrum? - javascript

I have the following code:
d3.csv("flights-airport_3.csv", function(flights) {
var linksByOrigin = {},
countByAirport = {},
cancelledByAirport = {},
locationByAirport = {},
positions = [];
var arc = d3.geo.greatArc()
.source(function(d) { return locationByAirport[d.source]; })
.target(function(d) { return locationByAirport[d.target]; });
flights.forEach(function(flight) {
var origin = flight.origin,
destination = flight.destination,
count_airport = flight.count,
cancelledByAirport = flight.count_cancelled,
links = linksByOrigin[origin] || (linksByOrigin[origin] = []);
links.push({source: origin, target: destination});
My flights data array looks like this:
0: Object
"": ""
count: "9"
count_cancelled: "0"
destination: "IAD"
origin: "ALB"
For some reason my cancelledByAirport is empty? I am not sure why since I am treating it exactly the same as my countByAirport variable. Can anyone help?

I think your problem is that you have two variables called "cancelledByAirport". One is declared just below d3.csv(...), another within foreach().
The solution would be giving different names to those variables, or perhaps getting rid of one of them.
Please review your code with respect to those two variables, and tell us what you find.

Related

Is it efficient to create multiple keys pointing to the same object?

I have an array of countries, where each country have three properties.
const countries = [
{ name: "Poland", alpha: "POL", code: "616" },
{ name: "Hungary", alpha: "HUN", code: "348" },
// and so on...
]
Later on I want to easily access each country by any of these properties.
I was thinking of reducing this array to an object that would have three keys for each country pointing to the very same country object.
Something like this:
const countriesObject = countries.reduce((object, country) => {
const { name, alpha, code } = country;
// Create individual country object
object[name] = { ...country };
// Reference just created country object
object[code] = object[name];
object[alpha] = object[name];
return object;
});
In the end I could access each country object either by its name, code or alpha.
countriesObject["Poland"] // →
countriesObject["POL"] // → The same object
countriesObject["616"] // →
My question is, would it be considered good practice, or there are some better ways to achieve the same or similar result?
Thank you!
That's fine, as all of those keys, as you correctly noted, will be pointing to the same object. The biggest problem that I see here is that it's easy to reduce readability of the code by using this approach. Let's say we have this fragment:
console.log( countriesObject[id] );
The question is, what is id here? Is it full country name? or just alpha? or code? You might just not care, true, but if you do, consider giving them additional structure:
const countriesObject = countries.reduce((object, country) => {
const { name, alpha, code } = country;
const countryCopy = { ...country };
// it makes sense to place them on the same line to show the intent
object.name[name] = object.code[code] = object.alpha[alpha] = countryCopy;
return object;
}, { name: {}, code: {}, alpha: {} });
Another potential issue is that you won't be able to drop the countries easily from this object; it's not enough to delete just a single key pointing to it, you'll have to go and remove all three. But that doesn't seem to be a big thing here; this looks more like a dictionary.
You can indeed write it like this:
var countries = {[
"poland": {
alpha: "POL", code: "616"
},
"hungary": {
alpha: "HUN", code: "348"
}
]}
Accessing each country like this:
var poland = countries.poland;
This, in turn, produces more readable code:
var alpha = countries.poland.alpha;
instead of
var alpha = countries[0].alpha;
But there is no set preference.
Docs

After creating a new sites List Page How can I add values to it?

I have created a new List Page but don't know how to populate it with values. As newDomainpage doesn't contain any values yet, I keep getting a NULL error while trying to set the value.
var domainPage = SitesApp.getPageByUrl("https://sites.google.com/a/idearebel.com/url-of-page");
var newDomainPage = newClientPage.createListPage(projectName, projectUrl, domainPageContent, [ "Used", "Title", "Notes" ]);
var domainPageItems = domainPage.getListItems();
var newDomainPageitems = newDomainPage.getListItems();
for(var i in domainPageItems) {
newDomainPageitems[i].setValueByIndex(2, domainPageItems[i].getValueByName("Title"));
// Logger.log(domainPageItems[i].getValueByName("Title"));
}
I am new to Google Scripts, therefore any help will be much appreciated.
Resolved, I was using the wrong function for the job. addListItem is the correct function to use.
for(var i in domainPageItems) {
newDomainPage.addListItem([ "", domainPageItems[i].getValueByName("Title"), "", "" ]);
}

Creating layered JSON object

I'm sure this is a simple question, but I can't find any information to help me, and I've been lost for a while. I'm trying to create a JSON object, and here is what I have so far:
var myJsonObject = new Object();
myJsonObject.context.applicationName = appName;
myJsonObject.context.ID = ID;
myJsonObject.context.domain = domain;
myJsonObject.context.production = "no";
myJsonObject.other.name = userName;
myJsonObject.other.date = userDate;
var myString = JSON.stringify(myJsonObject);
and here is what I want my JSON string to look like.
{
"context": {
"applicationName":"example",
"ID":"exampleID",
"domain":"someDomain",
"production","no"
},
"other": {
"name":"userName1",
"date":"userDate1"
}
}
However, I keep getting myJsonObject.context is undefined errors. I mean, I understand why it's happening, I never actually initialize it, but I don't know how to go about correcting this. Any help would be appreciated.
I'm guessing the myJsonObject.context has to be initialized as another object, and then I just add it to my original object as an array of objects....is this correct?
Yes, you need to first set it to an object, or you can just set them on the first line:
var myJsonObject = {context : {} , other: {} };
Also note that you can define your objects using a shorter syntax, like so:
var myJsonObject = {
context: {
applicationName: appName,
ID: ID,
domain: domain,
production: "no"
},
other: {
name: userName,
date: userDate
}
};
I'm guessing the myJsonObject.context has to be initialized as another object
Yes
and then I just add it to my original object
You'd generally do that at the same time
as an array of objects
No. You have nothing resembling an array there.
var myJsonObject = {};
myJsonObject.context = {};
myJsonObject.context.applicationName = appName;
Define myJsonObject.context = {}; property first.

Javascript length of array in object

I have a Javascript object defined as follows:
var active = {
waypoints: [],
scenario: []
}
I push to array scenario with:
var myScenario = {
id: terrainId,
text: text
};
active.scenario.push(myScenario);
However I get 0 when:
console.log(active.scenario.length);
So of course I cannot loop through the array content. If I do:
console.log(active.scenario)
I see the array content within Chrome plus the correct array length. I have similar code that defines and works with arrays, but outside of an object definition.
Most grateful for insight into why length is 0.
It works fine:
JSFiddle
var terrainId = 1;
var text = "text";
var active = {
waypoints: [],
scenario: []
}
var myScenario = {
id: terrainId,
text: text
};
active.scenario.push(myScenario);
console.log(active.scenario.length);
Looks like the problem is somewhere else.

AngularJS is removing my $_parent property when the object is passed back to the controller function

I have a linked list of JavaScript objects that I want to generate breadcrumbs from.
Because I'm using the list in recursive directive I need to use $_prev and $_next (instead of prev and next) so I won't get JSON.parse error about circular reference.
var myapp = angular.module('myApp', []);
var data00 = { id: 0, label: 'label_0' }
var data01 = { id: 1, label: 'label_1' }
var data02 = { id: 2, label: 'label_2' }
data00.$_next = data01;
data01.$_next = data02;
data01.$_prev = data00;
data02.$_prev = data01;
myapp.controller('testController', function($scope){
$scope.data = data02;
$scope.getBreadCrumbs = function(branch){
var crumbs = branch.label;
while(branch.$_prev){
branch = branch.$_prev;
crumbs = branch.label + ' \\ ' + crumbs;
}
return crumbs;
}
});
jsFiddle
Everything works in chrome, but in IE8 inside getBreadCrumbs function $_prev property does not exist.
Any input how I can debug the issue would be greatly appreciated.
I'm not sure about your IE8 problem but IMHO your approach is not very good. I believe that by using a better approach you will cut down future development/maintenance and quite possibly get rid of your IE8 bug. What I would do is put all your dataxx objects into a single array and then either use a function or a angular directive(s) to create your breadcrumbs from that array.
I strongly discourage you from doing something like this
data00.$_next = data01;
data01.$_next = data02;
data01.$_prev = data00;
data02.$_prev = data01;
Because as you add more data points it'll be more unnecessary work. You can either use the length of the array to see if you are on the first/last breadcrumb on or use the $first $last property that angular gives you on an ng-repeat

Categories