Copy link to clipboard
Copied
Hello all you masters of the InDesign universe...!
I created a fairly extensive script that, in part, writes user-input data into established tables based on the TextFrame label. It was all working completely fine until I moved that "table-writing" component into a Function, and now the script just stops when it gets to this line:
globalFrames[i].contents = jobCustomerText;
I am using the ".contents" method because I need to read and write with this data.
The jobCustomerText variable is defined outside of the Function after the user inputs that data, and right before the line in question, I can see that the variable does indeed contain the correct data, although the variable type comes in as "undefined."
When I copy this component into its own separate file to run/debug (and forcing the jobCustomerText variable to contain a specific string), it works as expected.
Previously, I was using this line:
globalFrames[i].contents = jobCustomer.text;
But I found with moving the component to a Function, I had to store this data differently, so now the variable gets filled as:
jobCustomerText = jobCustomer.text;
I suspect this doesn't given anyone here much to go on, unless there's some overall reason why it might not work (like .contents just doesn't execute properly within a function, or some silliness)... but I'm at a loss, and I'm really hoping to not have to go back to the bare bones of this project!
The correct answer of that thread is important. In Indesign, a scriptUI window is modal by default, which means in practice that you can't touch anything else until you've hit the OK button. But this can be difficult to understand due to the way scriptUI dialogs are usually implemented in our code. I recommend setting yourself the puzzle of separating the UI code from the "main engine" code. The test of success in this is if you can call your "main engine" with or without invoking the UI. This i
...Copy link to clipboard
Copied
You haven't given us much to go on, as much depends on your wider code. However, I think you problem is that the function you've written no longer has access to the jobCustomer variable (which I suspect is a reference to a ScriptUI edit text box).
If you could move the new function definition into the same scope as the jobCustomer object it should work. Does that make sense?
Look at this:
// NOT REAL CODE!
// Just a diagram.
function makeUI {
var w = new Window();
var jobCustomer = w.add('edittext');
function updateJobCustomer() {
var jc = jobCustomer.text; // should work!
}
}
function updateJobCustomer() {
var jc = jobCustomer.text; // won't work!
}
So the problem may be that the function cannot see the jobCustomer variable. But hard to say without more info.
- Mark
Copy link to clipboard
Copied
If the data is coming from outside the function, just pass it to the function:
function updateJobCustomer(jobCustomerText) {
globalFrame.contents = jobCustomerText; // should work!
}
Copy link to clipboard
Copied
Thank you Mark, my script is mostly set up as your "won't work" example, but more like the following code:
// NOT REAL CODE!
// Just a diagram.
var jobCustomerText = "";
var myDocument = app.documents[0];
function mainEngine() {
alert(jobCustomerText); // works!
var globalFrames = myDocument.textFrames;
for (var i=0; i< globalFrames.length ; i++) {
globalFrames[i].contents = jobCustomerText; // doesn't work!
}
}
function makeUI {
var w = new Window();
var jobCustomer = w.add('edittext');
var generateDocument = actionButtonGroup.add('button', undefined, 'Okay', {name:'generateDocument'});
generateDocument.onClick = function() {
jobCustomerText = jobCustomer.text;
mainEngine();
}
}
When it was working, it was set up more like the following code, which is why I think you're right... I'm just not sure why it wouldn't work after shuffling things around a bit. (I had to incorporate an additional user input step earlier in the script.) I'm quite Java-new and sometimes the underlying logic of objects escapes me.
// NOT REAL CODE!
// Just a diagram.
var myDocument = app.documents[0];
var w = new Window();
var jobCustomer = w.add('edittext');
var generateDocument = actionButtonGroup.add('button', undefined, 'Okay', {name:'generateDocument'});
generateDocument.onClick = function() {
var globalFrames = myDocument.textFrames;
for (var i=0; i< globalFrames.length ; i++) {
globalFrames[i].contents = jobCustomer.text;
}
}
Copy link to clipboard
Copied
For anyone facing the same dilemma, however rare it might be... I realize my folly, though I don't understand it at all!
Initially, I'd been given some good advice from this thread but in all my edits and changes and revisions, I'd removed this good advice from my script. When I reinstated the good advice, everything seems to fall back into place.
I don't understand why .contents won't write to the table without this in place, but I suppose my goal is to create something that works, not understand!
Copy link to clipboard
Copied
The correct answer of that thread is important. In Indesign, a scriptUI window is modal by default, which means in practice that you can't touch anything else until you've hit the OK button. But this can be difficult to understand due to the way scriptUI dialogs are usually implemented in our code. I recommend setting yourself the puzzle of separating the UI code from the "main engine" code. The test of success in this is if you can call your "main engine" with or without invoking the UI. This is very useful anyway because it means you can re-purpose your script to run in batch mode style, performing many repetitions using parameters that are fed to it via code.
Here's one way to structure this:
Edit: see actual example of this structure on my answer here.
If you're like me, you'll need to experiment with it before you really understand. And I've got *a lot* still to understand.
- Mark
Copy link to clipboard
Copied
Hi @mrlagace, when I read both your code examples above, I would think that they'd *both* work. The first has access to the global var jobCustomerText and the second has access to the non-global(!) var globalFrames via the global var myDocument. Also in the second example the onClick function has access to the var JobCustomer because it is defined in the same scope (it would anyway in this case because jobCustomer in this example is a global var).
As an aside, just for your learning, I'd like to offer some advice about variable naming. My strong preference is to be a bit more precise about what the variable actually holds. So in your example, jobCustomer would be called jobCustomerEditText because it holds a reference to a ScriptUI Edit text object. Your naming of jobCustomerText is perfect already because it holds a text string. I might call globalFrames -> allDocumentTextFrames, or just allTextFrames. The variable generateDocument I would call generateDocumentButton.
- Mark
Copy link to clipboard
Copied
Thank you Mark!
Good advice on variable naming, I'll keep that in mind.
Appreciate the explanation of structure as well; I'll start wrapping my head around it!
Thanks again.
Michael