Skip to main content
Known Participant
September 7, 2024
Question

Help on script for automatic threading

  • September 7, 2024
  • 1 reply
  • 1084 views

Hello, 

the below script automatically threads a selection of unthreaded text frames left to right 

but I notice that the copy from one frame when threaded is direcly against the copy in the previous frame.

I am not sure of the best way to prevent this. 

The left image is what the script does but i would prefer for it to do what is happening on the right 

 

 

 

 

Any suggestions for this issues would be great 

Thank you 

Smyth

 

 

 

var gScriptName = "Thread Text Frames (Left to Right)";

try {
    app.doScript(main, undefined, undefined, UndoModes.ENTIRE_SCRIPT, gScriptName);
    // Force a screen refresh to update the threading display (if necessary).
    app.menuActions.itemByName("$ID/Force Redraw").invoke();
} catch (e) {
    alert(e + ". An error has occurred, try again.", gScriptName);
}

function main() {
    var selectedFrames = app.selection;

    if (selectedFrames.length < 2) {
        alert("Select at least two text frames to thread.", gScriptName);
        return;
    }

    var allThreaded = true;
    var threadedCount = 0;
    var firstFrameThreaded = false;

    // Determine if all selected frames are threaded
    for (var i = 0; i < selectedFrames.length; i++) {
        if (selectedFrames[i] instanceof TextFrame) {
            // Check if the frame has a previousTextFrame
            if (selectedFrames[i].previousTextFrame != null) {
                threadedCount++;
            } else if (selectedFrames[i].nextTextFrame != null) {
                // If it has a nextTextFrame, it is the first frame in a threading chain
                firstFrameThreaded = true;
                threadedCount++;
            } else {
                allThreaded = false;
            }
        }
    }

    // If all frames are threaded (including the first in a chain), show the appropriate message
    if (allThreaded && (threadedCount === selectedFrames.length)) {
        alert("All selected frames are already threaded. Please select frames that are not yet threaded.", gScriptName);
        return;
    }

    // Show error if more than one previously threaded frame is selected
    if (threadedCount > 1) {
        alert("Please ensure no more than one previously threaded text frame is selected.", gScriptName);
        return;
    }

    // Sort the selected frames by their position
    selectedFrames.sort(compareFramesByPosition);

    // Add a carriage return to the end of each frame's text (except the first one)
    for (var i = 1; i < selectedFrames.length; i++) {
        addCarriageReturn(selectedFrames[i]);
    }

    // Start threading from the leftmost frame
    var leftmostFrame = selectedFrames[0];

    threadFrames(selectedFrames, leftmostFrame);
}

function compareFramesByPosition(frameA, frameB) {
    // Sort by x-position (geometricBounds[1] is the x-coordinate)
    return frameA.geometricBounds[1] - frameB.geometricBounds[1];
}

function threadFrames(frames, startFrame) {
    var previousFrame = startFrame;

    for (var i = 1; i < frames.length; i++) {
        var currentFrame = frames[i];

        // Thread the current frame to the previous one
        currentFrame.previousTextFrame = previousFrame;

        previousFrame = currentFrame;
    }
}

function addCarriageReturn(frame) {
    var text = frame.parentStory;
    var lastInsertionPoint = text.insertionPoints[-1];
    lastInsertionPoint.contents = "\r";
}

 

 

 



This topic has been closed for replies.

1 reply

Robert at ID-Tasker
Legend
September 7, 2024

 

    // Add a carriage return to the end of each frame's text (except the first one)

 

Why? 

 

You need to add enter before the loop, to the end of the ParentStory of the 1st TF's, as well.

 

Or check if there was one. 

 

Known Participant
September 7, 2024

Hello, 

Thank you for the advice, I tried to recreate the issue above  - which occured both using the script and manually - however I was unable to recreate it. This is a good thing ---- it seems it works.

Regarding the comment you mentioned, it was from an earlier version and can be ignored. 

Anyhow, below is the script minus that part. 

 

Best, 

 

Smyth

 

 

var gScriptName = "Thread Text Frames (Left to Right)";

try {
    app.doScript(main, undefined, undefined, UndoModes.ENTIRE_SCRIPT, gScriptName);
    // Force a screen refresh to update the threading display (if necessary).
    app.menuActions.itemByName("$ID/Force Redraw").invoke();
} catch (e) {
    alert(e + ". An error has occurred, try again.", gScriptName);
}

function main() {
    var selectedFrames = app.selection;

    if (selectedFrames.length < 2) {
        alert("Select at least two text frames to thread.", gScriptName);
        return;
    }

    var allThreaded = true;
    var threadedCount = 0;
    var firstFrameThreaded = false;

    // Determine if all selected frames are threaded
    for (var i = 0; i < selectedFrames.length; i++) {
        if (selectedFrames[i] instanceof TextFrame) {
            // Check if the frame has a previousTextFrame
            if (selectedFrames[i].previousTextFrame != null) {
                threadedCount++;
            } else if (selectedFrames[i].nextTextFrame != null) {
                // If it has a nextTextFrame, it is the first frame in a threading chain
                firstFrameThreaded = true;
                threadedCount++;
            } else {
                allThreaded = false;
            }
        }
    }

    // If all frames are threaded (including the first in a chain), show the appropriate message
    if (allThreaded && (threadedCount === selectedFrames.length)) {
        alert("All selected frames are already threaded. Please select frames that are not yet threaded.", gScriptName);
        return;
    }

    // Show error if more than one previously threaded frame is selected
    if (threadedCount > 1) {
        alert("Please ensure no more than one previously threaded text frame is part of your selection, then try again.", gScriptName);
        return;
    }

    // Sort the selected frames by their position
    selectedFrames.sort(compareFramesByPosition);

    // Start threading from the leftmost frame
    var leftmostFrame = selectedFrames[0];

    threadFrames(selectedFrames, leftmostFrame);
}

function compareFramesByPosition(frameA, frameB) {
    // Sort by x-position (geometricBounds[1] is the x-coordinate)
    return frameA.geometricBounds[1] - frameB.geometricBounds[1];
}

function threadFrames(frames, startFrame) {
    var previousFrame = startFrame;

    for (var i = 1; i < frames.length; i++) {
        var currentFrame = frames[i];

        // Thread the current frame to the previous one
        currentFrame.previousTextFrame = previousFrame;

        previousFrame = currentFrame;
    }
}
Robert at ID-Tasker
Legend
September 7, 2024

Great. 

 

But what is the reason for this part:

    // Start threading from the leftmost frame
    var leftmostFrame = selectedFrames[0];

    threadFrames(selectedFrames, leftmostFrame);
}

 

Why not just pass the array as an argument and in there "extract" / use first element as a "starting point"?