Skip to main content
Participant
February 13, 2024
Answered

Script to adjust page colums and gutter

  • February 13, 2024
  • 4 replies
  • 960 views

I am trying to write a script that opens a dialog so the user can choose if colums and gutter should be adjusted. This is ment for tesing. I want to take this further later on but at the moment I am stuck with this simple task. The dialog works fine and the columns part works fine but I can’t merge it together successully. Where is my mistake?

 

var doc = app.activeDocument;
var selectedPage = doc.pages.item(0);
var mp = selectedPage.marginPreferences;
 
var dialog = new Window("dialog");
dialog.text = "Columns and Gutter";
dialog.preferredSize.width = 400;
dialog.orientation = "column";
dialog.alignChildren = ["left","top"];
dialog.spacing = 10;
dialog.margins = 16;
 
// GROUP1
// ======
var group1 = dialog.add("group", undefined, {name: "group1"});
group1.orientation = "row";
group1.alignChildren = ["left","top"];
group1.spacing = 30;
group1.margins = 0;
 
var statictext1 = group1.add("statictext", undefined, undefined, {name: "statictext1"});
statictext1.text = "Adjust to 12 Columns, Gutter 4?";
 
// GROUP2
// ======
var group2 = dialog.add("group", undefined, {name: "group2"});
group2.orientation = "row";
group2.alignChildren = ["left","center"];
group2.spacing = 10;
group2.margins = [0,20,0,0];
group2.alignment = ["right","top"];
 
var button1 = group2.add("button", undefined, undefined, {name: "button1"});
button1.text = "Cancel";
 
var button2 = group2.add("button", undefined, undefined, {name: "button2"});
button2.text = "OK";
 
button2.onClick = function () {
// Set gutter
mp.columnGutter = 4;
// Set column count
mp.columnCount = 12;
dialog.close(1);
};
 
 
button1.onClick = function () {
         dialog.close(0);
};
 
dialog.show();
 
This topic has been closed for replies.
Correct answer Peter Kahrel

Daniel -- The problem with your script is that it moans about a modal dialog or alert that's open. That's the alert that your script shows. You can get around that by using RobOctopus's approach, but in general the solution is to use a palette-style window instead of a dialog window. That's all, so change

var dialog = new Window("dialog");

to

var dialog = new Window("palette");

And you may have to define a target engine, which you do by adding this line at the top of your script:

#targetengine session;

 

Rob Day's solution is correct but uses InDesign's own dialog system, which is entirely different but may suit your purpose better.

4 replies

Peter Kahrel
Community Expert
Community Expert
February 14, 2024

all of InDesign‘s ruler unit abbreviations work.

 

That can be handled in ScriptUI as well, see e.g. in this script:

https://creativepro.com/files/kahrel/indesign/page_set-up.html

rob day
Community Expert
Community Expert
February 14, 2024

Thanks Peter, you certainly can do more with scriptUI—it’s the measurementEditbox one liner that I prefer when building simple dialogs.

 

Not that it matters much now that newspapers are dead, but for some reason UnitValue doesn’t work with Agates and Ciceros—ag and c return errors.

Peter Kahrel
Community Expert
Peter KahrelCommunity ExpertCorrect answer
Community Expert
February 13, 2024

Daniel -- The problem with your script is that it moans about a modal dialog or alert that's open. That's the alert that your script shows. You can get around that by using RobOctopus's approach, but in general the solution is to use a palette-style window instead of a dialog window. That's all, so change

var dialog = new Window("dialog");

to

var dialog = new Window("palette");

And you may have to define a target engine, which you do by adding this line at the top of your script:

#targetengine session;

 

Rob Day's solution is correct but uses InDesign's own dialog system, which is entirely different but may suit your purpose better.

rob day
Community Expert
Community Expert
February 13, 2024

Hi @Daniel268281559oj9 , For simple dialogs like this I use InDesign’s built-in dialog object—less code. This creates integer only edit boxes:

 

//variables for columns and gutter
var cn, g;
var theDialog = app.dialogs.add({name:"Edit Columns", canCancel:true});
with(theDialog.dialogColumns.add()){
    //dialog labels
    staticTexts.add({staticLabel:"Number of Columns:"});
    staticTexts.add({staticLabel:"Gutter:"});
}
with(theDialog.dialogColumns.add()){
    //integer boxes
    cn = integerEditboxes.add({editValue:12, maximumValue:100, minimumValue:2, minWidth:100});
    g = integerEditboxes.add({editValue:4, maximumValue:100, minimumValue:0, minWidth:100});
}
if(theDialog.show() == true){
    //the returned dialog values
    cn = cn.editValue;
    g = g.editValue;
    //the function to run
    setColumns()
    theDialog.destroy();
}


function setColumns(){
    //using Points for the gutter dimension
    app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
    var doc = app.activeDocument;
    var selectedPage = doc.pages.item(0);
    var mp = selectedPage.marginPreferences;
    mp.columnCount = cn;
    mp.columnGutter = g;
    app.scriptPreferences.measurementUnit = AutoEnum.AUTO_VALUE;
}

 

Participant
February 14, 2024

Thank you, it works perfectly. In my case units are mixed. Gutter 4 produces 4pt Gutter = 1,411 mm. I´ll find an adjustment for that 🙂

rob day
Community Expert
Community Expert
February 14, 2024

I´ll find an adjustment for that 🙂

 

Another reason I prefer the InDesign dialog class is, it is easy to enforce dialog data types. So here I’ve set g to a measurementEditbox, which lets the user enter any kind of unit—4mm, 4in, 4px, etc. The returned units are automatically converted to Points:

 

//variables for columns and gutter
var cn, g;
var theDialog = app.dialogs.add({name:"Edit Columns", canCancel:true});
with(theDialog.dialogColumns.add()){
    //dialog labels
    staticTexts.add({staticLabel:"Number of Columns:"});
    staticTexts.add({staticLabel:"Gutter:"});
}
with(theDialog.dialogColumns.add()){
    //integer box
    cn = integerEditboxes.add({editValue:12, maximumValue:100, minimumValue:2, minWidth:100});
    //measurement box. Here the default unit is from the document’s horizontal ruler setting
    g = measurementEditboxes.add({editUnits:app.activeDocument.viewPreferences.horizontalMeasurementUnits, editValue:0, minWidth:100});
}
if(theDialog.show() == true){
    //the returned dialog values
    cn = cn.editValue;
    g = g.editValue;
    //the function to run
    setColumns()
    theDialog.destroy();
}

function setColumns(){
    //the returned value for a measurementEditbox is converted to Points, 
    //so use Points for the script
    app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
    var doc = app.activeDocument;
    var selectedPage = doc.pages.item(0);
    var mp = selectedPage.marginPreferences;
    mp.columnCount = cn;
    mp.columnGutter = g;
    
    app.scriptPreferences.measurementUnit = AutoEnum.AUTO_VALUE;
}




 

 

 

 
RobOctopus
Inspiring
February 13, 2024

quick troubleshooting help. try using a try/catch alert to help identify where some problems might be happening. here's what I did.

 

i took the mp.columnGutter=4 line and changed it to

button2.onClick = function () {
// Set gutter
alert(mp.columnGutter)
try{
//mp.columnGutter = 2;
} catch (e){alert(e.message)}
alert(mp.columnGutter)
// Set column count
//mp.columnCount = 12;
    dialog.close();
}

This alerts back that the column gutter cant be interacted with because "a modal dialog is still active" so I moved the dialog.close to be at the top of the onclick function. despite the dialog being "closed" it still wasnt functioning and so i rewrote how the buttons are working and wrapped it into a function to close the dialog before interacting with indesign. in this instance the buttons are only returning whether you hit ok or cancel. you can rewrite the entire onclick functions to be instead.

var button1 = group2.add("button", undefined, undefined, {name: "Cancel"});
button1.text = "Cancel";

var button2 = group2.add("button", undefined, undefined, {name: "Ok"});
button2.text = "OK";

if(dialog.show()==1){
    dialog.close()
    return true
} else {
    dialog.close()
    return false
}

by default scriptUI will return 1 on a button assigned to the OK name. this allows you to have the dialog.show() code return back as 1 which == 1 and then return true out of the function. So the entire script looked like this at the end

var doc = app.activeDocument;
var selectedPage = doc.pages.item(0);
var mp = selectedPage.marginPreferences;
var temp = getColumnGutterDialog()
if(temp){
    mp.columnGutter = 4;
    mp.columnCount = 12;
}


function getColumnGutterDialog(){
var dialog = new Window("dialog");
dialog.text = "Columns and Gutter";
dialog.preferredSize.width = 400;
dialog.orientation = "column";
dialog.alignChildren = ["left","top"];
dialog.spacing = 10;
dialog.margins = 16;
 
// GROUP1
// ======
var group1 = dialog.add("group", undefined, {name: "group1"});
group1.orientation = "row";
group1.alignChildren = ["left","top"];
group1.spacing = 30;
group1.margins = 0;
 
var statictext1 = group1.add("statictext", undefined, undefined, {name: "statictext1"});
statictext1.text = "Adjust to 12 Columns, Gutter 4?";
 
// GROUP2
// ======
var group2 = dialog.add("group", undefined, {name: "group2"});
group2.orientation = "row";
group2.alignChildren = ["left","center"];
group2.spacing = 10;
group2.margins = [0,20,0,0];
group2.alignment = ["right","top"];
 
var button1 = group2.add("button", undefined, undefined, {name: "Cancel"});
button1.text = "Cancel";
 
var button2 = group2.add("button", undefined, undefined, {name: "Ok"});
button2.text = "OK";
 
if(dialog.show()==1){
    dialog.close()
    return true
} else {
    dialog.close()
    return false
}

} /* end of dialog function */

Alternative approach, you can probably change the dialog window type to a palette and interact with indesign and not notice this interaction at all. 

 

Hope this helps!

Participant
February 14, 2024

Thnak you very much. Very good approach and testing idea! I keep it in mind as my script evolves.