Copy link to clipboard
Copied
Hi
I'm writing a script with the help of copilot.
I want to save only one fontFamilyName in a dropdownlist.
How can I do that?
#target indesign
// Create a new dialog
var dialog = new Window("dialog", "Choose a Font");
// Add a dropdown list for font family
var fontFamilyDropdown = dialog.add("dropdownlist", undefined, []);
fontFamilyDropdown.size = [200, 30];
// Add a dropdown list for font style
var fontStyleDropdown = dialog.add("dropdownlist", undefined, []);
fontStyleDropdown.size = [200, 30];
// Populate the font family dropdown list with all font families
var allfonts = app.fonts.everyItem().getElements();
for (var i = 0; i < allfonts.length; i++) {
fontFamilyDropdown.add("item", allfonts[i].fontFamily);
}
// Set the first item as the default selection
fontFamilyDropdown.selection = 0;
// Function to update the font style dropdown based on the selected font family
function updateFontStyleDropdown() {
fontStyleDropdown.removeAll();
var selectedFontFamily = fontFamilyDropdown.selection.text;
var fontStyles = [];
for (var i = 0; i < allfonts.length; i++) {
if (allfonts[i].fontFamily === selectedFontFamily) {
fontStyles.push(allfonts[i].fontStyleName);
}
}
for (var j = 0; j < fontStyles.length; j++) {
fontStyleDropdown.add("item", fontStyles[j]);
}
fontStyleDropdown.selection = 0;
}
// Update the font style dropdown when a new font family is selected
fontFamilyDropdown.onChange = updateFontStyleDropdown;
// Add a button to close the dialog
dialog.add("button", undefined, "OK");
// Initial population of font style dropdown
updateFontStyleDropdown();
// Show the dialog
dialog.show();
// Get the selected font family and style
var selectedFontFamily = fontFamilyDropdown.selection.text;
var selectedFontStyle = fontStyleDropdown.selection.text;
alert("You selected: " + selectedFontFamily + " - " + selectedFontStyle);
1 Correct answer
Hi @raldrald, one possible solution could be to collect only the unique font family names. Try this way:
// Create a new dialog
var dialog = new Window("dialog", "Choose a Font");
// Add a dropdown list for font family
var fontFamilyDropdown = dialog.add("dropdownlist", undefined, []);
fontFamilyDropdown.size = [200, 30];
// Add a dropdown list for font style
var fontStyleDropdown = dialog.add("dropdownlist", undefined, []);
fontStyleDropdown.size = [200, 30];
// Populate the font family drop
...
Copy link to clipboard
Copied
Hi @raldrald
It sounds like you want to ensure that your dropdown list contains only a single, specific font family name, rather than a list of all available font families. This means that when the user interacts with the dropdown, they will only see and be able to select that one particular font family.
Prabu
Design smarter, faster, and bolder with InDesign scripting.
Copy link to clipboard
Copied
A family name is repeated in the dropdownlist as many times as the number of font styles,
but I want to show only one font family name per a font.
Copy link to clipboard
Copied
Fonts are complicated.
The AI is missing that the font family is not distinct within the fonts collection.
Ask it to produce a distinct set of font family names, sort that and populate the family dropdown from that.
If you intend to get closer to the UI: this still misses document fonts, also the edge case where InDesign under the hood uses an extended concept of font families called font groups - multiple font groups can have the same family name but differ in font type.
Copy link to clipboard
Copied
At first copilot told me this, but it took too long and didn't stop.
// Populate the font family dropdown list with all font families
var fontFamilies = app.fonts.everyItem().name;
for( var i = 0; i < fontFamilies.length; i++){
fontFamilyDropdown.add("item", fontFamilies[i]);
}
so I've changed like this.
// Populate the font family dropdown list with all font families
var allfonts = app.fonts.everyItem().getElements();
for (var i = 0; i < allfonts.length; i++) {
fontFamilyDropdown.add("item", allfonts[i].fontFamily);
}
I'm new to scripting so I don't know what collection means exactly ...
Copy link to clipboard
Copied
Hi @raldrald
May i ask what purpose you have in mind for creating these scripts? it would help me better understand your needs and provide more relevent suggestions
Prabu
Design smarter, faster, and bolder with InDesign scripting.
Copy link to clipboard
Copied
Hi, @Anantha Prabu G Thank you for your reply.
I have a problem with too many fonts when designing.
So I want to manage fonts by design style.
Fonts are classified by design style, and when a font is added, I want to classify the added font by design style.
And I want to create text frames for the same content by design style to see the detailed difference.
I'm starting to study scripts, so I'm trying to make it little by little while learning the script.
I'm learning a lot from the community. Thank you all.
Copy link to clipboard
Copied
Is this what you expect?
Prabu
Design smarter, faster, and bolder with InDesign scripting.
Copy link to clipboard
Copied
I hope this way.
I want the same font family names show one time.
Copy link to clipboard
Copied
Collection is the term for these plural objects "fonts", "documents" that behave similar to an array, where you also have the item(), itemByName(), everyItem() and so forth functions.
In the quoted AI code it should have used the fontFamily property instead of the name property.
Outcome is similar though to your change, you still have to make the result array distinct and sort, or convince the AI to do that.
Problem with AIs is they produce "clean" modern javascript using bells and whistles that ExtendScript does not have - a Set class, forEach() and so forth. So if you're into this to learn scripting, find matching older books and follow them. Otherwise if this is an exercise how far AI can get you, better switch to InDesign's UXPScript which is modern Javascript. In that case you have to forget about ScriptUI (all your UI code above) and work more HTML-ish.
Copy link to clipboard
Copied
HI, @Dirk Becker
Thank you for you explanation about collection.
I have heard about collection, but I'm still hard to understand the exact difference and usage from array. I hope I can figure out someday.
As you said, AI tells me in a modern javascript way, so I get lost a lot every time,
but it is too hard for a beginner like me to start UXP...
So I appreciate this commutity a lot.
Copy link to clipboard
Copied
You can invoke UXPScript from ExtendScript.
var fontFamilies = app.doScript('require("uxp").script.setResult([...new Set(require("indesign").app.fonts.everyItem().fontFamily)])',ScriptLanguage.UXPSCRIPT)
require("uxp").script.setResult() is the convoluted UXP way to return a value to doScript.
require("indesign").app is the way to access the app object.
Copy link to clipboard
Copied
Thank you @Dirk Becker ,
I'll remember it and use it later.
Copy link to clipboard
Copied
That's really cool Dirk! I didn't know that sort of thing was possible with doScript. Interesting that the UXP version of fonts.everyItem().fontFamily gives unique results. I had assumed the "DOM stuff" was going to be much the same between ExtendScript and UXP. Have you observed that things are generally improved in UXP?
Copy link to clipboard
Copied
UXPScript yields the same results, its modern javascript just has a very short way to get the unique values.
Set(array) creates a Set (what you did with the object) automatically removing duplicates.
[... mySet] creates the array and initializes it using spread operator.
Copy link to clipboard
Copied
Oh right, I see now. I didn't read it properly. Thanks for responding.
Copy link to clipboard
Copied
That doScript still feels slow.
In a larger project I've turned to using plug-in code to query the fonts.
One trick to speed up things: when you build your unique map (actually not a set), assign an array instead of the true. Then push all found font styles into that array as they come along on the first turn.
Copy link to clipboard
Copied
Interesting. Yes good advice about collecting the styles at the same loop!
Copy link to clipboard
Copied
Hi @raldrald, one possible solution could be to collect only the unique font family names. Try this way:
// Create a new dialog
var dialog = new Window("dialog", "Choose a Font");
// Add a dropdown list for font family
var fontFamilyDropdown = dialog.add("dropdownlist", undefined, []);
fontFamilyDropdown.size = [200, 30];
// Add a dropdown list for font style
var fontStyleDropdown = dialog.add("dropdownlist", undefined, []);
fontStyleDropdown.size = [200, 30];
// Populate the font family dropdown list with all font families
var allfonts = app.fonts.everyItem().getElements();
// gather only unique font family names
var allFontFamilies = [],
unique = {};
for (var i = 0; i < allfonts.length; i++) {
if (true !== unique[allfonts[i].fontFamily]) {
allFontFamilies.push(allfonts[i].fontFamily);
unique[allfonts[i].fontFamily] = true;
}
}
for (var i = 0; i < allFontFamilies.length; i++) {
fontFamilyDropdown.add("item", allFontFamilies[i]);
}
// Set the first item as the default selection
fontFamilyDropdown.selection = 0;
// Function to update the font style dropdown based on the selected font family
function updateFontStyleDropdown() {
fontStyleDropdown.removeAll();
var selectedFontFamily = fontFamilyDropdown.selection.text;
var fontStyles = [];
for (var i = 0; i < allfonts.length; i++) {
if (allfonts[i].fontFamily === selectedFontFamily) {
fontStyles.push(allfonts[i].fontStyleName);
}
}
for (var j = 0; j < fontStyles.length; j++) {
fontStyleDropdown.add("item", fontStyles[j]);
}
fontStyleDropdown.selection = 0;
}
// Update the font style dropdown when a new font family is selected
fontFamilyDropdown.onChange = updateFontStyleDropdown;
// Add a button to close the dialog
dialog.add("button", undefined, "OK");
// Initial population of font style dropdown
updateFontStyleDropdown();
// Show the dialog
dialog.show();
// Get the selected font family and style
var selectedFontFamily = fontFamilyDropdown.selection.text;
var selectedFontStyle = fontStyleDropdown.selection.text;
alert("You selected: " + selectedFontFamily + " - " + selectedFontStyle);
I only changed a little section where I wrote "gather only unique font family names" and the next approx 12 lines.
- Mark
Copy link to clipboard
Copied
Thank you very much!
It woks well as I wanted.
By the way, may I ask what { } is?
I know [ ] means making array,
but this is my first time seeing { } in a script so I'm curious about what it is.
Copy link to clipboard
Copied
You're welcome!
{ } is an empty Object. You can read about it here and also this post might be a great one to read. You can make one like this:
var me = {
name: 'Mark',
username: 'm1b'
};
$.writeln('My name is ' + me.name);
// can also access like this:
$.writeln('My username is ' + me['username']); // this is how I use it in your script
// add to the object
me.lovesScripting = true;
I used an Object because I can check if something is unique by accessing the object's key—if the key exists already, then it isn't unique and we don't collect that font family.
- Mark
Copy link to clipboard
Copied
Thank you @m1b ,
I'll study more. Thank you for your reference links, too!
I'm learning a lot from your script.
Copy link to clipboard
Copied
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer
I've searched the { }, and I understand it a little.
Thank you, m1b.
I learned something new today.
Copy link to clipboard
Copied
Excellent! Good on you!
![](/skins/images/EAF9F7E131C5D03B206D7C6CFC7D852B/responsive_peak/images/icon_anonymous_message.png)
![](/skins/images/EAF9F7E131C5D03B206D7C6CFC7D852B/responsive_peak/images/icon_anonymous_message.png)