Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Blakles
Mar 10, 2008

I have lived a great deal among grown-ups. I have seen them intimately, close at hand. And that hasnt much improved my opinion of them.
Is it possible to build a string representing a JSON object element, then pass that string as the object to be searched in a foreach statement? The code below isn't working and I'm thinking it's because the obj variable is being built as a string, but how do I convert it to a JSON object reference?

code:
$(document).ready(function() {
	$.getJSON('data.json', function(data) {

		var url = window.location.pathname; // get url
		url = url.split("/"); // split into array

		var obj = "data";

		$.each(url, function(i, val) {
			obj += "[\""+val+"\"]";
		});

		// at this point, want obj to be = data["segment1"]["segment2"]["segment3"];
		$.each(obj, function(key, val) {
			alert(key);
		});
	});
});

Adbot
ADBOT LOVES YOU

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Blakles posted:

Is it possible to build a string representing a JSON object element, then pass that string as the object to be searched in a foreach statement? The code below isn't working and I'm thinking it's because the obj variable is being built as a string, but how do I convert it to a JSON object reference?

Back up. What exactly are you trying to achieve?

Find a specific object from the data returned by $.getJSON('data.json')?

What is the structure of "data"? An array of objects?

Actually, now that I've looked at your code for a while, I think you are trying to access data["segment1"]["segment2"]["segment3"], where the segments are part of the url?

If you know the exact depth of your objects and urls, then it would be data[url[0]][url[1]][url[2]]

If you don't know the exact number of levels, you could use recursion or iteration.

ManoliIsFat
Oct 4, 2002

I'm also confused what you're trying to do (how is json involved? You don't seem to be doing anything with that data object), but to answer your question, yes you can you JSON.parse() to change a JSON-representitive string in to an object. But knowing what you're actually trying to do (split on the slashes of a URL? the ambiguity of you assigning url, and then assigning the split of the url to the same variable will work, but is confusing)

Blakles
Mar 10, 2008

I have lived a great deal among grown-ups. I have seen them intimately, close at hand. And that hasnt much improved my opinion of them.
Sorry for the confusion. My data.json file is just a bunch of nested objects, no arrays.

I'm trying to find a specific object returned by data.json. The specific object I want will match the segments from the url.

So if I'm at http://domain.com/segment1/segment2/segment3, I want to get data[segment1][segment2][segment3] from data.json. Since I do not know how many levels deep the user will be on any given page you can see from my code that I built data[segment1][segment2][segment3] as a string and tried to pass that to the foreach function, but it won't accept it as a string. If I manually assign var obj = data[segment1][segment2][segment3] and use that in the foreach function, it works great.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
So maybe this is what you want
JavaScript code:
$(document).ready(function () {
	"use strict";

	$.getJSON('data.json', function (data) {
		var url = window.location.pathname; // get url
		var url_parts = url.split("/"); // split into array
		var current_part;
		var current_obj;

		current_obj = data;

		while (url_parts.length) {
			current_part = url_parts.pop();

			current_obj = current_obj[current_part];
		}

		//at this point, current_obj is the object you want.
	});
});

PhyrexianLibrarian
Feb 21, 2004

Compleat silence, please
Not sure if this is the best place to ask, but we have two platforms running at my company; one is a Java platform for content delivery, and one is a Rails application for all of the site's personalization aspects (reasons for this setup are long and historical). The Rails app is accessed through a sidebar that the Java app renders so that the links in that sidebar open in an iframe instead of the main window.

We'd like to convert this system to one that can be loaded via a single Javascript library, similar to how sites can use Facebook or Twitter via loading their Javascript SDKs asynchronously, and using tags on the site to indicate which parts should be controlled by that SDK. I can find a lot of examples of sites using this approach, but very few guidelines of how they work or un-minified examples. Does anyone know of a good tutorial for how to use this kind of approach?

Blakles
Mar 10, 2008

I have lived a great deal among grown-ups. I have seen them intimately, close at hand. And that hasnt much improved my opinion of them.

Wheany posted:

So maybe this is what you want
JavaScript code:
while (url_parts.length) {
	current_part = url_parts.pop();
	current_obj = current_obj[current_part];
}
Yes, that's what I was looking for. Thanks, wheany!

fuf
Sep 12, 2004

haha
I'm making a simple little media browser in Node (didn't there used to be a Node thread?).

I want to walk through my Movies directory and get all the file names:
code:
var fs = require('fs');

fs.readdir('/media/Movies', function(err, data) {
    // do stuff
});
But, if a movie is in its own sub-directory, I just wanna get the name of the biggest file in that directory (i.e. the actual movie), and nothing else. Any pointers?

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
You can use fs.stat() (and variants) to get information about a given file, including the size and whether it's a directory.

So you can check every file you come across, if it's a file just use the filename directly, if it's a directory get all the files in it and look at them all to pick out the largest one and use that.

waffle enthusiast
Nov 16, 2007



I'm hoping this is the right thread for this,

I'm trying to learn Angular (and just generally get better at JS) by mucking about with an ad-hoc project. The gist is that you select your city, a restaurant type, and a few other criteria in order to generate a stereotypical Yelp review. Unfortunately, I'm pretty sure I'm going about it the wrong way.

I cloned the stock Angular app template and started generating controllers, partials, and the back-end JSON (my repo is here, please ignore some of the DRY violations). Basically, I'm reading from various JSON docs (cities.json, restaurants.json, ratings.json, reviews.json) and, based on a user's selections (pick a city, click next, pick a restaurant type, click next, etc), creating the view accordingly. That ultimately leaves me with a review partial that has a filter for every user selection:

code:
...
{{ intro }} 
<span id="city" ng-repeat="city in cities | filter:data['city_id']">{{ city.name }}</span>, 
{{filler1}}
<span id="foodtype" ng-repeat="restaurant in restaurants | filter:data['cuisine_id']">{{ restaurant.cuisine }}</span>
...
So basically, the default view lists every city, but then angular filters out every one but the city that the user previously selected. Case in point: If I load the #/review route without having selected any user data, it just spits out all the cities, food types, etc. because nothing has been filtered out.

I presume the alternative solution would be to add some logic in the controller that creates scoped variables like $scope.city_name and $scope.cuisine_type, changing the above to:

code:
 ...
{{ intro }} 
{{ city_name }},
{{filler1}}
{{ cuisine_type }}
...
But that seems like it'll lead to a bunch of fat controllers and doesn't use any of the directive-based coolness of Angular. So I suppose my question is: How does one go about deciding what goes in a filter vs what should be pared down at the controller level before it gets to the HTML/template?

neurotech
Apr 22, 2004

Deep in my dreams and I still hear her callin'
If you're alone, I'll come home.

Does anyone have much experience with using Google Apps Script combined with Google Spreadsheets and Sites?

I have a few questions and am just wondering if this is the right place to ask them.

ynef
Jun 12, 2002

Dangerllama posted:

I'm hoping this is the right thread for this,

I'm trying to learn Angular (and just generally get better at JS) by mucking about with an ad-hoc project. The gist is that you select your city, a restaurant type, and a few other criteria in order to generate a stereotypical Yelp review. Unfortunately, I'm pretty sure I'm going about it the wrong way.

I cloned the stock Angular app template and started generating controllers, partials, and the back-end JSON (my repo is here, please ignore some of the DRY violations). Basically, I'm reading from various JSON docs (cities.json, restaurants.json, ratings.json, reviews.json) and, based on a user's selections (pick a city, click next, pick a restaurant type, click next, etc), creating the view accordingly. That ultimately leaves me with a review partial that has a filter for every user selection:

code:
...
{{ intro }} 
<span id="city" ng-repeat="city in cities | filter:data['city_id']">{{ city.name }}</span>, 
{{filler1}}
<span id="foodtype" ng-repeat="restaurant in restaurants | filter:data['cuisine_id']">{{ restaurant.cuisine }}</span>
...
So basically, the default view lists every city, but then angular filters out every one but the city that the user previously selected. Case in point: If I load the #/review route without having selected any user data, it just spits out all the cities, food types, etc. because nothing has been filtered out.

I presume the alternative solution would be to add some logic in the controller that creates scoped variables like $scope.city_name and $scope.cuisine_type, changing the above to:

code:
 ...
{{ intro }} 
{{ city_name }},
{{filler1}}
{{ cuisine_type }}
...
But that seems like it'll lead to a bunch of fat controllers and doesn't use any of the directive-based coolness of Angular. So I suppose my question is: How does one go about deciding what goes in a filter vs what should be pared down at the controller level before it gets to the HTML/template?
I am just learning Angular as well, so take my response with a grain of salt. Or two.

In the Guide, it is stated that filters are re-evaluated on each digest, making them expensive if they work on large arrays. This can be alleviated by using them within the controller, where you can have control over when they need to be evaluated (data has changed).

Thus, I think you can write your filtering functionality as an Angular filter, but use it cautiously (i.e. within a Controller) to ensure good performance. Given how your app works (stepwise, with a "click next" operation between steps), I think an approach that re-evaluates filters on each digest, where the criteria for filtering is not even available for changing on the fly, is not very good and the Controller-based version is best.

TildeATH
Oct 21, 2010

by Lowtax
Is there enough interest among goons for a d3.js thread? I use it quite a bit for data viz but also for mapping and traditional DOM manipulation instead of jQuery and think it's pretty awesome.

Tres Burritos
Sep 3, 2009

TildeATH posted:

Is there enough interest among goons for a d3.js thread? I use it quite a bit for data viz but also for mapping and traditional DOM manipulation instead of jQuery and think it's pretty awesome.

This looks reaaaaaaly cool. I dunno about a thread but I'd certainly read whatever words you decided to type about it.

Alligator
Jun 10, 2009

LOCK AND LOAF

TildeATH posted:

Is there enough interest among goons for a d3.js thread? I use it quite a bit for data viz but also for mapping and traditional DOM manipulation instead of jQuery and think it's pretty awesome.
I'd be all for one but I feel it'd probably get buried fairly quick.

As an aside, if you've got some resources you found particularly useful when starting out (besides the examples) I'd love to see them, I'm stumbling through my first few projects with d3 right now.

Cryolite
Oct 2, 2006
sodium aluminum fluoride
I was looking through three.js's source and saw that some functions return a closure which is immediately invoked, like this:

JavaScript code:
rotateOnAxis: function() {

		// rotate object on axis in object space
		// axis is assumed to be normalized

		var q1 = new THREE.Quaternion();

		return function ( axis, angle ) {

			q1.setFromAxisAngle( axis, angle );

			this.quaternion.multiply( q1 );

			return this;

		}

	}(),

	rotateX: function () {

		var v1 = new THREE.Vector3( 1, 0, 0 );

		return function ( angle ) {

			return this.rotateOnAxis( v1, angle );

		};

	}(),
I've seen this done with the module pattern to hide private state, but that doesn't seem to be the case here. What does this pattern achieve here?

Funking Giblet
Jun 28, 2004

Jiglightful!
This seems to ensure that new THREE.Quaternion() and the Right vector (1,0,0) are only initialized once. RotateOnAxis seems to be chainable.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
Object allocation is expensive, yo.

EAT THE EGGS RICOLA
May 29, 2008

TildeATH posted:

Is there enough interest among goons for a d3.js thread? I use it quite a bit for data viz but also for mapping and traditional DOM manipulation instead of jQuery and think it's pretty awesome.

I can contribute to a d3.js thread if someone else starts one. It owns.

TildeATH
Oct 21, 2010

by Lowtax

Alligator posted:

As an aside, if you've got some resources you found particularly useful when starting out (besides the examples) I'd love to see them, I'm stumbling through my first few projects with d3 right now.

Scott Murray's intro is good, and you can read it free online:
http://chimera.labs.oreilly.com/books/1230000000345

After that, pickings are pretty sparse. The various cookbooks are no better than the examples you can find everywhere. Bostock maintains a massive collection of examples, but they can be pretty opaque.

If you're into geospatial infoviz like I am, you should look at everything Jason Davies does, like this loving awesome satellite projection of mapbox raster tiles:

http://www.jasondavies.com/maps/raster/satellite/

EAT THE EGGS RICOLA posted:

I can contribute to a d3.js thread if someone else starts one. It owns.

It's really something. Because it requires a modern browser, you end up using really clean JavaScript and you can even ditch jQuery. The new OpenStreetmap editor is written entirely in D3:
https://github.com/openstreetmap/iD/

There was a big push to get the technical questions off the Google Group and into StackOverflow, so there's decent coverage for most of the issues people run into, but it's still a bit tricky to understand the way selection and binding and other core concepts work.

Tres Burritos
Sep 3, 2009

EAT THE EGGS RICOLA posted:

I can contribute to a d3.js thread if someone else starts one. It owns.

I'm using/learning highcharts at work right now, can you compare / contrast?

Dolex
May 5, 2001

Tres Burritos posted:

I'm using/learning highcharts at work right now, can you compare / contrast?
You could recreate highcharts with D3.

D3 is a low-ish level SVG toolkit that also includes some helper functions for common data visualization problems (scale, transition, axes, etc)

D3 doesn't do anything for you (though the d3.layout.* kinda does). You are expected to have an understanding of the SVG spec, how the DOM works, and a fair bit of functional javascript.

People complain about the learning curve of D3, when they are really complaining about the learning curve of more advanced javascript features, and the obtuse and unforgiving SVG spec.

Having said that, D3 is immensely powerful and fantastic to use once you have gotten over the initial learning period.

I use D3 in my day job building web-based data analysis tools for a cloud security company.

If you are serious about web based interactive visualization you would be doing yourself a service to learn how to use D3.

Dolex fucked around with this message at 17:00 on Feb 24, 2014

Zaxxon
Feb 14, 2004

Wir Tanzen Mekanik

Dolex posted:

You could build recreate highcharts with D3.

D3 is a low-ish level SVG toolkit that also includes some helper functions for common data visualization problems (scale, transition, axes, etc)

D3 doesn't do anything for you (though the d3.layout.* kinda does). You are expected to have an understanding of the SVG spec, how the DOM works, and a fair bit of functional javascript.

People complain about the learning curve of D3, when they are really complaining about the learning curve of more advanced javascript features, and the obtuse and unforgiving SVG spec.

Having said that, D3 is immensely powerful and fantastic to use once you have gotten over the initial learning period.

I use D3 in my day job building web-based data analysis tools for a cloud security company.

If you are serious about web based interactive visualization you would be doing yourself a service to learn how to use D3.

just chiming in to say that d3 does in fact rule.

Kobayashi
Aug 13, 2004

by Nyc_Tattoo

TildeATH posted:

It's really something. Because it requires a modern browser, you end up using really clean JavaScript and you can even ditch jQuery. The new OpenStreetmap editor is written entirely in D3:
https://github.com/openstreetmap/iD/

Can you say more about this? I'm aware of D3, but I'm mostly interested in it as a way to get familiar with clean, modern JavaScript. What techniques are used by D3 that allows it to get away from jQuery?

TildeATH
Oct 21, 2010

by Lowtax

Kobayashi posted:

Can you say more about this? I'm aware of D3, but I'm mostly interested in it as a way to get familiar with clean, modern JavaScript. What techniques are used by D3 that allows it to get away from jQuery?

A big part of it is just that so many of the things people think you need jQuery for, like array functions, are now supported in modern browsers in core ECMAscript 5. Beyond that, D3 has a selection syntax that uses CSS selectors and allows you to make bulk changes to DOM elements, complete with complex transitions and tweening if you need them. This is paired with an expectation that data will be a direct part of the process.

The only reason you need jQuery now is that so many libraries are built on top of it, but I never use it or those libraries, because it's bloated--not just the codebase, but the whole approach that thinks any interactive website needs jQuery. I'm not even sure what people use jQuery for anymore, except as syntactic sugar, unless they're fans of things like jquery.ui, which I think is really horrible.

The thing with D3 is that you get the clean, necessary low-level stuff, and at the same time it gives you the capacity to draw maps, adjacency matrices, force-directed network diagrams, tree maps, and a bunch of other graphical, interactive bits that I think are no longer optional.

Of course, jQuery is supposed to be great for old browsers, but if you're looking to support older browsers, then you've already passed on D3, under the mistaken belief that D3 requires you to use SVG.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



TildeATH posted:

a bunch of other graphical, interactive bits that I think are no longer optional.

I'm just curious as to what you mean by this. Pretty much every demo they link to is some kind of graph, with the exception of a rather neat photo accordion thing that's kind of a niche application.

I guess I'll have to learn how an SVG DOM works to do anything more interesting with it than jQuery already does? Not opposed to learning, just annoyed that it's yet another obtuse spec that I'll just end up writing my own mini-library to paper over until 'd4js' comes out and does it better :sigh:

isochronous
Jul 15, 2001

*Golf Clap*

Munkeymon posted:

I have a comment in the last line of one of my scripts that helps Chrome not be useless for debugging it when it's loaded dynamically (downloaded and exec'd, basically):
JavaScript code:
//@ sourceURL=anything.whatever
Some versions of IE (at least IE 9) are interpreting this line, as in running it as part of the script. Does anyone know what the everloving gently caress is up with this?

Edit: I think it only happens when the script is included on a page with a doctype that triggers compatibility mode. Maybe. Need to look into it more.

On the chance that this hasn't been answered yet (I don't have time to read all 4 pages past this) the solution is to add a block comment around this line.

JavaScript code:
/*
//@ sourceURL=anything.whatever
*/

LP0 ON FIRE posted:

I'm trying to simply copy an array of arrays into an array using the example:

teamRedVelArrays = velArraysBackup.slice(0);

This doesn't seem to make my array of arrays change to the backup or vise-versa. Is it different for an array of arrays?

Answer: use a utility library like lo-dash =P

isochronous fucked around with this message at 22:19 on Feb 24, 2014

TildeATH
Oct 21, 2010

by Lowtax

Munkeymon posted:

I'm just curious as to what you mean by this. Pretty much every demo they link to is some kind of graph, with the exception of a rather neat photo accordion thing that's kind of a niche application.

Well, by that I meant that charts and maps and "interactive infoviz" should and can be everywhere. I find that everyone wants a map, and if I can keep one more crappy Google Map with a bunch of crappy pastel markers from coming into existence, then I'm happy. But as far as using D3 for non-graphical stuff, I mean that it's just as easy to make buttons, divs, and list elements using selection and data binding. And if you take a look at the undo implementation in iD (the Open Street Map editor) or better the behaviors:
https://www.mapbox.com/osmdev/2013/02/27/id-architecture-part-2/

..then you can see how D3's behaviors have a lot more to do with general web development than with infoviz. Or you can look at something like:

https://kindred.stanford.edu

Which has a bunch of infoviz, but also has lists and tables and all that and only uses D3 for it all. Or realize that Mike Bostock now works for the New York Times and so the various amazing poo poo coming out of NYT lately has a lot of D3 DNA in it. The real problem with D3 examples is that everyone thinks that D3 is for one-offs or it's a replacement for Flash.

Munkeymon posted:

I guess I'll have to learn how an SVG DOM works to do anything more interesting with it than jQuery already does? Not opposed to learning, just annoyed that it's yet another obtuse spec that I'll just end up writing my own mini-library to paper over until 'd4js' comes out and does it better :sigh:

I think, and I'm really out of my depth when it comes to jQuery, since I was never a jQuery master, that D3 is useful precisely because modern JavaScript isn't a steaming pile of poo poo, and so when you're using it, you're only using it for the data-binding, behaviors, custom events, and of course awesome maps and stick-and-circle diagrams.

I think D3 is actually going to be as big for the modern web as jQuery was for the old one.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



TildeATH posted:

Well, by that I meant that charts and maps and "interactive infoviz" should and can be everywhere. I find that everyone wants a map, and if I can keep one more crappy Google Map with a bunch of crappy pastel markers from coming into existence, then I'm happy. But as far as using D3 for non-graphical stuff, I mean that it's just as easy to make buttons, divs, and list elements using selection and data binding. And if you take a look at the undo implementation in iD (the Open Street Map editor) or better the behaviors:
https://www.mapbox.com/osmdev/2013/02/27/id-architecture-part-2/

..then you can see how D3's behaviors have a lot more to do with general web development than with infoviz. Or you can look at something like:

https://kindred.stanford.edu

Which has a bunch of infoviz, but also has lists and tables and all that and only uses D3 for it all. Or realize that Mike Bostock now works for the New York Times and so the various amazing poo poo coming out of NYT lately has a lot of D3 DNA in it. The real problem with D3 examples is that everyone thinks that D3 is for one-offs or it's a replacement for Flash.


I think, and I'm really out of my depth when it comes to jQuery, since I was never a jQuery master, that D3 is useful precisely because modern JavaScript isn't a steaming pile of poo poo, and so when you're using it, you're only using it for the data-binding, behaviors, custom events, and of course awesome maps and stick-and-circle diagrams.

I think D3 is actually going to be as big for the modern web as jQuery was for the old one.

Maybe the disconnect is that you haven't used jQuery enough? I mostly use it to paper over DOM interaction, AJAXy crap, and [custom] event binding and triggering because that's all annoyingly verbose to do 'natively' no matter how un-broken most modern JS interpreters are. You can do content/structure generation with jQ in a similar but more verbose way, too. The rest of that is probably doable or has been done in jQ with plugins or libraries, but I'm not up on plugins for the most because base jQ suits my needs pretty well and knockout is a nice enough data binding library.

I'd predict the jQ people will borrow a bunch of D3's features (and especially improve the animation functionality) and it'll be another framework battle instead of the route you seem to be predicting. jQ does already have a massive user base and plugin library going for it.

That said, D3's Enter/Exit examples have me somewhat confused. (run on an empty page)
code:
//works fine but I'm not sure how selecting nonexistent elements does anything?
d3.select('body').selectAll('p')
    .data([12,3,65,87,45,6,18])
    .enter().append('p')
    .text(function(d){return "I'm " + d});

d3.select('body').selectAll('p')
    .enter().append('p')
    .data([12,3,65,87,45,6,18])//error - something about there being no enter method on an array
    .text(function(d){return "I'm " + d});

d3.select('body') //12 gets bound to the body, I guess? At any rate, it doesn't show up
    .data([12,3,65,87,45,6,18])
    .enter().append('p')
    .text(function(d){return "I'm " + d});
I guess I'm trying to treat it too much like jQ?

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
hi my name is method chaining and i make code unreadable. what's a variable?

Helado
Mar 7, 2004

Munkeymon posted:

That said, D3's Enter/Exit examples have me somewhat confused. (run on an empty page)
code:
//works fine but I'm not sure how selecting nonexistent elements does anything?
d3.select('body').selectAll('p')
    .data([12,3,65,87,45,6,18])
    .enter().append('p')
    .text(function(d){return "I'm " + d});

d3.select('body').selectAll('p')
    .enter().append('p')
    .data([12,3,65,87,45,6,18])//error - something about there being no enter method on an array
    .text(function(d){return "I'm " + d});

d3.select('body') //12 gets bound to the body, I guess? At any rate, it doesn't show up
    .data([12,3,65,87,45,6,18])
    .enter().append('p')
    .text(function(d){return "I'm " + d});
I guess I'm trying to treat it too much like jQ?

http://knowledgestockpile.blogspot.com/2012/01/understanding-selectall-data-enter.html helps quite a bit or http://bost.ocks.org/mike/join/ also describes it although, the former is more thorough.

First thing that threw me for a loop when I was trying to understand selectAll is that D3 appends new methods to the array (which is where we get data). Hence why your 2nd example doesn't work. There is a method data() but not enter() on the returned array object from selectAll.

https://github.com/mbostock/d3/wiki/Selections#wiki-d3_selectAll posted:

Selections are arrays of elements—literally. D3 binds additional methods to the array so that you can apply operators to the selected elements, such as setting an attribute on all the selected elements. One nuance is that selections are grouped: rather than a one-dimensional array, each selection is an array of arrays of elements. This preserves the hierarchical structure of subselections.

The reason why the first works and the 3rd doesn't work as expected is how data is returned from select and selectAll and how data() interacts with them. When you retrieve select('body') you have a singular group of your first matched body tag. When you apply data to it, you are saying apply this one data object, an array, to body. Since a Body already exists (you selected it) there is no change to the group of body tags (you started with one, after applying data, there is still one body tag). This means that the enter() call has nothing to do since no new objects were added.

An illustrative example of the working function would be (or http://bl.ocks.org/mbostock/3808218 might be better):
code:
d3.select('body').selectAll('p')
    .data([0,1,2,3])
    .enter().append('p')
    .text(function(d){return "I'm " + d});

d3.select('body').selectAll('p')
    .data([5,4,3,2,1])
    .enter().append('p')
    .text(function(d){return "I'm " + d});

If we walk through what it's doing, the first selectAll returns an empty selection. Calling data adds 4 new elements to the list of elements. Since we added 4 elements (at indices 0-3 in our array of elements), that means the enter() call has something to do. So we call append which creates the element associated with that index under the parent. On the new <p> object, we add the text.

The second call, starts out the same, but this time we have a list of <p> elements. After calling data() our new size is 5 and the data associated with the indices has changed. When enter gets called only 1 item has been added and it is at index 4 in the list, so <p> is added and the data is filled in for that one. Well what about all those other elements, well that's where you'd have to break out your calls into an update phase (see the bl.ocks example above). You just have to make sure you do that after your enter() or else the <p> has not been created which can contain the text.

http://jsfiddle.net/LZsfP/4/
code:
d3.select('body').selectAll('p')
    .data([0,1,2,3])
    .enter().append('p')
    .text(function(d){return "I'm " + d});


var para = d3.select('body').selectAll('p')
		.data([5,4,3,2,1]);

// Create new elements
para.enter().append('p');

// Update text on all elements
para.text(function(d){return "I'm " + d});
Sorry if I interchange some terms like element/object/array/group/list, but hopefully this helps a little.

Helado fucked around with this message at 23:17 on Feb 26, 2014

A MIRACLE
Sep 17, 2007

All right. It's Saturday night; I have no date, a two-liter bottle of Shasta and my all-Rush mix-tape... Let's rock.

Suspicious Dish posted:

hi my name is method chaining and i make code unreadable. what's a variable?

meh, it's easier to follow sometimes if your javascript is just procedural. although if you're going that route format it like this:

JavaScript code:
d3.select('body').
  selectAll('p').
  data([12, 3, 65, 87, 45, 6, 18]).
  enter().
  append('p').
  text(function (d) { return "I'm " + d; });
edit, also just create the function once

JavaScript code:
var myNumber = function (num) {
  return "I'm " + num;
};

// ...
d3.select('body').
  selectAll('p').
  data([12, 3, 65, 87, 45, 6, 18]).
  enter().
  append('p').
  text(myNumber);

A MIRACLE fucked around with this message at 18:02 on Feb 26, 2014

Kobayashi
Aug 13, 2004

by Nyc_Tattoo
^ I remember closures from school, but that was a decade ago and I haven't really coded much since then. How does the "num" parameter get passed in that last example? Stated another way, I'm having trouble intuiting the the way values are flowing through that chain.

peepsalot
Apr 24, 2007

        PEEP THIS...
           BITCH!

Kobayashi posted:

^ I remember closures from school, but that was a decade ago and I haven't really coded much since then. How does the "num" parameter get passed in that last example? Stated another way, I'm having trouble intuiting the the way values are flowing through that chain.

the myNumber function is being passed as an argument to .text rather than being called directly. So the that the .text function can call it on each piece of data.

https://github.com/mbostock/d3/wiki/Selections#wiki-text

quote:

selection.text([value])
...if value is a function, then the function is evaluated for each selected element (in order), being passed the current datum d and the current index i, with the this context as the current DOM element. The function's return value is then used to set each element's text content...

TildeATH
Oct 21, 2010

by Lowtax
Method chaining can be frustrating, especially with D3 where a selection is the function being returned until you enter/exit, in which case enter/exit is the function being returned, or if you append, in which case the append function is being returned, or on Tuesdays, or in words like neighbor and weigh...

A MIRACLE posted:

JavaScript code:
d3.select('body').
  selectAll('p').
  data([12, 3, 65, 87, 45, 6, 18]).
  enter().
  append('p').
  text(myNumber);

Dots after always makes more sense, but it looks so wrong because nobody does it.

A MIRACLE
Sep 17, 2007

All right. It's Saturday night; I have no date, a two-liter bottle of Shasta and my all-Rush mix-tape... Let's rock.

Kobayashi posted:

^ I remember closures from school, but that was a decade ago and I haven't really coded much since then. How does the "num" parameter get passed in that last example? Stated another way, I'm having trouble intuiting the the way values are flowing through that chain.

Let me preface this by saying it's been a couple months since I wrote javascript. But basically I think they're monkey-patching the array class like this (or an Array-like class, I don't speak D3 either)

JavaScript code:

Array.prototype.text = function (otherFunction) {
  for (var i = 0; i < this.length; i++) {
    // this[i] is a DOM node or something I guess
    this[i].innerHTML = otherFunction(this.innerHTML); // otherFunction points to myNum in this case and can be called here
  };
  return;
};

TildeATH posted:

Dots after always makes more sense, but it looks so wrong because nobody does it.

I've been in Ruby land for a couple years and this is just something I started doing with lambdas that I started applying to javascript. It feels like inverted functional programming or something, idk haha

A MIRACLE fucked around with this message at 19:29 on Feb 26, 2014

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Suspicious Dish posted:

hi my name is method chaining and i make code unreadable. what's a variable?

They avoid closures which could help prevent memory leaks :shrug:


Thanks - that certainly helps me understand the intent behind the methods better. The docs are really hurting for a summary at the top of each section so I can see the return type without having to read an essay each time.

I guess you just have to learn the stop words in D3 chains to get the examples.

Strong Sauce
Jul 2, 2003

You know I am not really your father.





TildeATH posted:

Method chaining can be frustrating, especially with D3 where a selection is the function being returned until you enter/exit, in which case enter/exit is the function being returned, or if you append, in which case the append function is being returned, or on Tuesdays, or in words like neighbor and weigh...


Dots after always makes more sense, but it looks so wrong because nobody does it.

Trailing dots don't make any sense at all. It's also very easy to get an error when you decide to delete the last command. Prepending dots helps it naturally align and doesn't cause any problems.

Kobayashi posted:

^ I remember closures from school, but that was a decade ago and I haven't really coded much since then. How does the "num" parameter get passed in that last example? Stated another way, I'm having trouble intuiting the the way values are flowing through that chain.

d3 stores that function and later calls the function with a parameter containing the contents/data of that node. You are not actually setting, the "num" variable. You are passing a function with the knowledge that d3 will pass each data element into that function as the first parameter.

edit: actually text() doesn't need to store it since it's essentially draining the chain.

Strong Sauce fucked around with this message at 21:56 on Feb 26, 2014

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Kobayashi posted:

^ I remember closures from school, but that was a decade ago and I haven't really coded much since then. How does the "num" parameter get passed in that last example? Stated another way, I'm having trouble intuiting the the way values are flowing through that chain.

Well, you can have
JavaScript code:
var printer = function (val) {
	console.log(val);
};

var someArray = [1, 2, 3, 'qwerty', 'asd'];

var iterateWith = function (arr, func) {
    for (var q = 0; q < arr.length; q++) {
		func(arr[q]);
    }
}

for (i = 0; i < someArray.length; i++) {
	printer(someArray[i]);
}

iterateWith(someArray, printer);
And that will print each array element into the console twice, first with simple iteration, then using iterateWith. You can achieve the same by doing someArray.forEach(printer), where forEach will do something similar to iterateWith.

Adbot
ADBOT LOVES YOU

Helado
Mar 7, 2004

Thinking about it more today, I misspoke about the 3rd case above where you call:

JavaScript code:
d3.select('body') //12 gets bound to the body, I guess? At any rate, it doesn't show up
    .data([12,3,65,87,45,6,18])
    .enter().append('p')
    .text(function(d){return "I'm " + d});
data() still applies the 7 elements, meaning 6 more are added than were there previously. However, the parent of body is html, meaning the append() appends to the html tag and not the body. So your output looks something like:

code:
<html>
<body></body>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
</html>
edit: I've only done 4-5 projects with d3js and the last couple were largely just data crunching and displaying tables. I couldn't really figure out how the examples for building tables worked with the nested calls on selectAll('tr') and selectAll('td'), which led me to those links above.

Helado fucked around with this message at 23:09 on Feb 26, 2014

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply