How to iterate on a list of strings?
Found out about nodebox recently. I'm loving it so far, but I'm having trouble with my first project and would like to ask for help:
What I'm trying to do:
Import a csv and based on the N entries, generate a group consisting of the text of the entry + a rectangle under it that is distributed across a grid.
What I'm having trouble with:
- I'm struggling to find a way to successfully iterate on the text and feed one entry at a time for the textpath in the group; whenever I try to connect the data to the textpath, all entries get rendered at once;
- Also, I see that once I connect the group to a grid, things will be repeated until the grid is full. How to prevent that and instead just fulfill it until there are entries in the csv? (my idea is to once the entry is used, to remove it from the list, possibly with the first node as I'd like to iterate on the list as first-in-first-out)
What I've succeeded to do so far:
In my sample.nbdx I've done 2 networks - the one in the left is the closest I got of getting this idea done, but not in the way I'd like; while the one in the right is closest to what I'd like it to be, but with static text.
Thank you in advance for the help and for such nice tool!
- nodebox.png 4.84 KB
- nodebox-code.zip 1.13 KB
|?||Show this help|
|ESC||Blurs the current field|
|r||Focus the comment reply box|
|^ + ↩||Submit the comment|
You can use
Command ⌘ instead of
Control ^ on Mac
Support Staff 1 Posted by john on 13 Jan, 2023 09:54 PM
Welcome to the Nodrbox community.
Before answering, I just wanted to say that yours was the best asked question I've received in ages. Your description of what you want to do was complete and crystal clear, and you supplied me with sample code to work with. This makes my job much easier - thanks!
Also, both of your questions are excellent! They deal with basic issues that every new Nodeboxer grapples with. Let's get to it.
Your first issue has to do with the ways lists arrive into node ports: sometimes one at a time, sometimes all at once. The combine node takes an entire list into each of its seven ports, so if you feed 10 text paths into the first port and a rectangle into the second port, it will spit out all 10 text paths followed by that one rectangle.
In this case you would prefer to take one textpath at a time so that you can group it and the rect into a pair. Fortunately there is an easy way to do this: subnetworks.
Subnetworks are a way to make your own node functions - and "functions" is the key word here. To make Nodebox sing you need to think functionally, that is, break your problem into functions and make a node for each one.
What you need is a "pair" function with two inputs: a text path and a shape. Your pair function will take a list of text paths - one at a time - along with a single shape and spit out a group with the text path centered over that shape.
I made a pair node for you (attached). To see how it works, control-click on it and choose "Edit Children". You will see two null nodes to take in the textpath and shape. (I renamed them label and shape, a good habit but entirely optional.). The textpath and rect are combined and grouped - that's it.
So why does that pesky combine node behave the way you want it to here, but not out in the wild? The reason is that the pair function only takes the textpaths one at a time, so each time the function fires, it only has one textpath to combine with the rect.
This is something you can control when you use subnetworks. If you select pair and open the Metadata dialog (from the link above the properties pane), you will see the two ports listed on the left: label and shape. Select label. On they right you will find that the Range property is set to "Value" - this means take items one at a time. If you were to change Range to "List" it would instead take the all at once, and you would be back to the normal behavior of the combine node.
If this seems unintuitive and almost entirely undocumented, that's because it is. But once you get over this hump, once you embrace subnetworks and learn to think functionally, Nodebox will become immensely powerful and easy to bend to your will.
So please practice by creating some subnetworks of your own. The tutorial for how to make them is here: https://www.nodebox.net/node/documentation/concepts/subnetworks
Now for your second question.
The grid node produces a list of points arranged in a grid of R rows and C columns, so there are always R x C points in that list. If you have a grid with 2 rows and 3 columns, it will produce 6 points. But suppose you only want the first four of those points?
The answer is to use the slice node, one of the handiest nodes in Nodebox. Just feed the output of the grid node into a slice node and set the size to 4. In order to make this general purpose, use a count node to find out how many items you need and feed that into the size node.
This is what I've done with the nodes I added to the bottom of your sample code. Have a look at that.
This situation of needing a grid with an odd number of items comes up all the time. So instead of reinventing this wheel each time, you can dip into the Cartan Node Library:
In there you will find my grid_plus node. It has a limiting option built in, so you don't have to add your own slice node each time. It also allows you define the grid based on the size of each cell instead of the overall size of the grid; this way you don't have to resize the grid each time the number of items to be displayed changes. I added it to the sample code as an alternative solution.
My library is free for you to use as little or as much as you want. It may be a bit overwhelming at first, so don't feel you need to examine it right away. I just wanted you to know that it's there when you need it.
Hope that helps! Please let me know and please keep asking questions!