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

Script to Paste Images with slight offset

New Here ,
Dec 09, 2025 Dec 09, 2025

Is there a script or a way to paste the same image on every page but each page a slight different position? 


I'm doing a fore-edge print and need the same image on every other page but each time it has to move 0.246mm left

 

Thank You!

TOPICS
Experiment , How to , Scripting
164
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 ,
Dec 09, 2025 Dec 09, 2025

Hi @Joaquin35467744k2vs here's a script that should be useful in your situation. There are instructions in the script documentation below.

- Mark

 

Notes:

  • You must name the start item "start_" then something to identify it (because you may have multiple interpolations in the same document). For example: "start_fore_edge_marker".
  • the "end_" item cannot be on the same page as the "start_" item.

 

Screenshot 2025-12-09 at 22.54.54.png

 

/**
 * @file Interpolate Item Across Pages.js
 *
 * Places a duplicate item on each intervening page
 * between start and end items. Interpolates the
 * positions between start and end items.
 *
 * Instructions:
 *   1. create a page item (can be a Group)
 *   2. position the item on the starting page,
 *      in the starting position
 *   3. in the layers panel, name the item "start_"
 *      + an identifier of your choice, eg. "start_line"
 *   4. copy the item and paste it on the ending page,
 *      and move to the ending position
 *   5. name the pasted item "end_" with the same
 *      identifier, eg. "end_line"
 *   6. select the start or end item and run script;
 *      will create duplicates called eg. "middle_line"
 *
 * Tips:
 *   - you can adjust the start and/or end items and
 *     run script again and it will update the interpolated
 *     duplicates (actually it will first remove them all
 *     and re-do the duplicating).
 *   - the interpolationed items will be placed on the same
 *     layer as the start item.
 *
 * @author m1b
 * @version 2025-12-13
 * @discussion https://community.adobe.com/t5/indesign-discussions/script-to-paste-images-with-slight-offset/m-p/15624584
 */
function main() {

    const PREFIX_START = 'start_';
    const PREFIX_MIDDLE = 'middle_';
    const PREFIX_END = 'end_';

    var doc = app.activeDocument;
    var item = doc.selection[0];

    if (
        !item
        || 'function' !== typeof item.duplicate
        || 'string' !== typeof item.name
    )
        return alert('Please select an item and try again.')


    var matchAnyPrefix = new RegExp('^(' + [PREFIX_START, PREFIX_MIDDLE, PREFIX_END].join('|') + ')');

    if (!matchAnyPrefix.test(item.name))
        return alert('The name of the selected item does not have an expected prefix, eg. "' + PREFIX_START + '". Please set up correctly and try again.');

    var id = item.name.replace(matchAnyPrefix, '');

    var startItemName = PREFIX_START + id;
    var middleItemName = PREFIX_MIDDLE + id;
    var endItemName = PREFIX_END + id;

    var middleItems = getThings(doc.allPageItems, 'name', middleItemName);

    // remove all middle items
    for (var i = middleItems.length - 1; i >= 0; i--)
        middleItems[i].remove();

    var startItem = getThing(doc.allPageItems, 'name', startItemName);
    var endItem = getThing(doc.allPageItems, 'name', endItemName);

    if (!startItem)
        return alert('Could not find the start item named "' + startItemName + '".');

    if (!endItem)
        return alert('Could not find the end item named "' + endItemName + '".');

    if (endItem.itemLayer !== startItem.itemLayer)
        endItem.move(startItem.itemLayer);

    var startPage = getNearestPage(startItem);
    var endPage = getNearestPage(endItem);

    var startSpread = startPage.parent;
    var endSpread = endPage.parent;

    if (startSpread === endSpread)
        return alert('Your start and end items must be on different spreads.');

    // collect the spreads we want
    var spreads = [];
    var count = Math.abs(endSpread.index - startSpread.index) - 1;
    var indices = interpolateRange(startSpread.index, endSpread.index, count);
    for (var i = 1; i <= count; i++)
        spreads.push(doc.spreads.item(indices[i]));

    // collect the pages we want
    var pages = [startPage];

    for (var i = 0, page, item; i < count; i++)
        pages.push(getPage(spreads[i]));

    pages.push(endPage);

    var startX = startItem.geometricBounds[1] - startPage.bounds[1];
    var startY = startItem.geometricBounds[0] - startPage.bounds[0];
    var endX = endItem.geometricBounds[1] - endPage.bounds[1];
    var endY = endItem.geometricBounds[0] - endPage.bounds[0];

    var xPositions = interpolateRange(startX, endX, count);
    var yPositions = interpolateRange(startY, endY, count);

    // duplicate the item to each page
    for (var i = 1, page, item; i < pages.length - 1; i++) {

        page = pages[i];
        item = startItem.duplicate(page);
        item.name = 'middle_' + id;

        positionItemRelativeToPage(item, xPositions[i], yPositions[i], page);

    }

    /**
     * Given a Spread, returns the page we want to interpolate onto.
     * @param {Spread} spread
     * @returns {Page}
     */
    function getPage(spread) {

        for (var i = 0, pg; i < spread.pages.length; i++) {

            pg = spread.pages[i];

            if (doc.documentPreferences.facingPages) {

                if (startPage.side === pg.side)
                    return pg;
                else
                    continue;

            }

            else if (startPage.index === pg.index)
                return pg;

        }

    };

};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Interpolate Item Across Pages');

/**
 * Returns an array including `count` interpolated
 * values between `start` and `end`, inclusive.
 * @author m1b
 * @version 2024-08-13
 * @param {Number} start - the first value.
 * @param {Number} end - the last value.
 * @param {Number} count - the number of interpolations.
 * @returns {Array<Number>}
 */
function interpolateRange(start, end, count) {

    var range = [start],
        step = (end - start) / (count + 1);

    for (var i = 1; i <= count; i++)
        range.push(start + i * step);

    range.push(end);

    return range;

};

/**
 * Moves `item` to the top left of the nearest page, offset by [dx, dy].
 * @author m1b
 * @version 2025-11-08
 * @param {PageItem} item - an Indesign PageItem.
 * @param {Number} dx - the X offset.
 * @param {Number} dy - the Y offset.
 * @param {Page} [nearestPage] - an Indesign Page (default: the nearest page).
 */
function positionItemRelativeToPage(item, dx, dy, nearestPage) {

    if ('function' !== typeof item.move)
        throw new Error('positionItemRelativeToPage: cannot move item.');

    // get the nearest page, in case the item isn't on a page
    var page = nearestPage || getNearestPage(item);

    // get the top left of the page
    var pos = [page.bounds[0], page.bounds[1]];

    // move the item
    item.move([pos[1] + dx, pos[0] + dy]);

};

/**
 * Returns the nearest page to `item`.
 * @author m1b
 * @version 2025-08-02
 * @param {PageItem} item - the target item.
 * @returns {Page} - the nearest page to `item`.
 */
function getNearestPage(item) {

    var page = item.parentPage;
    var spread;

    while (!page) {

        spread = item.parent;

        if ('Page' === spread.constructor.name)
            page = spread;


        if ('Spread' === spread.constructor.name) {

            var index = findClosestBounds(
                item.visibleBounds,
                spread.pages.everyItem().bounds
            );

            page = spread.pages.item(index);

        }

    }

    return page;

};

/**
 * Returns the index of the bounds in `boundsArray` that is
 * closest to the target bounds. All bounds are in [T, L, B, R] format.
 * @author m1b
 * @version 2025-08-02
 * @param {Array} targetBounds - The target bounds [T, L, B, R].
 * @param {Array<bounds>} boundsArray - An array of bounds arrays.
 * @returns {Number} Index of the closest bounds in the array.
 */
function findClosestBounds(targetBounds, boundsArray) {

    var targetCenter = centerOfBounds(targetBounds);
    var minDist = Infinity;
    var closestIndex = -1;

    for (var i = 0, center, dx, dy, distSq; i < boundsArray.length; i++) {

        center = centerOfBounds(boundsArray[i]);
        dx = targetCenter[0] - center[0];
        dy = targetCenter[1] - center[1];
        distSq = dx * dx + dy * dy;

        if (distSq < minDist) {
            minDist = distSq;
            closestIndex = i;
        }

    }

    return closestIndex;

};

/**
 * Returns the center of `bounds`;
 * @param {Array} bounds - The bounds [T, L, B, R].
 * @returns {Array<Number>} - [cx, cy].
 */
function centerOfBounds(bounds) {
    return [(bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2];
};

/**
 * Returns a thing with matching property.
 * If `key` is undefined, evaluate the object itself.
 * @author m1b
 * @version 2024-04-21
 * @param {Array|Collection} things - the things to look through.
 * @param {String} [key] - the property name (default: undefined).
 * @param {*} value - the value to match.
 * @returns {*?} - the thing, if found.
 */
function getThing(things, key, value) {

    for (var i = 0; i < things.length; i++)
        if ((undefined == key ? things[i] : things[i][key]) == value)
            return things[i];

};

/**
 * Returns a property of each object.
 * @author m1b
 * @version 2023-09-08
 * @param {Array|Collection} things - the things to look through.
 * @param {String} key - the property name.
 * @param {*} value - the value to match.
 * @returns {Array<*>}
 */
function getThings(things, key, value) {

    var found = [];

    for (var i = 0; i < things.length; i++)
        if (things[i][key] == value)
            found.push(things[i]);

    return found;

};

Edit 2025-12-13: added better handling of spreads and facing pages.

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 ,
Dec 12, 2025 Dec 12, 2025
LATEST

@Joaquin35467744k2vs sorry I just realized that the script didn't consider spreads and facing pages. I have updated the code above. You mention "every other page"—I am assuming that is due to using two-page spreads? If so, I hope that revised script will suit your case.

- Mark

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