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

Script needs to work across unconnected pages

Contributor ,
Feb 28, 2025 Feb 28, 2025

Copy link to clipboard

Copied

Hello, I have a swap script which works. But if a user selects two objects on unconnected pages it fails to work. Any hints would be great. 

(Also any hints of how to swap the object layer positions too, as currently if something is index x and the other is index y it doesnt swap)

 

Best, 

 

Smyth

 

//AutoSwap
app.doScript(function () {
    if (app.selection.length !== 2) {
        alert("Please select exactly two objects.");
    } else {
        var firstObject = app.selection[0];
        var secondObject = app.selection[1];

        // Check if either object is a GraphicLine
        if (firstObject.constructor.name === "GraphicLine" || secondObject.constructor.name === "GraphicLine") {
            alert("Cannot swap selection with a rule.");
            return; // Exit the script if a GraphicLine is detected
        }

        // Ensure both objects are valid
        if (!firstObject.isValid || !secondObject.isValid) {
            alert("Invalid selection. Please select two valid objects.");
        } else {
            // Function to remember text frame settings
            function rememberTextFrameSettings(object) {
                if (object.constructor.name === "TextFrame") {
                    return {
                        verticalJustification: object.textFramePreferences.verticalJustification,
                        columnCount: object.textFramePreferences.textColumnCount,
                        isMultiColumn: object.textFramePreferences.textColumnCount > 1
                    };
                }
                return null;
            }

            // Function to apply text frame settings
            function applyTextFrameSettings(object, settings) {
                if (settings !== null) {
                    object.textFramePreferences.verticalJustification = settings.verticalJustification;
                    object.textFramePreferences.textColumnCount = settings.columnCount;
                }
            }

            // Remember text frame settings
            var firstSettings = rememberTextFrameSettings(firstObject);
            var secondSettings = rememberTextFrameSettings(secondObject);

            // Get the geometric bounds of both objects
            var firstBounds = firstObject.geometricBounds;
            var secondBounds = secondObject.geometricBounds;

            // Calculate width and height from geometric bounds
            var firstWidth = firstBounds[3] - firstBounds[1];
            var firstHeight = firstBounds[2] - firstBounds[0];
            var secondWidth = secondBounds[3] - secondBounds[1];
            var secondHeight = secondBounds[2] - secondBounds[0];

            // Function to compare width and height
            function areDimensionsEqual(width1, height1, width2, height2) {
                return Math.abs(width1 - width2) < 6 && Math.abs(height1 - height2) < 6; // Tolerance for floating-point precision
            }

            // Check if either object is a multi-column text frame
            var isFirstMultiColumn = firstSettings && firstSettings.isMultiColumn;
            var isSecondMultiColumn = secondSettings && secondSettings.isMultiColumn;

            // Handle swapping based on the type of objects
            if ((isFirstMultiColumn && !isSecondMultiColumn && secondObject.constructor.name === "Rectangle") ||
                (!isFirstMultiColumn && isSecondMultiColumn && firstObject.constructor.name === "Rectangle")) {
                // Swap geometric bounds only for multi-column text frame with picture
                firstObject.geometricBounds = secondBounds;
                secondObject.geometricBounds = firstBounds;
            } else {
                // Swap geometric bounds and apply text frame settings
                firstObject.geometricBounds = secondBounds;
                secondObject.geometricBounds = firstBounds;

                // Apply text frame settings only if both are text frames
                if (firstSettings && secondSettings) {
                    applyTextFrameSettings(firstObject, secondSettings);
                    applyTextFrameSettings(secondObject, firstSettings);
                }
            }

            // Handle grouped objects specifically
            function adjustGroupImagesPosition(group, offsetX, offsetY) {
                if (group.constructor.name === "Group") {
                    for (var i = 0; i < group.allPageItems.length; i++) {
                        adjustMediaPosition(group.allPageItems[i], offsetX, offsetY);
                    }
                }
            }

            // Function to adjust media position (images and graphics) within the new frame
            function adjustMediaPosition(object, offsetX, offsetY) {
                if ((object.constructor.name === "Rectangle" || 
                     object.constructor.name === "Oval" || 
                     object.constructor.name === "Polygon") && 
                    (object.images.length > 0 || object.graphics.length > 0)) {
                    
                    // Handle both images and graphics (including .eps)
                    var media = object.images.length > 0 ? object.images[0] : object.graphics[0];

                    // Adjust geometric bounds for all shapes
                    media.geometricBounds = [
                        media.geometricBounds[0] + offsetY,
                        media.geometricBounds[1] + offsetX,
                        media.geometricBounds[2] + offsetY,
                        media.geometricBounds[3] + offsetX
                    ];
                }
            }

            // Function to fit content in images/graphics with proportional adjustment for all shapes
            function fitContentInMediaProportionally(object, fitOption) {
                if ((object.constructor.name === "Rectangle" || 
                     object.constructor.name === "Oval" || 
                     object.constructor.name === "Polygon") && 
                    (object.images.length > 0 || object.graphics.length > 0)) {

                    object.fit(fitOption);  // Use proportional fitting
                } else if (object.constructor.name === "Group") {
                    for (var i = 0; i < object.allPageItems.length; i++) {
                        fitContentInMediaProportionally(object.allPageItems[i], fitOption);
                    }
                }
            }

            // Check if the dimensions (width and height) are equal
            if (areDimensionsEqual(firstWidth, firstHeight, secondWidth, secondHeight)) {
                // Calculate the offset between the first and second object
                var offsetX = secondBounds[1] - firstBounds[1];
                var offsetY = secondBounds[0] - firstBounds[0];

                // Adjust the image/graphic position for both objects
                adjustMediaPosition(firstObject, offsetX, offsetY);
                adjustMediaPosition(secondObject, -offsetX, -offsetY);

                // Adjust media positions within groups if necessary
                adjustGroupImagesPosition(firstObject, offsetX, offsetY);
                adjustGroupImagesPosition(secondObject, -offsetX, -offsetY);

            } else {
                // Use FILL_PROPORTIONALLY option for fitting media without stretching
                var fitOptions = FitOptions.FILL_PROPORTIONALLY;

                // Fit content in media in both objects using proportional fitting for all shapes
                fitContentInMediaProportionally(firstObject, fitOptions);
                fitContentInMediaProportionally(secondObject, fitOptions);

                // Adjust media positions within groups if necessary
                adjustGroupImagesPosition(firstObject, 0, 0);
                adjustGroupImagesPosition(secondObject, 0, 0);
            }
        }
    }
}, ScriptLanguage.JAVASCRIPT, null, UndoModes.ENTIRE_SCRIPT, "Swap Object Sizes and Positions");
TOPICS
How to , Scripting , SDK , UXP Scripting

Views

180
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
Community Expert ,
Feb 28, 2025 Feb 28, 2025

Copy link to clipboard

Copied

Hi @SmythWharf, just for starters, are *you* able to select items on different pages (edit: I was thinking spreads) at the same time? I don't know how to do that. - Mark

 

Edit: Ah I think I understand now... you mean two items on unconnected pages in the same spread. Of course. Sorry.

Votes

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
Contributor ,
Mar 01, 2025 Mar 01, 2025

Copy link to clipboard

Copied

As in, two items from pages which have no connections. The quickest way to think about it is the pages panels, if there is a gap from one page to another or spread to a spread, I am unable to recognise both of these things as a selection in the script. It believes only one thing is being selected.

 

Hope this helps.

 

Votes

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
Community Expert ,
Mar 01, 2025 Mar 01, 2025

Copy link to clipboard

Copied

@SmythWharf

 

It's not possible to select items on two separate SPREADS.

 

Can you post some screenshots showing what you're trying to select? 

 

Votes

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
Community Expert ,
Feb 28, 2025 Feb 28, 2025

Copy link to clipboard

Copied

@SmythWharf

 

What error do you get? 

 

If by "swap" you mean "change location" - why not just move the selected objects? 

 

Votes

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
Community Expert ,
Feb 28, 2025 Feb 28, 2025

Copy link to clipboard

Copied

@SmythWharf

 

I can't check your code right now, but it's possible that your script is going high-wire, if you've "ruler origin" set to "per page" - and not "per Spread". 

 

https://www.indesignjs.de/extendscriptAPI/indesign-latest/#RulerOrigin.html 

 

Votes

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
Contributor ,
Mar 01, 2025 Mar 01, 2025

Copy link to clipboard

Copied

Hello, 

 

The script fails to run when two items are selected on unconnected pages. It flags this the built in error claiming there needs to be two things selected. in short, it cant read one of the selections. (I never tested this as I could maybe add a debug at the start to print out all selections), but this is my hunch. 

It seems to only be able to pick up selections from any connect page(s), i.e. page single or spread

Votes

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
Contributor ,
Mar 01, 2025 Mar 01, 2025

Copy link to clipboard

Copied

Hello, 

 

Silly me, it's an InDesign limitation, you simply cannot make selections of items which span across unconnected pages. 

 

SmythWharf_0-1740860271257.pngexpand image

For example I can only select one image at a time.

 

 

Votes

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
Community Expert ,
Mar 01, 2025 Mar 01, 2025

Copy link to clipboard

Copied

@SmythWharf

 

Yes, you can select objects only on the same Spread - unfortunately, it was always like that.

 

But you can modify your script to ask for selecting first object, save reference, then display second dialog - asking user to select another object. 

 

Votes

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
Contributor ,
Mar 01, 2025 Mar 01, 2025

Copy link to clipboard

Copied

LATEST

Alas, it was a slip of the mind, revisiting this script after about 6 or so months. 

Shame InDesign doesn't support such selections. Oh well.

 

Best, 

 

Smyth

Votes

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