Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
7

Undo a script in one control z A routine problem

Contributor ,
Aug 20, 2023 Aug 20, 2023

Hello 

There is a routine issue i face when I try to make a specific script which seems to make undoing the script in one control z impossible. 

Of note I ahve read the post about app.doScript(function()

So the script I am trying to make is to break a single text box with several columns inside into single text columns frames threaded the same way as the og text frame etc 

when i tried to make one before I got it to work but couldnt undo

So i tried to make one again

it duplicates the 1st frame the an eqaual amount of times to columns in the 1st text frame and then changes all of the duplicated frames to 1 column 


howwever it seems impossible to undo, and instead i have to watch indesign undoing every step

code below is a bit messy but potentially could anyone signpost me to solving this issue 

I ahve made a script which allows for rules to be placed inbetween differnt columns of different lengths and its a very multi step process, which has to come up with particaular values for particular situtions yet that can undo in one go.

As always many thanks all. 

Best


// Create a reference to the active document
var doc = app.activeDocument;

// Check if a text frame is selected
if (doc.selection.length === 1 && doc.selection[0] instanceof TextFrame) {
  var selectedTextFrame = doc.selection[0];

  // Get the number of columns in the selected text frame
  var numColumns = selectedTextFrame.textColumns.length;

  // Wrap the entire operation in a single undoable action
  app.doScript("duplicateAndPositionTextBoxes()", ScriptLanguage.JAVASCRIPT);

  // Function to duplicate and position the text boxes
  function duplicateAndPositionTextBoxes() {
    try {
      var frameBounds = selectedTextFrame.geometricBounds;

      for (var i = 0; i < numColumns; i++) {
        // Duplicate the selected text frame
        var duplicatedTextFrame = selectedTextFrame.duplicate(selectedTextFrame.parent);
        duplicatedTextFrame.contents = "";

        // Set the position of the duplicated text frame
        var xOffset = i * (frameBounds[3] - frameBounds[1]);
        duplicatedTextFrame.move(undefined, [xOffset, 0]); // Change the coordinates as needed

        // Set the duplicated frame to a single column layout
        duplicatedTextFrame.textFramePreferences.textColumnCount = 1;
      }
    } finally {
      // Perform undo if there's an error
      if (app.scriptPreferences.enableRedraw) {
        app.scriptPreferences.enableRedraw = false;
        app.undo();
        app.scriptPreferences.enableRedraw = true;
      }
    }
  }
} else {
  alert("Please select a single text frame.");
}






TOPICS
How to , Scripting , SDK
734
Translate
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

correct answers 1 Correct answer

Community Expert , Aug 20, 2023 Aug 20, 2023

Hi @SmythWharf, you've made a great start on your script and you seem to be learning a lot, so that's awesome. One of the confounding factors with your script is your use of app.undo(). I would avoid that if at all possible.

 

Here's something to guide you—I've written a script to do the column separating, and also called the whole thing from app.doScript, which means that the whole thing will be undo-able in one go. Hope that shows you one approach to the problem—but there are many ways.

- Mark

...
Translate
LEGEND ,
Aug 20, 2023 Aug 20, 2023
Translate
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
Community Expert ,
Aug 20, 2023 Aug 20, 2023

Hi @SmythWharf, you've made a great start on your script and you seem to be learning a lot, so that's awesome. One of the confounding factors with your script is your use of app.undo(). I would avoid that if at all possible.

 

Here's something to guide you—I've written a script to do the column separating, and also called the whole thing from app.doScript, which means that the whole thing will be undo-able in one go. Hope that shows you one approach to the problem—but there are many ways.

- Mark

 

/**
 * Separate selected text frame into column frames.
 * @author m1b
 * @discussion https://community.adobe.com/t5/indesign-discussions/undo-a-script-in-one-control-z-a-routine-problem/m-p/14021929
 */
function main() {

    separateTextColumns(app.activeDocument.selection[0]);

}
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Split Into Columns');


/**
 * Splits a multi-column text frame
 * into separate text frames.
 * @author m1b
 * @version 2023-08-21
 * @param {TextFrame} textFrame - the text frame to split.
 */
function separateTextColumns(textFrame) {

    if (
        textFrame == undefined
        || textFrame.constructor.name != 'TextFrame'
        || textFrame.textFramePreferences.textColumnCount < 2
    )
        return;

    app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;

    var columnCount = textFrame.textFramePreferences.textColumnCount,
        columnGutter = textFrame.textFramePreferences.textColumnGutter,
        b = textFrame.geometricBounds,
        frameWidth = b[3] - b[1],
        inset = textFrame.textFramePreferences.insetSpacing,
        frames = [textFrame];

    // calculate the column width
    var columnWidth = (frameWidth - inset[1] - inset[3] - (columnGutter * (columnCount - 1))) / columnCount;

    // adjust the textFrame to the width of one column
    // also remove inset spacing, if any
    textFrame.textFramePreferences.textColumnCount = 1;
    textFrame.textFramePreferences.insetSpacing = [inset[0], 0, inset[2], 0];
    textFrame.geometricBounds = [b[0], b[1] + inset[1], b[2], b[1] + inset[1] + columnWidth];

    // now add the other column frames and thread them
    for (var i = 1; i < columnCount; i++) {
        var frame = frames[i - 1].duplicate(undefined, [(columnWidth + columnGutter), 0]);
        frame.parentStory.contents = '';
        frames[i - 1].nextTextFrame = frame;
        frames.push(frame);
    }

    // done!

};

 

 

Translate
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
Contributor ,
Aug 20, 2023 Aug 20, 2023
LATEST

Hello, 

Thank you very much for this sample, Ill dig into to it and try and see if I can understand

Many thanks 

 

Smyth

Translate
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