You're working on some lower thirds, and you've got your ass-kickin', award-contendin' design and animation all worked out and you're riding your keyframe high only to realize... shit. You've got versioning to do. A dozen names and titles, maybe, or region/time zone splits-- whatever. You've done your pretty-making, and now the grunt work comes in.
Open a comp, change the text layer sourcetext, change the other text layer, duplicate the comp, open it up, change the text layer, change the other text layer, duplicate the comp... Yeah, I'd get tired of it too.
Instead of opening any comp (past initial setup), you can change all the text from your Project Panel
and have it propagate into each comp automagically using a handy expression that simplifies the process. Let's hit it.
We're going to turn this:

into this:

The Code
We're going to rely on a method called split()
. What this does is break apart a string (some text) into an array, so we can make use of parts of the string independent of others.
As a nice change from my inflated code with odd twists of logic and comments, here's the expression in all its entirety and glory. This gets applied to the Source Text
field of a Text layer.
thisComp.name.split(" - ")[0]
The Explanation
thisComp.name
fetches the name of the comp. That's it-- easy enough, and .split()
is what pulls it apart.
Looking in our Project panel, you can see our comp name is set up with the dash separating each component. That is, we've got Full Name - Title
.
We pass the hyphen through the round brackets of split()
so it can identify which character(s) will act to split up the text (actually called a delimiter).
So, split(" - ")
would give us: "Full Name," and "Title"-- it's properly fractured the comp name string, as expected.
In order to address either component, we address them in its array like any other property.
thisComp.name.split(" - ")[0] // results in "Full Name" thisComp.name.split(" - ")[1] // results in "Title"
The Application
If we slot these expressions into the Source Text
fields on both our primary and secondary text layers, they'll now pull their text from the name of the comp, as determined by the array call. From here, we can duplicate the whole composition, change each comp name and end up with a stack of versions with not so much work after all.
I hope someone can help!
I’m trying to do a simple expression that can split a text in to two lines if the text is longer than 30 characters. But it needs to keep all words complete, meaning that the 1st line should end at the space in between words closest to that 30th character, and the 2nd line should start at the next word.
Hoping to hear suggestions.
not a wizard with expressions.
Nick.
compName = thisComp.name;
Some of my comps have to include semi-colons anyway to incorporate them without breaking the text?
Unsure what you’re asking, but having semicolons in your comp names won’t affect anything.
Thanks, very good tip! BTW, what if I did a lot of such compositions (lets say I have 100 songs) and then I want to tweak something in the animation or color in all of them? Is there any way to do this?
I’ve been searching all around the internet but I can’t find any way…
These days this method is a little outdated. Instead, set up a comp as a template with Master Properties, then duplicate that for each instance and change the text in the Master Properties panel.
Then when there’s a tweak to do, you can change it in any one of the child comps and it’ll update globally.
See: https://www.youtube.com/watch?v=H1ZsiQy764Q
Zack, awesome tut! I’m trying to use the split text function to take a list of comma separated values in a single text layer and add lines breaks instead of commas to separate them in that same text layer.
For example:
item 1, item2, item 3, item 4
Split text to put them on separate lines like this:
item 1
item 2
item 3
item 4
Here’s what I got for code. Is this right so that it affects the same layer we’re getting the text from and splitting to reformat it with line breaks? or do I need to assign this to another layer to output it?
thisLayer.split(“,”)[0] // item 1
thisLayer.split(“,”)[1] // item 2
thisLayer.split(“,”)[2] // item 3
thisLayer.split(“,”)[3] // item 4
Where is the text coming from? If it’s text within a text layer, you need to access it via
thisComp.layer("layerName").sourceText.text.value
Next up, to insert newlines, you can use a special command of
\n
— this tells Javascript to insert a new line wherever it sees it.To put it all together, there’s an easier shortcut to replace all instances of one symbol with another.
We’re still going to
split
the text, which turns a String into an Array, but then we’re going tojoin
the text, which turns an Array into a String, inserting whatever you want between the elements– in our case, a new line.var text = thisComp.layer("layerName").sourceText.text.value;
text.split(",").join("\n");
Nope….got it 🙂
Hi Zack,
I don’t understand where you applied the expression to. Did you apply it to the comp or the text layers?
Thank you,
Is there a script I can access to achieve this?
Is there a way to do the opposite? Type in the name/role and it changes the name of the comp to the text you use in the text field…?
Not without writing a script. Comp names aren’t “dynamic” in that way.
Good thing! But coming from development I´m not happy about having to create that many comps. It would be cool if I could just throw my comp with the text layers where I need it, adjust the name of the comp (with right click->rename) just for that spot and have the text layers take the text from that custom comp name. But I can´t find a way to access that custom name with After Effects expressions?! If anybody knows a way … let me know!
Hey Zack,
First of all thanks so much for sharing your knowledge and contributing so much for a better community.
I’ve got this file structure:
MASTER (main comp)
SHOT 09 – STROKE (precomp in the main comp which contains 3d stroke, particular etc – like brush stroke template)
SHOT 09 – STROKE – PRECOMP (where all my expressions are)
So I’m trying a way to control my expressions at the bottom of the food chain (inside SHOT 09 – STROKE – PRECOMP)
For instance I want my stroke path (which is a mask path as I’m using 3d stroke) to follow the path I draw on the main comp on the layer “SHOT 09 – STROKE”.
Which would be an expression like this one (which works fine):
comp(“MASTER”).layer(“SHOT 09 – STROKE”).effect(“STROKE COLOR”)(“Color”);
But now, as I will have many strokes throughout the different shots – I’m trying to find a way to automatize this just by TRUE duplicating my comps – so the naming is key.
I’m somewhere near but not making it work yet…
(so putting this expression on the bottom precomp “SHOT 09 – STROKE – PRECOMP”)
mainComp= comp (“MASTER”);
selfComp = thisComp.name;
parentComp = selfComp – thisComp.name.split(” – “)[3]; // Which ideally would give back SHOT 09 – STROKE
comp(“MASTER”).layer(parentComp).mask(“Mask 1”).maskPath
Does this make any sense to you?
Ideally if I made this work I would just true duplicate it and I would always have control over it from the layer on the main comp (controling stroke path, colour, width etc…)
Thanks in advance,
Joao
Sorry I meant:
comp(“MASTER”).layer(“SHOT 09 – STROKE”).mask(“Mask 1”).maskPath;
and not STROKE COLOR…
This saved my life, thanks!
Nevermind! Got it.
Just name comp: John Doe-Title-Date
Then in source text expression, define array, and for each text layer:
L3=thisComp.name;
L3.split(“-“)[0]
L3=thisComp.name;
L3.split(“-“)[1]
L3=thisComp.name;
L3.split(“-“)[2]
Pretty sure you could do this with as many lines as you wanted…
Not sure if this is answered above, but I’m essentially trying to have a 3-line lower third graphic based on comp name. I’ve messed with all the above expressions and I can’t quite get it.
I understand the array/delimiter concept for the two line one, but is a 3rd line with a separate delimiter possible?
ie: Comp name: JOHN DOE + District Attorney # 1995 – 2000
returns:
JOHN DOE
District Attorney
1995 – 2000
Thanks!
Great simple solution there, cheers.
I have been trawling the web, looking for a simple solution to this….
I have TEXT layers in multiple comps, and I want to control the actual text content from one master COMPOSITION.
I have tried everything to try and pull the Text file from a text layer, using expressions to no avail, but I am no java guru by a longshot.
Any ideas you could share?
Cheers
Ok!
So you have a master comp (we’ll name this composition “MASTER”), and you have child comps (we’ll name them “CHILD COMP – 1”, “CHILD COMP – 2”, “CHILD COMP – 3”). The ” – ” here is important to do an easy split.
In your master comp, create a text layer (“TEXT”), and split the text up so that each piece of text per comp is on a separate line; it should be structured like this:
TEXT FOR COMP 1
TEXT FOR COMP 2
TEXT FOR COMP 3
Now, from each child comp, what we need to do is say “Hey, go into MASTER comp, find layer TEXT, get its source text, and grab the contents from line [whatever comp number this is].” (If this is getting too complex, email me! Otherwise you can find a test AEP here (CC2014+))
Add this expression to the desired text layer within each CHILD COMP.
Hopefully this helps! In this way, you can have all of your text in one text layer in a master comp, and each child can pull from it without you having to go in and mess with anything yourself. Again– if you have any questions, email me! (This comment section is pretty limited).
That’s a great/awesome solution to Brett’s q. As interesting to read as the article!
Hi, is it possible to split twice in one text layer like this:?
I put this in my text layer: “*, #”
text_array = text.sourceText.split(“*”);
text_array[0]+thisComp.layer(“text_1”).text.sourceText+text_array[1]
text_array = text.sourceText.split(“#”);
text_array[0]+thisComp.layer(“text_2”).text.sourceText+text_array[1]
When I try this it only works on the last one, so this will show up like this:
“*, text_2”
So– you’re telling it to output two different things, and as that can’t happen, it only follows the very last instruction.
As an alternative, try something like this and it should result in what you’re after.
Very nice expression 😀
Thanks for the tip! This is huge time-saver!
thanks for the tips! I use this one almost on daily basis. Very useful.
Very nice, thanks for the handy tip.
This is a brilliant solution to a common task that takes up a lot of my time.
You have done a beautiful job coming up with this. I can’t wait to put it to use tomorrow at work on our weekly changing lower-thirds graphics!
Thanks, David! Let me know if you have any questions / come across any issues with it!