Dynamic Variable Naming

Explorer ,
Jan 27, 2022 Jan 27, 2022

Copy link to clipboard

Copied

Hey everyone,

 

I'm trying to get confirmation on whether ExtendScript supports dynamic variable naming. Everything I've read up to this point suggests that it doesn't. Sad face.

 

Basically, my goal is to create a dialog window that has a list of items (page numbers), and the total number of items will vary depending on earlier user input. Probably using radio buttons, I am hoping that users can see each item and select for it either Option A or Option B (and not both).

 

If dynamic variable naming is a possiblity, I'm hoping to be able to use variables like optionAPage1 and optionBPage1 with true/false values, wherein the integer changes based on the item/page number. (Or maybe optionsPage1 with values like A/B.)

 

If dynamic variable naming isn't supported, I'm all ears on an alternative solution! Better this than having hundreds of lines of code!

 

Thanks everyone,

 

Michael

TOPICS
Scripting

Views

171

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jan 27, 2022 Jan 27, 2022

Copy link to clipboard

Copied

Unclear what the use case is. Have you looked into text variables to see if they can accomplish your task?  

 

https://helpx.adobe.com/indesign/using/text-variables.html

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jan 27, 2022 Jan 27, 2022

Copy link to clipboard

Copied

Here's a article on dynamic variable names in javascript. At a quick glance it isn't clear to me that your use case needs any of that though.

 

Where and when does the user choose Option A or B? I'm picturing a dialog asking which option, then, after choosing that, changing to show a UI just for that chosen option. This can be done with normal variables naming.

 

You can make an object with *keys* named "optionA" and "optionB" that could be referenced dynamically.

var options = {
    A: {
        pages: [
            {
                // page 1
                something: ...
            },
            {
                // page 2
                something: ...
            }
        ]
    },
    B:         pages: [
            {
                // page 1
                something: ...
            },
            {
                // page 2
                something: ...
            }
        ]
    }
}

Then access it like this:

var currentOption = "B";
var currentPages = options[currentOption].pages;

But then again, it would be more normal to have an Array of options, each which had a "name" or "label" of "A", "B" etc. I'd have a look at the data structures you are using and see if there's a better way.

 

Or, if I'm missing your point entirely, please ignore. 🙂

- Mark

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Feb 01, 2022 Feb 01, 2022

Copy link to clipboard

Copied

Thanks for your time thinking this over, Mark!

I've started looking into keys as a solution, but I'm not totally sure it's going to work. I realize part of the problem is that I've been so vague, so I hope to correct that here!

Early in my script, the user will select a CSV file that contains imposition data; it contains the list of Signatures with the Pages that are contained on each Signature. The problem I'm facing is that some Signatures contain multiple Sections, and without another option at my disposal, I'm trying to have the script open a dialog window that lets the user manually select if, for example, Page 43 should be in Section A or Section B (or in some cases, there might be Section C or even D). Depending on the imposition, any given Signature could have between 2 and 64 pages.

Presently, I think my bottleneck is with the radio buttons. If I'm not mistaken, my dialog code will look something like:

var group2 = BlahBlahBlah.add("group", undefined, {name: "group2"}); 
    group2.orientation = "row"; 
var statictext2 = group2.add("statictext", undefined, undefined, {name: "statictext2"}); 
    statictext2.text = "Page 1"; 
var radiobutton1 = group2.add("radiobutton", undefined, undefined, {name: "radiobutton1"}); 
    radiobutton1.text = "Section A"; 
var radiobutton2 = group2.add("radiobutton", undefined, undefined, {name: "radiobutton2"}); 
    radiobutton2.text = "Section B"; 


var group3 = BlahBlahBlah.add("group", undefined, {name: "group3"}); 
    group3.orientation = "row"; 
var statictext3 = group3.add("statictext", undefined, undefined, {name: "statictext3"}); 
    statictext3.text = "Page 2"; 
var radiobutton3 = group3.add("radiobutton", undefined, undefined, {name: "radiobutton3"}); 
    radiobutton3.text = "Section A"; 
var radiobutton4 = group3.add("radiobutton", undefined, undefined, {name: "radiobutton4"}); 
    radiobutton4.text = "Section B"; 

My initial thought process (coming from a PHP knowledge base) was to have those radio button variables set up as...

radiobutton<page number> and containing the value of either A or B or C, etc. Something like that I know I can easily build in a loop, but in ExtendScript I'm totally unsure.

I'd love to be able to just use an Array (ie, named SectionA, containing Pages like 42, 43, 44, etc). If I had an Array like that, I don't know how to name those radio button variables so I can get the correct data from them later. Sigh.

And unless I don't understand you correctly (read: very likely!), I don't know if objects/keys will eliminate this dumbness I'm experiencing! 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Feb 01, 2022 Feb 01, 2022

Copy link to clipboard

Copied

In your code above you store the radio buttons as local variables, possibly in a "make UI" type function. If you want a handy way to link those radio buttons to some other data, just store the radio button *with* that other data in an object.

For example:

// first you I think you want to parse your csv data
// into an array of signatures something like this:

// (this is a global var so can be accessed later from makeUI function)
var signatures = [

    {
        jobName: 'my test job 1',
        sections: [
            {
                name: 'A',
                pages: [1, 2, 3, 4]
            },
            {
                name: 'B',
                pages: [5, 6, 7, 8]
            },
            {
                name: 'C',
                pages: [9, 10, 11, 12]
            }
        ]
    },
    {
        jobName: 'my test job 2',
        sections: [
            {
                name: 'Front',
                pages: [1, 2, 3, 4, 5, 6, 7, 8]
            },
            {
                name: 'Back',
                pages: [9, 10, 11, 12, 13, 14, 15, 16]
            },
        ]
    },

]

// so signatures is an array of objects
// each 'signature' object has a jobName string and sections array
// each signature's sections array contains 'section' objects
// which each have a name and a pages array


// ... later during makeUI code not in same variable scope

// this line is just to simulate an earlier choice by user to select the 2nd signature
var currentSignature = signatures[1];

// make a radio button for each section in current signature
for (var i = 0; i < currentSignature.sections.length; i++) {
    var section = currentSignature.sections[i];
    section.radioButton = myRadioButtonGroup.add("radiobutton", undefined, undefined);
    section.radioButton.text = "Section " + section.name;
}

// so, if you know what signature you're working on (currentSignature)
// and the current section you're working on (currentSection)
// you can refer to its radio buttons like this:
currentSignature.sections[currentSection].radioButton;

// or
signatures[1].sections[0].radioButton.value;

// and because it is stored in the global signatures variable
// you'll always have access to it

Of course this is all just examples and won't all match your specific needs, but I hope it might give you something to ponder.

- Mark

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Feb 02, 2022 Feb 02, 2022

Copy link to clipboard

Copied

That's starting to make sense, Mark, thanks again. I owe you a <insert bribe object>.

 

I've used your guidelines/advice, and I've now got a loop that creates my dialog selection options, and then a quick alert check on the values that come through.

 

My variable has this structure: 

var signatures = [
    {
        number: 1,
        sections: [
            {
                name: A,
                pages: [ 1, 2, 3, 4, 5, 6, 7, 8 ]
            }
                   ]
    }
]

 

As far as I understand (?), each page's set of radio buttons must be in its own group for InDesign to automatically deselect other radio buttons. I don't think this code here is correct, but it does allow InDesign to do automatic deselection (ie, if 'Section A' is selected for Page 1, selecting 'Section B' will deselect the first option)... so many I fumbled through it successfully?

for (var x = 0; x < numberOfSignatures; x++) {
    var currentSignature = signatures[x];
    for (var y = 0; y < pageList.length; y++) {
        var pageGroup = pageList[y];
        pageGroup = BlahBlahBlah.add("group", undefined, {name: pageGroup}); 
        pageGroup.orientation = "row"; 
        pageGroup.alignChildren = ["left","center"]; 
        pageGroup.spacing = 10; 
        pageGroup.margins = 0; 
        var pageGroupstatictext = pageGroup.add("statictext", undefined, undefined, {name: "statictext2"}); 
            pageGroupstatictext.text = "Page " + pageList[y]; 

        for (var i = 0; i < currentSignature.sections.length; i++) {
            var section = currentSignature.sections[i];
            section.radioButton = pageGroup.add("radiobutton", undefined, undefined);
            section.radioButton.text = "Section " + section.name;
        }
    }
}

The pageList variable is an array containing [ 1, 2, 3, 4, 5, 6, 7, 8 ].

 

My failed alert looks like this:

alert(
  "Debugging\n\n" +
  "Page " + signatures[0].sections[0].pages[0] + ": " + signatures[0].sections[0].radioButton.value + "\n" +
  "    " + signatures[0].sections[0].radioButton.text + "\n\n" + 
  "Page " + signatures[0].sections[0].pages[1] + ": " + signatures[0].sections[0].radioButton.value + "\n" +
  "    " + signatures[0].sections[0].radioButton.text + "\n\n" +
 "Page " + signatures[0].sections[0].pages[2] + ": " + signatures[0].sections[0].radioButton.value + "\n" +
  "    " + signatures[0].sections[0].radioButton.text + "\n\n"
);

 

And they obviously return the same value (the value of the last button that is selected), and I know this is because they all reference:

signatures[0].sections[0].radioButton.value

 

I hate having to keep bothering you (and everyone here!), but how do I drill that down to get the value for the respective Page? Do I need to be more specific when declaring the variable:

var section = currentSignature.sections[i];

 

I initially played around with var section = currentSignature.sections[i].pages[0] but quickly realized that won't work when, say, Page 1 gets moved from Section A to Section B based on user selection.

 

I'm attaching this script (with a .txt extension because I can't upload .jsx) in case it helps to understand my muddled ignorance.

 

I appreciate any additional insight you can spare...!

 

Michael

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Feb 03, 2022 Feb 03, 2022

Copy link to clipboard

Copied

Hi Michael, I've had a look at your test script and I don't think I can make much sense out of it until you explain what you're trying to do—for example, I think it would be helpful if you posted a mockup of your imagined UI, and maybe even a couple if the UI changes for different signatures. Would that be possible?

By the way, there are some parts of your test script that seem quite strange and could do with some help, but first things first. The best thing is that you're giving it a good go! You'll learn a lot from this project.

- Mark

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jan 28, 2022 Jan 28, 2022

Copy link to clipboard

Copied

Hi Michael,

dynamic variable naming?

 

Hm. Some thoughts:

One could write a script in ExtendScript that could rewrite itself because you have access to the file class.

But to what purpose? If a user should interact with a script this is not necessary at all, I think. But I can be wrong, because I do not understand your use case.

 

If no user interaction should take place one could write a startup script with some event handlers that could react to things that happen with a document. You see, I am just poking around…

 

Also note, that you can use method insertLabel() and extractLabel() to store and retrieve data or even code with page items, documents or even the application.

 

Regards,
Uwe Laubender

( ACP )

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Feb 01, 2022 Feb 01, 2022

Copy link to clipboard

Copied

Thanks Uwe! 

I added some more details regarding my case use in a response above. Hopefully my dilemma is clearer now.

On a related note, your assistance in other threads has been invaluable to get me to this point! I appreciate it!

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Feb 03, 2022 Feb 03, 2022

Copy link to clipboard

Copied

"… but how do I drill that down to get the value for the respective Page?"

 

Hi Michael,

I'm not sure what you are asking here, but if you want to address a page where you start out with a number only, you could work like this, if the number denotes the position of the document page in the document:

var myPageNumber = 1;
var pageToAddress = app.documents[0].pages[ myPageNumber-1 ];

The numbering of the index of a page starts with 0 .

 

Now that you have the page stored in variable pageToAddress you always have access to that page even if you move it around in the document:

pageToAddress.move( LocationOptions.AT_END );
pageToAddress.rectangles.add({ geometricBounds : [0,0,"100mm","100mm"]});

 

Regards,
Uwe Laubender

( ACP )

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Feb 03, 2022 Feb 03, 2022

Copy link to clipboard

Copied

LATEST

Hi @mrlagace , not sure if this helps, but could you do it with dropdowns? this uses the built in InDesign dialog class to build a dropdown from your object:

 


var signatures = [
    {
        number: 1,
        sections: [
            {
                name: 'A',
                //needs to be a string list
                pages: [ '1', '2', '3', '4', '5', '6', '7', '8' ]
            }
        ]
    }
]


makeDialog();

var sigDropdown;
var sigList;

function makeDialog(){
    var theDialog = app.dialogs.add({name:"Signatures", canCancel:true});
    with(theDialog){
        with(dialogColumns.add()){
            with(borderPanels.add()){
                with(dialogColumns.add()){
                    staticTexts.add({staticLabel:"Signature " + signatures[0].number + " Pages"});
                }
                with(dialogColumns.add()){
                    sigList =  signatures[0].sections[0].pages
                    sigDropdown = dropdowns.add({stringList:sigList, selectedIndex:0, minWidth:80});
                }
            }
        }
    }

    //the dialog results
    var res = theDialog.show();
    if(res == true){
        sigDropdown = sigList[sigDropdown.selectedIndex];
        main()
	}else{
        theDialog.destroy();
    }
}


function main(){
    alert("Chosen Page: " + sigDropdown);
    return 
}

 

Screen Shot 54.pngScreen Shot 55.png

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines